/** * *************************************************************** * 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; import jade.lang.acl.ACLMessage; import jade.util.leap.*; import jade.content.lang.Codec; import jade.content.lang.StringCodec; import jade.content.lang.ByteArrayCodec; import jade.content.lang.Codec.CodecException; import jade.content.abs.AbsContentElement; import jade.content.schema.ObjectSchema; import jade.content.onto.*; import jade.core.CaseInsensitiveString; /** * This class provides all methods to manage the content languages * and ontologies "known" by a given agent and to fill and extract the * content of an ACL message according to a given content language and * ontology. * Each agent has a <code>ContentManager</code> object accessible through * the <code>getContentManager()</code> method of the <code>Agent</code> * class. * * @author Federico Bergenti * @author Govanni Caire - TILAB */ public class ContentManager implements Serializable { transient private Map languages = new HashMap(); transient private Map ontologies = new HashMap(); private boolean validationMode = true; //#MIDP_EXCLUDE_BEGIN private void readObject(java.io.ObjectInputStream oin) throws java.io.IOException, ClassNotFoundException { oin.defaultReadObject(); languages = new HashMap(); ontologies = new HashMap(); } //#MIDP_EXCLUDE_END /** * Registers a <code>Codec</code> for a given content language * with its default name (i.e. * the name returned by its <code>getName()</code> method. * Since this operation is performed the agent that owns this * <code>ContentManager</code> is able to "speak" the language * corresponding to the registered <code>Codec</code>. * @param c the <code>Codec</code> to be registered. */ public void registerLanguage(Codec c) { if (c == null) { throw new IllegalArgumentException("Null codec registered"); } registerLanguage(c, c.getName()); } /** * Registers a <code>Codec</code> for a given content language * with a given name. * @param c the <code>Codec</code> to be registered. * @param name the name associated to the registered codec. */ public void registerLanguage(Codec c, String name) { if (c == null) { throw new IllegalArgumentException("Null codec registered"); } languages.put(new CaseInsensitiveString(name), c); } /** * Registers an <code>Ontology</code> with its default name (i.e. * the name returned by its <code>getName()</code> method. * Since this operation is performed the agent that owns this * <code>ContentManager</code> "knows" the registered * <code>Ontology</code>. * @param o the <code>Ontology</code> to be registered. */ public void registerOntology(Ontology o) { if (o == null) { throw new IllegalArgumentException("Null ontology registered"); } registerOntology(o, o.getName()); } /** * Registers an <code>Ontology</code> with a given name. * @param o the <code>Ontology</code> to be registered. * @param name the name associated to the registered Ontology. */ public void registerOntology(Ontology o, String name) { if (o == null) { throw new IllegalArgumentException("Null ontology registered"); } ontologies.put(new CaseInsensitiveString(name), o); } /** * Retrieves a previously registered <code>Codec</code> * giving its <code>name</code>. * @param name the name associated to the <code>Codec</code> * to be retrieved. * @return the <code>Codec</code> associated to * <code>name</code> or <code>null</code> if no Codec was registered * with the given name. */ public Codec lookupLanguage(String name) { return (name==null?null:(Codec) languages.get(new CaseInsensitiveString(name))); } /** * Retrieves a previously registered <code>Ontology</code> * giving its <code>name</code>. * @param name the name associated to the <code>Ontology</code> * to be retrieved. * @return the <code>Ontology</code> associated to * <code>name</code> or <code>null</code> if no Ontology was registered * with the given name. */ public Ontology lookupOntology(String name) { return (name==null?null:(Ontology) ontologies.get(new CaseInsensitiveString(name))); } /** * Fills the <code>:content</code> slot of an * <code>ACLMessage msg</code> using the content language * and ontology indicated in the <code>:language</code> and * <code>:ontology</code> fields of <code>msg</code>. * @param msg the message whose content has to be filled. * @param content the content of the message represented as an * <code>AbsContentElement</code>. * @throws CodecException if <code>content</code> is not compliant * to the content language used for this operation. * @throws OntologyException if <code>content</code> is not compliant * to the ontology used for this operation. */ public void fillContent(ACLMessage msg, AbsContentElement content) throws CodecException, OntologyException { Codec codec = lookupLanguage(msg.getLanguage()); if (codec == null) { throw new CodecException("Unknown language "+msg.getLanguage()); } String ontoName = msg.getOntology(); Ontology o = null; if (ontoName != null) { o = lookupOntology(ontoName); if (o == null) { throw new OntologyException("Unknown ontology "+msg.getOntology()); } } Ontology onto = getMergedOntology(codec, o); validate(content, onto); encode(msg, content, codec, onto); } /** * Fills the <code>:content</code> slot of an * <code>ACLMessage msg</code> using the content language * and ontology indicated in the <code>:language</code> and * <code>:ontology</code> fields of <code>msg</code>. * @param msg the message whose content has to be filled. * @param content the content of the message represented as a * <code>ContentElement</code>. * @throws CodecException if <code>content</code> is not compliant * to the content language used for this operation. * @throws OntologyException if <code>content</code> is not compliant * to the ontology used for this operation. */ public void fillContent(ACLMessage msg, ContentElement content) throws CodecException, OntologyException { Codec codec = lookupLanguage(msg.getLanguage()); if (codec == null) { throw new CodecException("Unknown language "+msg.getLanguage()); } String ontoName = msg.getOntology(); Ontology o = null; if (ontoName != null) { o = lookupOntology(ontoName); if (o == null) { throw new OntologyException("Unknown ontology "+msg.getOntology()); } } Ontology onto = getMergedOntology(codec, o); AbsContentElement abs = (AbsContentElement) onto.fromObject(content); validate(abs, onto); encode(msg, abs, codec, onto); } /** * Translates the <code>:content</code> slot of an * <code>ACLMessage msg</code> into an <code>AbsContentElement</code> * using the content language and ontology indicated in the * <code>:language</code> and <code>:ontology</code> fields of <code>msg</code>. * @param msg the message whose content has to be extracted. * @return the content of the message represented as an * <code>AbsContentElement</code>. * @throws CodecException if the content of the message is not compliant * to the content language used for this operation. * @throws OntologyException if the content of the message is not compliant * to the ontology used for this operation. */ public AbsContentElement extractAbsContent(ACLMessage msg) throws CodecException, OntologyException { Codec codec = lookupLanguage(msg.getLanguage()); if (codec == null) { throw new CodecException("Unknown language "+msg.getLanguage()); } String ontoName = msg.getOntology(); Ontology o = null; if (ontoName != null) { o = lookupOntology(ontoName); if (o == null) { throw new OntologyException("Unknown ontology "+msg.getOntology()); } } Ontology onto = getMergedOntology(codec, o); AbsContentElement content = decode(msg, codec, onto); validate(content, onto); return content; } /** * Translates the <code>:content</code> slot of an * <code>ACLMessage msg</code> into a <code>ContentElement</code> * using the content language and ontology indicated in the * <code>:language</code> and <code>:ontology</code> fields of <code>msg</code>. * @param msg the message whose content has to be extracted. * @return the content of the message represented as a * <code>ContentElement</code>. * @throws CodecException if the content of the message is not compliant * to the content language used for this operation. * @throws OntologyException if the content of the message is not compliant * to the ontology used for this operation. */ public ContentElement extractContent(ACLMessage msg) throws CodecException, UngroundedException, OntologyException { Codec codec = lookupLanguage(msg.getLanguage()); if (codec == null) { throw new CodecException("Unknown language "+msg.getLanguage()); } String ontoName = msg.getOntology(); Ontology o = null; if (ontoName != null) { o = lookupOntology(ontoName); if (o == null) { throw new OntologyException("Unknown ontology "+msg.getOntology()); } } Ontology onto = getMergedOntology(codec, o); AbsContentElement content = decode(msg, codec, onto); validate(content, onto); return (ContentElement) onto.toObject(content); } /** Set the validation mode i.e. whether contents that are managed by this content manager should be validated during message content filling/extraction. Default value is <code>true</code> @param mode the new validation mode */ public void setValidationMode(boolean mode) { validationMode = mode; } /** Return the currently set validation mode i.e. whether contents that are managed by this content manager should be validated during message content filling/extraction. Default value is <code>true</code> @return the currently set validation mode */ public boolean getValidationMode() { return validationMode; } //#APIDOC_EXCLUDE_BEGIN /** */ public Ontology getOntology(ACLMessage msg) { return getMergedOntology(lookupLanguage(msg.getLanguage()), lookupOntology(msg.getOntology())); } //#APIDOC_EXCLUDE_END /** * Merge the reference ontology with the inner ontology of the * content language */ private Ontology getMergedOntology(Codec c, Ontology o) { Ontology ontology = null; Ontology langOnto = c.getInnerOntology(); if (langOnto == null) { ontology = o; } else if (o == null) { ontology = langOnto; } else { ontology = new Ontology(null, new Ontology[]{o, langOnto}, null); } return ontology; } private void validate(AbsContentElement content, Ontology onto) throws OntologyException { if (validationMode) { // Validate the content against the ontology ObjectSchema schema = onto.getSchema(content.getTypeName()); if (schema == null) { throw new OntologyException("No schema found for type "+content.getTypeName()); } schema.validate(content, onto); } } private void encode(ACLMessage msg, AbsContentElement content, Codec codec, Ontology onto) throws CodecException, OntologyException { if (codec instanceof ByteArrayCodec) msg.setByteSequenceContent(((ByteArrayCodec) codec).encode(onto, content)); else if (codec instanceof StringCodec) msg.setContent(((StringCodec) codec).encode(onto, content)); else throw new CodecException("UnsupportedTypeOfCodec"); } private AbsContentElement decode(ACLMessage msg, Codec codec, Ontology onto) throws CodecException, OntologyException { if (codec instanceof ByteArrayCodec) return ((ByteArrayCodec) codec).decode(onto, msg.getByteSequenceContent()); else if (codec instanceof StringCodec) return ((StringCodec) codec).decode(onto, msg.getContent()); else throw new CodecException("UnsupportedTypeOfCodec"); } public String toString() { StringBuffer sb = new StringBuffer("(ContentManager:\n - registered-ontologies = "); sb.append(ontologies); sb.append("\n - registered-languages = "); sb.append(languages); sb.append(")"); return sb.toString(); } public String[] getLanguageNames() { String[] langs = new String[languages.size()]; int i = 0; for (Iterator it = languages.keySet().iterator(); it.hasNext(); i++) { langs[i] = it.next().toString(); } return langs; } public String[] getOntologyNames() { String[] onts = new String[ontologies.size()]; int i = 0; for (Iterator it = ontologies.keySet().iterator(); it.hasNext(); i++) { onts[i] = it.next().toString(); } return onts; } }