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;
14 import java.util.IdentityHashMap;
\r
15 import java.util.Set;
\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
32 * This is a binding of Optional Type and a Java Object.
35 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
37 public abstract class OptionalBinding extends Binding {
39 public Binding componentBinding;
41 public OptionalBinding(OptionalType type, Binding componentBinding) {
42 this.componentBinding = componentBinding;
46 public OptionalBinding(Binding componentBinding) {
47 this.componentBinding = componentBinding;
48 this.type = new OptionalType(componentBinding.type());
52 public OptionalType type() {
53 return (OptionalType) type;
57 * Create result with no value
61 public abstract Object createNoValue() throws BindingException;
64 * Create result with a value
67 * @return argument that contains a value
69 public abstract Object createValue(Object value) throws BindingException;
73 * Tests whether arg contains a value
76 * @return true if arg contained a value
78 public abstract boolean hasValue(Object arg) throws BindingException;
81 * Get the non-null value, the arg did not contain a value,
82 * BindingException is thrown.
84 * @param arg argument that contains a value
85 * @return the composite value
86 * @throws BindingException
88 public abstract Object getValue(Object arg) throws BindingException;
90 public abstract void setValue(Object optional, Object componentValue) throws BindingException;
92 public abstract void setNoValue(Object optional) throws BindingException;
94 public abstract boolean isInstance(Object obj);
96 public Binding getComponentBinding() {
97 return componentBinding;
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
110 Object v = Bindings.clone(scv, scb, dcb);
\r
111 v = dcb.readFromTry(scb, scv, v);
\r
113 } catch (AdaptException e) {
\r
114 throw new BindingException(e);
\r
117 Object v = getValue(src);
\r
118 v = dcb.readFromTry(scb, scv, v);
\r
127 public void accept(Visitor1 v, Object obj) {
132 public <T> T accept(Visitor<T> v) {
133 return v.visit(this);
137 * Assert tje obj is a correct instance.
138 * Assert the obj is valid also according to the component binding.
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);
148 public int deepHashValue(Object value, IdentityHashMap<Object, Object> hashedObjects) throws BindingException {
149 return hasValue(value) ? componentBinding.deepHashValue( getValue(value), hashedObjects ) : 0;
153 public int deepCompare(Object o1, Object o2, Set<IdentityPair<Object, Object>> compareHistory) throws BindingException
\r
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;
161 Binding c = getComponentBinding();
162 Object v1 = getValue(o1);
163 Object v2 = getValue(o2);
164 return c.deepCompare(v1, v2, compareHistory);
167 public Object createNoValueUnchecked() throws RuntimeBindingException {
169 return createNoValue();
170 } catch (BindingException e) {
171 throw new RuntimeBindingException(e);
175 public Object createValueUnchecked(Object value)
176 throws RuntimeBindingException {
178 return createValue(value);
179 } catch (BindingException e) {
180 throw new RuntimeBindingException(e);
184 public boolean hasValueUnchecked(Object arg) throws RuntimeBindingException {
186 return hasValue(arg);
187 } catch (BindingException e) {
188 throw new RuntimeBindingException(e);
193 protected void toString(Object value, BindingPrintContext ctx) throws BindingException {
\r
194 if(hasValue(value)) {
\r
195 getComponentBinding().toString(getValue(value), ctx);
\r
197 ctx.b.append("null");
\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
212 public int getComponentCount() {
\r
217 public Binding getComponentBinding(int index) {
\r
218 if (index==0) return componentBinding;
\r
219 throw new IllegalArgumentException();
\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
229 public int deepHashCode(IdentityHashMap<Object, Object> hashedObjects) {
\r
230 return super.deepHashCode( hashedObjects ) + componentBinding.hashCode(hashedObjects);
\r