]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/DefaultAdapter.java
Improved Bindings.getBinding(Class) caching for Datatype.class
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / adapter / DefaultAdapter.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
4  *  All rights reserved. This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License v1.0
6  *  which accompanies this distribution, and is available at
7  *  http://www.eclipse.org/legal/epl-v10.html
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.adapter;
13
14 import java.util.ArrayList;
15
16 import org.simantics.databoard.binding.ArrayBinding;
17 import org.simantics.databoard.binding.Binding;
18 import org.simantics.databoard.binding.BooleanBinding;
19 import org.simantics.databoard.binding.ByteBinding;
20 import org.simantics.databoard.binding.DoubleBinding;
21 import org.simantics.databoard.binding.FloatBinding;
22 import org.simantics.databoard.binding.IntegerBinding;
23 import org.simantics.databoard.binding.LongBinding;
24 import org.simantics.databoard.binding.OptionalBinding;
25 import org.simantics.databoard.binding.RecordBinding;
26 import org.simantics.databoard.binding.StringBinding;
27 import org.simantics.databoard.binding.UnionBinding;
28 import org.simantics.databoard.binding.error.BindingException;
29 import org.simantics.databoard.binding.impl.ArrayListBinding;
30 import org.simantics.databoard.binding.impl.BooleanArrayBinding;
31 import org.simantics.databoard.binding.impl.ByteArrayBinding;
32 import org.simantics.databoard.binding.impl.DoubleArrayBinding;
33 import org.simantics.databoard.binding.impl.FloatArrayBinding;
34 import org.simantics.databoard.binding.impl.IntArrayBinding;
35 import org.simantics.databoard.binding.impl.LongArrayBinding;
36
37 /**
38  * DefaultAdapter adapts anything to anything.
39  * 
40  * @deprecated Use {@link AdapterFactory} instead (more efficient)
41  */
42 public class DefaultAdapter implements Adapter {
43
44         Binding domain;
45         Binding range;
46         
47         DefaultAdapter(Binding domain, Binding range) {
48                 this.domain = domain;
49                 this.range = range;
50         }
51         
52     /**
53      * Adapt instance of one binding to format of another binding.
54      * The datatype of the two bindings must be structurally equal. 
55      * 
56      * @param src source instance
57      * @return result
58      * @throws AdaptException 
59      */
60     public static Object adapt(Object src, Binding domain, Binding range)
61     throws AdaptException
62     {
63         try {
64                 if (domain instanceof RecordBinding && range instanceof RecordBinding)
65                 {
66                         RecordBinding srcRec = (RecordBinding) domain;
67                         RecordBinding dstRec = (RecordBinding) range;
68                         Object dst = dstRec.createPartial();
69                         Object[] dstComponents = new Object[dstRec.componentBindings.length];
70                         for (int i=0; i<srcRec.componentBindings.length; i++)
71                         {
72                                 Binding cdomain = srcRec.componentBindings[i];
73                                 Binding crange = dstRec.componentBindings[i];
74                                 Object srcComponent = srcRec.getComponent(src, i);
75                                 Object dstComponent = adapt(srcComponent, cdomain, crange);
76                                 dstComponents[i] = dstComponent;
77                         }
78                                 dstRec.setComponents(dst, dstComponents);
79                                 return dst;
80                 }
81                 
82                 if (domain instanceof UnionBinding && range instanceof UnionBinding)
83                 {
84                         UnionBinding srcUni = (UnionBinding) domain;
85                         UnionBinding dstUni = (UnionBinding) range;
86                         int tag = srcUni.getTag(src);
87                                 Binding cdomain = srcUni.getComponentBindings()[tag];
88                                 Binding crange = dstUni.getComponentBindings()[tag];
89                                 Object srcComponent = srcUni.getValue(src);
90                                 Object dstComponent = adapt(srcComponent, cdomain, crange);
91                                 Object dst = dstUni.create(tag, dstComponent);
92                                 return dst;
93                 }
94                 
95                 if (domain instanceof BooleanBinding && range instanceof BooleanBinding)
96                 {
97                         BooleanBinding srcBoo = (BooleanBinding) domain;
98                         BooleanBinding dstBoo = (BooleanBinding) range;
99                         boolean srcBoolean = srcBoo.getValue_(src);
100                         Object dst = dstBoo.create(srcBoolean);
101                         return dst;
102                 }               
103                 
104                 if (domain instanceof StringBinding && range instanceof StringBinding)
105                 {
106                         StringBinding srcStr = (StringBinding) domain;
107                         StringBinding dstStr = (StringBinding) range;
108                         String srcString = srcStr.getValue(src);
109                         Object dst = dstStr.create(srcString);
110                         return dst;
111                 }               
112         
113                 if (domain instanceof ByteBinding && range instanceof ByteBinding)
114                 {
115                         ByteBinding srcNum = (ByteBinding) domain;
116                         ByteBinding dstNum = (ByteBinding) range;
117                         byte srcNumber = srcNum.getValue_(src);
118                         Object dst = dstNum.create(srcNumber);
119                         return dst;
120                 }       
121                 
122                 if (domain instanceof IntegerBinding && range instanceof IntegerBinding)
123                 {
124                         IntegerBinding srcNum = (IntegerBinding) domain;
125                         IntegerBinding dstNum = (IntegerBinding) range;
126                         int srcNumber = srcNum.getValue_(src);
127                         Object dst = dstNum.create(srcNumber);
128                         return dst;
129                 }
130                 
131                 if (domain instanceof LongBinding && range instanceof LongBinding)
132                 {
133                         LongBinding srcNum = (LongBinding) domain;
134                         LongBinding dstNum = (LongBinding) range;
135                         long srcNumber = srcNum.getValue_(src);
136                         Object dst = dstNum.create(srcNumber);
137                         return dst;
138                 }
139                 
140                 if (domain instanceof FloatBinding && range instanceof FloatBinding)
141                 {
142                         FloatBinding srcNum = (FloatBinding) domain;
143                         FloatBinding dstNum = (FloatBinding) range;
144                         float srcNumber = srcNum.getValue_(src);
145                         Object dst = dstNum.create(srcNumber);
146                         return dst;
147                 }
148                 
149                 if (domain instanceof DoubleBinding && range instanceof DoubleBinding)
150                 {
151                         DoubleBinding srcNum = (DoubleBinding) domain;
152                         DoubleBinding dstNum = (DoubleBinding) range;
153                         double srcNumber = srcNum.getValue_(src);
154                         Object dst = dstNum.create(srcNumber);
155                         return dst;
156                 }               
157                         
158                 if (domain instanceof ByteArrayBinding && range instanceof ByteArrayBinding)
159                 {
160                         ByteArrayBinding srcArr = (ByteArrayBinding) domain;
161                         ByteArrayBinding dstArr = (ByteArrayBinding) range;                     
162                         return dstArr.create( srcArr.getArray(src) );
163                 }       
164                 if (domain instanceof BooleanArrayBinding && range instanceof BooleanArrayBinding)
165                 {
166                         BooleanArrayBinding srcArr = (BooleanArrayBinding) domain;
167                         BooleanArrayBinding dstArr = (BooleanArrayBinding) range;                       
168                         return dstArr.create( srcArr.getArray(src) );
169                 }       
170                 if (domain instanceof IntArrayBinding && range instanceof IntArrayBinding)
171                 {
172                         IntArrayBinding srcArr = (IntArrayBinding) domain;
173                         IntArrayBinding dstArr = (IntArrayBinding) range;                       
174                         return dstArr.create( srcArr.getArray(src) );
175                 }       
176                 if (domain instanceof LongArrayBinding && range instanceof LongArrayBinding)
177                 {
178                         LongArrayBinding srcArr = (LongArrayBinding) domain;
179                         LongArrayBinding dstArr = (LongArrayBinding) range;                     
180                         return dstArr.create( srcArr.getArray(src) );
181                 }       
182                 if (domain instanceof FloatArrayBinding && range instanceof FloatArrayBinding)
183                 {
184                         FloatArrayBinding srcArr = (FloatArrayBinding) domain;
185                         FloatArrayBinding dstArr = (FloatArrayBinding) range;                   
186                         return dstArr.create( srcArr.getArray(src) );
187                 }       
188                 if (domain instanceof DoubleArrayBinding && range instanceof DoubleArrayBinding)
189                 {
190                         DoubleArrayBinding srcArr = (DoubleArrayBinding) domain;
191                         DoubleArrayBinding dstArr = (DoubleArrayBinding) range;                 
192                         return dstArr.create( srcArr.getArray(src) );
193                 }       
194                 
195                 if (domain instanceof ArrayBinding && range instanceof ArrayBinding)
196                 {
197                         ArrayBinding srcArr = (ArrayBinding) domain;
198                         ArrayBinding dstArr = (ArrayBinding) range;             
199                         int length = srcArr.size(src);
200                         Binding cdomain = srcArr.getComponentBinding();
201                         Binding crange = dstArr.getComponentBinding();
202                         ArrayList<Object> dstArray = new ArrayList<Object>(length);
203                         for (int i=0; i<length; i++)
204                         {
205                                 Object srcComponent = srcArr.get(src, i);
206                                 Object dstComponent = adapt(srcComponent, cdomain, crange);
207                                 dstArray.add(dstComponent);
208                         }
209                         Object dst = dstArr instanceof ArrayListBinding ? dstArray : dstArr.create(dstArray);
210                         return dst;
211                 }
212                 
213                 if (domain instanceof OptionalBinding && range instanceof OptionalBinding)
214                 {
215                         OptionalBinding domainOptional = (OptionalBinding) domain;
216                         OptionalBinding rangeOptional = (OptionalBinding) range;
217                         Binding domainComponentBinding = domainOptional.getComponentBinding();
218                         Binding rangeComponentBinding = rangeOptional.getComponentBinding();
219                         Object value = src;
220                         
221                         if (!domainOptional.hasValue(value)) return rangeOptional.createNoValue();
222                         
223                         value = domainOptional.getValue(value);
224                         value = adapt(value, domainComponentBinding, rangeComponentBinding);
225                         value = rangeOptional.createValue(value);
226                         return value;
227                 }
228         } catch (BindingException e) {
229                 throw new AdaptException(e);
230         }
231
232         
233         throw new AdaptException("Source binding "+domain.getClass().getName()+" and destination binding "+range.getClass().getName()+" are not compatible.");
234     }
235
236         
237     /**
238      * Adapt instance of one binding to format of another binding.
239      * The datatype of the two bindings must be structurally equal. 
240      * 
241      * @param obj source instance
242      * @return result
243      * @throws AdaptException 
244      */
245     @Override
246         public Object adapt(Object obj) throws AdaptException {
247                 return adapt(obj, domain, range);
248         }
249     
250     @Override
251     public Object adaptUnchecked(Object obj) throws RuntimeAdaptException {
252                 try {
253                         return adapt(obj, domain, range);
254                 } catch (AdaptException e) {
255                         if (e.getCause() != null) throw new RuntimeAdaptException( e );
256                         throw new RuntimeAdaptException( e ); 
257                 }
258     }
259
260         public Binding getDomain() {
261                 return domain;
262         }
263         
264         public Binding getRange() {
265                 return range;
266         }
267         @Override
268         public int hashCode() {
269         return domain.hashCode() + 31*range.hashCode();
270         }
271         
272         @Override
273         public boolean equals(Object obj) {
274         if (obj == null) return false;
275         if (!(obj.getClass().equals(this.getClass()))) return false;
276         DefaultAdapter other = (DefaultAdapter) obj;
277         return objectEquals(other.domain, domain) && objectEquals(other.range, range);
278         }
279         
280     private static boolean objectEquals(Object o1, Object o2) {
281         if (o1==o2) return true;
282         if (o1==null && o2==null) return true;
283         if (o1==null || o2==null) return false;
284         return o1.equals(o2);
285     }
286         
287 }
288