]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java
Initial version of validating derived properties formulas
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / StandardGraphPropertyVariable.java
1 package org.simantics.db.layer0.variable;
2
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.simantics.databoard.Bindings;
10 import org.simantics.databoard.accessor.reference.ChildReference;
11 import org.simantics.databoard.binding.Binding;
12 import org.simantics.databoard.binding.impl.ObjectVariantBinding;
13 import org.simantics.databoard.type.Datatype;
14 import org.simantics.db.ReadGraph;
15 import org.simantics.db.Resource;
16 import org.simantics.db.WriteGraph;
17 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
18 import org.simantics.db.common.validation.L0Validations;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.exception.ValidationException;
21 import org.simantics.db.layer0.exception.MissingVariableValueException;
22 import org.simantics.db.layer0.exception.PendingVariableException;
23 import org.simantics.db.layer0.exception.VariableException;
24 import org.simantics.db.layer0.function.All;
25 import org.simantics.db.layer0.request.PropertyInfo;
26 import org.simantics.db.layer0.request.PropertyInfoRequest;
27 import org.simantics.db.layer0.scl.SCLDatabaseException;
28 import org.simantics.db.layer0.util.Layer0Utils;
29 import org.simantics.layer0.Layer0;
30 import org.simantics.utils.Development;
31 import org.simantics.utils.datastructures.Pair;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
36     private static final Logger LOGGER = LoggerFactory.getLogger(StandardGraphPropertyVariable.class);
37     
38         protected static final PropertyInfo NO_PROPERTY = new PropertyInfo(null, null,
39                         false, Collections.<String> emptySet(), null, null, null, null, null, null,
40                         Collections.<String, Pair<Resource, ChildReference>> emptyMap(),
41                         null, false);
42
43         final public Variable parent;
44         final public Resource parentResource;
45         final public PropertyInfo property;
46         final public Resource represents;
47         
48         transient private int hash = 0;
49
50         public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource property) throws DatabaseException {
51                 this(graph, parent, node, (Resource)parent.getPossibleRepresents(graph), getPropertyInfo(graph, property));
52         }
53         
54         public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource parentResource, Resource property) throws DatabaseException {
55                 this(graph, parent, node, parentResource, getPropertyInfo(graph, property));
56         }
57
58         public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, Resource property) throws DatabaseException {
59         this(graph, parent, null, (Resource)parent.getPossibleRepresents(graph), getPropertyInfo(graph, property));
60     }
61
62     public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, Resource parentResource, PropertyInfo property) throws DatabaseException {
63         this(parent, null, parentResource, property, getPossibleRepresents(graph, parentResource, property.predicate));
64     }
65     
66     public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource parentResource, PropertyInfo property) throws DatabaseException {
67         this(parent, node, parentResource, property, getPossibleRepresents(graph, parentResource, property.predicate));
68     }
69
70     private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource property) throws DatabaseException {
71             return property != null ? graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance()) : NO_PROPERTY;
72     }
73     
74     private static Resource getPossibleRepresents(ReadGraph graph, Resource parentResource, Resource predicate) throws DatabaseException {
75         if(parentResource == null || predicate == null) return null;
76         return graph.getPossibleObject(parentResource, predicate);
77     }
78     
79     public boolean isAsserted() {
80         return false;
81     }
82
83     public StandardGraphPropertyVariable(Variable parent, VariableNode node, Resource parentResource, PropertyInfo property, Resource represents) throws DatabaseException {
84         super(node);
85                 assert parent != null;
86                 this.parent = parent;
87                 this.property = property;
88                 this.parentResource = parentResource;
89                 this.represents = represents;
90         }
91
92         @Override
93         public String getName(ReadGraph graph) throws DatabaseException {
94             if(node != null) return node.support.manager.getName(node.node);
95                 return property.name;
96         }
97
98         @Override
99         public String getPossibleLabel(ReadGraph graph) throws DatabaseException {
100                 return graph.getPossibleRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
101         }
102
103         @Override
104         public String getLabel(ReadGraph graph) throws DatabaseException {
105                 return graph.getRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
106         }
107
108         @Override
109         public Variable getParent(ReadGraph graph) throws DatabaseException {
110                 return parent;
111         }
112         
113         @Override
114         public PropertyInfo getPropertyInfo(ReadGraph graph) throws DatabaseException {
115                 return property;
116         }
117
118         @SuppressWarnings("unchecked")
119         @Override
120         public <T> T getValue(ReadGraph graph) throws DatabaseException {
121                 
122                 if(Development.DEVELOPMENT) {
123                         String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
124                         if(error != null) {
125                             LOGGER.error(error);
126                                 //throw new ValidationException(error);
127                         }
128                 }
129                 
130                 return (T)getValueAccessor(graph).getValue(graph, this);
131                 
132         }
133
134         @SuppressWarnings("unchecked")
135         @Override
136         public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
137                 // Fall back to the bindingless method, if the expected output is a Java object 
138                 if (binding instanceof ObjectVariantBinding)
139                         return getValue(graph);         
140
141                 if(Development.DEVELOPMENT) {
142                         String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
143                         if(error != null) {
144                             LOGGER.error(error);
145                                 throw new ValidationException(error);
146                         }
147                 }
148         
149                 try {
150                         
151                         return (T) getValueAccessor(graph).getValue(graph, this, binding);
152                 } catch (SCLDatabaseException e) { // these can be thrown when compiling e.g. derived properties
153                         throw e;
154                 } catch (MissingVariableValueException | PendingVariableException e) {
155                         throw e;
156                 } catch (Throwable t) {
157                         throw new MissingVariableValueException(t);
158                 }
159                 
160         }
161         
162         @Override
163         public Resource getRepresents(ReadGraph graph) throws DatabaseException {
164                 if(represents == null)
165                         throw new VariableException("Variable is not represented by any resource (URI=" + getPossibleURI(graph) + ").");
166                 return represents;
167 //              return graph.getSingleObject(parentResource, property.predicate);
168         }
169
170         @Override
171         public Resource getPossibleRepresents(ReadGraph graph) throws DatabaseException {
172 //        if(parentResource == null) return null;
173 //              return graph.getPossibleObject(parentResource, property.predicate);
174                 return represents;
175         }
176
177         @Override
178         public void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException {
179                 
180                 if(Development.DEVELOPMENT) {
181                         String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
182                         if(error != null) {
183                             LOGGER.error(error);
184                                 //throw new ValidationException(error);
185                         }
186                 }
187                 
188                 getValueAccessor(graph).setValue(graph, this, value, binding);
189                 
190         }
191         
192         @Override
193         public void setValue(WriteGraph graph, Object value) throws DatabaseException {
194                 
195                 if(Development.DEVELOPMENT) {
196                         String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
197                         if(error != null) {
198                             LOGGER.error(error);
199                                 throw new ValidationException(error);
200                         }
201                 }
202                 
203                 getValueAccessor(graph).setValue(graph, this, value);
204                 
205         }
206
207         @Override
208         public Binding getDefaultBinding(ReadGraph graph) throws DatabaseException {
209                 return Layer0Utils.getDefaultBinding(graph, this);
210         }
211         
212         @Override
213         public Binding getPossibleDefaultBinding(ReadGraph graph) throws DatabaseException {
214                 return Layer0Utils.getPossibleDefaultBinding(graph, this);
215         }
216
217         @Override
218         public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
219 //<<<<<<< .mine
220 //              
221 //      Binding binding = getPossibleDefaultBinding(graph);
222 //        if(binding != null) return binding.type();
223 //
224 //              Variant vt = getVariantValue(graph);
225 //              binding = vt.getBinding();
226 //              if(binding == null) throw new DatabaseException("No binding in Variant with value " + vt.getValue());
227 //              return binding.type();
228 //=======
229                 Datatype type;
230                 try {                   
231                         type = getValueAccessor(graph).getDatatype(graph, this);
232                 } catch (Throwable t) {
233                         throw new MissingVariableValueException(t);
234                 }
235                 
236                 if (type == null) {
237                         String uri = this.getPossibleURI(graph);
238                         if (uri != null)
239                                 throw new DatabaseException("No data type for " + uri);
240                         else
241                                 throw new DatabaseException("No data type for " + this.getIdentifier());
242                 }
243                 
244                 return type;
245 //>>>>>>> .r30794
246                 
247         }
248         
249         @Override
250         public Datatype getPossibleDatatype(ReadGraph graph) throws DatabaseException {
251
252                 try {
253                         return getDatatype(graph);
254                 } catch (DatabaseException e) {
255                         return null;
256                 }
257                 
258         }
259         
260         @Override
261         public String getUnit(ReadGraph graph) throws DatabaseException {
262                 try {
263                         return Layer0Utils.getUnit(graph, this);
264                 } catch (DatabaseException e) {
265                         return null;
266                 }
267         }
268
269         @Override
270         public Resource getPropertyResource(ReadGraph graph) {
271                 return property.predicate;
272         }
273         
274         @Override
275         public Resource getContainerResource(ReadGraph graph) throws DatabaseException {
276                 return parentResource;
277         }
278
279         @Override
280         public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
281
282                 Map<String, Variable> result = new HashMap<String, Variable>();
283                 VariableMap map = getPossibleChildVariableMap(graph);
284                 if(map != null) map.getVariables(graph, this, result);
285                 return result.values();
286                 
287         }
288         
289         @Override
290         public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
291
292                 VariableMap map = getPossibleChildVariableMap(graph);
293                 if(map == null) return null;
294                 try {
295                         return map.getVariable(graph, this, name);
296                 } catch (DatabaseException e) {
297                         return null;
298                 }
299                 
300         }
301         
302         
303         @Override
304         protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
305
306                 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
307                 if(valueMap == null) return null;
308                 try {
309                         return valueMap.getVariable(graph, this, name);
310                 } catch (DatabaseException e) {
311                         return null;
312                 } catch (Exception t) {
313                         LOGGER.error("getPossibleDomainProperty is implemented incorrectly, but returns null on Exception for backward compatibility. URI="+getURI(graph)+", name="+name+".", t);
314                         return null;
315                 }
316                 
317         }
318         
319         @Override
320         public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {
321
322                 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
323                 if(valueMap == null) return properties;
324                 return valueMap.getVariables(graph, this, properties);
325                 
326         }
327         
328         @Override
329         public Variable getPredicate(ReadGraph graph) throws DatabaseException {
330                 return Variables.getVariable(graph, graph.getURI(property.predicate));
331         }
332         
333         @Override
334         public Resource getPredicateResource(ReadGraph graph) throws DatabaseException {
335                 return property.predicate;
336         }
337         
338         @Override
339         public Resource getPossiblePredicateResource(ReadGraph graph) throws DatabaseException {
340                 return property.predicate;
341         }
342
343         @Override
344         public int hashCode() {
345                 if(hash == 0) {
346                         final int prime = 31;
347                         int result = 1;
348             result = prime * result + (parent != null ? parent.hashCode() : 0);
349             result = prime * result + (node != null ? node.hashCode() : 0);
350             result = prime * result + (property.predicate != null ? property.predicate.hashCode() : 0);
351             result = prime * result + (parentResource != null ? parentResource.hashCode() : 0);
352             result = prime * result + (represents != null ? represents.hashCode() : 0);
353                         hash =result;
354                 }
355                 return hash;
356         }
357
358         @Override
359         public boolean equals(Object obj) {
360                 if (this == obj)
361                         return true;
362                 if (obj == null)
363                         return false;
364                 if (getClass() != obj.getClass())
365                         return false;
366                 StandardGraphPropertyVariable other = (StandardGraphPropertyVariable) obj;
367                 
368         if(node != null) {
369                 if(!node.equals(other.node)) return false;
370         } else if (other.node != null) return false;
371
372         if(property.predicate != null) {
373                 if(!property.predicate.equals(other.property.predicate)) return false;
374         } else if (other.property.predicate != null) return false;
375         
376         if(parentResource != null) {
377                 if(!parentResource.equals(other.parentResource)) return false;
378         } else if (other.parentResource != null) return false;
379
380         if(parent != null) {
381                 if(!parent.equals(other.parent)) return false;
382         } else if (other.parent != null) return false;
383
384         if(represents != null) {
385                 if(!represents.equals(other.represents)) return false;
386         } else if (other.represents != null) return false;
387
388         return true;
389                 
390         }
391
392         @Override
393         protected Variable getNameVariable(ReadGraph graph) throws DatabaseException {
394             throw new UnsupportedOperationException();
395         }
396         
397         protected ValueAccessor getValueAccessor(ReadGraph graph) throws DatabaseException {
398                 if((property == null || property == NO_PROPERTY) && parentResource == null) return All.standardValueAccessor;
399             ValueAccessor accessor = property.valueAccessor;
400             if(accessor != null) return accessor;
401             else {
402                 System.err.println("No value accessor for " + getURI(graph));
403                 return All.standardValueAccessor;
404             }
405         }
406
407         protected VariableMap getPossibleChildVariableMap(ReadGraph graph) throws DatabaseException {
408                 if(represents == null) return All.standardPropertyDomainChildren;
409             Resource domainChildren = Layer0.getInstance(graph).domainChildren;
410                 return graph.getPossibleRelatedValue2(represents, domainChildren, 
411                                 new StandardGraphPropertyVariable(graph, this, domainChildren));
412         }
413
414         protected VariableMap getPossiblePropertyVariableMap(ReadGraph graph) throws DatabaseException {
415         if(property == null) return All.standardPropertyDomainProperties;
416         if(property.predicate == null) return null;
417                 return graph.syncRequest(new PropertyVariableMapRequest(property.predicate), TransientCacheAsyncListener.<VariableMap>instance());
418         }
419         
420         public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
421                 return property.classifications;
422         }
423         
424         @Override
425     public Map<String, Variable> collectDomainProperties(ReadGraph graph, String classification, Map<String, Variable> properties) throws DatabaseException {
426         
427         VariableMap valueMap = getPossiblePropertyVariableMap(graph);
428                 if(valueMap == null) return properties;
429                 return valueMap.getVariables(graph, this, classification, properties);
430                 
431     }
432         
433     public Collection<Variable> getProperties(ReadGraph graph, String classification) throws DatabaseException {
434         
435         VariableMap valueMap = getPossiblePropertyVariableMap(graph);
436                 if(valueMap == null) return Collections.emptyList();
437                 Map<String,Variable> propertyMap = valueMap.getVariables(graph, this, classification, null);
438         if(propertyMap == null || propertyMap.isEmpty()) return Collections.emptyList();
439         else return propertyMap.values();
440         
441     }
442         
443 }