1 package org.simantics.db.layer0.variable;
3 import java.text.Format;
5 import org.simantics.databoard.Bindings;
6 import org.simantics.databoard.Datatypes;
7 import org.simantics.databoard.accessor.reference.ChildReference;
8 import org.simantics.databoard.accessor.reference.IndexReference;
9 import org.simantics.databoard.adapter.AdaptException;
10 import org.simantics.databoard.binding.ArrayBinding;
11 import org.simantics.databoard.binding.Binding;
12 import org.simantics.databoard.binding.error.BindingException;
13 import org.simantics.databoard.binding.mutable.Variant;
14 import org.simantics.databoard.binding.reflection.GenericArrayBinding;
15 import org.simantics.databoard.type.ArrayType;
16 import org.simantics.databoard.type.Datatype;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.WriteGraph;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.exception.RuntimeDatabaseException;
22 import org.simantics.db.layer0.variable.RVI.RVIPart;
23 import org.simantics.db.layer0.variable.RVI.StringRVIPart;
24 import org.simantics.db.layer0.variable.Variables.Role;
25 import org.simantics.operation.Layer0X;
27 public class SubliteralPropertyVariableDeprecated extends AbstractPropertyVariable {
29 private final Variable parent;
30 private final ChildReference reference;
32 public SubliteralPropertyVariableDeprecated(Variable parent, ChildReference reference) {
34 this.reference = reference;
38 public Variable getPredicate(ReadGraph graph) throws DatabaseException {
39 return parent.getPredicate(graph);
43 public Resource getPropertyResource(ReadGraph graph) throws DatabaseException {
44 if (parent instanceof AbstractPropertyVariable) {
45 return ((AbstractPropertyVariable) parent).getPropertyResource(graph);
47 throw new RuntimeDatabaseException("not supported for parent " + parent);
51 public Resource getContainerResource(ReadGraph graph) throws DatabaseException {
52 if (parent instanceof AbstractPropertyVariable) {
53 return ((AbstractPropertyVariable) parent).getContainerResource(graph);
55 throw new RuntimeDatabaseException("not supported for parent " + parent);
58 static class DisplayPropertyVariable extends ValueProxyVariable {
60 private String suffix;
62 public DisplayPropertyVariable(Variable proxy, Variable parent, String suffix) {
64 assert suffix != null;
68 public boolean equals(Object obj) {
71 if (!(obj instanceof DisplayPropertyVariable))
73 DisplayPropertyVariable other = (DisplayPropertyVariable) obj;
74 return proxy.equals(other.proxy) && suffix.equals(suffix);
78 public int hashCode() {
79 return proxy.hashCode() * 31 + suffix.hashCode();
84 public String getURI(ReadGraph graph) throws DatabaseException {
85 return parent.getURI(graph) + Role.PROPERTY.getIdentifier() + getName(graph);
89 public String getName(ReadGraph graph) throws DatabaseException {
90 return Variables.DISPLAY_PROPERTY;
94 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
95 return Datatypes.STRING;
99 public RVI getRVI(ReadGraph graph) throws DatabaseException {
100 return new RVIBuilder(parent.getRVI(graph))
101 .append(new StringRVIPart(Role.PROPERTY, getName(graph)))
106 public <T> T getPossibleValue(ReadGraph graph) throws DatabaseException {
107 return getPossibleValue(graph, Bindings.STRING);
110 @SuppressWarnings("unchecked")
112 public <T> T getPossibleValue(ReadGraph graph, Binding binding) throws DatabaseException {
113 String str = proxy.getPossiblePropertyValue(graph, Variables.DISPLAY_PROPERTY, Bindings.STRING);
114 return (T) (str != null ? str + " " + suffix : null);
118 public <T> T getValue(ReadGraph graph) throws DatabaseException {
119 return getValue(graph, Bindings.STRING);
122 @SuppressWarnings("unchecked")
124 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
125 return (T) (proxy.getPropertyValue(graph, Variables.DISPLAY_PROPERTY, binding) + " " + suffix);
128 public Variant getVariantValue(ReadGraph graph) throws DatabaseException {
129 return new Variant(Bindings.STRING, getValue(graph, Bindings.STRING));
134 static class DisplayUnitVariable extends ValueProxyVariable {
136 public DisplayUnitVariable(Variable proxy, Variable parent) {
137 super(proxy, parent);
140 public boolean equals(Object obj) {
143 if (!(obj instanceof DisplayUnitVariable))
145 DisplayUnitVariable other = (DisplayUnitVariable) obj;
146 return proxy.equals(other.proxy);
150 public int hashCode() {
151 return proxy.hashCode() * 53;
155 public String getURI(ReadGraph graph) throws DatabaseException {
156 return parent.getURI(graph) + Role.PROPERTY.getIdentifier() + getName(graph);
160 public String getName(ReadGraph graph) throws DatabaseException {
161 return Variables.DISPLAY_UNIT;
165 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
166 return Datatypes.STRING;
170 public RVI getRVI(ReadGraph graph) throws DatabaseException {
171 return new RVIBuilder(parent.getRVI(graph))
172 .append(new StringRVIPart(Role.PROPERTY, getName(graph)))
177 public <T> T getPossibleValue(ReadGraph graph) throws DatabaseException {
178 return getPossibleValue(graph, Bindings.STRING);
182 public <T> T getPossibleValue(ReadGraph graph, Binding binding) throws DatabaseException {
183 return proxy.getPossiblePropertyValue(graph, Variables.DISPLAY_UNIT, Bindings.STRING);
187 public <T> T getValue(ReadGraph graph) throws DatabaseException {
188 return getValue(graph, Bindings.STRING);
192 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
193 return proxy.getPropertyValue(graph, Variables.DISPLAY_UNIT, binding);
196 public Variant getVariantValue(ReadGraph graph) throws DatabaseException {
197 return new Variant(Bindings.STRING, getValue(graph, Bindings.STRING));
202 protected String getReferenceString(ReadGraph graph) throws DatabaseException {
203 Layer0X L0X = Layer0X.getInstance(graph);
204 Format formatter = parent.getPossiblePropertyValue(graph, L0X.HasChildReferenceFormatter);
205 if (formatter != null) {
207 String format = formatter.format(reference);
210 } catch (IllegalArgumentException e) {
211 // Ignore it this, use default formatting.
214 if (reference instanceof IndexReference) {
215 // Fallback logic [i] where 0 <= i <= N-1, N = sizeof(array)
216 IndexReference index = (IndexReference) reference;
217 return "[" + index.getIndex() + "]";
219 return reference.toString();
222 public Variable getPossibleExtraProperty(ReadGraph graph, String name) throws DatabaseException {
223 if (Variables.DISPLAY_PROPERTY.equals(name)) {
224 return new DisplayPropertyVariable(parent, this, getReferenceString(graph));
225 } else if (Variables.DISPLAY_UNIT.equals(name)) {
226 return new DisplayUnitVariable(parent, this);
227 } /*else if (Variables.DATATYPE.equals(name)) {
228 Object value = getPossibleDatatype(graph);
230 return new ConstantPropertyVariable(this, name, value, datatype_binding);
231 } else if (Variables.UNIT.equals(name)) {
232 Object value = parent.getPossiblePropertyValue(graph, name);
234 return new ConstantPropertyVariable(this, name, value, Bindings.STRING);
235 } else if (Variables.PREDICATE.equals(name)) {
236 Object value = getPossiblePredicate(graph);
238 return new ConstantPropertyVariable(this, name, value, null);
244 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
245 Datatype parentType = parent.getDatatype(graph);
246 if(parentType instanceof ArrayType) {
247 ArrayType at = (ArrayType)parentType;
248 return at.getComponentType(0);
253 @SuppressWarnings("unchecked")
255 public <T> T getValue(ReadGraph graph) throws DatabaseException {
256 Object parentValue = parent.getValue(graph);
257 Datatype parentType = parent.getDatatype(graph);
258 Binding parentBinding = Bindings.getBinding(parentType);
259 if (parentType instanceof ArrayType) {
260 ArrayBinding ab = (ArrayBinding)parentBinding;
261 IndexReference ref = (IndexReference)reference;
263 return (T)ab.get(parentValue, ref.index);
264 } catch (IndexOutOfBoundsException e) {
265 throw new RuntimeDatabaseException(e);
266 } catch (BindingException e) {
267 throw new RuntimeDatabaseException(e);
270 throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType");
273 @SuppressWarnings("unchecked")
275 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
276 Object parentValue = parent.getValue(graph);
277 Datatype parentType = parent.getDatatype(graph);
278 Binding parentBinding = Bindings.getBinding(parentType);
279 if (parentType instanceof ArrayType) {
280 ArrayBinding ab = (ArrayBinding)parentBinding;
281 IndexReference ref = (IndexReference)reference;
283 Object indexValue = ab.get(parentValue, ref.index);
284 return (T) Bindings.adapt(indexValue, ab.getComponentBinding(), binding);
285 } catch (IndexOutOfBoundsException e) {
286 throw new RuntimeDatabaseException(e);
287 } catch (BindingException e) {
288 throw new RuntimeDatabaseException(e);
289 } catch (AdaptException e) {
290 throw new RuntimeDatabaseException(e);
293 throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType");
297 public void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException {
298 Object parentValue = parent.getValue(graph);
299 Datatype parentType = parent.getDatatype(graph);
300 if(parentType instanceof ArrayType) {
301 Binding parentBinding = Bindings.getBinding(parentType);
302 ArrayBinding ab = (ArrayBinding)parentBinding;
303 IndexReference ref = (IndexReference)reference;
305 Object indexValue = adaptValueForArray(parentValue, value, binding, ab.getComponentBinding());
306 if (indexValue == value) {
307 // Adaption was passthrough, trust specified binding and
308 // create a generic array binding out of it.
309 ab = resolveArrayBinding(parentValue.getClass(), binding);
311 ab.set(parentValue, ref.index, indexValue);
312 parent.setValue(graph, parentValue, ab);
313 } catch (IndexOutOfBoundsException e) {
314 throw new RuntimeDatabaseException(e);
315 } catch (BindingException e) {
316 throw new RuntimeDatabaseException(e);
317 } catch (AdaptException e) {
318 throw new RuntimeDatabaseException(e);
323 private ArrayBinding resolveArrayBinding(Class<? extends Object> arrayClass, Binding binding) {
324 Class<?> componentClass = arrayClass.getComponentType();
325 if (componentClass.isPrimitive()) {
326 if (componentClass == boolean.class)
327 return Bindings.BOOLEAN_ARRAY;
328 if (componentClass == byte.class)
329 return Bindings.BYTE_ARRAY;
330 if (componentClass == int.class)
331 return Bindings.INT_ARRAY;
332 if (componentClass == long.class)
333 return Bindings.LONG_ARRAY;
334 if (componentClass == float.class)
335 return Bindings.FLOAT_ARRAY;
336 if (componentClass == double.class)
337 return Bindings.DOUBLE_ARRAY;
339 if (componentClass.equals(String.class))
340 return Bindings.STRING_ARRAY;
341 return new GenericArrayBinding(arrayClass, new ArrayType(binding.type()), binding);
344 private Object adaptValueForArray(Object array, Object indexValue, Binding from, Binding to) throws AdaptException {
345 Class<?> arrayType = array.getClass();
346 if (!arrayType.isArray())
347 throw new AdaptException("array " + array + " is not of an array class");
348 Class<?> arrayComponentType = arrayType.getComponentType();
349 if (arrayComponentType.isAssignableFrom(indexValue.getClass())) {
350 // Type match, be happy.
353 // Only adapt if necessary.
354 return Bindings.adapt(indexValue, from, to);
358 public String getName(ReadGraph graph) throws DatabaseException {
359 return reference.toString(false);
363 // public Object getSerialized(ReadGraph graph) throws DatabaseException {
364 // return reference.toString(false);
368 public Variable getParent(ReadGraph graph) throws DatabaseException {
373 public Role getRole(ReadGraph graph) throws DatabaseException {
378 public RVIPart getRVIPart(ReadGraph graph) throws DatabaseException {
379 return new StringRVIPart(Role.CHILD, reference.toString(false));
383 public boolean equals(Object obj) {
384 if (!super.equals(obj))
386 if (!(obj instanceof SubliteralPropertyVariableDeprecated))
388 SubliteralPropertyVariableDeprecated other = (SubliteralPropertyVariableDeprecated) obj;
389 return reference.equals(other.reference);
393 public int hashCode() {
394 return super.hashCode() * 31 + reference.hashCode();