]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/OptionalBinding.java
Use type reflection tools from databoard in objmap2.
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / OptionalBinding.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.binding;
13
14 import java.util.IdentityHashMap;
15 import java.util.Set;
16
17 import org.simantics.databoard.Bindings;
18 import org.simantics.databoard.accessor.reference.ChildReference;
19 import org.simantics.databoard.accessor.reference.IndexReference;
20 import org.simantics.databoard.accessor.reference.KeyReference;
21 import org.simantics.databoard.accessor.reference.LabelReference;
22 import org.simantics.databoard.accessor.reference.NameReference;
23 import org.simantics.databoard.adapter.AdaptException;
24 import org.simantics.databoard.binding.error.BindingException;
25 import org.simantics.databoard.binding.error.RuntimeBindingException;
26 import org.simantics.databoard.binding.impl.BindingPrintContext;
27 import org.simantics.databoard.type.OptionalType;
28 import org.simantics.databoard.util.IdentityPair;
29
30
31 /**
32  * This is a binding of Optional Type and a Java Object.
33  * 
34  * @see OptionalType
35  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
36  */
37 public abstract class OptionalBinding extends Binding {
38         
39     public Binding componentBinding;
40
41     public OptionalBinding(OptionalType type, Binding componentBinding) {
42         this.componentBinding = componentBinding;
43         this.type = type;        
44     }
45     
46     public OptionalBinding(Binding componentBinding) {
47         this.componentBinding = componentBinding;
48         this.type = new OptionalType(componentBinding.type());
49     }
50     
51     @Override
52     public OptionalType type() {
53         return (OptionalType) type;
54     }
55     
56     /**
57      * Create result with no value
58      * 
59      * @return no value
60      */
61     public abstract Object createNoValue() throws BindingException;
62         
63     /**
64      * Create result with a value
65      * 
66      * @param value
67      * @return argument that contains a value
68      */
69     public abstract Object createValue(Object value) throws BindingException;
70
71
72     /**
73      * Tests whether arg contains a value
74      * 
75      * @param arg 
76      * @return true if arg contained a value
77      */
78     public abstract boolean hasValue(Object arg) throws BindingException;
79     
80     /**
81      * Get the non-null value, the arg did not contain a value,
82      * BindingException is thrown. 
83      *  
84      * @param arg argument that contains a value
85      * @return the composite value
86      * @throws BindingException
87      */
88     public abstract Object getValue(Object arg) throws BindingException;
89
90     public abstract void setValue(Object optional, Object componentValue) throws BindingException;
91     
92     public abstract void setNoValue(Object optional) throws BindingException;
93     
94         public abstract boolean isInstance(Object obj);
95     
96     public Binding getComponentBinding() {
97         return componentBinding;
98     }
99         
100         @Override
101         public void readFrom(Binding srcBinding, Object src, Object dst)
102                         throws BindingException {
103                 OptionalBinding sb = (OptionalBinding) srcBinding;
104                 if (sb.hasValue(src)) {
105                         Binding dcb = getComponentBinding();
106                         Binding scb = sb.getComponentBinding();
107                         Object scv = sb.getValue(src);
108                         if (dcb.isImmutable() || !hasValue(dst)) {
109                                 try {
110                                         Object v = Bindings.clone(scv, scb, dcb);
111                                         v = dcb.readFromTry(scb, scv, v);
112                                         setValue(dst, v);
113                                 } catch (AdaptException e) {
114                                         throw new BindingException(e);
115                                 }
116                         } else {
117                                 Object v = getValue(src);
118                                 v = dcb.readFromTry(scb, scv, v);
119                                 setValue(dst, v);
120                         }
121                 } else {
122                         setNoValue(dst);
123                 }
124         }
125     
126     @Override
127     public void accept(Visitor1 v, Object obj) {
128         v.visit(this, obj);        
129     }
130     
131     @Override
132     public <T> T accept(Visitor<T> v) {
133         return v.visit(this);
134     }
135         
136         /**
137          * Assert tje obj is a correct instance.
138          * Assert the obj is valid also according to the component binding.
139          */
140         @Override
141         public void assertInstaceIsValid(Object obj, Set<Object> validInstances) throws BindingException {
142                 if (!hasValue(obj)) return;
143                 Object componentValue = getValue(obj);
144                 componentBinding.assertInstaceIsValid(componentValue, validInstances);
145         }
146         
147         @Override
148     public int deepHashValue(Object value, IdentityHashMap<Object, Object> hashedObjects) throws BindingException {
149                 return hasValue(value) ? componentBinding.deepHashValue( getValue(value), hashedObjects ) : 0;
150         }
151         
152         @Override
153         public int deepCompare(Object o1, Object o2, Set<IdentityPair<Object, Object>> compareHistory) throws BindingException 
154         {
155                 Boolean h1 = hasValue(o1);
156                 Boolean h2 = hasValue(o2);
157                 if (!h1 && !h2) return 0;               
158                 int dif = h1.compareTo(h2);
159                 if (dif!=0) return dif;
160                 
161                 Binding c = getComponentBinding();
162                 Object v1 = getValue(o1);
163                 Object v2 = getValue(o2);
164                 return c.deepCompare(v1, v2, compareHistory);           
165         }
166         
167     public Object createNoValueUnchecked() throws RuntimeBindingException {
168         try {
169                 return createNoValue();
170                 } catch (BindingException e) {
171                         throw new RuntimeBindingException(e);
172                 }
173     }
174     
175     public Object createValueUnchecked(Object value) 
176     throws RuntimeBindingException {
177         try {
178                         return createValue(value);
179                 } catch (BindingException e) {
180                         throw new RuntimeBindingException(e);
181                 }
182     }
183    
184     public boolean hasValueUnchecked(Object arg) throws RuntimeBindingException {
185         try {
186                         return hasValue(arg);
187                 } catch (BindingException e) {
188                         throw new RuntimeBindingException(e);
189                 }
190     }
191
192     @Override
193         protected void toString(Object value, BindingPrintContext ctx) throws BindingException {
194         if(hasValue(value)) {
195                 getComponentBinding().toString(getValue(value), ctx);
196         } else {
197                 ctx.b.append("null");
198         }
199     }
200     
201     @Override
202     public Binding getComponentBinding(ChildReference path) {
203         if (path==null) return this;
204         if (path instanceof KeyReference) throw new IllegalArgumentException("KeyReference is not supported in OptionalType"); 
205         if (path instanceof NameReference) throw new IllegalArgumentException("NameReference is not supported in OptionalType"); 
206         if (path instanceof IndexReference && ((IndexReference) path).index!=0) throw new IllegalArgumentException("Index out of bounds");
207         if (path instanceof LabelReference && !((LabelReference) path).label.equals("v")) throw new IllegalArgumentException("Unknown label");
208         return componentBinding.getComponentBinding(path.childReference);
209     }    
210     
211     @Override
212     public int getComponentCount() {
213         return 1;
214     }
215     
216     @Override
217     public Binding getComponentBinding(int index) {
218         if (index==0) return componentBinding;
219         throw new IllegalArgumentException();
220     }
221
222     @Override
223     protected boolean deepEquals(Object obj,
224                 Set<IdentityPair<Binding, Binding>> compareHistory) {
225         return super.deepEquals( obj, compareHistory ) && componentBinding.equals(((OptionalBinding) obj).componentBinding, compareHistory);
226     }
227     
228     @Override
229     public int deepHashCode(IdentityHashMap<Object, Object> hashedObjects) {
230         return super.deepHashCode( hashedObjects ) + componentBinding.hashCode(hashedObjects);
231     }
232 }