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
61
62 AbsObject abs = schema.newInstance();
63
64 Method[] methods = javaClass.getMethods();
65 String[] names = schema.getNames();
66
67
68
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
78
79 AbsObject attributeValue = invokeGetMethod(referenceOnto, m, obj);
80
81
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
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
142
143 ObjectSchema schema = onto.getSchema(type, false);
144 if (schema == null) {
145 throw new UnknownSchemaException();
146 }
147
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
157
158 Object obj = javaClass.newInstance();
159
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
173 AbsObject attributeValue = abs.getAbsObject(attributeName);
174
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
211
212
213 if (objValue instanceof Long) {
214 Integer i = new Integer((int) ((Long) objValue).longValue());
215 params[0] = i;
216 }
217
218 else if (objValue instanceof Double) {
219 Float f = new Float((float) ((Double) objValue).doubleValue());
220 params[0] = f;
221 }
222
223 method.invoke(obj, params);
224 }
225 }
226 catch (OntologyException oe) {
227
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
246 }
247 }
248