1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.databoard.binding.reflection;
14 import java.lang.reflect.Field;
\r
15 import java.lang.reflect.InvocationTargetException;
\r
16 import java.lang.reflect.Method;
\r
17 import java.lang.reflect.Modifier;
\r
18 import java.lang.reflect.Type;
\r
20 import org.simantics.databoard.binding.Binding;
\r
21 import org.simantics.databoard.binding.BooleanBinding;
\r
22 import org.simantics.databoard.binding.ByteBinding;
\r
23 import org.simantics.databoard.binding.DoubleBinding;
\r
24 import org.simantics.databoard.binding.FloatBinding;
\r
25 import org.simantics.databoard.binding.IntegerBinding;
\r
26 import org.simantics.databoard.binding.LongBinding;
\r
27 import org.simantics.databoard.binding.error.BindingConstructionException;
\r
28 import org.simantics.databoard.binding.error.BindingException;
\r
29 import org.simantics.databoard.type.RecordType;
\r
32 * ReflectionRecordBinding binding of a Record Type and Java Class.
33 * If binds Record Values to Java Objects. <p>
36 * There are three types of classes supported:
37 * 1) record-like class
38 * - All fields are public
39 * - No-argument public constructor
41 * 2) immutable-like class
42 * - All fields are set in constructor
45 * - All fields are set with getter/setter
47 class RecordClassBinding extends ClassBinding {
49 private static final Object[] NO_ARGS = new Object[0];
\r
52 * Create a Reflection Record Bindings.
54 * There is a 2-phase construction.
58 * @throws BindingConstructionException
60 public RecordClassBinding(ClassInfo ci, RecordType type)
63 if ( ci == null ) throw new IllegalArgumentException("null ClassInfo");
\r
65 componentBindings = new Binding[ ci.fields.length ];
\r
69 public Object createPartial() throws BindingException {
71 if (ci.noArgsConstructor!=null)
72 return ci.noArgsConstructor.newInstance();
73 else if (ci.argsConstructor!=null) {
\r
75 // Create default values
\r
76 Object values[] = new Object[ci.fields.length];
\r
77 for (int i=0; i<values.length; i++) {
\r
78 Binding fb = componentBindings[i];
\r
79 values[i] = fb.createDefault();
\r
81 return ci.argsConstructor.newInstance((Object[])values);
82 // return clazz.newInstance();
\r
83 } else throw new BindingException("Class "+ci.clazz.getName()+" doesn't support construction. No no-args or args(fields) constructor.");
84 } catch (InstantiationException e) {
85 throw new BindingException(e);
86 } catch (IllegalAccessException e) {
87 throw new BindingException(e);
88 } catch (IllegalArgumentException e) {
89 throw new BindingException(e);
90 } catch (InvocationTargetException e) {
91 throw new BindingException(e);
96 public Object create(Object... values)
97 throws BindingException {
100 if (ci.argsConstructor != null)
103 return ci.argsConstructor.newInstance(values);
104 } catch (IllegalArgumentException e) {
105 throw new BindingException(e);
106 } catch (InstantiationException e) {
107 throw new BindingException(e);
108 } catch (IllegalAccessException e) {
109 throw new BindingException(e);
110 } catch (InvocationTargetException e) {
111 throw new BindingException(e);
117 Object result = null;
118 if (ci.noArgsConstructor!=null)
119 result = ci.noArgsConstructor.newInstance();
121 result = ci.clazz.newInstance();
122 // Object result = clazz.newInstance();
123 for (int i=0; i<ci.fields.length; i++) {
124 Object value = values[i];
125 Field f = ci.fields[i];
126 Class<?> type = f.getType();
128 Method setter = ci.setters[i];
132 setter.invoke(result, (Integer)value);
133 else if (type==long.class)
134 setter.invoke(result, (Long)value);
135 else if (type==float.class)
136 setter.invoke(result, (Float)value);
137 else if (type==double.class)
138 setter.invoke(result, (Double)value);
139 else if (type==boolean.class)
140 setter.invoke(result, (Boolean)value);
141 else setter.invoke(result, value);
146 f.setInt(result, (Integer)value);
147 else if (type==long.class)
148 f.setLong(result, (Long)value);
149 else if (type==float.class)
150 f.setFloat(result, (Float)value);
151 else if (type==double.class)
152 f.setDouble(result, (Double)value);
153 else if (type==boolean.class)
154 f.setBoolean(result, (Boolean)value);
155 else f.set(result, value);
160 } catch (InstantiationException e) {
\r
161 boolean isPublic = (ci.clazz.getModifiers() & Modifier.PUBLIC)!=0;
\r
162 if (!isPublic) throw new BindingException("Failed to instantiate "+ci.clazz.getName()+", maybe it should be public class.");
163 throw new BindingException("Failed to instantiate "+ci.clazz.getName());
164 } catch (IllegalAccessException e) {
165 throw new BindingException(e);
166 } catch (IllegalArgumentException e) {
167 throw new BindingException(e);
168 } catch (InvocationTargetException e) {
169 throw new BindingException(e);
174 public Object getComponent(Object obj, int index) throws BindingException {
176 Field getter = fields[index];
179 return getter.get(obj);
180 } catch (IllegalArgumentException e) {
181 throw new BindingException(e);
182 } catch (IllegalAccessException e) {
183 throw new BindingException(e);
188 Field f = ci.fields[index];
189 Class<?> type = f.getType();
190 if (type.isPrimitive()) {
191 if (type==int.class) return (Integer) f.getInt(obj);
192 else if (type==byte.class) return (Byte) f.getByte(obj);
193 else if (type==boolean.class) return (Boolean) f.getBoolean(obj);
194 else if (type==float.class) return (Float) f.getFloat(obj);
195 else if (type==double.class) return (Double) f.getDouble(obj);
196 else if (type==long.class) return (Long) f.getLong(obj);
200 } catch (IllegalArgumentException e) {
201 throw new BindingException(e);
202 } catch (IllegalAccessException e) {
203 Field getter = ci.fields[index];
206 return getter.get(obj);
207 } catch (IllegalArgumentException e2) {
208 } catch (IllegalAccessException e2) {
211 throw new BindingException(e);
216 public boolean isInstance(Object obj) {
217 return ci.clazz.isInstance(obj);
221 public boolean isImmutable() {
\r
225 public Class<?> getComponentClass(int index) {
226 return ci.fields[index].getDeclaringClass();
230 public void setComponent(Object obj, int index, Object value) throws BindingException {
232 Method setter = ci.setters[index];
234 setter.invoke(obj, value);
236 Field f = ci.fields[index];
237 Class<?> type = f.getType();
238 if (type.isPrimitive()) {
239 if (type==int.class) f.setInt(obj, (Integer) value);
240 else if (type==byte.class) f.setByte(obj, (Byte) value);
241 else if (type==boolean.class) f.setBoolean(obj, (Boolean) value);
242 else if (type==float.class) f.setFloat(obj, (Float) value);
243 else if (type==double.class) f.setDouble(obj, (Double) value);
244 else if (type==long.class) f.setLong(obj, (Long) value);
245 else f.set(obj, value);
250 } catch (IllegalAccessException e) {
251 throw new BindingException(e);
252 } catch (IllegalArgumentException e) {
253 throw new BindingException(e);
254 } catch (InvocationTargetException e) {
256 throw new BindingException(e);
260 public void setComponents(Object obj, Object... value) throws BindingException {
262 for(int i = 0;i<ci.fields.length;++i) {
263 Method setter = ci.setters[i];
265 setter.invoke(obj, value[i]);
267 Field f = ci.fields[i];
268 Class<?> type = f.getType();
269 if (type.isPrimitive()) {
270 if (type==int.class) f.setInt(obj, (Integer) value[i]);
271 else if (type==byte.class) f.setByte(obj, (Byte) value[i]);
272 else if (type==boolean.class) f.setBoolean(obj, (Boolean) value[i]);
273 else if (type==float.class) f.setFloat(obj, (Float) value[i]);
274 else if (type==double.class) f.setDouble(obj, (Double) value[i]);
275 else if (type==long.class) f.setLong(obj, (Long) value[i]);
276 else f.set(obj, value[i]);
278 f.set(obj, value[i]);
282 } catch (IllegalAccessException e) {
283 throw new BindingException(e);
284 } catch (IllegalArgumentException e) {
285 throw new BindingException(e);
286 } catch (InvocationTargetException e) {
287 throw new BindingException(e);
\r
291 public void setBoolean(Object r, int index, boolean z) throws BindingException
\r
294 Field f = ci.fields[index];
\r
295 Class<?> cl = f.getType();
\r
296 if ( cl==boolean.class || cl==Boolean.class ) {
\r
297 f.setBoolean(r, z);
\r
299 BooleanBinding b = (BooleanBinding) getComponentBinding(index);
\r
300 setComponent(r, index, b.create(z));
\r
302 } catch (IllegalArgumentException e) {
\r
303 throw new BindingException(e);
\r
304 } catch (IllegalAccessException e) {
\r
305 throw new BindingException(e);
\r
309 public boolean getBoolean(Object r, int index) throws BindingException
\r
312 Field f = ci.fields[index];
\r
313 Class<?> cl = f==null?null:f.getType();
\r
314 if ( cl==boolean.class || cl==Boolean.class ) return f.getBoolean(r);
\r
315 Object o = getComponent(r, index);
\r
316 BooleanBinding b = (BooleanBinding) getComponentBinding(index);
\r
317 return b.getValue_(o);
\r
318 } catch (IllegalArgumentException e) {
\r
319 throw new BindingException(e);
\r
320 } catch (IllegalAccessException e) {
\r
321 throw new BindingException(e);
\r
325 public void setByte(Object r, int index, byte x) throws BindingException
\r
328 Field f = ci.fields[index];
\r
329 Class<?> cl = f.getType();
\r
330 if ( cl==byte.class || cl==Byte.class ) {
\r
333 ByteBinding b = (ByteBinding) getComponentBinding(index);
\r
334 setComponent(r, index, b.create(x));
\r
336 } catch (IllegalArgumentException e) {
\r
337 throw new BindingException(e);
\r
338 } catch (IllegalAccessException e) {
\r
339 throw new BindingException(e);
\r
343 public byte getByte(Object r, int index) throws BindingException
\r
346 Field f = ci.fields[index];
\r
347 Class<?> cl = f==null?null:f.getType();
\r
348 if ( cl==byte.class || cl==Byte.class ) return f.getByte(r);
\r
349 Object o = getComponent(r, index);
\r
350 ByteBinding b = (ByteBinding) getComponentBinding(index);
\r
351 return b.getValue_(o);
\r
352 } catch (IllegalArgumentException e) {
\r
353 throw new BindingException(e);
\r
354 } catch (IllegalAccessException e) {
\r
355 throw new BindingException(e);
\r
359 public void setInt(Object r, int index, int x) throws BindingException
\r
362 Field f = ci.fields[index];
\r
363 Class<?> cl = f.getType();
\r
364 if ( cl==int.class || cl==Integer.class ) {
\r
367 IntegerBinding b = (IntegerBinding) getComponentBinding(index);
\r
368 setComponent(r, index, b.create(x));
\r
370 } catch (IllegalArgumentException e) {
\r
371 throw new BindingException(e);
\r
372 } catch (IllegalAccessException e) {
\r
373 throw new BindingException(e);
\r
377 public int getInt(Object r, int index) throws BindingException
\r
380 Field f = ci.fields[index];
\r
381 Class<?> cl = f==null?null:f.getType();
\r
382 if ( cl==int.class || cl==Integer.class ) return f.getInt(r);
\r
383 Object o = getComponent(r, index);
\r
384 IntegerBinding b = (IntegerBinding) getComponentBinding(index);
\r
385 return b.getValue_(o);
\r
386 } catch (IllegalArgumentException e) {
\r
387 throw new BindingException(e);
\r
388 } catch (IllegalAccessException e) {
\r
389 throw new BindingException(e);
\r
393 public void setLong(Object r, int index, long x) throws BindingException
\r
396 Field f = ci.fields[index];
\r
397 Class<?> cl = f.getType();
\r
398 if ( cl==long.class || cl==Long.class ) {
\r
401 LongBinding b = (LongBinding) getComponentBinding(index);
\r
402 setComponent(r, index, b.create(x));
\r
404 } catch (IllegalArgumentException e) {
\r
405 throw new BindingException(e);
\r
406 } catch (IllegalAccessException e) {
\r
407 throw new BindingException(e);
\r
411 public long getLong(Object r, int index) throws BindingException
\r
414 Field f = ci.fields[index];
\r
415 Class<?> cl = f==null?null:f.getType();
\r
416 if ( cl==long.class || cl==Long.class ) return f.getLong(r);
\r
417 Object o = getComponent(r, index);
\r
418 LongBinding b = (LongBinding) getComponentBinding(index);
\r
419 return b.getValue_(o);
\r
420 } catch (IllegalArgumentException e) {
\r
421 throw new BindingException(e);
\r
422 } catch (IllegalAccessException e) {
\r
423 throw new BindingException(e);
\r
427 public void setFloat(Object r, int index, float x) throws BindingException
\r
430 Field f = ci.fields[index];
\r
431 Class<?> cl = f.getType();
\r
432 if ( cl==float.class || cl==Float.class ) {
\r
435 FloatBinding b = (FloatBinding) getComponentBinding(index);
\r
436 setComponent(r, index, b.create(x));
\r
438 } catch (IllegalArgumentException e) {
\r
439 throw new BindingException(e);
\r
440 } catch (IllegalAccessException e) {
\r
441 throw new BindingException(e);
\r
445 public float getFloat(Object r, int index) throws BindingException
\r
448 Field f = ci.fields[index];
\r
449 Class<?> cl = f==null?null:f.getType();
\r
450 if ( cl==float.class || cl==Float.class ) return f.getFloat(r);
\r
451 Object o = getComponent(r, index);
\r
452 FloatBinding b = (FloatBinding) getComponentBinding(index);
\r
453 return b.getValue_(o);
\r
454 } catch (IllegalArgumentException e) {
\r
455 throw new BindingException(e);
\r
456 } catch (IllegalAccessException e) {
\r
457 throw new BindingException(e);
\r
461 public void setDouble(Object r, int index, double x) throws BindingException
\r
464 Field f = ci.fields[index];
\r
465 Class<?> cl = f.getType();
\r
466 if ( cl==double.class || cl==Double.class ) {
\r
467 f.setDouble(r, x);
\r
469 DoubleBinding b = (DoubleBinding) getComponentBinding(index);
\r
470 setComponent(r, index, b.create(x));
\r
472 } catch (IllegalArgumentException e) {
\r
473 throw new BindingException(e);
\r
474 } catch (IllegalAccessException e) {
\r
475 throw new BindingException(e);
\r
479 public double getDouble(Object r, int index) throws BindingException
\r
482 Field f = ci.fields[index];
\r
483 Class<?> cl = f==null?null:f.getType();
\r
484 if ( cl==double.class || cl==Double.class ) return f.getDouble(r);
\r
485 Object o = getComponent(r, index);
\r
486 DoubleBinding b = (DoubleBinding) getComponentBinding(index);
\r
487 return b.getValue_(o);
\r
488 } catch (IllegalArgumentException e) {
\r
489 throw new BindingException(e);
\r
490 } catch (IllegalAccessException e) {
\r
491 throw new BindingException(e);
\r