]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/OptionalBinding.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / OptionalBinding.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;
13
14 import java.util.IdentityHashMap;\r
15 import java.util.Set;\r
16 \r
17 import org.simantics.databoard.Bindings;\r
18 import org.simantics.databoard.accessor.reference.ChildReference;\r
19 import org.simantics.databoard.accessor.reference.IndexReference;\r
20 import org.simantics.databoard.accessor.reference.KeyReference;\r
21 import org.simantics.databoard.accessor.reference.LabelReference;\r
22 import org.simantics.databoard.accessor.reference.NameReference;\r
23 import org.simantics.databoard.adapter.AdaptException;\r
24 import org.simantics.databoard.binding.error.BindingException;\r
25 import org.simantics.databoard.binding.error.RuntimeBindingException;\r
26 import org.simantics.databoard.binding.impl.BindingPrintContext;\r
27 import org.simantics.databoard.type.OptionalType;\r
28 import org.simantics.databoard.util.IdentityPair;\r
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         \r
100         @Override\r
101         public void readFrom(Binding srcBinding, Object src, Object dst)\r
102                         throws BindingException {\r
103                 OptionalBinding sb = (OptionalBinding) srcBinding;\r
104                 if (sb.hasValue(src)) {\r
105                         Binding dcb = getComponentBinding();\r
106                         Binding scb = sb.getComponentBinding();\r
107                         Object scv = sb.getValue(src);\r
108                         if (dcb.isImmutable() || !hasValue(dst)) {\r
109                                 try {\r
110                                         Object v = Bindings.clone(scv, scb, dcb);\r
111                                         v = dcb.readFromTry(scb, scv, v);\r
112                                         setValue(dst, v);\r
113                                 } catch (AdaptException e) {\r
114                                         throw new BindingException(e);\r
115                                 }\r
116                         } else {\r
117                                 Object v = getValue(src);\r
118                                 v = dcb.readFromTry(scb, scv, v);\r
119                                 setValue(dst, v);\r
120                         }\r
121                 } else {\r
122                         setNoValue(dst);\r
123                 }\r
124         }\r
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 \r
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 \r
192     @Override\r
193         protected void toString(Object value, BindingPrintContext ctx) throws BindingException {\r
194         if(hasValue(value)) {\r
195                 getComponentBinding().toString(getValue(value), ctx);\r
196         } else {\r
197                 ctx.b.append("null");\r
198         }\r
199     }\r
200     \r
201     @Override\r
202     public Binding getComponentBinding(ChildReference path) {\r
203         if (path==null) return this;\r
204         if (path instanceof KeyReference) throw new IllegalArgumentException("KeyReference is not supported in OptionalType"); \r
205         if (path instanceof NameReference) throw new IllegalArgumentException("NameReference is not supported in OptionalType"); \r
206         if (path instanceof IndexReference && ((IndexReference) path).index!=0) throw new IllegalArgumentException("Index out of bounds");\r
207         if (path instanceof LabelReference && !((LabelReference) path).label.equals("v")) throw new IllegalArgumentException("Unknown label");\r
208         return componentBinding.getComponentBinding(path.childReference);\r
209     }    \r
210     \r
211     @Override\r
212     public int getComponentCount() {\r
213         return 1;\r
214     }\r
215     \r
216     @Override\r
217     public Binding getComponentBinding(int index) {\r
218         if (index==0) return componentBinding;\r
219         throw new IllegalArgumentException();\r
220     }\r
221 \r
222     @Override\r
223     protected boolean deepEquals(Object obj,\r
224                 Set<IdentityPair<Binding, Binding>> compareHistory) {\r
225         return super.deepEquals( obj, compareHistory ) && componentBinding.equals(((OptionalBinding) obj).componentBinding, compareHistory);\r
226     }\r
227     \r
228     @Override\r
229     public int deepHashCode(IdentityHashMap<Object, Object> hashedObjects) {\r
230         return super.deepHashCode( hashedObjects ) + componentBinding.hashCode(hashedObjects);\r
231     }
232 }