/*********************************************************************/
/*                                                                   */
/*                     AgentService Framework                        */
/*                       www.agentservice.it                         */
/*                                                                   */
/* Copyright (C) 2007 l.i.d.o. - DIST, University of Genoa, Italy    */
/* GNU Lesser General Public License                                 */
/*                                                                   */
/* This library is free software; you can redistribute it and/or     */
/* modify it under the terms of the GNU Lesser General Public        */
/* License as published by the Free Software Foundation,             */
/* version 2.1 of the License.                                       */
/*                                                                   */
/* This library 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 */
/* Lesser General Public License for more details.                   */
/*                                                                   */
/* You should have received a copy of the GNU Lesser General Public  */
/* License along with this library; if not, write to the             */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330,      */
/* Boston, MA  02111-1307, USA.                                      */
/*                                                                   */
/*********************************************************************/
using AgentService.Ontology;
using System;
using AgentService.Ontology.Schema.Abstract;
using AgentService.Ontology.Validation;

namespace AgentService.Ontology.Schema 
{

	/// <summary>
	/// This class is used to define schema of concepts in an ontology.
	/// </summary>
	public class ConceptSchema : TermSchema 
	{

		public static readonly new string   base_name = "Concept";
		private static new ConceptSchema baseSchema = new ConceptSchema();

		/// <summary>
		/// Constructs a schema that vinculates an entity to be a generic concept.
		/// </summary>
		public ConceptSchema(): base(base_name)
		{
			
		}

		/// <summary>
		/// Constructs a concept with a given name.
		/// </summary>
		/// <param name="typeName">The name of the concept.</param>
		public ConceptSchema(string typeName): base(typeName) 
		{
		}

		
		/// <summary>
		/// Retrieves the generic baseschema for all concepts.
		/// </summary>
		/// <returns></returns>
		public new static ObjectSchema GetBaseSchema() 
		{
			return baseSchema;
		} 

		
		/// <summary>
		/// Adds a named slot to the concept. The schema for this slot must be a TermSchema.
		/// </summary>
		/// <param name="name">The name of the slot.</param>
		/// <param name="slotSchema">The schema of the slot.</param>
		public void Add(string name, TermSchema slotSchema) 
		{
			base.Add(name, slotSchema);
		} 

		/// <summary>
		/// Adds a named slot to the concept, with optionality. The schema for this slot must be a TermSchema.
		/// </summary>
		/// <param name="name">The name of the slot.</param>
		/// <param name="slotSchema">The schema of the slot.</param>
		/// <param name="optionality">OPTIONAL or MANDATORY.</param>
		public void Add(string name, TermSchema slotSchema, int optionality) 
		{
			base.Add(name, slotSchema, optionality);
		} 

		/// <summary>
		/// Adds a named slot with minimum and maximum cardinality.
		/// </summary>
		/// <param name="name">The name of the slot.</param>
		/// <param name="elementsSchema">The schema of the slot.</param>
		/// <param name="cardMin">The slot must have at least <code>cardMin</code> values.</param>
		/// <param name="cardMax">The slot must have at most <code>cardMax</code> values.</param>
		public void Add(string name, TermSchema elementsSchema, int cardMin, int cardMax) 
		{
			base.Add(name, elementsSchema, cardMin, cardMax);
		} 

		/// <summary>
		/// Adds a slot, specifying the type of the aggregate element.
		/// </summary>
		/// <param name="name">The name of the slot.</param>
		/// <param name="elementsSchema">The schema of the slot.</param>
		/// <param name="cardMin">The slot must have at least <code>cardMin</code> values.</param>
		/// <param name="cardMax">The slot must have at most <code>cardMax</code> values.</param>
		/// <param name="aggType">The type of the aggregate.</param>
		public void Add(string name, TermSchema elementsSchema, int cardMin, int cardMax, string aggType) 
		{
			base.Add(name, elementsSchema, cardMin, cardMax, aggType);
		} 
    
		/// <summary>
		/// Adds a super schema to this concept. If this entity is a concept, the super schema must be a concept.
		/// </summary>
		/// <param name="superClassSchema">The superschema schema.</param>
		public void AddSuperSchema(ConceptSchema superClassSchema) 
		{
			base.AddSuperSchema(superClassSchema);
		} 

		/// <summary>
		/// Adds a facet to a given slot.
		/// </summary>
		/// <param name="slotName">The name of the slot.</param>
		/// <param name="f">The facet.</param>
		public new void AddFacet(string slotName, Facet f) 
		{
			try
			{
				base.AddFacet(slotName, f);
			}
			catch(Exception ex)
			{
				throw new OntologyException(ex.ToString());
			}
		}
		
		/// <summary>
		/// Returns true if 
		///- s is the base schema for the XXXSchema class and this schema is
		///	 an instance of (e.g. s is ConceptSchema.GetBaseSchema() and this 
		///	 schema is an instance of ConceptSchema)
		///	- s is the base schema for a super-class of the XXXSchema class and
		///	 this schema is an instance of (e.g. s is TermSchema.GetBaseSchema()
		///	 and this schema is an instance of ConceptSchema.
		/// </summary>
		/// <param name="s">Object schema</param>
		/// <returns>Returns true if <code>s</code> is a base schema for this schema.</returns>
		public override bool DescendsFrom(ObjectSchema s) 
		{
			try
			{
				if (s != null) 
				{
					if (s.Equals(GetBaseSchema())) 
					{
						return true;
					}
					return base.DescendsFrom(s);
				}
				else 
				{
					return false;
				}
			}
			catch(Exception ex)
			{
				throw new OntologyException(ex.ToString());
			}
		}

		
		/// <summary>
		/// Returns an abstract object that represents this concept.
		/// </summary>
		/// <returns></returns>
		public override AbsObject NewInstance() 
		{
			return new AbsConcept(GetTypeName());
		} 

	
		
		/// <summary>
		/// Validates a given abstract object, using a given ontology.
		/// </summary>
		/// <param name="abs">The abstract object to Validate.</param>
		/// <param name="onto">The ontology to use.</param>
		public override void Validate(AbsObject abs, Ontology onto) 
		{
			try
			{
				if (!(abs is AbsConcept)) 
				{
					throw new OntologyException(abs+" is not an AbsConcept");
				}
				ValidateSlots(abs, onto);
			}
			catch(Exception ex)
			{
				throw new ValidationException("Unable to Validate "+abs+": "+ex.ToString());
			}
		}
	}
}