]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/UnionClassBinding.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / reflection / UnionClassBinding.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/UnionClassBinding.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/UnionClassBinding.java
new file mode 100644 (file)
index 0000000..1628542
--- /dev/null
@@ -0,0 +1,159 @@
+/*******************************************************************************\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 org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.UnionBinding;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.serialization.SpecializedSerializerProvider;\r
+import org.simantics.databoard.type.UnionType;\r
+
+/**\r
+ * Bindings an abstract class with @Union annotation to a DataBoard's UnionType.
+ * \r
+ * Example of usage:\r
+ *  @Union({Rectangle.class, Circle.class, Triangle.class}) class Shape {}\r
+ *     \r
+ *  class Rectangle extends Shape { public int width, height; }\r
+ *  class Circle extends Shape { public int radius; }          \r
+ *  class Triangle extends Shape { public int sideLength; }            \r
+ *
+ * @author Toni Kalajainen
+ */
+class UnionClassBinding extends UnionBinding implements SpecializedSerializerProvider {
+
+       Class<?>[] componentClasses;\r
+       Serializer specializedSerializer;\r
+       
+       public UnionClassBinding(UnionType type) 
+       throws BindingConstructionException {
+               this.type = type;\r
+       }\r
+       \r
+       @Override
+       public Object create(int tag, Object value) {
+               return value;
+       }
+
+    @Override
+    public void setValue(Object union, int tag, Object value)
+       throws BindingException {\r
+       if (tag != getTag(union)) throw new BindingException("Cannot change the class of an instance");\r
+       Binding cb = getComponentBinding(tag);\r
+       cb.readFrom(cb, value, union);
+    }\r
+       
+       @Override
+       public int getTag(Object obj) throws BindingException {
+               for (int i=0; i<componentClasses.length; i++)
+                       if (componentClasses[i].isInstance(obj)) return i;\r
+               throw new BindingException(obj.getClass().getSimpleName()+" is not a known component class");\r
+       }
+       @Override
+       public Object getValue(Object obj) {
+               return obj;
+       }
+       @Override
+       public boolean isInstance(Object obj) {
+               for (Class<?> c : componentClasses) 
+                       if (c.isInstance(obj)) return true;                                     
+               return false;
+       }\r
+\r
+    @Override\r
+    public Serializer getSpecializedSerializer() {\r
+        return specializedSerializer;\r
+    }
+\r
+\r
+       transient Boolean isImmutable;\r
+       \r
+       @Override\r
+       public synchronized boolean isImmutable() {\r
+               if ( isImmutable == null ) {\r
+                       boolean b = true;\r
+                       for ( Binding cb : getComponentBindings() ) {\r
+                               b &= cb.isImmutable();\r
+                               if (!b) break;\r
+                       }\r
+                       isImmutable = b;\r
+               }\r
+               return isImmutable;\r
+       }\r
+\r
+       @Override\r
+    public Object readFromTry(Binding srcBinding, Object src, Object dst) throws BindingException\r
+    {\r
+               UnionBinding sb = (UnionBinding) srcBinding;\r
+               int st = sb.getTag(src);\r
+               int dt = getTag(dst);\r
+               Binding scb = sb.getComponentBinding(st);\r
+               Object sv = sb.getValue(src);\r
+               \r
+               \r
+               if (st==dt) {\r
+                       // Same Tag\r
+                       Object dv = getValue(dst);\r
+                       Binding dcb = getComponentBinding(dt);\r
+                       dcb.readFrom(scb, sv, dv);\r
+                       return dv;\r
+               } else {\r
+                       // Different Tag -> return cloned or (same, if immutable) value\r
+                       try {\r
+                               Binding dcb = getComponentBinding(st);\r
+                               return Bindings.adapt(src, scb, dcb);\r
+                       } catch(AdaptException e) {\r
+                               throw new BindingException(e);\r
+                       }\r
+               }\r
+               \r
+       }       \r
+       \r
+       /**\r
+        * Returns true if the tag of this union type can be modified\r
+        *  \r
+        * @return\r
+        */\r
+       public boolean isTagMutable() {\r
+               return true;\r
+       }\r
\r
+       @Override\r
+       protected boolean baseEquals(Object obj) {\r
+               if (!super.baseEquals(obj)) return false;       \r
+\r
+               UnionClassBinding o = (UnionClassBinding)obj;\r
+               if (isImmutable != o.isImmutable) return false;\r
+               if (specializedSerializer != o.specializedSerializer) return false;\r
+               if (componentClasses.length != o.componentClasses.length) return false;\r
+               \r
+               for (int i = 0; i < componentClasses.length; i++) {\r
+                       if (!componentClasses[i].equals(o.componentClasses[i]))\r
+                               return false;\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       @Override\r
+       public int baseHashCode() {\r
+               int code = super.baseHashCode();\r
+               for (int i = 0; i < componentClasses.length; i++)\r
+                       code = 23 * code + componentClasses.hashCode();\r
+               \r
+               return code;\r
+       }
+}\r