#region Copyright and GPL
/*************************************************************************
 * dataMagus - The open source database learning software
 * Copyright (C) 2007 by all authors
 * Authors: Monika Schwitter (monsy@gmx.ch)
 *          Jürg Zgraggen (j.zgraggen@ejaz.net)
 *          HSLU (Hochschule Luzern - Technik+Architektur)
 * 
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *************************************************************************/
#endregion
#region Using
using System;
using System.Collections;
using System.ComponentModel;
using System.Collections.Generic;
#endregion

namespace dataMagus.Common.Logical
{
	/// <summary>
	/// This class represents an abstract logical relationship.
	/// </summary>
	[Serializable]
	public abstract class LogicalRelationship : LogicalElement
	{
		#region Members
		/// <summary>
		/// First entity.
		/// </summary>
		private LogicalEntity _entity1;
		
		/// <summary>
		/// Second entity.
		/// </summary>
		private LogicalEntity _entity2;
		
		/// <summary>
		/// Rolename of first entity.
		/// </summary>
		private string _rolename1;
		
		/// <summary>
		/// Rolename of second entity.
		/// </summary>
		private string _rolename2;
        #endregion
		
		#region Constructors / Destructors
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="name">Name of the relationship.</param>
		/// <param name="entity1">First entity.</param>
		/// <param name="entity2">Second entity.</param>
		/// <param name="rolename1">Rolename of the first entity.</param>
		/// <param name="rolename2">Rolename of the second entity.</param>
		protected LogicalRelationship(string name, LogicalEntity entity1, LogicalEntity entity2,
			string rolename1, string rolename2)
			: base(name)
		{
            if (null == entity1)
            {
                throw new Exception("Property Entity1 must not be null.");
            }
            if (null == entity2)
            {
                throw new Exception("Property Entity2 must not be null.");
            }
			this._entity1 = entity1;
			this._entity2 = entity2;
			this._rolename1 = rolename1;
			this._rolename2 = rolename2;
		}

		/// <summary>
		/// Default constructor
		/// </summary>
        protected LogicalRelationship()
        { 
        }
		#endregion
		
		#region Properties
		/// <summary>
		/// First entity.
		/// </summary>
		[ReadOnly(true)]
		public LogicalEntity Entity1
		{
			get { return this._entity1; }
			set 
			{
                if (null == value)
                {
                    throw new Exception("Property Entity1 must not be null.");
                }
				if (this._entity1 != value)
				{
					this._entity1 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
				}
			}
		}

		/// <summary>
		/// Second entity.
		/// </summary>
		[ReadOnly(true)]
		public LogicalEntity Entity2
		{
			get { return this._entity2; }
			set 
			{
                if (null == value)
                {
                    throw new Exception("Property Entity2 must not be null.");
                }
				if (this._entity2 != value)
				{
					this._entity2 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
			}
		}
		
		/// <summary>
		/// Indicates if the relationship is a self relation.
		/// </summary>
		public bool IsSelfRelationship
		{
			get { return this._entity1 == this._entity2; }
		}
		
		/// <summary>
		/// Rolename of first entity.
		/// </summary>
		public string Rolename1 
		{
			get { return this._rolename1; }
			set 
			{ 
				if (this._rolename1 != value)
				{
					this._rolename1 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
			}
		}
		
		/// <summary>
		/// Rolename of second entity.
		/// </summary>
		public string Rolename2 
		{
			get { return this._rolename2; }
			set 
			{ 
				if (this._rolename2 != value)
				{
					this._rolename2 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
			}
		}
		#endregion
		
		#region Methodes
        /// <summary>
        /// Reads back all attributes of this class from a reader.
        /// </summary>
        /// <remarks>This method has to be called by all classes extending this class.</remarks>
        /// <param name="reader">Reader object to read from.</param>
        public override void ReadXml(System.Xml.XmlReader reader)
        {
            base.BeginInit();

            base.ReadXml(reader);
            this.Rolename1 = reader.GetAttribute("rolename1");
            this.Rolename2 = reader.GetAttribute("rolename2");

            base.EndInit(false);
        }

        /// <summary>
        /// Writes all attributes of this class to a writer.
        /// </summary>
        /// <remarks>This method has to be called by all classes extending this class.</remarks>
        /// <param name="writer">Writer object to write into.</param>
        public override void WriteXml(System.Xml.XmlWriter writer)
        {
            base.WriteXml(writer);

            writer.WriteAttributeString("entity1", this.Entity1.Id);
            writer.WriteAttributeString("entity2", this.Entity2.Id);
            writer.WriteAttributeString("rolename1", this.Rolename1);
            writer.WriteAttributeString("rolename2", this.Rolename2);
        }
		#endregion
	}
}
