-/*******************************************************************************\r
- * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.databoard.binding.reflection;\r
-\r
-import java.lang.reflect.Constructor;\r
-import java.lang.reflect.Field;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Modifier;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.LinkedList;\r
-\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-\r
-public class ClassInfo {\r
-\r
- public Constructor<?> argsConstructor, noArgsConstructor, beanConstructor;\r
- public Class<?> clazz;\r
- public Field[] fields;\r
- public Method[] getters, setters;\r
- public boolean[] writable;\r
- public boolean partialConstructionPossible; // set to true, if partial construction is possible\r
- \r
- public static ClassInfo getInfo(Class<?> clazz)\r
- throws BindingConstructionException\r
- {\r
- boolean isAbstract = (clazz.getModifiers() & Modifier.ABSTRACT) != 0; \r
-// if ( isAbstract )\r
-// throw new BindingConstructionException("Cannot create reflection binding to abstract class "+clazz);\r
- \r
- ClassInfo ci = new ClassInfo();\r
- ci.clazz = clazz;\r
- try {\r
- ci.fields = getFields(clazz);\r
- for (Field f : ci.fields)\r
- f.setAccessible(true);\r
-\r
- int c = ci.fields.length;\r
- ci.getters = new Method[ c ];\r
- ci.setters = new Method[ c ];\r
- ci.writable = new boolean[ c ];\r
- for (int i=0; i<ci.fields.length; i++)\r
- {\r
- Field f = ci.fields[i];\r
- \r
- boolean isPublic = (f.getModifiers() & (Modifier.PUBLIC)) > 0;\r
- boolean isFinal = (f.getModifiers() & (Modifier.FINAL)) > 0;\r
- boolean isPrimitive = (f.getType().getName().length()=='1');\r
- \r
- ci.writable[i] = isPublic && (!isFinal || isPrimitive); \r
- String name = f.getName();\r
- try {\r
- String getterName = "get"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());\r
- Method getter = clazz.getMethod(getterName);\r
- if (getter.getReturnType().equals(f.getType()))\r
- ci.getters[i] = getter;\r
- } catch (NoSuchMethodException e) {\r
- }\r
- \r
- try {\r
- String setterName = "set"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());\r
- Method setter = clazz.getMethod(setterName, f.getType());\r
- if (setter.getReturnType().equals(void.class)) {\r
- ci.setters[i] = setter;\r
- ci.writable[i] = true;\r
- }\r
- \r
- } catch (NoSuchMethodException e) { \r
- }\r
- \r
- }\r
- \r
- // Prepare constuctor for case 2)\r
- if (!isAbstract) {\r
- Class<?>[] constructorArgs = new Class<?>[ci.fields.length];\r
- for (int i=0; i<ci.fields.length; i++) {\r
- constructorArgs[i] = ci.fields[i].getType();\r
- }\r
- \r
- try {\r
- ci.argsConstructor = clazz.getDeclaredConstructor(constructorArgs);\r
- ci.argsConstructor.setAccessible(true);\r
- } catch (NoSuchMethodException e) {}\r
- \r
- try {\r
- ci.noArgsConstructor = clazz.getDeclaredConstructor();\r
- ci.noArgsConstructor.setAccessible(true); \r
- } catch (NoSuchMethodException e) {}\r
- \r
- \r
- try {\r
- ci.beanConstructor = clazz.getDeclaredConstructor(org.simantics.databoard.binding.Binding.class);\r
- ci.beanConstructor.setAccessible(true);\r
- } catch (NoSuchMethodException e) {}\r
- }\r
- \r
- boolean allWritable = true;\r
- for (boolean b : ci.writable) allWritable &= b;\r
- \r
- ci.partialConstructionPossible = allWritable;\r
- \r
- return ci;\r
- } catch (SecurityException e1) {\r
- throw new BindingConstructionException(e1);\r
- }\r
- \r
- }\r
- \r
- /**\r
- * Get all, including inherited, public, protected and default \r
- * non-transient, non-static, non-final fields. All returned fields have access.\r
- * \r
- * @param clazz\r
- * @return\r
- */\r
- static Field[] getFields(Class<?> clazz)\r
- {\r
- // TODO Sort as order is not guaranteed\r
- // Sort priority 1-class, 2-modifiers, 3-name, 4-signature\r
- Field[] fields = getAllFields(clazz);\r
- \r
- ArrayList<Field> result = new ArrayList<Field>(fields.length);\r
- for (Field f : fields) {\r
- if (Modifier.isStatic(f.getModifiers())) continue;\r
-// if (Modifier.isFinal(f.getModifiers())) continue;\r
- if (Modifier.isTransient(f.getModifiers())) continue; \r
- if (Modifier.isVolatile(f.getModifiers())) continue; \r
- f.setAccessible(true);\r
- result.add(f);\r
- }\r
- return result.toArray( new Field[result.size()] );\r
- }\r
- \r
- // Get all fields except fields of Throwable\r
- static Field[] getAllFields(Class<?> clazz)\r
- {\r
- LinkedList<Class<?>> classes = new LinkedList<Class<?>>();\r
- while (clazz!=null) {\r
- classes.addFirst(clazz);\r
- clazz = clazz.getSuperclass();\r
- if (clazz==Throwable.class) clazz=null;\r
- }\r
- \r
- ArrayList<Field> result = new ArrayList<Field>();\r
- for (Class<?> _class : classes) {\r
- _getAllFields(_class, result);\r
- }\r
- \r
- return result.toArray(new Field[result.size()]);\r
- }\r
- \r
- public static void _getAllFields(Class<?> clazz, Collection<Field> result)\r
- {\r
- for (Field m : clazz.getDeclaredFields())\r
- result.add(m);\r
- } \r
-\r
- @Override\r
- public boolean equals(Object arg0) {\r
- return this == arg0 || (arg0.getClass().equals(this.getClass()) && ((ClassInfo)arg0).clazz.equals(clazz));\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- return clazz.hashCode();\r
- };\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.databoard.binding.reflection;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.simantics.databoard.binding.error.BindingConstructionException;
+
+public class ClassInfo {
+
+ public Constructor<?> argsConstructor, noArgsConstructor, beanConstructor;
+ public Class<?> clazz;
+ public Field[] fields;
+ public Method[] getters, setters;
+ public boolean[] writable;
+ public boolean partialConstructionPossible; // set to true, if partial construction is possible
+
+ public static ClassInfo getInfo(Class<?> clazz)
+ throws BindingConstructionException
+ {
+ boolean isAbstract = (clazz.getModifiers() & Modifier.ABSTRACT) != 0;
+// if ( isAbstract )
+// throw new BindingConstructionException("Cannot create reflection binding to abstract class "+clazz);
+
+ ClassInfo ci = new ClassInfo();
+ ci.clazz = clazz;
+ try {
+ ci.fields = getFields(clazz);
+ for (Field f : ci.fields)
+ f.setAccessible(true);
+
+ int c = ci.fields.length;
+ ci.getters = new Method[ c ];
+ ci.setters = new Method[ c ];
+ ci.writable = new boolean[ c ];
+ for (int i=0; i<ci.fields.length; i++)
+ {
+ Field f = ci.fields[i];
+
+ boolean isPublic = (f.getModifiers() & (Modifier.PUBLIC)) > 0;
+ boolean isFinal = (f.getModifiers() & (Modifier.FINAL)) > 0;
+ boolean isPrimitive = (f.getType().getName().length()=='1');
+
+ ci.writable[i] = isPublic && (!isFinal || isPrimitive);
+ String name = f.getName();
+ try {
+ String getterName = "get"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());
+ Method getter = clazz.getMethod(getterName);
+ if (getter.getReturnType().equals(f.getType()))
+ ci.getters[i] = getter;
+ } catch (NoSuchMethodException e) {
+ }
+
+ try {
+ String setterName = "set"+name.substring(0, 1).toUpperCase()+name.substring(1, name.length());
+ Method setter = clazz.getMethod(setterName, f.getType());
+ if (setter.getReturnType().equals(void.class)) {
+ ci.setters[i] = setter;
+ ci.writable[i] = true;
+ }
+
+ } catch (NoSuchMethodException e) {
+ }
+
+ }
+
+ // Prepare constuctor for case 2)
+ if (!isAbstract) {
+ Class<?>[] constructorArgs = new Class<?>[ci.fields.length];
+ for (int i=0; i<ci.fields.length; i++) {
+ constructorArgs[i] = ci.fields[i].getType();
+ }
+
+ try {
+ ci.argsConstructor = clazz.getDeclaredConstructor(constructorArgs);
+ ci.argsConstructor.setAccessible(true);
+ } catch (NoSuchMethodException e) {}
+
+ try {
+ ci.noArgsConstructor = clazz.getDeclaredConstructor();
+ ci.noArgsConstructor.setAccessible(true);
+ } catch (NoSuchMethodException e) {}
+
+
+ try {
+ ci.beanConstructor = clazz.getDeclaredConstructor(org.simantics.databoard.binding.Binding.class);
+ ci.beanConstructor.setAccessible(true);
+ } catch (NoSuchMethodException e) {}
+ }
+
+ boolean allWritable = true;
+ for (boolean b : ci.writable) allWritable &= b;
+
+ ci.partialConstructionPossible = allWritable;
+
+ return ci;
+ } catch (SecurityException e1) {
+ throw new BindingConstructionException(e1);
+ }
+
+ }
+
+ /**
+ * Get all, including inherited, public, protected and default
+ * non-transient, non-static, non-final fields. All returned fields have access.
+ *
+ * @param clazz
+ * @return
+ */
+ static Field[] getFields(Class<?> clazz)
+ {
+ // TODO Sort as order is not guaranteed
+ // Sort priority 1-class, 2-modifiers, 3-name, 4-signature
+ Field[] fields = getAllFields(clazz);
+
+ ArrayList<Field> result = new ArrayList<Field>(fields.length);
+ for (Field f : fields) {
+ if (Modifier.isStatic(f.getModifiers())) continue;
+// if (Modifier.isFinal(f.getModifiers())) continue;
+ if (Modifier.isTransient(f.getModifiers())) continue;
+ if (Modifier.isVolatile(f.getModifiers())) continue;
+ f.setAccessible(true);
+ result.add(f);
+ }
+ return result.toArray( new Field[result.size()] );
+ }
+
+ // Get all fields except fields of Throwable
+ static Field[] getAllFields(Class<?> clazz)
+ {
+ LinkedList<Class<?>> classes = new LinkedList<Class<?>>();
+ while (clazz!=null) {
+ classes.addFirst(clazz);
+ clazz = clazz.getSuperclass();
+ if (clazz==Throwable.class) clazz=null;
+ }
+
+ ArrayList<Field> result = new ArrayList<Field>();
+ for (Class<?> _class : classes) {
+ _getAllFields(_class, result);
+ }
+
+ return result.toArray(new Field[result.size()]);
+ }
+
+ public static void _getAllFields(Class<?> clazz, Collection<Field> result)
+ {
+ for (Field m : clazz.getDeclaredFields())
+ result.add(m);
+ }
+
+ @Override
+ public boolean equals(Object arg0) {
+ return this == arg0 || (arg0.getClass().equals(this.getClass()) && ((ClassInfo)arg0).clazz.equals(clazz));
+ }
+
+ @Override
+ public int hashCode() {
+ return clazz.hashCode();
+ };
+}