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