View Javadoc

1   /***
2    * ***************************************************************
3    * JADE - Java Agent DEvelopment Framework is a framework to develop
4    * multi-agent systems in compliance with the FIPA specifications.
5    * Copyright (C) 2000 CSELT S.p.A.
6    * 
7    * GNU Lesser General Public License
8    * 
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation,
12   * version 2.1 of the License.
13   * 
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   * 
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the
21   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22   * Boston, MA  02111-1307, USA.
23   * **************************************************************
24   */
25  package JADE_SL.onto;
26  
27  import JADE_SL.*;
28  import JADE_SL.abs.*;
29  import JADE_SL.schema.*;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.lang.reflect.*;
33  
34  /***
35   * @author Federico Bergenti - Universita` di Parma
36   */
37  public class ReflectiveIntrospector implements Introspector {
38  
39      /***
40       * Translate an object of a class representing an element in an
41       * ontology into a proper abstract descriptor 
42       * @param onto The ontology that uses this Introspector.
43       * @param referenceOnto The reference ontology in the context of
44       * this translation i.e. the most extended ontology that extends 
45       * <code>onto</code> (directly or indirectly). 
46       * @param obj The Object to be translated
47       * @return The Abstract descriptor produced by the translation 
48  		 * @throws UnknownSchemaException If no schema for the object to be
49  		 * translated is defined in the ontology that uses this Introspector
50  		 * @throws OntologyException If some error occurs during the translation
51       */
52      public AbsObject externalise(Ontology onto, Ontology referenceOnto, Object obj) 
53      				throws UnknownSchemaException, OntologyException {
54          try {
55              Class        javaClass = obj.getClass();            
56              ObjectSchema schema = onto.getSchema(javaClass);
57              if (schema == null) {
58              	throw new UnknownSchemaException();
59              }
60              //DEBUG 
61              //System.out.println("Schema is: "+schema);
62              AbsObject    abs = schema.newInstance();
63              
64              Method[]     methods = javaClass.getMethods();
65              String[]     names = schema.getNames();
66  
67              //FIXME: The correct way to do this would be to loop on
68              // slot names and call related get methods.
69              for (int i = 0; i < methods.length; i++) {
70              	Method m = methods[i];
71                String methodName = m.getName();
72  
73                if (methodName.startsWith("get")) {
74                  String attributeName = (methodName.substring(3, methodName.length())).toUpperCase();
75  
76                  if (schema.containsSlot(attributeName)) {
77              			//DEBUG 
78                  	//System.out.println("Handling attribute "+attributeName);
79                    AbsObject attributeValue = invokeGetMethod(referenceOnto, m, obj);
80              			//DEBUG 
81                    //System.out.println("Attribute value is: "+attributeValue);
82  
83                    if (attributeValue != null) {
84                    	Ontology.setAttribute(abs, attributeName, attributeValue);
85                    } 
86                  } 
87                } 
88              } 
89  
90              return abs;
91          } 
92          catch (OntologyException oe) {
93              throw oe;
94          } 
95          catch (Throwable t) {
96              throw new OntologyException("Schema and Java class do not match", t);
97          } 
98      } 
99  
100     private AbsObject invokeGetMethod(Ontology onto, Method method, 
101                                       Object obj) throws OntologyException {
102         Object result = null;
103         try {
104             result = method.invoke(obj, null);
105 
106             if (result == null) {
107                 return null;
108             } 
109 
110             return onto.fromObject(result);
111         } 
112         catch (OntologyException oe) {
113         		// Forward the exception
114             throw oe;
115         } 
116         catch (Exception e) {
117             throw new OntologyException("Error invoking get method");
118         } 
119     } 
120 
121     /***
122      * Translate an abstract descriptor into an object of a proper class 
123      * representing an element in an ontology 
124      * @param onto The ontology that uses this Introspector.
125      * @param referenceOnto The reference ontology in the context of
126      * this translation i.e. the most extended ontology that extends 
127      * <code>onto</code> (directly or indirectly). 
128      * @param abs The abstract descriptor to be translated
129      * @return The Java object produced by the translation 
130      * @throws UngroundedException If the abstract descriptor to be translated 
131      * contains a variable
132 		 * @throws UnknownSchemaException If no schema for the abstract descriptor
133 		 * to be translated is defined in the ontology that uses this Introspector
134      * @throws OntologyException If some error occurs during the translation
135      */
136     public Object internalise(Ontology onto, Ontology referenceOnto, AbsObject abs) 
137             throws UngroundedException, UnknownSchemaException, OntologyException {
138 
139         try {
140         		String type = abs.getTypeName();
141         		//DEBUG System.out.println("Abs is "+abs);
142         		// Retrieve the schema
143             ObjectSchema schema = onto.getSchema(type, false);
144             if (schema == null) {
145             	throw new UnknownSchemaException();
146             }
147             //DEBUG System.out.println("Schema is: "+schema);
148         		if (schema instanceof IRESchema || schema instanceof VariableSchema) {
149         			throw new UngroundedException();
150         		}
151             
152             Class        javaClass = onto.getClassForElement(type);
153         		if (javaClass == null) {
154         			throw new OntologyException("No java class associated to type "+type);
155         		}
156             //DEBUG System.out.println("Class is: "+javaClass.getName());
157             
158             Object       obj = javaClass.newInstance();
159             //DEBUG System.out.println("Object created");
160             
161             Method[]     methods = javaClass.getMethods();
162             String[]     names = schema.getNames();
163 
164             for (int i = 0; i < methods.length; i++) {
165             	Method m = methods[i];
166               String methodName = m.getName();
167 
168               if (methodName.startsWith("set")) {
169                 String attributeName = (methodName.substring(3, methodName.length())).toUpperCase();
170 
171                 if (schema.containsSlot(attributeName)) {
172             			//DEBUG System.out.println("Handling attribute "+attributeName);
173                 	AbsObject attributeValue = abs.getAbsObject(attributeName);
174             			//DEBUG System.out.println("Attribute value is: "+attributeValue);
175 
176                   if (attributeValue != null) {
177                   	invokeSetMethod(referenceOnto, m, obj, attributeValue);
178                   } 
179                 } 
180               } 
181             } 
182 
183             return obj;
184         } 
185         catch (OntologyException oe) {
186             throw oe;
187         } 
188         catch (Throwable t) {
189             throw new OntologyException("Schema and Java class do not match", t);
190         } 
191     } 
192 
193     private void invokeSetMethod(Ontology onto, Method method, Object obj, 
194                                  AbsObject value) throws OntologyException {
195         try {
196             Object objValue = onto.toObject(value);
197 
198             if (objValue == null) {
199                 return;
200             } 
201 
202             Object[] params = new Object[] {
203                 objValue
204             };
205 						
206             try {
207 	            method.invoke(obj, params);
208             }
209         		catch (IllegalArgumentException iae) {
210         			// Maybe the method required an int argument and we supplied 
211         			// a Long. Similarly maybe the the method required a float and 
212         			// we supplied a Double. Try these possibilities
213         			if (objValue instanceof Long) {
214         				Integer i = new Integer((int) ((Long) objValue).longValue());
215         				params[0] = i;
216         			}
217         			//__CLDC_UNSUPPORTED__BEGIN
218         			else if (objValue instanceof Double) {
219         				Float f = new Float((float) ((Double) objValue).doubleValue());
220         				params[0] = f;
221         			}
222         			//__CLDC_UNSUPPORTED__END
223         			method.invoke(obj, params);
224         		}
225         } 
226         catch (OntologyException oe) {
227         		// Forward the exception
228             throw oe;
229         } 
230         catch (Exception e) {
231             throw new OntologyException("Error invoking set method");
232         } 
233     } 
234 
235     /***
236        Check the structure of a java class associated to an ontological element 
237        to ensure that translations to/from abstract descriptors and java objects
238        (instances of that class) can be accomplished by this introspector.
239        @param schema The schema of the ontological element
240        @param javaClass The java class associated to the ontologcal element
241        @throws OntologyException if the java class does not have the correct 
242        structure
243      */
244     public void checkClass(ObjectSchema schema, Class javaClass) throws OntologyException {
245     	// FIXME: Not yet implemented
246     }
247 }
248