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 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
25 * Bindings an abstract class with @Union annotation to a DataBoard's UnionType.
28 * @Union({Rectangle.class, Circle.class, Triangle.class}) class Shape {}
\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
34 * @author Toni Kalajainen
36 class UnionClassBinding extends UnionBinding implements SpecializedSerializerProvider {
38 Class<?>[] componentClasses;
\r
39 Serializer specializedSerializer;
\r
41 public UnionClassBinding(UnionType type)
42 throws BindingConstructionException {
47 public Object create(int tag, Object value) {
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);
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
66 public Object getValue(Object obj) {
70 public boolean isInstance(Object obj) {
71 for (Class<?> c : componentClasses)
72 if (c.isInstance(obj)) return true;
77 public Serializer getSpecializedSerializer() {
\r
78 return specializedSerializer;
\r
82 transient Boolean isImmutable;
\r
85 public synchronized boolean isImmutable() {
\r
86 if ( isImmutable == null ) {
\r
88 for ( Binding cb : getComponentBindings() ) {
\r
89 b &= cb.isImmutable();
\r
98 public Object readFromTry(Binding srcBinding, Object src, Object dst) throws BindingException
\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
109 Object dv = getValue(dst);
\r
110 Binding dcb = getComponentBinding(dt);
\r
111 dcb.readFrom(scb, sv, dv);
\r
114 // Different Tag -> return cloned or (same, if immutable) value
\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
126 * Returns true if the tag of this union type can be modified
\r
130 public boolean isTagMutable() {
\r
135 protected boolean baseEquals(Object obj) {
\r
136 if (!super.baseEquals(obj)) return false;
\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
143 for (int i = 0; i < componentClasses.length; i++) {
\r
144 if (!componentClasses[i].equals(o.componentClasses[i]))
\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