1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.binding.reflection;
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.Field;
16 import java.lang.reflect.Method;
17 import java.lang.reflect.Modifier;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.LinkedList;
22 import org.simantics.databoard.binding.error.BindingConstructionException;
24 public class ClassInfo {
26 public Constructor<?> argsConstructor, noArgsConstructor, beanConstructor;
27 public Class<?> clazz;
28 public Field[] fields;
29 public Method[] getters, setters;
30 public boolean[] writable;
31 public boolean partialConstructionPossible; // set to true, if partial construction is possible
33 public static ClassInfo getInfo(Class<?> clazz)
34 throws BindingConstructionException
36 boolean isAbstract = (clazz.getModifiers() & Modifier.ABSTRACT) != 0;
38 // throw new BindingConstructionException("Cannot create reflection binding to abstract class "+clazz);
40 ClassInfo ci = new ClassInfo();
43 ci.fields = getFields(clazz);
44 for (Field f : ci.fields)
45 f.setAccessible(true);
47 int c = ci.fields.length;
48 ci.getters = new Method[ c ];
49 ci.setters = new Method[ c ];
50 ci.writable = new boolean[ c ];
51 for (int i=0; i<ci.fields.length; i++)
53 Field f = ci.fields[i];
55 boolean isPublic = (f.getModifiers() & (Modifier.PUBLIC)) > 0;
56 boolean isFinal = (f.getModifiers() & (Modifier.FINAL)) > 0;
57 boolean isPrimitive = (f.getType().getName().length()=='1');
59 ci.writable[i] = isPublic && (!isFinal || isPrimitive);
60 String name = f.getName();
62 String getterName = "get"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());
63 Method getter = clazz.getMethod(getterName);
64 if (getter.getReturnType().equals(f.getType()))
65 ci.getters[i] = getter;
66 } catch (NoSuchMethodException e) {
70 String setterName = "set"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());
71 Method setter = clazz.getMethod(setterName, f.getType());
72 if (setter.getReturnType().equals(void.class)) {
73 ci.setters[i] = setter;
74 ci.writable[i] = true;
77 } catch (NoSuchMethodException e) {
82 // Prepare constuctor for case 2)
84 Class<?>[] constructorArgs = new Class<?>[ci.fields.length];
85 for (int i=0; i<ci.fields.length; i++) {
86 constructorArgs[i] = ci.fields[i].getType();
90 ci.argsConstructor = clazz.getDeclaredConstructor(constructorArgs);
91 ci.argsConstructor.setAccessible(true);
92 } catch (NoSuchMethodException e) {}
95 ci.noArgsConstructor = clazz.getDeclaredConstructor();
96 ci.noArgsConstructor.setAccessible(true);
97 } catch (NoSuchMethodException e) {}
101 ci.beanConstructor = clazz.getDeclaredConstructor(org.simantics.databoard.binding.Binding.class);
102 ci.beanConstructor.setAccessible(true);
103 } catch (NoSuchMethodException e) {}
106 boolean allWritable = true;
107 for (boolean b : ci.writable) allWritable &= b;
109 ci.partialConstructionPossible = allWritable;
112 } catch (SecurityException e1) {
113 throw new BindingConstructionException(e1);
119 * Get all, including inherited, public, protected and default
120 * non-transient, non-static, non-final fields. All returned fields have access.
125 static Field[] getFields(Class<?> clazz)
127 // TODO Sort as order is not guaranteed
128 // Sort priority 1-class, 2-modifiers, 3-name, 4-signature
129 Field[] fields = getAllFields(clazz);
131 ArrayList<Field> result = new ArrayList<Field>(fields.length);
132 for (Field f : fields) {
133 if (Modifier.isStatic(f.getModifiers())) continue;
134 // if (Modifier.isFinal(f.getModifiers())) continue;
135 if (Modifier.isTransient(f.getModifiers())) continue;
136 if (Modifier.isVolatile(f.getModifiers())) continue;
137 f.setAccessible(true);
140 return result.toArray( new Field[result.size()] );
143 // Get all fields except fields of Throwable
144 static Field[] getAllFields(Class<?> clazz)
146 LinkedList<Class<?>> classes = new LinkedList<Class<?>>();
147 while (clazz!=null) {
148 classes.addFirst(clazz);
149 clazz = clazz.getSuperclass();
150 if (clazz==Throwable.class) clazz=null;
153 ArrayList<Field> result = new ArrayList<Field>();
154 for (Class<?> _class : classes) {
155 _getAllFields(_class, result);
158 return result.toArray(new Field[result.size()]);
161 public static void _getAllFields(Class<?> clazz, Collection<Field> result)
163 for (Field m : clazz.getDeclaredFields())
168 public boolean equals(Object arg0) {
169 return this == arg0 || (arg0.getClass().equals(this.getClass()) && ((ClassInfo)arg0).clazz.equals(clazz));
173 public int hashCode() {
174 return clazz.hashCode();