/******************************************************************************* * Copyright (c) 2010 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.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.BooleanBinding; import org.simantics.databoard.binding.ByteBinding; import org.simantics.databoard.binding.DoubleBinding; import org.simantics.databoard.binding.FloatBinding; import org.simantics.databoard.binding.IntegerBinding; import org.simantics.databoard.binding.LongBinding; import org.simantics.databoard.binding.error.BindingConstructionException; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.type.RecordType; /** * ReflectionRecordBinding binding of a Record Type and Java Class. * If binds Record Values to Java Objects.

* * * There are three types of classes supported: * 1) record-like class * - All fields are public * - No-argument public constructor * * 2) immutable-like class * - All fields are set in constructor * * 3) bean-like class * - All fields are set with getter/setter */ class RecordClassBinding extends ClassBinding { private static final Object[] NO_ARGS = new Object[0]; /** * Create a Reflection Record Bindings. * * There is a 2-phase construction. * * @param ci * @param type * @throws BindingConstructionException */ public RecordClassBinding(ClassInfo ci, RecordType type) { super(ci); if ( ci == null ) throw new IllegalArgumentException("null ClassInfo"); this.type = type; componentBindings = new Binding[ ci.fields.length ]; } @Override public Object createPartial() throws BindingException { try { if (ci.noArgsConstructor!=null) return ci.noArgsConstructor.newInstance(); else if (ci.argsConstructor!=null) { // Create default values Object values[] = new Object[ci.fields.length]; for (int i=0; i type = f.getType(); Method setter = ci.setters[i]; if (setter!=null) { // Case 3 if (type==int.class) setter.invoke(result, (Integer)value); else if (type==long.class) setter.invoke(result, (Long)value); else if (type==float.class) setter.invoke(result, (Float)value); else if (type==double.class) setter.invoke(result, (Double)value); else if (type==boolean.class) setter.invoke(result, (Boolean)value); else setter.invoke(result, value); } else { // Case 1 if (type==int.class) f.setInt(result, (Integer)value); else if (type==long.class) f.setLong(result, (Long)value); else if (type==float.class) f.setFloat(result, (Float)value); else if (type==double.class) f.setDouble(result, (Double)value); else if (type==boolean.class) f.setBoolean(result, (Boolean)value); else f.set(result, value); } } return result; } catch (InstantiationException e) { boolean isPublic = (ci.clazz.getModifiers() & Modifier.PUBLIC)!=0; if (!isPublic) throw new BindingException("Failed to instantiate "+ci.clazz.getName()+", maybe it should be public class."); throw new BindingException("Failed to instantiate "+ci.clazz.getName()); } catch (IllegalAccessException e) { throw new BindingException(e); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (InvocationTargetException e) { throw new BindingException(e.getCause()); } } @Override public Object getComponent(Object obj, int index) throws BindingException { /* Field getter = fields[index]; if (getter!=null) { try { return getter.get(obj); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } */ try { Field f = ci.fields[index]; Class type = f.getType(); if (type.isPrimitive()) { if (type==int.class) return (Integer) f.getInt(obj); else if (type==byte.class) return (Byte) f.getByte(obj); else if (type==boolean.class) return (Boolean) f.getBoolean(obj); else if (type==float.class) return (Float) f.getFloat(obj); else if (type==double.class) return (Double) f.getDouble(obj); else if (type==long.class) return (Long) f.getLong(obj); return f.get(obj); } else return f.get(obj); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { Field getter = ci.fields[index]; if (getter!=null) { try { return getter.get(obj); } catch (IllegalArgumentException e2) { } catch (IllegalAccessException e2) { } } throw new BindingException(e); } } @Override public boolean isInstance(Object obj) { return ci.clazz.isInstance(obj); } @Override public boolean isImmutable() { return false; } public Class getComponentClass(int index) { return ci.fields[index].getDeclaringClass(); } @Override public void setComponent(Object obj, int index, Object value) throws BindingException { try { Method setter = ci.setters[index]; if (setter!=null) { setter.invoke(obj, value); } else { Field f = ci.fields[index]; Class type = f.getType(); if (type.isPrimitive()) { if (type==int.class) f.setInt(obj, (Integer) value); else if (type==byte.class) f.setByte(obj, (Byte) value); else if (type==boolean.class) f.setBoolean(obj, (Boolean) value); else if (type==float.class) f.setFloat(obj, (Float) value); else if (type==double.class) f.setDouble(obj, (Double) value); else if (type==long.class) f.setLong(obj, (Long) value); else f.set(obj, value); } else { f.set(obj, value); } } } catch (IllegalAccessException e) { throw new BindingException(e); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (InvocationTargetException e) { e.getCause().printStackTrace(); throw new BindingException(e.getCause()); } } @Override public void setComponents(Object obj, Object... value) throws BindingException { try { for(int i = 0;i type = f.getType(); if (type.isPrimitive()) { if (type==int.class) f.setInt(obj, (Integer) value[i]); else if (type==byte.class) f.setByte(obj, (Byte) value[i]); else if (type==boolean.class) f.setBoolean(obj, (Boolean) value[i]); else if (type==float.class) f.setFloat(obj, (Float) value[i]); else if (type==double.class) f.setDouble(obj, (Double) value[i]); else if (type==long.class) f.setLong(obj, (Long) value[i]); else f.set(obj, value[i]); } else { f.set(obj, value[i]); } } } } catch (IllegalAccessException e) { throw new BindingException(e); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (InvocationTargetException e) { throw new BindingException(e.getCause()); } } public void setBoolean(Object r, int index, boolean z) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==boolean.class || cl==Boolean.class ) { f.setBoolean(r, z); } else { BooleanBinding b = (BooleanBinding) getComponentBinding(index); setComponent(r, index, b.create(z)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public boolean getBoolean(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==boolean.class || cl==Boolean.class ) return f.getBoolean(r); Object o = getComponent(r, index); BooleanBinding b = (BooleanBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public void setByte(Object r, int index, byte x) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==byte.class || cl==Byte.class ) { f.setByte(r, x); } else { ByteBinding b = (ByteBinding) getComponentBinding(index); setComponent(r, index, b.create(x)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public byte getByte(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==byte.class || cl==Byte.class ) return f.getByte(r); Object o = getComponent(r, index); ByteBinding b = (ByteBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public void setInt(Object r, int index, int x) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==int.class || cl==Integer.class ) { f.setInt(r, x); } else { IntegerBinding b = (IntegerBinding) getComponentBinding(index); setComponent(r, index, b.create(x)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public int getInt(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==int.class || cl==Integer.class ) return f.getInt(r); Object o = getComponent(r, index); IntegerBinding b = (IntegerBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public void setLong(Object r, int index, long x) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==long.class || cl==Long.class ) { f.setLong(r, x); } else { LongBinding b = (LongBinding) getComponentBinding(index); setComponent(r, index, b.create(x)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public long getLong(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==long.class || cl==Long.class ) return f.getLong(r); Object o = getComponent(r, index); LongBinding b = (LongBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public void setFloat(Object r, int index, float x) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==float.class || cl==Float.class ) { f.setFloat(r, x); } else { FloatBinding b = (FloatBinding) getComponentBinding(index); setComponent(r, index, b.create(x)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public float getFloat(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==float.class || cl==Float.class ) return f.getFloat(r); Object o = getComponent(r, index); FloatBinding b = (FloatBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public void setDouble(Object r, int index, double x) throws BindingException { try { Field f = ci.fields[index]; Class cl = f.getType(); if ( cl==double.class || cl==Double.class ) { f.setDouble(r, x); } else { DoubleBinding b = (DoubleBinding) getComponentBinding(index); setComponent(r, index, b.create(x)); } } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } public double getDouble(Object r, int index) throws BindingException { try { Field f = ci.fields[index]; Class cl = f==null?null:f.getType(); if ( cl==double.class || cl==Double.class ) return f.getDouble(r); Object o = getComponent(r, index); DoubleBinding b = (DoubleBinding) getComponentBinding(index); return b.getValue_(o); } catch (IllegalArgumentException e) { throw new BindingException(e); } catch (IllegalAccessException e) { throw new BindingException(e); } } }