]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/RecordClassBinding.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / reflection / RecordClassBinding.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/RecordClassBinding.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/RecordClassBinding.java
new file mode 100644 (file)
index 0000000..c84e76a
--- /dev/null
@@ -0,0 +1,496 @@
+/*******************************************************************************\r
+ *  Copyright (c) 2010 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;
+
+import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.lang.reflect.Type;\r
+\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.BooleanBinding;\r
+import org.simantics.databoard.binding.ByteBinding;\r
+import org.simantics.databoard.binding.DoubleBinding;\r
+import org.simantics.databoard.binding.FloatBinding;\r
+import org.simantics.databoard.binding.IntegerBinding;\r
+import org.simantics.databoard.binding.LongBinding;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.type.RecordType;\r
+
+/**
+ * ReflectionRecordBinding binding of a Record Type and Java Class.
+ * If binds Record Values to Java Objects. <p>
+ *  
+ * 
+ * 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 {
+\r
+       private static final Object[] NO_ARGS = new Object[0];  \r
+       \r
+       /**
+        * Create a Reflection Record Bindings. 
+        * 
+        * There is a 2-phase construction.
+        * 
+        * @param ci
+        * @param type
+        * @throws BindingConstructionException
+        */
+       public RecordClassBinding(ClassInfo ci, RecordType type)
+       {\r
+               super(ci);\r
+               if ( ci == null ) throw new IllegalArgumentException("null ClassInfo");\r
+               this.type = type;\r
+               componentBindings = new Binding[ ci.fields.length ];            \r
+       }\r
+       \r
+       @Override
+       public Object createPartial() throws BindingException {
+               try {
+                       if (ci.noArgsConstructor!=null)
+                               return ci.noArgsConstructor.newInstance();
+                       else if (ci.argsConstructor!=null) {\r
+                               \r
+                               // Create default values \r
+                               Object values[] = new Object[ci.fields.length];\r
+                               for (int i=0; i<values.length; i++) {\r
+                                       Binding fb = componentBindings[i];\r
+                                       values[i] = fb.createDefault();\r
+                               }                               \r
+                               return ci.argsConstructor.newInstance((Object[])values);
+//                             return clazz.newInstance();\r
+                       } else throw new BindingException("Class "+ci.clazz.getName()+" doesn't support construction. No no-args or args(fields) constructor.");
+               } catch (InstantiationException e) {
+                       throw new BindingException(e);
+               } catch (IllegalAccessException e) {
+                       throw new BindingException(e);
+               } catch (IllegalArgumentException e) {
+                       throw new BindingException(e);
+               } catch (InvocationTargetException e) {
+                       throw new BindingException(e);
+               }
+       }
+
+       @Override
+       public Object create(Object... values) 
+       throws BindingException {
+
+               // Case 2
+               if (ci.argsConstructor != null) 
+               {
+                       try {
+                               return ci.argsConstructor.newInstance(values);
+                       } catch (IllegalArgumentException e) {
+                   throw new BindingException(e);
+                       } catch (InstantiationException e) {
+                   throw new BindingException(e);
+                       } catch (IllegalAccessException e) {
+                   throw new BindingException(e);
+                       } catch (InvocationTargetException e) {
+                   throw new BindingException(e);
+                       }
+               }
+
+               // Case 1 or 3
+               try {
+                       Object result = null;
+                       if (ci.noArgsConstructor!=null)
+                               result = ci.noArgsConstructor.newInstance();
+                       else
+                               result = ci.clazz.newInstance();
+//                     Object result = clazz.newInstance();
+                       for (int i=0; i<ci.fields.length; i++) {
+                               Object value = values[i];
+                               Field f = ci.fields[i];
+                               Class<?> 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) {\r
+                       boolean isPublic = (ci.clazz.getModifiers() & Modifier.PUBLIC)!=0;\r
+                       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);
+               }
+               
+       }
+       @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() {\r
+               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.printStackTrace();
+                       throw new BindingException(e);
+               }                                       
+       }               
+       @Override
+       public void setComponents(Object obj, Object... value) throws BindingException {
+               try {
+                       for(int i = 0;i<ci.fields.length;++i) {
+                               Method setter = ci.setters[i];
+                               if (setter!=null) {
+                                       setter.invoke(obj, value[i]);
+                               } else {
+                                       Field f = ci.fields[i];
+                                       Class<?> 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);\r
+               }                                       
+       }\r
+       \r
+       public void setBoolean(Object r, int index, boolean z) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==boolean.class || cl==Boolean.class ) {\r
+                               f.setBoolean(r, z); \r
+                       } else { \r
+                               BooleanBinding b = (BooleanBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(z));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public boolean getBoolean(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==boolean.class || cl==Boolean.class ) return f.getBoolean(r);\r
+                       Object o = getComponent(r, index);\r
+                       BooleanBinding b = (BooleanBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public void setByte(Object r, int index, byte x) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==byte.class || cl==Byte.class ) {\r
+                               f.setByte(r, x); \r
+                       } else { \r
+                               ByteBinding b = (ByteBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(x));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public byte getByte(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==byte.class || cl==Byte.class ) return f.getByte(r);\r
+                       Object o = getComponent(r, index);\r
+                       ByteBinding b = (ByteBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+\r
+       public void setInt(Object r, int index, int x) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==int.class || cl==Integer.class ) {\r
+                               f.setInt(r, x); \r
+                       } else { \r
+                               IntegerBinding b = (IntegerBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(x));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public int getInt(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==int.class || cl==Integer.class ) return f.getInt(r);\r
+                       Object o = getComponent(r, index);\r
+                       IntegerBinding b = (IntegerBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public void setLong(Object r, int index, long x) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==long.class || cl==Long.class ) {\r
+                               f.setLong(r, x); \r
+                       } else { \r
+                               LongBinding b = (LongBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(x));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public long getLong(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==long.class || cl==Long.class ) return f.getLong(r);\r
+                       Object o = getComponent(r, index);\r
+                       LongBinding b = (LongBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public void setFloat(Object r, int index, float x) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==float.class || cl==Float.class ) {\r
+                               f.setFloat(r, x); \r
+                       } else { \r
+                               FloatBinding b = (FloatBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(x));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public float getFloat(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==float.class || cl==Float.class ) return f.getFloat(r);\r
+                       Object o = getComponent(r, index);\r
+                       FloatBinding b = (FloatBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public void setDouble(Object r, int index, double x) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f.getType();\r
+                       if ( cl==double.class || cl==Double.class ) {\r
+                               f.setDouble(r, x); \r
+                       } else { \r
+                               DoubleBinding b = (DoubleBinding) getComponentBinding(index);\r
+                               setComponent(r, index, b.create(x));\r
+                       }\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+       \r
+       public double getDouble(Object r, int index) throws BindingException\r
+       {\r
+               try {\r
+                       Field f = ci.fields[index];\r
+                       Class<?> cl = f==null?null:f.getType();\r
+                       if ( cl==double.class || cl==Double.class ) return f.getDouble(r);\r
+                       Object o = getComponent(r, index);\r
+                       DoubleBinding b = (DoubleBinding) getComponentBinding(index); \r
+                       return b.getValue_(o);\r
+               } catch (IllegalArgumentException e) {\r
+                       throw new BindingException(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new BindingException(e);\r
+               }\r
+       }\r
+\r
+}
+