]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/SubliteralPropertyVariableDeprecated.java
New implementation NearestOwnerFinder of CommonDBUtils.getNearestOwner
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / SubliteralPropertyVariableDeprecated.java
1 package org.simantics.db.layer0.variable;
2
3 import java.text.Format;
4
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;
26
27 public class SubliteralPropertyVariableDeprecated extends AbstractPropertyVariable {
28         
29         private final Variable parent;
30         private final ChildReference reference;
31
32         public SubliteralPropertyVariableDeprecated(Variable parent, ChildReference reference) {
33                 this.parent = parent;
34                 this.reference = reference;
35         }
36
37         @Override
38         public Variable getPredicate(ReadGraph graph) throws DatabaseException {
39                 return parent.getPredicate(graph);
40         }
41
42         @Override
43         public Resource getPropertyResource(ReadGraph graph) throws DatabaseException {
44                 if (parent instanceof AbstractPropertyVariable) {
45                         return ((AbstractPropertyVariable) parent).getPropertyResource(graph);
46                 }
47                 throw new RuntimeDatabaseException("not supported for parent " + parent);
48         }
49
50         @Override
51         public Resource getContainerResource(ReadGraph graph) throws DatabaseException {
52                 if (parent instanceof AbstractPropertyVariable) {
53                         return ((AbstractPropertyVariable) parent).getContainerResource(graph);
54                 }
55                 throw new RuntimeDatabaseException("not supported for parent " + parent);
56         }
57
58         static class DisplayPropertyVariable extends ValueProxyVariable {
59
60                 private String suffix;
61
62                 public DisplayPropertyVariable(Variable proxy, Variable parent, String suffix) {
63                         super(proxy, parent);
64                         assert suffix != null;
65                         this.suffix = suffix;
66                 }
67
68                 public boolean equals(Object obj) {
69                         if (this == obj)
70                                 return true;
71                         if (!(obj instanceof DisplayPropertyVariable))
72                                 return false;
73                         DisplayPropertyVariable other = (DisplayPropertyVariable) obj;
74                         return proxy.equals(other.proxy) && suffix.equals(suffix);
75                 }
76
77                 @Override
78                 public int hashCode() {
79                         return proxy.hashCode() * 31 + suffix.hashCode();
80                 }
81
82
83                 @Override
84                 public String getURI(ReadGraph graph) throws DatabaseException {
85                         return parent.getURI(graph) + Role.PROPERTY.getIdentifier() + getName(graph);
86                 }
87
88                 @Override
89                 public String getName(ReadGraph graph) throws DatabaseException {
90                         return Variables.DISPLAY_PROPERTY;
91                 }
92
93                 @Override
94                 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
95                         return Datatypes.STRING;
96                 }
97
98                 @Override
99                 public RVI getRVI(ReadGraph graph) throws DatabaseException {
100                         return new RVIBuilder(parent.getRVI(graph))
101                                 .append(new StringRVIPart(Role.PROPERTY, getName(graph)))
102                                 .toRVI();
103                 }
104
105                 @Override
106                 public <T> T getPossibleValue(ReadGraph graph) throws DatabaseException {
107                         return getPossibleValue(graph, Bindings.STRING);
108                 }
109
110                 @SuppressWarnings("unchecked")
111                 @Override
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);
115                 }
116
117                 @Override
118                 public <T> T getValue(ReadGraph graph) throws DatabaseException {
119                         return getValue(graph, Bindings.STRING);
120                 }
121
122                 @SuppressWarnings("unchecked")
123                 @Override
124                 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
125                         return (T) (proxy.getPropertyValue(graph, Variables.DISPLAY_PROPERTY, binding) + " " + suffix);
126                 }
127
128                 public Variant getVariantValue(ReadGraph graph) throws DatabaseException {
129                         return new Variant(Bindings.STRING, getValue(graph, Bindings.STRING));
130                 }
131
132         }
133
134         static class DisplayUnitVariable extends ValueProxyVariable {
135
136                 public DisplayUnitVariable(Variable proxy, Variable parent) {
137                         super(proxy, parent);
138                 }
139
140                 public boolean equals(Object obj) {
141                         if (this == obj)
142                                 return true;
143                         if (!(obj instanceof DisplayUnitVariable))
144                                 return false;
145                         DisplayUnitVariable other = (DisplayUnitVariable) obj;
146                         return proxy.equals(other.proxy);
147                 }
148
149                 @Override
150                 public int hashCode() {
151                         return proxy.hashCode() * 53;
152                 }
153
154                 @Override
155                 public String getURI(ReadGraph graph) throws DatabaseException {
156                         return parent.getURI(graph) + Role.PROPERTY.getIdentifier() + getName(graph);
157                 }
158
159                 @Override
160                 public String getName(ReadGraph graph) throws DatabaseException {
161                         return Variables.DISPLAY_UNIT;
162                 }
163
164                 @Override
165                 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
166                         return Datatypes.STRING;
167                 }
168
169                 @Override
170                 public RVI getRVI(ReadGraph graph) throws DatabaseException {
171                         return new RVIBuilder(parent.getRVI(graph))
172                                 .append(new StringRVIPart(Role.PROPERTY, getName(graph)))
173                                 .toRVI();
174                 }
175
176                 @Override
177                 public <T> T getPossibleValue(ReadGraph graph) throws DatabaseException {
178                         return getPossibleValue(graph, Bindings.STRING);
179                 }
180
181                 @Override
182                 public <T> T getPossibleValue(ReadGraph graph, Binding binding) throws DatabaseException {
183                         return proxy.getPossiblePropertyValue(graph, Variables.DISPLAY_UNIT, Bindings.STRING);
184                 }
185
186                 @Override
187                 public <T> T getValue(ReadGraph graph) throws DatabaseException {
188                         return getValue(graph, Bindings.STRING);
189                 }
190
191                 @Override
192                 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
193                         return proxy.getPropertyValue(graph, Variables.DISPLAY_UNIT, binding);
194                 }
195
196                 public Variant getVariantValue(ReadGraph graph) throws DatabaseException {
197                         return new Variant(Bindings.STRING, getValue(graph, Bindings.STRING));
198                 }
199
200         }
201
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) {
206                         try {
207                                 String format = formatter.format(reference);
208                                 if (format != null)
209                                         return format;
210                         } catch (IllegalArgumentException e) {
211                                 // Ignore it this, use default formatting.
212                         }
213                 }
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() + "]";
218                 }
219                 return reference.toString();
220         }
221
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);
229                         if (value != null)
230                                 return new ConstantPropertyVariable(this, name, value, datatype_binding);
231                 } else if (Variables.UNIT.equals(name)) {
232                         Object value = parent.getPossiblePropertyValue(graph, name);
233                         if (value != null)
234                                 return new ConstantPropertyVariable(this, name, value, Bindings.STRING);
235                 } else if (Variables.PREDICATE.equals(name)) {
236                         Object value = getPossiblePredicate(graph);
237                         if (value != null)
238                                 return new ConstantPropertyVariable(this, name, value, null);
239                 } */
240                 return null;
241         }
242
243         @Override
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);
249                 }
250                 return null;
251         }
252
253         @SuppressWarnings("unchecked")
254         @Override
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;
262                         try {
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);
268                         }
269                 }
270                 throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType");
271         }
272
273         @SuppressWarnings("unchecked")
274         @Override
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;
282                         try {
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);
291                         }
292                 }
293                 throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType");
294         }
295
296         @Override
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;
304                         try {
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);
310                                 }
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);
319                         }
320                 }
321         }
322
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;
338                 }
339                 if (componentClass.equals(String.class))
340                         return Bindings.STRING_ARRAY;
341                 return new GenericArrayBinding(arrayClass, new ArrayType(binding.type()), binding);
342         }
343
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.
351                         return indexValue;
352                 }
353                 // Only adapt if necessary.
354                 return Bindings.adapt(indexValue, from, to);
355         }
356
357         @Override
358         public String getName(ReadGraph graph) throws DatabaseException {
359                 return reference.toString(false);
360         }
361
362 //      @Override
363 //      public Object getSerialized(ReadGraph graph) throws DatabaseException {
364 //              return reference.toString(false);
365 //      }
366
367         @Override
368         public Variable getParent(ReadGraph graph) throws DatabaseException {
369                 return parent;
370         }
371
372         @Override
373         public Role getRole(ReadGraph graph) throws DatabaseException {
374                 return Role.CHILD;
375         }
376
377         @Override
378         public RVIPart getRVIPart(ReadGraph graph) throws DatabaseException {
379                 return new StringRVIPart(Role.CHILD, reference.toString(false));
380         }
381
382         @Override
383         public boolean equals(Object obj) {
384                 if (!super.equals(obj))
385                         return false;
386                 if (!(obj instanceof SubliteralPropertyVariableDeprecated))
387                         return false;
388                 SubliteralPropertyVariableDeprecated other = (SubliteralPropertyVariableDeprecated) obj;
389                 return reference.equals(other.reference);
390         }
391
392         @Override
393         public int hashCode() {
394                 return super.hashCode() * 31 + reference.hashCode();
395         }
396
397 }