]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\r
4  *  All rights reserved. This program and the accompanying materials\r
5  *  are made available under the terms of the Eclipse Public License v1.0\r
6  *  which accompanies this distribution, and is available at\r
7  *  http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.binding.reflection;
13
14 import org.simantics.databoard.Bindings;\r
15 import org.simantics.databoard.adapter.AdaptException;\r
16 import org.simantics.databoard.binding.Binding;\r
17 import org.simantics.databoard.binding.UnionBinding;\r
18 import org.simantics.databoard.binding.error.BindingConstructionException;\r
19 import org.simantics.databoard.binding.error.BindingException;\r
20 import org.simantics.databoard.serialization.Serializer;\r
21 import org.simantics.databoard.serialization.SpecializedSerializerProvider;\r
22 import org.simantics.databoard.type.UnionType;\r
23
24 /**\r
25  * Bindings an abstract class with @Union annotation to a DataBoard's UnionType.
26  * \r
27  * Example of usage:\r
28  *  @Union({Rectangle.class, Circle.class, Triangle.class}) class Shape {}\r
29  *      \r
30  *  class Rectangle extends Shape { public int width, height; }\r
31  *  class Circle extends Shape { public int radius; }           \r
32  *  class Triangle extends Shape { public int sideLength; }             \r
33  *
34  * @author Toni Kalajainen
35  */
36 class UnionClassBinding extends UnionBinding implements SpecializedSerializerProvider {
37
38         Class<?>[] componentClasses;\r
39         Serializer specializedSerializer;\r
40         
41         public UnionClassBinding(UnionType type) 
42         throws BindingConstructionException {
43                 this.type = type;\r
44         }\r
45         \r
46         @Override
47         public Object create(int tag, Object value) {
48                 return value;
49         }
50
51     @Override
52     public void setValue(Object union, int tag, Object value)
53         throws BindingException {\r
54         if (tag != getTag(union)) throw new BindingException("Cannot change the class of an instance");\r
55         Binding cb = getComponentBinding(tag);\r
56         cb.readFrom(cb, value, union);
57     }\r
58         
59         @Override
60         public int getTag(Object obj) throws BindingException {
61                 for (int i=0; i<componentClasses.length; i++)
62                         if (componentClasses[i].isInstance(obj)) return i;\r
63                 throw new BindingException(obj.getClass().getSimpleName()+" is not a known component class");\r
64         }
65         @Override
66         public Object getValue(Object obj) {
67                 return obj;
68         }
69         @Override
70         public boolean isInstance(Object obj) {
71                 for (Class<?> c : componentClasses) 
72                         if (c.isInstance(obj)) return true;                                     
73                 return false;
74         }\r
75 \r
76     @Override\r
77     public Serializer getSpecializedSerializer() {\r
78         return specializedSerializer;\r
79     }
80 \r
81 \r
82         transient Boolean isImmutable;\r
83         \r
84         @Override\r
85         public synchronized boolean isImmutable() {\r
86                 if ( isImmutable == null ) {\r
87                         boolean b = true;\r
88                         for ( Binding cb : getComponentBindings() ) {\r
89                                 b &= cb.isImmutable();\r
90                                 if (!b) break;\r
91                         }\r
92                         isImmutable = b;\r
93                 }\r
94                 return isImmutable;\r
95         }\r
96 \r
97         @Override\r
98     public Object readFromTry(Binding srcBinding, Object src, Object dst) throws BindingException\r
99     {\r
100                 UnionBinding sb = (UnionBinding) srcBinding;\r
101                 int st = sb.getTag(src);\r
102                 int dt = getTag(dst);\r
103                 Binding scb = sb.getComponentBinding(st);\r
104                 Object sv = sb.getValue(src);\r
105                 \r
106                 \r
107                 if (st==dt) {\r
108                         // Same Tag\r
109                         Object dv = getValue(dst);\r
110                         Binding dcb = getComponentBinding(dt);\r
111                         dcb.readFrom(scb, sv, dv);\r
112                         return dv;\r
113                 } else {\r
114                         // Different Tag -> return cloned or (same, if immutable) value\r
115                         try {\r
116                                 Binding dcb = getComponentBinding(st);\r
117                                 return Bindings.adapt(src, scb, dcb);\r
118                         } catch(AdaptException e) {\r
119                                 throw new BindingException(e);\r
120                         }\r
121                 }\r
122                 \r
123         }       \r
124         \r
125         /**\r
126          * Returns true if the tag of this union type can be modified\r
127          *  \r
128          * @return\r
129          */\r
130         public boolean isTagMutable() {\r
131                 return true;\r
132         }\r
133  \r
134         @Override\r
135         protected boolean baseEquals(Object obj) {\r
136                 if (!super.baseEquals(obj)) return false;       \r
137 \r
138                 UnionClassBinding o = (UnionClassBinding)obj;\r
139                 if (isImmutable != o.isImmutable) return false;\r
140                 if (specializedSerializer != o.specializedSerializer) return false;\r
141                 if (componentClasses.length != o.componentClasses.length) return false;\r
142                 \r
143                 for (int i = 0; i < componentClasses.length; i++) {\r
144                         if (!componentClasses[i].equals(o.componentClasses[i]))\r
145                                 return false;\r
146                 }\r
147                 \r
148                 return true;\r
149         }\r
150         \r
151         @Override\r
152         public int baseHashCode() {\r
153                 int code = super.baseHashCode();\r
154                 for (int i = 0; i < componentClasses.length; i++)\r
155                         code = 23 * code + componentClasses.hashCode();\r
156                 \r
157                 return code;\r
158         }
159 }\r