#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.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
#endregion

namespace dataMagus.Common.Logical
{
	/// <summary>
	/// This class represents a logical attribute.
	/// </summary>
	[Serializable]
	public class LogicalAttribute : LogicalElement
	{
		#region Members
		/// <summary>
		/// Parent element the attribute belongs to.
		/// </summary>
        private LogicalElement _parent;
		#endregion
		
		#region Constructors / Destructors
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="parent">Element the attribute belongs to.</param>
		/// <param name="name">Name of the attribute.</param>
        public LogicalAttribute(LogicalElement parent, string name)
			: base(name)
		{
            this._parent = parent;
		}
		#endregion
		
		#region Properties
		/// <summary>
		/// Parent element the attribute belongs to.
		/// </summary>
		[Browsable(false)]
        public LogicalElement Parent
        {
            get { return this._parent; }
            set 
            { 
                if (this._parent != value)
                {
                    this._parent = value;
                   	this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
            }
        }

        /// <summary>
        /// Checks if the attribute is part of the key.
        /// </summary>
        public bool IsPartOfKey
        {
            get
            {
                if (null == this._parent)
                {
                    return false;
                }
                if (this._parent is LogicalEntity)
                {
                    return ((LogicalEntity)this._parent).ContainsKeyAttribute(this);
                }
                if (this._parent is ManyToManyLogicalRelationship)
                {
                    return ((ManyToManyLogicalRelationship)this._parent).ContainsKeyAttribute(this);
                }
                return false;
            }
            set
            {
                // Rules:
                // 1: If parent will be extended (by a is-a relationship), it has to get its attribute from the BBM (big bad master)
            	// 2: Only LogicalEntities and ManyToManyLogicalRelationships can have Attributes
                if (null != this._parent)
                {
                    if (value)
                    {
                        if (this._parent is LogicalEntity)
                        {
                            LogicalEntity parent = (LogicalEntity)this._parent;
                            
                            //--- Rule 1 ---
                            IEnumerator relEnum = parent.GetRelationships();
                            while (relEnum.MoveNext())
                            {
                            	LogicalRelationship rel = (LogicalRelationship)relEnum.Current;
                            	if (rel is IsALogicalRelationship && parent == rel.Entity2)
                            	{
                            		return;
                            	}
                            }
                            
                            if (!parent.ContainsKeyAttribute(this))
                            {
                                parent.AddKeyAttribute(this);
                            }
                        }
                        else if (this._parent is ManyToManyLogicalRelationship)
                        {
                            ManyToManyLogicalRelationship parent = (ManyToManyLogicalRelationship)this._parent;
                            if (!parent.ContainsKeyAttribute(this))
                            {
                                parent.AddKeyAttribute(this);
                            }
                        }
                        else
                        {
                            //--- Rule 2 ---
                        	return;
                        }
                    }
                    else
                    { 
                    	// Rule 1
                        if (this._parent is LogicalEntity)
                        {
                            LogicalEntity parent = (LogicalEntity)this._parent;
                            if (parent.ContainsKeyAttribute(this))
                            {
                                parent.RemoveKeyAttribute(this);
                            }
                        }
                        else if (this._parent is ManyToManyLogicalRelationship)
                        {
                            ManyToManyLogicalRelationship parent = (ManyToManyLogicalRelationship)this._parent;
                            if (parent.ContainsKeyAttribute(this))
                            {
                                parent.RemoveKeyAttribute(this);
                            }
                        }
                        else
                        {
                            //--- Rule 2 ---
                        	return;
                        }
                    }
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
            }
        }
		#endregion
		
		#region Methodes
		/// <summary>
		/// Gets the parent element.
		/// </summary>
		/// <returns>Parent element.</returns>
        public override IElement GetParent()
        {
        	return this._parent;
        }
		
        /// <summary>
        /// Writes a the instace of this class to a writer.
        /// </summary>
        /// <param name="writer">Writer object to write into.</param>
        public override void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteStartElement("Attribute");
            base.WriteXml(writer);
            writer.WriteEndElement();
        }
		#endregion
    }
}
