/** * *************************************************************** * JADE - Java Agent DEvelopment Framework is a framework to develop * multi-agent systems in compliance with the FIPA specifications. * Copyright (C) 2000 CSELT S.p.A. * * 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. * ************************************************************** */ package jade.content.onto; import jade.content.*; import jade.content.schema.*; import jade.content.abs.*; import jade.content.ContentElementList; import jade.content.onto.basic.*; import jade.content.lang.sl.SL0Vocabulary; import jade.core.AID; import jade.core.CaseInsensitiveString; import jade.lang.acl.ACLMessage; import jade.lang.acl.ISO8601; import jade.util.leap.*; import java.util.Date; /** * This class implements an ontology containing schemas for * Primitive types and SL0 operators i.e. basic ontological elements * required for minimal agent interaction. * Users should always extend this ontology when defining their * ontologies. * @author Federico Bergenti - Universita` di Parma * @author Giovanni Caire - TILAB */ public class BasicOntology extends Ontology implements SL0Vocabulary { // The singleton instance of this ontology private static final BasicOntology theInstance = new BasicOntology(); static { theInstance.initialize(); } // Primitive types names public static final String STRING = "BO_String"; public static final String FLOAT = "BO_Float"; public static final String INTEGER = "BO_Integer"; public static final String BOOLEAN = "BO_Boolean"; public static final String DATE = "BO_Date"; public static final String BYTE_SEQUENCE = "BO_Byte-sequence"; // Content element list public static final String CONTENT_ELEMENT_LIST = ContentElementListSchema.BASE_NAME; //#MIDP_EXCLUDE_BEGIN private transient Map primitiveSchemas; //#MIDP_EXCLUDE_END /** * Constructor */ private BasicOntology() { super("BASIC_ONTOLOGY", (Ontology) null, null); } private void initialize() { // Note that the association between schemas and classes is not // necessary for the elements of the BasicOntology as the // BasicOntology does not use schemas to translate between // Java objects and abstract descriptors, but performs a hardcoded // translation try { // Schemas for primitives add(new PrimitiveSchema(FLOAT)); add(new PrimitiveSchema(INTEGER)); add(new PrimitiveSchema(BOOLEAN)); // Schemas for aggregates add(new AggregateSchema(SEQUENCE)); add(new AggregateSchema(SET)); // Content element list Schema add(ContentElementListSchema.getBaseSchema()); //#MIDP_EXCLUDE_BEGIN add(new PrimitiveSchema(STRING), String.class); add(new PrimitiveSchema(DATE), Date.class); add(new PrimitiveSchema(BYTE_SEQUENCE), byte[].class); add(new ConceptSchema(AID), AID.class); add(new AgentActionSchema(ACLMSG), ACLMessage.class); add(new PredicateSchema(TRUE_PROPOSITION), TrueProposition.class); add(new PredicateSchema(FALSE_PROPOSITION), FalseProposition.class); add(new AgentActionSchema(ACTION), Action.class); add(new PredicateSchema(DONE), Done.class); add(new PredicateSchema(RESULT), Result.class); add(new PredicateSchema(EQUALS), Equals.class); //#MIDP_EXCLUDE_END /*#MIDP_INCLUDE_BEGIN add(new PrimitiveSchema(STRING)); add(new PrimitiveSchema(DATE)); add(new PrimitiveSchema(BYTE_SEQUENCE)); add(new ConceptSchema(AID)); add(new AgentActionSchema(ACLMSG)); add(new PredicateSchema(TRUE_PROPOSITION)); add(new PredicateSchema(FALSE_PROPOSITION)); add(new AgentActionSchema(ACTION)); add(new PredicateSchema(DONE)); add(new PredicateSchema(RESULT)); add(new PredicateSchema(EQUALS)); #MIDP_INCLUDE_END*/ // AID Schema ConceptSchema aidSchema = (ConceptSchema)getSchema(AID); aidSchema.add(AID_NAME, (TermSchema) getSchema(STRING)); aidSchema.add(AID_ADDRESSES, (TermSchema) getSchema(STRING), 0, ObjectSchema.UNLIMITED); aidSchema.add(AID_RESOLVERS, aidSchema, 0, ObjectSchema.UNLIMITED); // ACLMessage Schema AgentActionSchema msgSchema = (AgentActionSchema)getSchema(ACLMSG); msgSchema.add(ACLMSG_SENDER, (ConceptSchema) getSchema(AID), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_RECEIVERS, (ConceptSchema) getSchema(AID), 0, ObjectSchema.UNLIMITED); msgSchema.add(ACLMSG_REPLY_TO, (ConceptSchema) getSchema(AID), 0, ObjectSchema.UNLIMITED); msgSchema.add(ACLMSG_LANGUAGE, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_ONTOLOGY, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_PROTOCOL, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_IN_REPLY_TO, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_REPLY_WITH, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_CONVERSATION_ID, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_REPLY_BY, (PrimitiveSchema) getSchema(DATE), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_CONTENT, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_BYTE_SEQUENCE_CONTENT, (PrimitiveSchema) getSchema(BYTE_SEQUENCE), ObjectSchema.OPTIONAL); msgSchema.add(ACLMSG_ENCODING, (PrimitiveSchema) getSchema(STRING), ObjectSchema.OPTIONAL); // ACTION Schema AgentActionSchema actionSchema = (AgentActionSchema)getSchema(ACTION); actionSchema.add(ACTION_ACTOR, (TermSchema) getSchema(AID)); actionSchema.add(ACTION_ACTION, (TermSchema) ConceptSchema.getBaseSchema()); actionSchema.setEncodingByOrder(true); // DONE Schema PredicateSchema doneSchema = (PredicateSchema)getSchema(DONE); doneSchema.add(DONE_ACTION, (AgentActionSchema) AgentActionSchema.getBaseSchema()); doneSchema.add(DONE_CONDITION, (PredicateSchema) PredicateSchema.getBaseSchema(), ObjectSchema.OPTIONAL); // RESULT Schema PredicateSchema resultSchema = (PredicateSchema)getSchema(RESULT); resultSchema.add(RESULT_ACTION, (AgentActionSchema) AgentActionSchema.getBaseSchema()); resultSchema.add(RESULT_VALUE, (TermSchema) TermSchema.getBaseSchema()); // EQUALS Schema PredicateSchema equalsSchema = (PredicateSchema)getSchema(EQUALS); equalsSchema.add(EQUALS_LEFT, TermSchema.getBaseSchema()); equalsSchema.add(EQUALS_RIGHT, TermSchema.getBaseSchema()); //#MIDP_EXCLUDE_BEGIN fillPrimitiveSchemas(); //#MIDP_EXCLUDE_END } catch (OntologyException oe) { oe.printStackTrace(); } } //#MIDP_EXCLUDE_BEGIN private void fillPrimitiveSchemas() throws OntologyException { // This map is only needed to make the getSchema(Class) method work properly also in the case of java primitives primitiveSchemas = new HashMap(10); primitiveSchemas.put(boolean.class, getSchema(BasicOntology.BOOLEAN)); primitiveSchemas.put(java.lang.Boolean.class, getSchema(BasicOntology.BOOLEAN)); primitiveSchemas.put(int.class, getSchema(BasicOntology.INTEGER)); primitiveSchemas.put(long.class, getSchema(BasicOntology.INTEGER)); primitiveSchemas.put(java.lang.Integer.class, getSchema(BasicOntology.INTEGER)); primitiveSchemas.put(java.lang.Long.class, getSchema(BasicOntology.INTEGER)); primitiveSchemas.put(float.class, getSchema(BasicOntology.FLOAT)); primitiveSchemas.put(double.class, getSchema(BasicOntology.FLOAT)); primitiveSchemas.put(java.lang.Float.class, getSchema(BasicOntology.FLOAT)); primitiveSchemas.put(java.lang.Double.class, getSchema(BasicOntology.FLOAT)); } private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { in.defaultReadObject(); try { fillPrimitiveSchemas(); } catch (OntologyException oe) { // Should never happen oe.printStackTrace(); } } //#MIDP_EXCLUDE_END /** * Returns the singleton instance of the <code>BasicOntology</code>. * @return the singleton instance of the <code>BasicOntology</code> */ public static Ontology getInstance() { return theInstance; } //#APIDOC_EXCLUDE_BEGIN /** * This method is redefined as BasicOntology does not use an * Introspector for performance reason * @see Ontology#toObject(AbsObject) */ protected Object toObject(AbsObject abs, String lcType, Ontology referenceOnto) throws UngroundedException, OntologyException { try { if (abs == null) { return null; } // PRIMITIVE if (abs.getAbsType() == AbsObject.ABS_PRIMITIVE) { return ((AbsPrimitive) abs).getObject(); } // AGGREGATES if (abs.getAbsType() == AbsObject.ABS_AGGREGATE) { String absTypeName = abs.getTypeName(); if (BasicOntology.SEQUENCE.equals(absTypeName)) { return AbsHelper.internaliseList((AbsAggregate) abs, referenceOnto); } else if (BasicOntology.SET.equals(absTypeName)) { return AbsHelper.internaliseSet((AbsAggregate) abs, referenceOnto); //#MIDP_EXCLUDE_BEGIN } else { return AbsHelper.internaliseJavaCollection((AbsAggregate) abs, referenceOnto); //#MIDP_EXCLUDE_END } } // CONTENT ELEMENT LIST if (abs.getAbsType() == AbsObject.ABS_CONTENT_ELEMENT_LIST) { return AbsHelper.internaliseContentElementList((AbsContentElementList) abs, referenceOnto); } //#MIDP_EXCLUDE_BEGIN // CONCEPT_SLOT_FUNCTION if (abs.getAbsType() == AbsObject.ABS_CONCEPT_SLOT_FUNCTION) { AbsObject absConcept = abs.getAbsObject(ConceptSlotFunctionSchema.CONCEPT_SLOT_FUNCTION_CONCEPT); return referenceOnto.createConceptSlotFunction(abs.getTypeName(), (Concept) referenceOnto.toObject(absConcept)); } //#MIDP_EXCLUDE_END // AID if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.AID)) { return AbsHelper.internaliseAID((AbsConcept) abs); } // TRUE_PROPOSITION if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.TRUE_PROPOSITION)) { TrueProposition t = new TrueProposition(); return t; } // FALSE_PROPOSITION if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.FALSE_PROPOSITION)) { FalseProposition t = new FalseProposition(); return t; } // DONE if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.DONE)) { Done d = new Done(); d.setAction((AgentAction) referenceOnto.toObject(abs.getAbsObject(BasicOntology.DONE_ACTION))); return d; } // RESULT if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.RESULT)) { Result r = new Result(); r.setAction((AgentAction) referenceOnto.toObject(abs.getAbsObject(BasicOntology.RESULT_ACTION))); r.setValue(referenceOnto.toObject(abs.getAbsObject(BasicOntology.RESULT_VALUE))); return r; } // EQUALS if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.EQUALS)) { Equals e = new Equals(); e.setLeft(referenceOnto.toObject(abs.getAbsObject(BasicOntology.EQUALS_LEFT))); e.setRight(referenceOnto.toObject(abs.getAbsObject(BasicOntology.EQUALS_RIGHT))); return e; } // ACTION if (CaseInsensitiveString.equalsIgnoreCase(abs.getTypeName(), BasicOntology.ACTION)) { Action a = new Action(); a.internalise(abs, referenceOnto); return a; } // ACLMESSAGE if (ACLMessage.getInteger(abs.getTypeName()) != -1) { return AbsHelper.internaliseACLMessage((AbsAgentAction) abs, referenceOnto); } throw new UnknownSchemaException(); } catch (OntologyException oe) { // Forward the exception throw oe; } catch (Throwable t) { throw new OntologyException("Unexpected error internalising "+abs+".", t); } } /** * This method is redefined as BasicOntology does not use an * Introspector for performance reason * @see Ontology#toObject(AbsObject) */ protected AbsObject fromObject(Object obj, Ontology referenceOnto) throws OntologyException{ try { if (obj == null) { return null; } if (obj instanceof String) { return AbsPrimitive.wrap((String) obj); } if (obj instanceof Boolean) { return AbsPrimitive.wrap(((Boolean) obj).booleanValue()); } if (obj instanceof Integer) { return AbsPrimitive.wrap(((Integer) obj).intValue()); } if (obj instanceof Long) { return AbsPrimitive.wrap(((Long) obj).longValue()); } //#MIDP_EXCLUDE_BEGIN if (obj instanceof Float) { return AbsPrimitive.wrap(((Float) obj).floatValue()); } if (obj instanceof Double) { return AbsPrimitive.wrap(((Double) obj).doubleValue()); } //#MIDP_EXCLUDE_END if (obj instanceof Date) { return AbsPrimitive.wrap((Date) obj); } if (obj instanceof byte[]) { return AbsPrimitive.wrap((byte[]) obj); } if (obj instanceof List) { return AbsHelper.externaliseList((List) obj, referenceOnto, SEQUENCE); } if (obj instanceof Set) { return AbsHelper.externaliseSet((Set) obj, referenceOnto, SET); } if (obj instanceof Iterator) { return AbsHelper.externaliseIterator((Iterator) obj, referenceOnto, SEQUENCE); } if(obj instanceof AID) { return AbsHelper.externaliseAID((AID)obj); } if (obj instanceof ContentElementList) { return AbsHelper.externaliseContentElementList((ContentElementList) obj, referenceOnto); } if(obj instanceof TrueProposition) { AbsPredicate absTrueProp = new AbsPredicate(BasicOntology.TRUE_PROPOSITION); return absTrueProp; } if(obj instanceof FalseProposition) { AbsPredicate absTrueProp = new AbsPredicate(BasicOntology.FALSE_PROPOSITION); return absTrueProp; } if(obj instanceof Done) { AbsPredicate absDone = new AbsPredicate(BasicOntology.DONE); absDone.set(BasicOntology.DONE_ACTION, (AbsAgentAction) referenceOnto.fromObject(((Done) obj).getAction())); return absDone; } if(obj instanceof Result) { AbsPredicate absResult = new AbsPredicate(BasicOntology.RESULT); absResult.set(BasicOntology.RESULT_ACTION, (AbsAgentAction) referenceOnto.fromObject(((Result) obj).getAction())); absResult.set(BasicOntology.RESULT_VALUE, (AbsTerm) referenceOnto.fromObject(((Result) obj).getValue())); return absResult; } if(obj instanceof Equals) { AbsPredicate absEquals = new AbsPredicate(BasicOntology.EQUALS); absEquals.set(BasicOntology.EQUALS_LEFT, (AbsTerm) referenceOnto.fromObject(((Equals) obj).getLeft())); absEquals.set(BasicOntology.EQUALS_RIGHT, (AbsTerm) referenceOnto.fromObject(((Equals) obj).getRight())); return absEquals; } if (obj instanceof Action) { AbsAgentAction absAction = new AbsAgentAction(BasicOntology.ACTION); ((Action) obj).externalise(absAction, referenceOnto); return absAction; } if (obj instanceof ACLMessage) { return AbsHelper.externaliseACLMessage((ACLMessage)obj, referenceOnto); } //#MIDP_EXCLUDE_BEGIN if (obj instanceof ConceptSlotFunction) { ConceptSlotFunction csf = (ConceptSlotFunction) obj; AbsObject absConcept = referenceOnto.fromObject(csf.getConcept()); AbsConcept absCsf = new AbsConcept(csf.getSlotName()); absCsf.set(ConceptSlotFunctionSchema.CONCEPT_SLOT_FUNCTION_CONCEPT, absConcept); return absCsf; } //#MIDP_EXCLUDE_END throw new UnknownSchemaException(); } catch (OntologyException oe) { // Forward the exception throw oe; } catch (Throwable t) { throw new OntologyException("Unexpected error externalising "+obj+".", t); } } //#APIDOC_EXCLUDE_END /** * Redefine the <code>getSchema()</code> method to take into * account ACL performatives. * @param name the name of the schema in the vocabulary. * @return the schema or <code>null</code> if the schema is not found. * @throws OntologyException */ public ObjectSchema getSchema(String name) throws OntologyException { ObjectSchema ret = super.getSchema(name); if (ret == null) { int perf = ACLMessage.getInteger(name); if (perf != -1) { ret = createMsgSchema(name); } } return ret; } /** * Redefine the <code>getSchema()</code> method to take into * account java primitives. * @param clazz the class whose associated schema must be retrieved. * @return the schema associated to the given class or <code>null</code> if the schema is not found. * @throws OntologyException */ public ObjectSchema getSchema(Class clazz) throws OntologyException { //#MIDP_EXCLUDE_BEGIN ObjectSchema schema = (ObjectSchema)primitiveSchemas.get(clazz); if (schema == null) { schema = super.getSchema(clazz); } //#MIDP_EXCLUDE_END /*#MIDP_INCLUDE_BEGIN ObjectSchema schema = super.getSchema(clazz); #MIDP_INCLUDE_END*/ return schema; } /** Note that we don't want to keep 22 different schemas for the 22 FIPA communicative acts --> We generate the schemas for communicative acts on the fly as needed. */ private ObjectSchema createMsgSchema(String performative) throws OntologyException { AgentActionSchema msgSchema = new AgentActionSchema(performative); msgSchema.addSuperSchema((AgentActionSchema) getSchema(ACLMSG)); return msgSchema; } //#MIDP_EXCLUDE_BEGIN /** Convert, if possible, the numeric value srcValue into an instance of destClass */ public static Object adjustPrimitiveValue(Object srcValue, Class destClass) { Object destValue = srcValue; if (srcValue != null) { Class srcClass = srcValue.getClass(); // Note that we deal with Integer, int, Long, long... classes only --> we can compare the classes using == and != instead of using instanceof if (srcClass != destClass) { if (destClass == Integer.class || destClass == int.class) { if (srcClass == Long.class) { destValue = new Integer(((Long)srcValue).intValue()); } else if (srcClass == String.class) { destValue = new Integer(Integer.parseInt((String)srcValue)); } } else if (destClass == Long.class || destClass == long.class) { if (srcClass == Integer.class) { destValue = new Long(((Integer)srcValue).longValue()); } else if (srcClass == String.class) { destValue = new Long(Long.parseLong((String)srcValue)); } } else if (destClass == Float.class || destClass == float.class) { if (srcClass == Integer.class) { destValue = new Float(((Integer)srcValue).floatValue()); } else if (srcClass == Long.class) { destValue = new Float(((Long)srcValue).floatValue()); } else if (srcClass == Double.class) { destValue = new Float(((Double)srcValue).floatValue()); } else if (srcClass == String.class) { destValue = new Float(Float.parseFloat((String)srcValue)); } } else if (destClass == Double.class || destClass == double.class) { if (srcClass == Integer.class) { destValue = new Double(((Integer)srcValue).doubleValue()); } else if (srcClass == Long.class) { destValue = new Double(((Long)srcValue).doubleValue()); } else if (srcClass == Float.class) { destValue = new Double(((Float)srcValue).doubleValue()); } else if (srcClass == String.class) { destValue = new Double(Double.parseDouble((String)srcValue)); } } else if (destClass == String.class) { destValue = srcValue.toString(); } else if (destClass == Boolean.class || destClass == boolean.class) { if (srcClass == String.class) { String s = (String) srcValue; if (s.equalsIgnoreCase("true")) { destValue = new Boolean(true); } else if (s.equalsIgnoreCase("false")) { destValue = new Boolean(false); } } } else if (destClass == Date.class) { try { // Try to convert string from FIPA-ISO8601 format destValue = ISO8601.toDate(srcValue.toString()); } catch (Exception e) { try { // Try to convert string from W3C-ISO8601 format java.text.SimpleDateFormat W3CISO8601DateFormat = new java.text.SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.SSS"); destValue = W3CISO8601DateFormat.parse(srcValue.toString()); } catch (java.text.ParseException e1) { // Date format not correct } } } } } return destValue; } /** * @deprecated Use adjustPrimitiveValue() instead */ public static Object resolveNumericValue(Object srcValue, Class destClass) { return adjustPrimitiveValue(srcValue, destClass); } //#MIDP_EXCLUDE_END }