View Javadoc

1   /******************************************************************
2   JADE - Java Agent DEvelopment Framework is a framework to develop
3   multi-agent systems in compliance with the FIPA specifications.
4   Copyright (C) 2000 CSELT S.p.A. 
5   
6   GNU Lesser General Public License
7   
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation, 
11  version 2.1 of the License. 
12  
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  Lesser General Public License for more details.
17  
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the
20  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  Boston, MA  02111-1307, USA.
22  *****************************************************************/
23  
24  
25  package sl;
26  
27  import java.lang.reflect.*;
28  import java.util.*;
29  import java.io.BufferedWriter;
30  import java.io.BufferedReader;
31  import java.io.IOException;
32  import java.text.*;
33  
34  
35  
36  /***
37    A simple implementation of the <code>Ontology</code> interface. Instances of
38    this class keeps all the ontology data in memory, and don't support an
39    external archive format.
40  
41    @author Giovanni Rimassa - Universita` di Parma
42    @version $Date: 2003/10/09 13:00:37 $ $Revision: 1.1.1.1 $
43  */
44  public final class DefaultOntology implements Ontology {
45  
46  	private Map schemas;
47    private Map roleClasses;
48  
49    /***
50      Default constructor.
51    */
52    public DefaultOntology() {
53      schemas = new HashMap();
54      roleClasses = new HashMap();
55    }
56  
57    // Raw interface, exposes Frame Schemas directly.
58    // This is package scoped, not to be used by applications.
59  
60    FrameSchema lookupSchema(String name) {
61      return (FrameSchema)schemas.get(new CaseInsensitiveString(name));
62    }
63  
64  
65    /***
66      Adds a new role to this ontology, without a user defined Java class to
67      represent it.
68      @see jade.onto.Ontology#addRole(String roleName, SlotDescriptor[] slots)
69    */
70    public void addRole(String roleName, SlotDescriptor[] slots) throws OntologyException {
71      // Checks whether a role with this name already exists in the ontology
72      if (lookupSchema(roleName) != null)
73        throw new OntologyException("A role with name \""+roleName+"\" already exists in the ontology");
74    	
75      // Adds the new role
76      FrameSchema fs = new FrameSchema(this, roleName);
77  
78      for(int i = 0; i < slots.length; i++) {
79        String n = slots[i].getName();
80        if(n.length() == 0)
81  				slots[i].setName(Frame.UNNAMEDPREFIX+ "_"+i);
82        fs.addSlot(slots[i]);
83      }
84  
85      addSchemaToTable(roleName, fs);
86  
87    }
88    
89    /***
90      Adds a new role to this ontology, with a user defined Java class to
91      represent it.
92      @see jade.onto.Ontology#addRole(String roleName, SlotDescriptor[] slots, Class c)
93    */  
94    public void addRole(String roleName, SlotDescriptor[] slots, Class newClass) throws OntologyException {
95      // Checks whether the user defined class representing the role already represents another role in the ontology
96      if (roleClasses.containsValue(newClass))
97        throw new OntologyException("The class \""+newClass.getName()+"\" already represents a role in this ontology");
98      // Adds the role to the ontology
99      addRole(roleName, slots);
100     // Registers the user defined class representing the role
101     checkClass(roleName, newClass);
102     roleClasses.put(new CaseInsensitiveString(roleName), newClass);
103   }
104 
105   /***
106     Adds to this ontology all roles included into another ontology 
107     @param o The <code>Ontology</code> object whose roles will 
108     be added
109     @see jade.onto.Ontology#joinOntology(Ontology o)
110   */
111   public void joinOntology(Ontology o) throws OntologyException {
112     // Gets the names of all roles in the ontology to join
113     for (Iterator i=o.getVocabulary().iterator(); i.hasNext(); ) {
114       // For each role try to add it to the current ontology
115       String name = (String) i.next();
116       SlotDescriptor[] slots = o.getSlots(name);
117       Class c = o.getClassForRole(name);
118       if (c != null)
119 	addRole(name, slots, c);
120       else
121 	addRole(name, slots);
122     }
123   }
124   	
125 
126   /***
127     Creates a List of Java objects from the given list of frame.
128     @see jade.onto.Ontology#createObject(List v)
129   */
130   public List createObject(List v) throws OntologyException {
131     List outvec = new ArrayList();
132     for (int i=0; i<v.size(); i++) 
133       outvec.add(createSingleObject( (Frame)v.get(i) ));
134     return outvec;
135   }
136 		 
137   /*
138    * Creates a Java object from the given Frame.
139    * This method is called by createObject().
140    */
141   private Object createSingleObject(Frame f) throws OntologyException {
142 
143       String roleName = f.getName();
144       Class c = getClassForRole(roleName);
145       if(c == null)
146 	throw new OntologyException("No class able to represent " + roleName + " role. Check the definition of the ontology.");
147 
148       Object o = create(f);
149       return initObject(f, o, c);
150   }
151 
152   /***
153     Creates a frame from a given Java Object representing an instance of 
154     a given role.
155     @see jade.onto.Ontology#createFrame(Object o, String roleName)
156   */
157   public Frame createFrame(Object o, String roleName) throws OntologyException {
158     Class theRoleClass = getClassForRole(roleName);
159     if (theRoleClass == null)
160       throw new OntologyException("No class able to represent " + roleName + " role. Check the definition of the ontology.");
161     if(!theRoleClass.isInstance(o))
162       throw new OntologyException("The object <" + o + "> is not an instance of " + theRoleClass.getName() + " class.");
163 
164     FrameSchema fs = lookupSchema(roleName);
165     if(fs == null)
166       throw new OntologyException("Internal error: inconsistency between schema and class table");
167     //if(!fs.isConcept())
168     //  throw new OntologyException("The role " + roleName + " is not a concept in this ontology.");
169 
170     Frame f = new Frame(roleName);
171     buildFromObject(f, fs, o, theRoleClass);
172 
173     return f;
174   }
175 
176   /***
177     Checks whether a given frame is correct with respect to this ontology.
178     @see jade.onto.Ontology#check(Frame f)
179   */
180   public void check(Frame f) throws OntologyException {
181     String roleName = f.getName();
182     FrameSchema fs = lookupSchema(roleName);
183     fs.checkAgainst(f);
184   }
185 
186   /***
187     Checks whether a given Java object is correct with respect to the given role
188     in this ontology.
189     @see jade.onto.Ontology#check(Object o, String roleName)
190   */
191   public void check(Object o, String roleName) throws OntologyException {
192     /*
193      *  Algorithm: 
194      *
195      * - Check that the object is an instance of the correct class
196      * - FOR EACH mandatory slot S
197      *   - The getS method of the class o is an instance of must not return 'null'
198      */
199     Class theRoleClass = getClassForRole(roleName);
200     if (theRoleClass == null)
201       throw new OntologyException("No class able to represent " + roleName + " role.");
202     if(!theRoleClass.isInstance(o))
203       throw new OntologyException("The object is not an instance of " + theRoleClass.getName() + " class.");
204 
205     FrameSchema fs = lookupSchema(roleName);
206     Iterator it = fs.subSchemas(); // This iterates on the slots of the FrameSchema
207 
208     while(it.hasNext()) {
209       SlotDescriptor desc = (SlotDescriptor)it.next();
210 			Method m = findMethodCaseInsensitive("get" + translateName(desc.getName()), theRoleClass);
211 			try {
212 	  		Object value = m.invoke(o, new Object[] { });
213 
214 	  		if(!desc.isOptional() && (value == null))
215 	    		throw new OntologyException("The given object has a 'null' value for the mandatory term " + desc.getName());
216 
217 	  		if(desc.isComplex() || desc.isSet())// Recursive check for sub-objects
218 	    		check(value, desc.getType());
219 			}
220 			catch(InvocationTargetException ite) {
221 	  		String msg = ite.getTargetException().getMessage();
222 	  		throw new OntologyException("Internal error: a reflected method threw an exception.\nMessage was " + msg);
223 			}
224 			catch(IllegalAccessException iae) {
225 	  		throw new OntologyException("Internal error: the required method is not accessible [" + iae.getMessage() + "]");
226 			}
227 			catch(SecurityException se) {
228 	  		throw new OntologyException("Wrong class: some required method is not accessible."); 
229 			}
230     }
231   }
232 
233   /***
234     Checks whether a given string is the name of a role in this ontology.
235     @see jade.onto.Ontology#isRole(String roleName)
236   */
237   public boolean isRole(String roleName) throws OntologyException {
238   	FrameSchema fs = lookupSchema(roleName);
239   	return (fs != null);
240   }
241 
242   /***
243     Get the descriptions for all the slots that define the structure of a given
244     ontological role.
245     @see jade.onto.Ontology#getSlots(String roleName)
246   */
247   public SlotDescriptor[] getSlots(String roleName) throws OntologyException {
248     FrameSchema fs = lookupSchema(roleName);
249     return fs.slotsArray();
250   }
251 
252   /*** 
253     @return the name of the role represented by the passed class as 
254     registered in this ontology
255     @throws OntologyException if no role is found for this class
256     @see jade.onto.Ontology#getRoleName(Class c)
257   **/
258   public String getRoleName(Class c) throws OntologyException{
259     for (Iterator i=roleClasses.entrySet().iterator(); i.hasNext(); ) {
260       Map.Entry elem = (Map.Entry)i.next();
261       if (c.equals((Class)elem.getValue())) 
262       	return ((CaseInsensitiveString)elem.getKey()).toString();
263     } 
264     // if this instruction is executed, then no class has been found
265     throw new OntologyException("No rolename registered in this ontology for class "+c.getName());
266   }
267   
268   /*** 
269     @return a <code>List</code> including the names of all the roles
270     in the ontology, i.e. the Vocabulary used by the ontology
271     @see jade.onto.Ontology#getVocabulary()
272     **/
273   public List getVocabulary(){
274     // The Vocabulary is the list of the names of the roles in the ontology;
275     // role names are stored as Name while we want to return them as String
276   	List vocabulary = new ArrayList();
277   	Iterator i = schemas.keySet().iterator();
278   	while (i.hasNext()){
279   		String roleNameAsString = ((CaseInsensitiveString) (i.next())).toString();
280   		vocabulary.add(roleNameAsString);
281   	}
282   	return vocabulary;	
283   }
284   
285 
286 
287 
288 
289   /***
290     Provides the Java class associated with this ontological role. This class is
291     usually the class used by the <code>create()</code> method to instantiate
292     objects. A useful technique is returning an interface or an abstract class,
293     while using concrete subclasses to create objects.
294     @param a string representing the name of the ontological role
295     @return the Java class that plays this ontological role (e.g. <code>DFAgentDescription.class</code>
296   */
297   public Class getClassForRole(String roleName) {
298     return (Class) roleClasses.get(new CaseInsensitiveString(roleName));
299   }
300   
301 
302 
303   // Private methods.
304 
305   /***
306    * if name starts with UNNAMED_PREFIX, it removes it
307    * @return the name of a method, given the name of a slot
308    */
309   private String translateName(String name) {
310     StringBuffer buf;
311     if (name.startsWith(Frame.UNNAMEDPREFIX))
312       buf = new StringBuffer(name.substring(Frame.UNNAMEDPREFIX.length()));
313     else
314       buf = new StringBuffer(name);
315     for(int i = 0; i < buf.length(); i++) {
316       char c = buf.charAt(i);
317       switch(c) {
318       case ':':
319 				buf.deleteCharAt(i);
320 				--i;
321 				break;
322       case '-':
323 				buf.deleteCharAt(i);
324 				buf.setCharAt(i, Character.toUpperCase(buf.charAt(i)));
325 				--i;
326 				break;
327       }
328     }
329     
330     return new String(buf);
331   }
332 
333 
334   private Class checkGetAndSet(String name, Class c) throws OntologyException {
335     Class result;
336     Method getMethod = findMethodCaseInsensitive("get" + name, c);
337     Method setMethod = findMethodCaseInsensitive("set" + name, c);
338 
339     // Make sure "get" method takes no arguments.
340     Class[] getParams = getMethod.getParameterTypes();
341     if(getParams.length > 0)
342       throw new OntologyException("Wrong class: method " +  getMethod.getName() + "() must take no arguments.");
343 
344     // Now find a matching set method.
345     result = getMethod.getReturnType();
346 
347     Class[] setParams = setMethod.getParameterTypes();
348     if((setParams.length != 1) || (!setParams[0].equals(result)))
349       throw new OntologyException("Wrong class: method " +  setMethod.getName() + "() must take a single argument of type " + result.getName() + ".");
350     Class setReturn = setMethod.getReturnType();
351     if(!setReturn.equals(Void.TYPE))
352       throw new OntologyException("Wrong class: method " +  setMethod.getName() + "() must return void.");
353 
354     return result;
355 
356   }
357 
358   /***
359    * @return the number of arguments of the method m
360    */
361   private int getArgumentLength(Method m) {
362     Class[] getParams = m.getParameterTypes();
363     return getParams.length;
364   }
365 
366   /***
367     @ return the Class of the return type of the method m
368    */
369   private Class getReturnType(Method m) {
370     return m.getReturnType();
371   }
372 
373   /***
374     @ return the Class of the argument type number no. of the method m
375    */
376   private Class getArgumentType(Method m, int no) {
377     Class[] setParams = m.getParameterTypes();
378     return setParams[no];
379   }
380 
381   /***
382    * This method checks for correct get and set methods for the
383    * current descriptor and retrieves the implementation type.
384    * This check is for slots of category SET_SLOT or SEQUENCE_SLOT.
385    * <p> 
386    * For every <code>SlotDescriptor</code> 
387    * of category <code>SET_SLOT</code> or <code>SEQUENCE_SLOT</code>
388    * and named <code>XXX</code>, with elements of type <code>T</code>, the
389    * class must have two accessible methods, with the following
390    * signature:</i>
391    *  <ul>
392    *  <li> <code>Iterator getAllXXX()</code>
393    *  <li> <code>void addXXX(T t)</code>
394    *  </ul>
395    */
396   private Class checkGetAndSet2(String name, Class c) throws OntologyException {
397     Method getMethod = findMethodCaseInsensitive("getAll" + name, c);
398     Method addMethod = findMethodCaseInsensitive("add" + name, c);
399     //Method remMethod = findMethodCaseInsensitive("remove" + name, c);
400     //Method clrMethod = findMethodCaseInsensitive("clearAll" + name, c);
401     Class result = getArgumentType(addMethod,0);  
402     //FIXME. The type of result should be taken from the SlotDescriptor 
403     // and not directly from the method argument. 
404 
405     // check "get" method 
406     if (getArgumentLength(getMethod) != 0)
407       throw new OntologyException("Wrong class: method " +  getMethod.getName() + "() must take no arguments.");
408     if (!getReturnType(getMethod).equals(java.util.Iterator.class))
409       throw new OntologyException("Wrong class: method " +  getMethod.getName() + "() must return a java.util.Iterator." + getReturnType(getMethod).toString());
410 
411     // check 'add' method 
412     if (getArgumentLength(addMethod) != 1)
413       throw new OntologyException("Wrong class: method " +  addMethod.getName() + "() must take one argument.");
414     if (!getArgumentType(addMethod,0).equals(result))
415       throw new OntologyException("Wrong class: method " +  addMethod.getName() + "() has the wrong argument type.");
416     if (!getReturnType(addMethod).equals(Void.TYPE))
417       throw new OntologyException("Wrong class: method " +  addMethod.getName() + "() must return a void.");
418 
419     /* check remove method
420     if (getArgumentLength(remMethod) != 1)
421       throw new OntologyException("Wrong class: method " +  remMethod.getName() + "() must take one argument.");
422     if (!getArgumentType(remMethod,0).equals(result))
423       throw new OntologyException("Wrong class: method " +  remMethod.getName() + "() has the wrong argument type.");
424     if (!getReturnType(remMethod).equals(Boolean.TYPE))
425       throw new OntologyException("Wrong class: method " +  remMethod.getName() + "() must return a boolean.");
426       */
427     /* check clear method
428     if (getArgumentLength(clrMethod) != 0)
429       throw new OntologyException("Wrong class: method " +  clrMethod.getName() + "() must take no arguments.");
430     if (!getReturnType(clrMethod).equals(Void.TYPE))
431       throw new OntologyException("Wrong class: method " +  clrMethod.getName() + "() must return a void.");
432       */
433     return result;
434 
435   }
436 
437   private void checkClass(String roleName, Class c) throws OntologyException {
438 
439     FrameSchema fs = lookupSchema(roleName);
440     if(fs == null)
441       throw new OntologyException("No schema was found for " + roleName + "role.");
442 
443     Iterator it = fs.subSchemas();
444     // System.out.println("checkClass. Role=\""+fs.getName()+"\" represented by class "+c.getName());
445     
446     while(it.hasNext()) {
447       SlotDescriptor desc = (SlotDescriptor)it.next();
448       // System.out.println("checkClass. SlotDescriptor="+desc.toString());
449       String slotName = translateName(desc.getName());
450       try {
451 	// Check for correct set and get methods for the current
452 	// descriptor and retrieve the implementation type.
453 	Class implType;
454 	//if ((desc.getType() == SET_SLOT) || (desc.getType() == SEQUENCE_SLOT))
455 	if (desc.isSet())
456 	  implType = checkGetAndSet2(slotName, c);
457 	else
458 	  implType = checkGetAndSet(slotName, c);
459 	// System.out.println("- implType class is: "+implType.getName());
460 
461 	// If the descriptor is a complex slot (i.e. its values are instances of a 
462 	// role) and some class C is registered for that role,
463 	// then the implementation type must be a supertype of C.
464 	if(desc.isComplex() || desc.isSet()) { //DUBBIO Non dovrebbe essere if (!desc.hasPrimitiveTypes())
465 	  Class complex = getClassForRole(desc.getType());
466 	  if (complex != null) {
467 	    // System.out.println("- complex class is: "+complex.getName());
468 	    if(!implType.isAssignableFrom(complex))
469 	      throw new OntologyException("Wrong class: the " + desc.getName() + " role is represented by " + complex + " class, which is not a subtype of " + implType + " class.");
470 	  }
471 	} else {	// Check that the returned type is compatible with the one dictated by the SlotDescriptor
472 	  Class slotType = null;
473 	  try {
474 	    slotType = Class.forName(desc.getType()); 
475 	    // System.out.println("- primitive class is: "+primitive.getName());
476 	    if(!implType.isAssignableFrom(slotType))
477 	      throw new OntologyException("1 Wrong class: the primitive slot " + desc.getName() + " is of type "+ implType + ", but must be a subtype of " + slotType + ".");
478 	  } 
479 	  catch (Exception e) {
480 	    // The check might have failed because the compared types are arrays.
481 	    // In this case in fact Class.forName() does not work.
482 	    // Let's try also this case
483 	    try{
484 	      String type = desc.getType();
485 	      Class componentImplType = implType.getComponentType();
486 	      if (type.endsWith("[]") && componentImplType != null){
487 		String componentType = type.substring(0, type.length() - 2); 
488 		slotType = Class.forName(componentType);
489 		if (!componentImplType.isAssignableFrom(slotType)) 
490 		  throw new OntologyException("2 Wrong class: the primitive slot " + desc.getName() + " is of type "+ componentImplType + "[], but must be a subtype of " + slotType + "[].");
491 	      }
492 	      else
493 		throw new OntologyException("3 Wrong class: the primitive slot " + desc.getName() + " is of type "+ implType + ", but must be a subtype of " + slotType + ".");
494 	    }
495 	    catch (Exception e1) {
496 	      throw new OntologyException("4 Wrong class: the primitive slot " + desc.getName() + " is of type "+ implType + ", but must be a subtype of " + desc.getType() + ".");
497 	    }
498 	  }
499 	}
500       }
501       catch(SecurityException se) {
502 	throw new OntologyException("Wrong class: some required method is not accessible."); 
503       }
504       
505     }
506     
507   }
508 
509 
510   private Object initObject(Frame f, Object entity, Class theRoleClass) throws OntologyException {
511 
512     String roleName = f.getName();
513 
514     FrameSchema fs = lookupSchema(roleName);
515     Iterator it = fs.subSchemas();
516     int slotPosition = 0;
517     
518     // LOOP on slots 
519     while(it.hasNext()) {
520       SlotDescriptor desc = (SlotDescriptor)it.next();
521       String slotName = desc.getName();
522       String methodName;
523       if (desc.isSet())
524 				methodName = "add" + translateName(slotName);
525       else
526 				methodName = "set" + translateName(slotName);
527       
528       // Retrieve the modifier method from the class and call it
529       Method setMethod = findMethodCaseInsensitive(methodName, theRoleClass);
530       try {
531 				Object slotValue;
532 				if (slotName.startsWith(Frame.UNNAMEDPREFIX))
533 	  			slotValue = f.getSlot(slotPosition);
534 				else
535 	  			slotValue = f.getSlot(slotName);
536 	  			
537 				// COMPLEX SLOT: the value of this slot is another Frame object -->
538 	  		// Transform from sub-frame to sub-object by calling 
539 				// createObject() recursively.
540 	  		if(desc.isComplex()) {
541 	  			slotValue = createSingleObject((Frame)slotValue);
542 	  			setMethod.invoke(entity, new Object[] { slotValue });
543 				}
544 				
545 				// SET SLOT or SEQUENCE SLOT: the value of this slot is a set or sequence
546 				else if (desc.isSet()) {
547 	  			Frame set = (Frame) slotValue; //this is the frame representing the set
548 	  			if (desc.getType().equalsIgnoreCase(Ontology.ANY_TYPE)){
549 	    			for (int i=0; i<set.size(); i++) { 
550 	      			try { //try as a complex frame
551 								Object element = createSingleObject((Frame)set.getSlot(i));
552 								setMethod.invoke(entity, new Object[]{element});
553 	      			} 
554 	      			catch (Exception ee1) {
555 								// if exception then it is a primitive frame
556 								setMethod.invoke(entity, new Object[]{set.getSlot(i)}); 
557 	      			}
558 	    			} //end of for int
559 	  			} 
560 	  			else if (desc.hasPrimitiveType()) {
561 	    			for (int i=0; i<set.size(); i++) // add all the elements of the set
562 	      			setMethod.invoke(entity, new Object[]{ castPrimitiveValue(set.getSlot(i), desc.getType())});
563 	  			}
564 	  			else {// convert the elements into an object and then add
565 	    			for (int i=0; i<set.size(); i++) { 
566 	      			Object element = createSingleObject((Frame)set.getSlot(i));
567 	      			setMethod.invoke(entity, new Object[]{element});
568 	    			} 
569 	  			}
570 				}
571 				
572 				// PRIMITIVE SLOT: the value of this slot has a primitive type -->
573 				// It can be directly set.
574 				else { 
575 	  			setMethod.invoke(entity, new Object[] { castPrimitiveValue(slotValue, desc.getType()) });
576 				}
577 				slotPosition++;
578 				
579       } // END of try
580       catch(Frame.NoSuchSlotException fnsse) { // Ignore 'No such slot' errors for optional slots
581 				if(!desc.isOptional())
582 	  			throw fnsse;
583       }
584       catch(InvocationTargetException ite) {
585 				Throwable e = ite.getTargetException();
586 				e.printStackTrace();
587 				throw new OntologyException("Internal error: a reflected method threw an exception.\n e.getMessage()",ite);
588       }
589       catch(IllegalAccessException iae) {
590 				throw new OntologyException("Internal error: the required method is not accessible [" + iae.getMessage() + "]",iae);
591       }
592       catch(SecurityException se) {
593 				throw new OntologyException("Wrong class: some required method is not accessible.",se); 
594       }
595       catch(IllegalArgumentException iare){
596       	throw new OntologyException("Possible mismatch between the type returned by the parser and the type declared in the ontology [" + iare.getMessage() + "]. For role "+roleName+" and slot "+slotName,iare);	
597       }
598       catch(ClassCastException iacce) {
599       	throw new OntologyException("Possibly a primitive value has been used instead of a Frame slot",iacce);
600       }
601       
602     } // END of LOOP on slots
603     
604     return entity;
605   }
606 
607 	private Object castPrimitiveValue(Object value, String type) throws IllegalArgumentException {
608 		// The CLParser cannot distinguish between Byte, Short, Integer, Long and 
609 		// between Character and string ....
610 		// Therefore it simply returns 
611 		// - Long for strings representing a valid integer value
612 		// - Double for strings representing a valid rational value 
613 		// - Boolean for strings equals to "true" and "false"
614 		// - Date for strings representing a valid UTCTime
615 		// - String for strings not belonging to the above cases
616 		// - Byte[] for non-string values
617 		// This method performs the necessary checks and conversions.
618 		
619 		String stringifiedValue = value.toString();
620 		Object castedValue = null;
621 		try{
622 			if (type.equalsIgnoreCase(Ontology.INTEGER_TYPE))
623 				castedValue = (Object) new Integer(stringifiedValue);
624 			else if (type.equalsIgnoreCase(Ontology.SHORT_TYPE))
625 				castedValue = (Object) new Short(stringifiedValue);
626 			else if (type.equalsIgnoreCase(Ontology.FLOAT_TYPE))
627 				castedValue = (Object) new Float(stringifiedValue);
628 			else if (type.equalsIgnoreCase(Ontology.CHARACTER_TYPE)){
629 				if (stringifiedValue.length() != 1)
630 					throw new IllegalArgumentException("Type mismatch for value " + stringifiedValue + " and type " + type);
631 				castedValue = (Object) new Character(stringifiedValue.charAt(0));
632 			}
633 			else if (type.equalsIgnoreCase(Ontology.BYTE_TYPE)){
634 				castedValue = (Object) new Byte(stringifiedValue);
635 			}
636 			else if (type.equalsIgnoreCase(Ontology.STRING_TYPE)){
637 				if (!value.getClass().equals(java.lang.Byte[].class))
638 					castedValue = stringifiedValue;
639 			}
640 			else 
641 				castedValue = value;
642 		}
643 		catch(NumberFormatException nfe) {
644 			throw new IllegalArgumentException("Format mismatch between value " + stringifiedValue + " and type " + type);
645 		}
646 		
647 		return castedValue;
648 	}
649 	
650 	private void buildFromObject(Frame f, FrameSchema fs, Object o, Class theRoleClass) throws OntologyException {
651     Iterator it = fs.subSchemas();
652     while(it.hasNext()) {
653       SlotDescriptor desc = (SlotDescriptor)it.next();
654       String slotName = desc.getName();
655       String methodName;
656       if (desc.isSet())
657 	methodName = "getAll" + translateName(slotName);
658       else
659 	methodName = "get" + translateName(slotName);
660 
661       // Retrieve the accessor method from the class and call it
662       Method getMethod = findMethodCaseInsensitive(methodName, theRoleClass);
663       try {
664 	Object value = getMethod.invoke(o, new Object[] { });
665 	if (value == null) {
666 	  if (!desc.isOptional())
667 	    throw new OntologyException("Slot "+slotName+" has a null value and it is mandatory"); 
668 	} 
669 	else {
670 	  // Now set the corresponding frame subterm appropriately
671 	  if(!desc.isComplex() && !desc.isSet()) { // For elementary terms, just put the Object as a slot
672 	    f.putSlot(slotName, value);
673 	  }
674 	  else if (desc.isComplex()) { 
675 	    // For complex terms, do a name lookup and 
676 	    // call createFrame() recursively
677 	    String roleName = desc.getType();
678 	    if (roleName.equalsIgnoreCase(Ontology.ANY_TYPE))
679 	      roleName = getRoleName(value.getClass());
680 	    f.putSlot(slotName, createFrame(value, roleName));
681 	  }
682 	  else if (desc.isSet()) {
683 	    Frame setFrame;
684 	    if (desc.getCategory() == Ontology.SET_SLOT)
685 	      setFrame = new Frame(Ontology.NAME_OF_SET_FRAME); 
686 	    else
687 	      setFrame = new Frame(Ontology.NAME_OF_SEQUENCE_FRAME); 
688 	    Iterator i = (Iterator)value;
689 	    if (desc.getType().equalsIgnoreCase(Ontology.ANY_TYPE)) {
690 	      while (i.hasNext()) {
691 		Object elem = i.next();
692 		try { //try before as a complex frame
693 		  setFrame.putSlot(createFrame(elem, getRoleName(elem.getClass()))); 
694 		} catch (Exception e) {
695 		  // if exception then it is a primitive slot
696 		  setFrame.putSlot(elem);
697 		}
698 	      }
699 	    } else if (desc.hasPrimitiveType())
700 	      while (i.hasNext()) 
701 		setFrame.putSlot(i.next());
702 	    else 
703 	      while (i.hasNext()) 
704 		setFrame.putSlot(createFrame(i.next(), desc.getType()));
705 	    f.putSlot(slotName,setFrame);
706 	  }
707 	} //if (value==null) else
708       }
709       catch(InvocationTargetException ite) {
710 				String msg = ite.getTargetException().getMessage();
711 				throw new OntologyException("Internal error: a reflected method threw an exception.\nMessage was " + msg);
712       }
713       catch(IllegalAccessException iae) {
714 				throw new OntologyException("Internal error: the required method is not accessible [" + iae.getMessage() + "]");
715       }
716       catch(SecurityException se) {
717 				throw new OntologyException("Wrong class: some required method is not accessible."); 
718       }
719 
720     }
721 
722   }
723 
724 
725   private void addSchemaToTable(String roleName, FrameSchema fs) {
726     schemas.put(new CaseInsensitiveString(roleName), fs);
727   }
728 
729 
730 
731 
732   private Method findMethodCaseInsensitive(String name, Class c) throws OntologyException {
733     Method[] methods = c.getMethods();
734     for(int i = 0; i < methods.length; i++) {
735       String ithName = methods[i].getName();
736       if(ithName.equalsIgnoreCase(name))
737 				return methods[i];
738     }
739     throw new OntologyException("Method " + name + " not found in class "+c.getName());
740   }
741   
742 
743   /***
744    * @see Ontology.fromSL0String(String)
745   **/
746   public String fromSL0String(String str) throws CodecException, OntologyException {
747     Ontology meta = JADEMetaOntology.instance();
748     schemas.clear();
749     roleClasses.clear();
750     List l = (new SL0Codec()).decode(str, meta); 
751     AnOntology o = (AnOntology)meta.createObject(l).get(0);
752     fromMetaOntologyRepresentation(o);
753     return o.getName(); 
754   }
755 
756   /***
757     @see Ontology.fromMetaOntologyRepresentation(AnOntology)
758     **/
759   public void fromMetaOntologyRepresentation(AnOntology o) throws OntologyException {
760     for (Iterator i=o.getAllRoles(); i.hasNext(); ) { //iteration on roles
761       Role r = (Role)i.next();
762       ArrayList slots = new ArrayList();
763       for (Iterator j=r.getAllSlots(); j.hasNext(); ) { //iteration on slots
764 	Slot s = (Slot)j.next();
765 	SlotDescriptor sd;
766 	if (s.getName() != null) 
767 	  sd = new SlotDescriptor(s.getName(), s.getCategory().intValue(), s.getType(), s.getPresence().booleanValue());
768 	else
769 	  sd = new SlotDescriptor(s.getCategory().intValue(), s.getType(), s.getPresence().booleanValue());
770 	slots.add(sd);
771       } //end iteration on slots
772       SlotDescriptor[] sdarray = new SlotDescriptor[slots.size()];
773       slots.toArray(sdarray);
774       if (r.getClassName() == null)
775 	addRole(r.getName(),sdarray);
776       else 
777 	try {
778 	  addRole(r.getName(), sdarray, Class.forName(r.getClassName()));
779 	} catch (ClassNotFoundException e) {
780 	  System.out.println("WARNING: ClassNotFoundException in adding role "+r.getName()+" to the ontology. The role has been then added without any class");
781 	  addRole(r.getName(), sdarray);
782 	}
783     } // end iteration on roles
784   }
785   
786 
787   /***
788    * Return a String representing this ontology Object by calling
789    * the method <code>toSL0String()</code> and catching any exception.
790    * Notice that this method ignores the name of the ontology and, therefore,
791    * the method <code>toSL0String()</code> should be preferred, instead.
792    * @return the String representing this ontology, or null if any
793    * exception occurs.
794   **/
795   public String toString() {
796     try {
797       return toSL0String("unknownOntologyName");
798     } catch (OntologyException o) {
799       o.printStackTrace();
800     }
801     return null;
802   }
803 
804   /***
805     @see Ontology.toMetaOntologyRepresentation(String)
806     **/
807   public AnOntology toMetaOntologyRepresentation (String ontologyName){
808     AnOntology o = new AnOntology();
809     if ((ontologyName == null) || (ontologyName.trim().equals("")))
810       o.setName("unknownOntologyName");
811     else
812       o.setName(ontologyName);
813     
814     // Loop on roles
815     for (Iterator i=schemas.values().iterator(); i.hasNext(); ) {
816       FrameSchema fs = (FrameSchema) i.next();
817       String roleName = fs.getName();
818       Role r = new Role();
819       r.setName(roleName);
820       Class c = getClassForRole(roleName);
821       if (c != null) 
822 	r.setClassName(c.getName());
823       // Loop on slots
824       for (Iterator j = fs.subSchemas(); j.hasNext(); ) {
825 	SlotDescriptor dsc = (SlotDescriptor) j.next();
826 	Slot s = new Slot();
827 	// Slot Name
828 	if (!(dsc.getName().equals("") || dsc.getName().startsWith(Frame.UNNAMEDPREFIX) ) ) 
829 	  s.setName(dsc.getName());
830 	// Slot Category
831 	s.setCategory(new Long(dsc.getCategory()));
832 	// Slot Type
833 	s.setType(dsc.getType());
834 	// Slot Presence
835 	s.setPresence(new Boolean(dsc.isOptional()));
836 	r.addSlots(s);
837       } // END loop on slots
838       o.addRoles(r);
839     } // END loop on roles
840     return o;
841   }
842 
843   /***
844     Writes the ontology represented by this Ontology object as an
845     SL-0 expression. 
846     @see Ontology.toSL0String() 
847   */  
848   public String toSL0String(String ontologyName) throws OntologyException {
849     AnOntology o = toMetaOntologyRepresentation(ontologyName);
850     Ontology meta = JADEMetaOntology.instance();
851     String s;
852     List l = new ArrayList(1);
853     l.add(meta.createFrame(o, meta.getRoleName(o.getClass())));
854     s = (new SL0Codec()).encode(l, meta); 
855     return(s);
856   }
857 
858 
859 
860   public Object create(Frame f) throws OntologyException {
861     try {
862       return getClassForRole(f.getName()).newInstance();
863     } catch (Exception e) {
864       throw new OntologyException(e.getMessage()); 
865     }
866   }
867 
868 }