1 package org.simantics.scl.reflection.internal.registry;
\r
3 import gnu.trove.map.hash.THashMap;
\r
4 import gnu.trove.procedure.TObjectObjectProcedure;
\r
6 import java.lang.reflect.Constructor;
\r
7 import java.lang.reflect.Field;
\r
8 import java.lang.reflect.Method;
\r
9 import java.lang.reflect.Modifier;
\r
10 import java.util.ArrayList;
\r
12 import org.simantics.scl.compiler.types.Type;
\r
13 import org.simantics.scl.compiler.types.Types;
\r
14 import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException;
\r
15 import org.simantics.scl.compiler.types.util.ITypeEnvironment;
\r
16 import org.simantics.scl.reflection.MinimalTypeBindingScheme;
\r
17 import org.simantics.scl.reflection.ReflectionUtils;
\r
18 import org.simantics.scl.reflection.TypeBindingScheme;
\r
19 import org.simantics.scl.reflection.TypeNotFoundException;
\r
20 import org.simantics.scl.reflection.TypedValue;
\r
21 import org.simantics.scl.reflection.ValueNotFoundException;
\r
22 import org.simantics.scl.reflection.annotations.SCLType;
\r
23 import org.simantics.scl.reflection.annotations.SCLValue;
\r
24 import org.simantics.scl.reflection.functions.ClassMethodFunction;
\r
25 import org.simantics.scl.reflection.functions.ClassMethodFunction3;
\r
26 import org.simantics.scl.reflection.functions.ConstructorFunction;
\r
27 import org.simantics.scl.reflection.functions.FieldAccessorFunction;
\r
28 import org.simantics.scl.reflection.functions.InstanceMethodFunction;
\r
29 import org.simantics.scl.reflection.internal.Activator;
\r
30 import org.simantics.scl.reflection.internal.typeRegistry.TypeRegistry;
\r
32 public class Namespace {
\r
34 ImportSeq importSeq;
\r
35 ArrayList<Entry> classes = new ArrayList<Entry>();
\r
36 ArrayList<ExternalClass> externalClasses =
\r
37 new ArrayList<ExternalClass>();
\r
38 ArrayList<ExternalMethod> externalMethods =
\r
39 new ArrayList<ExternalMethod>();
\r
40 volatile THashMap<String, Class<?>> types;
\r
41 volatile THashMap<String, TypedValue> values;
\r
43 public Namespace(String namespace, ImportSeq importSeq) {
\r
44 this.namespace = namespace;
\r
45 this.importSeq = importSeq;
\r
48 public void addClass(Entry e) {
\r
52 public void addExternalMethod(ExternalMethod e) {
\r
53 externalMethods.add(e);
\r
56 public void addExternalClass(ExternalClass e) {
\r
57 externalClasses.add(e);
\r
60 public Class<?> getClass(String name) throws TypeNotFoundException {
\r
64 } catch (Exception e) {
\r
65 throw new TypeNotFoundException(e);
\r
68 Class<?> type = types.get(name);
\r
70 throw new TypeNotFoundException("Didn't find type " + name + ".");
\r
74 public TypedValue getValue(String name) throws ValueNotFoundException {
\r
75 if(values == null) {
\r
78 } catch (Exception e) {
\r
79 e.printStackTrace();
\r
80 throw new ValueNotFoundException(e);
\r
83 TypedValue value = values.get(name);
\r
85 throw new ValueNotFoundException("Didn't find value " + name + ".");
\r
89 ITypeEnvironment typeEnvironment = new ITypeEnvironment() {
\r
92 public Type resolve(String namespace, String name) {
\r
93 if(namespace == null) {
\r
94 if(TypeRegistry.isBuiltin(name))
\r
95 namespace = Types.BUILTIN;
\r
96 else if(types.contains(name))
\r
97 namespace = Namespace.this.namespace;
\r
102 for(ImportSeq cur = importSeq;cur != null;cur = cur.parent) {
\r
103 if(namespace.equals(cur.localName)) {
\r
104 namespace = cur.path;
\r
109 return Types.con(namespace, name);
\r
114 private Type parseType(String typeText) throws SCLTypeParseException {
\r
115 return Types.closure(Types.parseType(typeEnvironment, typeText));
\r
118 private synchronized void initializeTypes() {
\r
119 if(types == null) {
\r
120 types = new THashMap<String, Class<?>>();
\r
122 for(Entry entry : classes) {
\r
123 Class<?> clazz = entry.loadClass();
\r
124 if(clazz == null) {
\r
125 Activator.logError("Didn't find class " + entry.name + ".");
\r
129 SCLType sclType = clazz.getAnnotation(SCLType.class);
\r
130 if(sclType != null) {
\r
131 String name = sclType.name();
\r
133 name = clazz.getSimpleName();
\r
134 types.put(name, clazz);
\r
138 for(ExternalClass entry : externalClasses) {
\r
139 Class<?> clazz = entry.loadClass();
\r
140 if(clazz == null) {
\r
141 Activator.logError("Didn't find class " + entry.className + ".");
\r
145 String name = entry.alternativeName;
\r
147 name = clazz.getSimpleName();
\r
148 types.put(name, clazz);
\r
153 private void handleMethod(TypeBindingScheme scheme, Class<?> clazz, Method method) {
\r
154 SCLValue sclValue = method.getAnnotation(SCLValue.class);
\r
155 if(sclValue != null) {
\r
156 String name = sclValue.name();
\r
158 name = method.getName();
\r
161 type = parseType(sclValue.type());
\r
162 } catch (SCLTypeParseException e) {
\r
163 Activator.logError("Method " + method.getName() + " in class " +
\r
164 clazz.getCanonicalName() + " has invalid type declaration.", e
\r
169 if(ReflectionUtils.isCompatible(scheme, type, method)) {
\r
171 if(Modifier.isStatic(method.getModifiers())) {
\r
172 int arity = method.getParameterTypes().length;
\r
174 value = new ClassMethodFunction3(method);
\r
176 value = new ClassMethodFunction(method);
\r
179 value = new InstanceMethodFunction(method);
\r
180 values.put(name, new TypedValue(type, value));
\r
183 Activator.logError("Method " + method.getName() + " in class " +
\r
184 clazz.getCanonicalName() + " has incompantible SCL type in the SCLValue annotation."
\r
186 ReflectionUtils.isCompatible(scheme, type, method);
\r
188 } catch (TypeNotFoundException e) {
\r
189 Activator.logError("Couldn't find all types in the type declaration of method " + method.getName() + " in class " +
\r
190 clazz.getCanonicalName() + "."
\r
196 private void handleConstructor(TypeBindingScheme scheme, Class<?> clazz, Constructor<?> constr) {
\r
197 SCLValue sclValue = constr.getAnnotation(SCLValue.class);
\r
198 if(sclValue != null) {
\r
199 String name = sclValue.name();
\r
201 name = constr.getDeclaringClass().getSimpleName();
\r
204 type = parseType(sclValue.type());
\r
205 } catch (SCLTypeParseException e) {
\r
206 Activator.logError("Constructor in " +
\r
207 clazz.getCanonicalName() + " has invalid type declaration.", e
\r
212 if(ReflectionUtils.isCompatible(scheme, type, constr)) {
\r
213 Object value = new ConstructorFunction(constr);
\r
214 values.put(name, new TypedValue(type, value));
\r
217 Activator.logError("Constructor of " +
\r
218 clazz.getCanonicalName() + " has incompantible SCL type in the SCLValue annotation."
\r
221 } catch (TypeNotFoundException e) {
\r
222 Activator.logError("Couldn't find all types in the type declaration of constructor in " +
\r
223 clazz.getCanonicalName() + "."
\r
229 private void handleField(TypeBindingScheme scheme, Class<?> clazz, Field field) {
\r
230 SCLValue sclValue = field.getAnnotation(SCLValue.class);
\r
231 if(sclValue != null) {
\r
232 String name = sclValue.name();
\r
234 name = field.getName();
\r
237 type = parseType(sclValue.type());
\r
238 } catch (SCLTypeParseException e) {
\r
239 Activator.logError("Field " + field.getName() + " in class " +
\r
240 clazz.getCanonicalName() + " has invalid type declaration.", e
\r
245 if(ReflectionUtils.isCompatible(scheme, type, field)) {
\r
247 if(Modifier.isStatic(field.getModifiers()))
\r
249 value = field.get(null);
\r
250 } catch (IllegalArgumentException e) {
\r
251 Activator.logError("Cannot read field " + field.getName() + " in class " +
\r
252 clazz.getCanonicalName() + ".", e
\r
255 } catch (IllegalAccessException e) {
\r
256 Activator.logError("Cannot read field " + field.getName() + " in class " +
\r
257 clazz.getCanonicalName() + ".", e
\r
262 value = new FieldAccessorFunction(field);
\r
263 values.put(name, new TypedValue(type, value));
\r
266 Activator.logError("Field " + field.getName() + " in class " +
\r
267 clazz.getCanonicalName() + " has incompantible SCL type in the SCLValue annotation."
\r
270 } catch (TypeNotFoundException e) {
\r
271 Activator.logError("Couldn't find all types in the type declaration of field " + field.getName() + " in class " +
\r
272 clazz.getCanonicalName() + "."
\r
278 private synchronized void initializeValues() {
\r
279 if(values == null) {
\r
281 TypeBindingScheme scheme = MinimalTypeBindingScheme.INSTANCE;
\r
283 values = new THashMap<String, TypedValue>();
\r
285 for(Entry entry : classes) {
\r
286 Class<?> clazz = entry.loadClass();
\r
288 if(clazz == null) {
\r
289 Activator.logError("Didn't find class " + entry.name + ".");
\r
293 for(Method method : clazz.getMethods()) {
\r
294 handleMethod(scheme, clazz, method);
\r
297 for(Constructor<?> constr : clazz.getConstructors()) {
\r
298 handleConstructor(scheme, clazz, constr);
\r
301 for(Field field : clazz.getFields()) {
\r
302 handleField(scheme, clazz, field);
\r
306 for(ExternalMethod entry : externalMethods) {
\r
307 Class<?> clazz = entry.loadClass();
\r
309 if(clazz == null) {
\r
310 Activator.logError("Didn't find class " + entry.className + ".");
\r
314 Method method = entry.getMethod(clazz);
\r
316 if(method == null) {
\r
317 Activator.logError("Didn't find method " + entry.methodName +
\r
318 " in class " + entry.className + ".");
\r
322 handleMethod(scheme, clazz, method);
\r
327 public void print() {
\r
328 for(Entry entry : classes) {
\r
329 System.out.println(" " + entry.name + " (" + entry.bundle + ")");
\r
333 } catch (Exception e) {
\r
334 e.printStackTrace();
\r
335 throw new RuntimeException(e);
\r
337 types.forEachEntry(new TObjectObjectProcedure<String, Class<?>>() {
\r
339 public boolean execute(String name, Class<?> clazz) {
\r
340 System.out.println(" type " + name + " = " + clazz.getCanonicalName());
\r
345 initializeValues();
\r
346 } catch (Exception e) {
\r
347 e.printStackTrace();
\r
348 throw new RuntimeException(e);
\r
350 values.forEachEntry(new TObjectObjectProcedure<String, TypedValue>() {
\r
352 public boolean execute(String name, TypedValue value) {
\r
353 System.out.println(" " + name + " :: " + value.getType());
\r