/*********************************************************************/ /* */ /* 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 System; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Collections; using AgentService.Ontology.Schema; using AgentService.Ontology.Schema.Abstract; using System.Reflection; using AgentService.Ontology.Interfaces; using AgentService.Ontology.Validation; namespace AgentService.Ontology { /// /// An ontology provides a set of elements that agents can use within content message. /// The ontology defines a vocabulary and relationships between elements in the vocabulary. /// [Serializable] public class Ontology { private Ontology[] Base = new Ontology[0]; private string name; private Hashtable elements = new Hashtable(); // Maps type-names to schemas private Hashtable classes = new Hashtable(); // Maps type-names to classes private Hashtable schemas = new Hashtable(); // Maps classes to schemas private Introspector introspector;// = new ReflectiveIntrospector(); /// /// Constructs an Ontology with a given name and that extends a base ontology. /// /// The name of ontology /// The base ontology /// An introspector user-defined. public Ontology(string name, Ontology Base, Introspector introspector) { try { this.name = name; if(Base!=null) { this.Base = new Ontology[1]; this.Base[0]=Base; } else { this.Base = new Ontology[0]; } this.introspector=introspector; } catch(Exception ex) { throw new OntologyException(ex.ToString()); } } /// /// Constructs an Ontology with a given name and that extends a base ontology. /// /// The name of ontology /// The base ontology public Ontology(string name, Ontology Base):this(name,Base,new ReflectiveIntrospector()) { } /// /// Constructs an ontology with a given name and a set of base ontologies. /// /// The name of the ontology /// The set of base ontologies /// An introspector user-defined. public Ontology(string name, Ontology []Base, Introspector introspector) { try { this.name = name; if(Base!=null) { this.Base = Base; } else { this.Base = new Ontology[0]; } this.introspector=introspector; } catch(Exception ex) { throw new OntologyException("Unable to create an ontology named "+name+" :"+ex.ToString()); } } /// /// Constructs an ontology with a given name and a set of base ontologies. /// /// The name of the ontology /// The set of base ontologies public Ontology(string name, Ontology []Base): this(name, Base, new ReflectiveIntrospector()) { } /// /// Constructs an ontology with a given name. /// /// The name of the ontology. /// An introspector user-defined. public Ontology(string name, Introspector introspector) { try { this.name= name; this.Base = new Ontology[0]; this.introspector=introspector; } catch(Exception ex) { throw new OntologyException("Unable to create an ontology named "+name+": "+ex.ToString()); } } /// /// Constructs an ontology with a given name. /// /// The name of the ontology. public Ontology(string name): this(name, new ReflectiveIntrospector()) { } /// /// Retrieves the name of the ontology. /// /// Returns the name of this ontology. public string GetName() { return name; } /// /// Adds a schema to this ontology. /// /// The schema to Add. public void Add(ObjectSchema schema) { try { Add(schema, null); } catch(Exception ex) { throw new OntologyException("Unable to Add the schema "+schema.GetType()+" to the ontology "+this.GetName()+": "+ex.ToString()); } } /// /// Adds a schema to this ontology, with its type class associated. /// /// The schema to Add. /// The class of the schema. public void Add(ObjectSchema schema, Type Class) { try { if (schema.GetTypeName() == null) { throw new OntologyException("Invalid schema identifier"); } string s = schema.GetTypeName().ToLower(); elements.Add(s,schema); if (Class != null) { classes.Add(s, Class); schemas.Add(Class, schema); } } catch(Exception ex) { throw new OntologyException("Unable to Add the schema "+schema.GetType()+" associated to the class "+Class.FullName+" to the ontology "+this.GetName()+": "+ex.ToString()); } } /// /// Retrieves the schema of the element name in this ontology or in the set of base ontologies. /// /// The name of the schema in the vocabulary /// Returnsnull if not exists a schema associated to the name public ObjectSchema GetSchema(string name) { try { if (name == null) { throw new OntologyException("Null schema identifier"); } ObjectSchema ret = (ObjectSchema) elements[name.ToLower()]; if (ret == null) { for (int i = 0; i < Base.Length; ++i) { ret = Base[i].GetSchema(name); if (ret != null) { return ret; } } } return ret; } catch { throw new OntologyException("The schema of the element "+name+" doesn't exist in ontology "+this.GetName()+" or in its base ontologies"); } } /// /// Retrieves the class associated with the element with a given name, in this ontology or in the set of base ontologies. /// /// The name of the element. /// The Type of the given element. public Type GetClassForElement(string name) { try { if (name == null) { throw new OntologyException("Null schema identifier"); } Type ret = (Type) classes[name.ToLower()]; if (ret == null) { for (int i = 0; i < Base.Length; ++i) { ret = Base[i].GetClassForElement(name); if (ret != null) { return ret; } } } return ret; } catch { throw new OntologyException("The class of the element "+name+" doesn't exist in ontology "+this.GetName()+" or in its base ontologies"); } } /// /// Checks if the object is a valid Term /// /// public static void CheckIsTerm(Object obj) { try { if (obj is string || obj is bool || obj is int|| obj is long || obj is float || obj is double || obj is System.DateTime || obj is Term) { return; } if (obj is ArrayList) { ArrayList myList = (ArrayList) obj; foreach(object o in myList) { CheckIsTerm(o); } return; } throw new OntologyException("This object is not a Term."); } catch(Exception ex) { throw new OntologyException(ex.ToString()); } } /* protected object toObject(AbsObject abs, string lcType, Ontology globalOnto) { ObjectSchema schema = (ObjectSchema) elements[lcType]; if (schema != null) { Type Class = (Type) classes[lcType]; if (Class == null) { return null; } if (Class is AbsObject) { return abs; } if (introspector != null) { return introspector.internalise(abs, schema, Class, globalOnto); } } return null; }*/ /// /// Returns an abstract object: an abstract representation for a given object, using a given ontology. /// /// The object to convert. /// The ontology to use. /// public virtual AbsObject FromObject(object obj, Ontology globalOnto) { try { if (obj is AbsObject) { return (AbsObject) obj; } Type Class = obj.GetType(); ObjectSchema schema = (ObjectSchema) schemas[Class]; if (schema != null) { if (introspector != null) { return introspector.Externalise(obj, schema, Class, globalOnto); } } for (int i = 0; i < Base.Length; i++) { //This is a monument to my ignorance. Please see how I managed the call to //method of a derived class that overrides a method of a base class. //I'm stupid! I didn't use the virtual keyword... /*MethodInfo fromObject = this.Base[i].GetType().GetMethod("FromObjectBasic"); if(fromObject!=null) { try { object [] ob = new object[2]; ob[0]=obj; ob[1]=globalOnto; object o = fromObject.Invoke(this.Base[i],ob); return (AbsObject)o; } catch(Exception e) { throw new OntologyException("Unable to convert the object "+obj.GetType() +" into AbsObject in the ontology "+this.Base[i].GetName()+": "+e.ToString()); } } return this.Base[i].FromObject(obj, globalOnto);*/ AbsObject abs = this.Base[i].FromObject(obj, globalOnto); if (abs != null) return abs; } return null; } catch(Exception e) { throw new OntologyException("Unable to convert the object "+obj.GetType() +" into AbsObject in the ontology "+this.GetName()+": "+e.ToString()); } } /* public Object toObject(AbsObject abs) { if (abs == null) { return null; } try { return toObject(abs, abs.GetTypeName().ToLower(), this); } catch (OntologyException oe) { if (!abs.isGrounded()) { throw new OntologyException("This absolute object is ungrounded"); } else { throw oe; } } }*/ /// /// Returns an abstract object: an abstract representation for a given object, using a given ontology. /// /// The object to convert. public AbsObject FromObject(Object obj) { if (obj == null) { return null; } try { return FromObject(obj, this); } catch { throw new OntologyException("No schema found for class "+obj.GetType().Name); } } /// /// An hash table that maps type-names and schemas. /// public Hashtable Elements { get { return this.elements; } } /// /// An hash table that maps type-names and classes. /// public Hashtable Schemas { get { return this.schemas; } } /// /// An hash table that maps classes and schemas. /// public Hashtable Classes { get { return this.classes; } } /// /// An array that Contains the base ontologies of this ontology. /// public Ontology [] BaseOntologies { get { return this.Base; } } } }