/******************************************************************************* * 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 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 clazz) { // TODO Sort as order is not guaranteed // Sort priority 1-class, 2-modifiers, 3-name, 4-signature Field[] fields = getAllFields(clazz); ArrayList result = new ArrayList(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> classes = new LinkedList>(); while (clazz!=null) { classes.addFirst(clazz); clazz = clazz.getSuperclass(); if (clazz==Throwable.class) clazz=null; } ArrayList result = new ArrayList(); for (Class _class : classes) { _getAllFields(_class, result); } return result.toArray(new Field[result.size()]); } public static void _getAllFields(Class clazz, Collection 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(); }; }