/*********************************************************************/
/* */
/* 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;
}
}
}
}