1 package org.simantics.db.layer0.variable;
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashMap;
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.util.Layer0Utils;
30 import org.simantics.layer0.Layer0;
31 import org.simantics.utils.Development;
32 import org.simantics.utils.datastructures.Pair;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
37 private static final Logger LOGGER = LoggerFactory.getLogger(StandardGraphPropertyVariable.class);
39 protected static final PropertyInfo NO_PROPERTY = new PropertyInfo(null, null,
40 false, Collections.<String> emptySet(), null, null, null, null, null, null,
41 Collections.<String, Pair<Resource, ChildReference>> emptyMap(),
44 final public Variable parent;
45 final public Resource parentResource;
46 final public PropertyInfo property;
47 final public Resource represents;
49 transient private int hash = 0;
51 public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource property) throws DatabaseException {
52 this(graph, parent, node, (Resource)parent.getPossibleRepresents(graph), getPropertyInfo(graph, property));
55 public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource parentResource, Resource property) throws DatabaseException {
56 this(graph, parent, node, parentResource, getPropertyInfo(graph, property));
59 public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, Resource property) throws DatabaseException {
60 this(graph, parent, null, (Resource)parent.getPossibleRepresents(graph), getPropertyInfo(graph, property));
63 public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, Resource parentResource, PropertyInfo property) throws DatabaseException {
64 this(parent, null, parentResource, property, getPossibleRepresents(graph, parentResource, property.predicate));
67 public StandardGraphPropertyVariable(ReadGraph graph, Variable parent, VariableNode node, Resource parentResource, PropertyInfo property) throws DatabaseException {
68 this(parent, node, parentResource, property, getPossibleRepresents(graph, parentResource, property.predicate));
71 private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource property) throws DatabaseException {
72 return property != null ? graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance()) : NO_PROPERTY;
75 private static Resource getPossibleRepresents(ReadGraph graph, Resource parentResource, Resource predicate) throws DatabaseException {
76 if(parentResource == null || predicate == null) return null;
77 return graph.getPossibleObject(parentResource, predicate);
80 public boolean isAsserted() {
84 public StandardGraphPropertyVariable(Variable parent, VariableNode node, Resource parentResource, PropertyInfo property, Resource represents) throws DatabaseException {
86 assert parent != null;
88 this.property = property;
89 this.parentResource = parentResource;
90 this.represents = represents;
94 public String getName(ReadGraph graph) throws DatabaseException {
95 if(node != null) return node.support.manager.getName(node.node);
100 public String getPossibleLabel(ReadGraph graph) throws DatabaseException {
101 return graph.getPossibleRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
105 public String getLabel(ReadGraph graph) throws DatabaseException {
106 return graph.getRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
110 public Variable getParent(ReadGraph graph) throws DatabaseException {
115 public PropertyInfo getPropertyInfo(ReadGraph graph) throws DatabaseException {
119 @SuppressWarnings("unchecked")
121 public <T> T getValue(ReadGraph graph) throws DatabaseException {
123 if(Development.DEVELOPMENT) {
124 String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
127 //throw new ValidationException(error);
131 return (T)getValueAccessor(graph).getValue(graph, this);
135 @SuppressWarnings("unchecked")
137 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
138 // Fall back to the bindingless method, if the expected output is a Java object
139 if (binding instanceof ObjectVariantBinding)
140 return getValue(graph);
142 if(Development.DEVELOPMENT) {
143 String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
146 throw new ValidationException(error);
152 return (T)getValueAccessor(graph).getValue(graph, this, binding);
153 } catch (PendingVariableException e) {
155 } catch (Throwable t) {
156 throw new MissingVariableValueException(t);
162 public Resource getRepresents(ReadGraph graph) throws DatabaseException {
163 if(represents == null)
164 throw new InvalidVariableException("Variable is not represented by any resource (URI=" + getPossibleURI(graph) + ").");
166 // return graph.getSingleObject(parentResource, property.predicate);
170 public Resource getPossibleRepresents(ReadGraph graph) throws DatabaseException {
171 // if(parentResource == null) return null;
172 // return graph.getPossibleObject(parentResource, property.predicate);
177 public void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException {
179 if(Development.DEVELOPMENT) {
180 String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
183 //throw new ValidationException(error);
187 getValueAccessor(graph).setValue(graph, this, value, binding);
192 public void setValue(WriteGraph graph, Object value) throws DatabaseException {
194 if(Development.DEVELOPMENT) {
195 String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
198 throw new ValidationException(error);
202 getValueAccessor(graph).setValue(graph, this, value);
207 public Binding getDefaultBinding(ReadGraph graph) throws DatabaseException {
208 return Layer0Utils.getDefaultBinding(graph, this);
212 public Binding getPossibleDefaultBinding(ReadGraph graph) throws DatabaseException {
213 return Layer0Utils.getPossibleDefaultBinding(graph, this);
217 public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
220 // Binding binding = getPossibleDefaultBinding(graph);
221 // if(binding != null) return binding.type();
223 // Variant vt = getVariantValue(graph);
224 // binding = vt.getBinding();
225 // if(binding == null) throw new DatabaseException("No binding in Variant with value " + vt.getValue());
226 // return binding.type();
230 type = getValueAccessor(graph).getDatatype(graph, this);
231 } catch (Throwable t) {
232 throw new MissingVariableValueException(t);
236 String uri = this.getPossibleURI(graph);
238 throw new DatatypeNotFoundException("No data type for " + uri);
240 throw new DatatypeNotFoundException("No data type for " + this.getIdentifier());
249 public Datatype getPossibleDatatype(ReadGraph graph) throws DatabaseException {
252 return getDatatype(graph);
253 } catch (DatabaseException e) {
260 public String getUnit(ReadGraph graph) throws DatabaseException {
262 return Layer0Utils.getUnit(graph, this);
263 } catch (DatabaseException e) {
269 public Resource getPropertyResource(ReadGraph graph) {
270 return property.predicate;
274 public Resource getContainerResource(ReadGraph graph) throws DatabaseException {
275 return parentResource;
279 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
281 Map<String, Variable> result = new HashMap<String, Variable>();
282 VariableMap map = getPossibleChildVariableMap(graph);
283 if(map != null) map.getVariables(graph, this, result);
284 return result.values();
289 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
291 VariableMap map = getPossibleChildVariableMap(graph);
292 if(map == null) return null;
294 return map.getVariable(graph, this, name);
295 } catch (DatabaseException e) {
303 protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
305 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
306 if(valueMap == null) return null;
308 return valueMap.getVariable(graph, this, name);
309 } catch (DatabaseException e) {
311 } catch (Exception t) {
312 LOGGER.error("getPossibleDomainProperty is implemented incorrectly, but returns null on Exception for backward compatibility. URI="+getURI(graph)+", name="+name+".", t);
319 public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {
321 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
322 if(valueMap == null) return properties;
323 return valueMap.getVariables(graph, this, properties);
328 public Variable getPredicate(ReadGraph graph) throws DatabaseException {
329 return Variables.getVariable(graph, graph.getURI(property.predicate));
333 public Resource getPredicateResource(ReadGraph graph) throws DatabaseException {
334 return property.predicate;
338 public Resource getPossiblePredicateResource(ReadGraph graph) throws DatabaseException {
339 return property.predicate;
343 public int hashCode() {
345 final int prime = 31;
347 result = prime * result + (parent != null ? parent.hashCode() : 0);
348 result = prime * result + (node != null ? node.hashCode() : 0);
349 result = prime * result + (property.predicate != null ? property.predicate.hashCode() : 0);
350 result = prime * result + (parentResource != null ? parentResource.hashCode() : 0);
351 result = prime * result + (represents != null ? represents.hashCode() : 0);
358 public boolean equals(Object obj) {
363 if (getClass() != obj.getClass())
365 StandardGraphPropertyVariable other = (StandardGraphPropertyVariable) obj;
368 if(!node.equals(other.node)) return false;
369 } else if (other.node != null) return false;
371 if(property.predicate != null) {
372 if(!property.predicate.equals(other.property.predicate)) return false;
373 } else if (other.property.predicate != null) return false;
375 if(parentResource != null) {
376 if(!parentResource.equals(other.parentResource)) return false;
377 } else if (other.parentResource != null) return false;
380 if(!parent.equals(other.parent)) return false;
381 } else if (other.parent != null) return false;
383 if(represents != null) {
384 if(!represents.equals(other.represents)) return false;
385 } else if (other.represents != null) return false;
392 protected Variable getNameVariable(ReadGraph graph) throws DatabaseException {
393 throw new UnsupportedOperationException();
396 protected ValueAccessor getValueAccessor(ReadGraph graph) throws DatabaseException {
397 if((property == null || property == NO_PROPERTY) && parentResource == null) return All.standardValueAccessor;
398 ValueAccessor accessor = property.valueAccessor;
399 if(accessor != null) return accessor;
401 System.err.println("No value accessor for " + getURI(graph));
402 return All.standardValueAccessor;
406 protected VariableMap getPossibleChildVariableMap(ReadGraph graph) throws DatabaseException {
407 if(represents == null) return All.standardPropertyDomainChildren;
408 Resource domainChildren = Layer0.getInstance(graph).domainChildren;
409 return graph.getPossibleRelatedValue2(represents, domainChildren,
410 new StandardGraphPropertyVariable(graph, this, domainChildren));
413 protected VariableMap getPossiblePropertyVariableMap(ReadGraph graph) throws DatabaseException {
414 if(property == null) return All.standardPropertyDomainProperties;
415 if(property.predicate == null) return null;
416 return graph.syncRequest(new PropertyVariableMapRequest(property.predicate), TransientCacheAsyncListener.<VariableMap>instance());
419 public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
420 return property.classifications;
424 public Map<String, Variable> collectDomainProperties(ReadGraph graph, String classification, Map<String, Variable> properties) throws DatabaseException {
426 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
427 if(valueMap == null) return properties;
428 return valueMap.getVariables(graph, this, classification, properties);
432 public Collection<Variable> getProperties(ReadGraph graph, String classification) throws DatabaseException {
434 VariableMap valueMap = getPossiblePropertyVariableMap(graph);
435 if(valueMap == null) return Collections.emptyList();
436 Map<String,Variable> propertyMap = valueMap.getVariables(graph, this, classification, null);
437 if(propertyMap == null || propertyMap.isEmpty()) return Collections.emptyList();
438 else return propertyMap.values();