#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.ComponentModel;
using System.Collections.Generic;
using System.Text;
using dataMagus.Common.Logical;
#endregion

namespace dataMagus.Common.Physical.Objectoriented
{
	/// <summary>
	/// This class extends a physical objectoriented association for n:m implementation.
	/// </summary>
    [Serializable]
    public class ManyToManyPhysicalObjectorientedAssociation : PhysicalObjectorientedAssociation
    {
        #region Constants
        /// <summary>
        /// Name of the Cardinality1 property
        /// </summary>
        private const string Cardinality1PropertyName = "Cardinality1";
        
        /// <summary>
        /// Name of the Cardinality2 property
        /// </summary>
        private const string Cardinality2PropertyName = "Cardinality2";
        #endregion

        #region Enumerations
		/// <summary>
		/// Possible cardinalities.
		/// </summary>
        public enum Cardinality
        {
			/// <summary>
			/// Zero, one or more.
			/// </summary>
			ZeroOneOrMore,
			
			/// <summary>
			/// One or more.
			/// </summary>
            OneOrMore
        }
        #endregion

        #region Members
		/// <summary>
		/// Cardinality to the first class.
		/// </summary>
        private Cardinality _cardinality1 = Cardinality.ZeroOneOrMore;

		/// <summary>
		/// Cardinality to the second class.
		/// </summary>
        private Cardinality _cardinality2 = Cardinality.ZeroOneOrMore;
        #endregion

        #region Constructors / Destructors
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="schema">Physical objectoriented schema.</param>
        /// <param name="id">Unique id of the object.</param>
        /// <param name="origin">Origin element the association is based on.</param>
        /// <param name="name">Name of the association.</param>
        /// <param name="class1">First class.</param>
        /// <param name="class2">Second class.</param>
        /// <param name="rolename1">Rolename of the first class.</param>
        /// <param name="rolename2">Rolename of the second class.</param>
		/// <param name="cardinality1">Cardinality to the first class.</param>
		/// <param name="cardinality2">Cardinality to the second class.</param>
        public ManyToManyPhysicalObjectorientedAssociation(PhysicalObjectorientedSchema schema, string id, IElement origin, string name,
            PhysicalObjectorientedClass class1, PhysicalObjectorientedClass class2,
            string rolename1, string rolename2, Cardinality cardinality1, Cardinality cardinality2)
            : base(schema, id, origin, name, class1, class2, rolename1, rolename2)
        {
            this._cardinality1 = cardinality1;
            this._cardinality2 = cardinality2;

            // Restore physical changes if available
            object cardinality1ToRestore = DataContainer.Instance.PhysicalData.GetRestoreDataItem(base._schema, this.Id, ManyToManyPhysicalObjectorientedAssociation.Cardinality1PropertyName);
            if (null != cardinality1ToRestore)
            {
                this._cardinality1 = (Cardinality)cardinality1ToRestore;
            }

            object cardinality2ToRestore = DataContainer.Instance.PhysicalData.GetRestoreDataItem(base._schema, this.Id, ManyToManyPhysicalObjectorientedAssociation.Cardinality2PropertyName);
            if (null != cardinality2ToRestore)
            {
                this._cardinality2 = (Cardinality)cardinality2ToRestore;
            }
        }
        #endregion

        #region Properties
		/// <summary>
		/// Cardinality to the first class.
		/// </summary>
		[ReadOnly(true)]
        public Cardinality Cardinality1
        {
            get { return this._cardinality1; }
            set
            {
                if (this._cardinality1 != value)
                {
	                this.EnsureUpdateOriginalRestoreDataItem(base._schema, this, ManyToManyPhysicalObjectorientedAssociation.Cardinality1PropertyName, value);
                    this._cardinality1 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
            }
        }

		/// <summary>
		/// Cardinality to the second class.
		/// </summary>
		[ReadOnly(true)]
        public Cardinality Cardinality2
        {
            get { return this._cardinality2; }
            set
            {
                if (this._cardinality2 != value)
                {
                    this.EnsureUpdateOriginalRestoreDataItem(base._schema, this, ManyToManyPhysicalObjectorientedAssociation.Cardinality2PropertyName, value);
                    this._cardinality2 = value;
                    this.FireElementChangedEvent(this, new ElementEventArgs(this, ElementChangedAction.ChangedProperty));
                }
            }
        }
        #endregion

        #region Methodes
        /// <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("ManyToManyAssociation");
            base.WriteXml(writer);

            writer.WriteAttributeString("cardinality1", this.Cardinality1.ToString());
            writer.WriteAttributeString("cardinality2", this.Cardinality2.ToString());

            writer.WriteEndElement();
        }
        #endregion
    }
}
