1 package org.simantics.db.layer0.function;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
5 import java.util.Collections;
\r
6 import java.util.List;
\r
7 import java.util.Map;
\r
8 import java.util.Set;
\r
9 import java.util.concurrent.atomic.AtomicReference;
\r
11 import org.simantics.databoard.Bindings;
\r
12 import org.simantics.databoard.accessor.reference.ChildReference;
\r
13 import org.simantics.databoard.accessor.reference.IndexReference;
\r
14 import org.simantics.databoard.adapter.AdaptException;
\r
15 import org.simantics.databoard.binding.Binding;
\r
16 import org.simantics.databoard.binding.error.BindingConstructionException;
\r
17 import org.simantics.databoard.binding.error.BindingException;
\r
18 import org.simantics.databoard.binding.mutable.Variant;
\r
19 import org.simantics.databoard.type.ArrayType;
\r
20 import org.simantics.databoard.type.Datatype;
\r
21 import org.simantics.databoard.type.NumberType;
\r
22 import org.simantics.databoard.util.Range;
\r
23 import org.simantics.db.Issue;
\r
24 import org.simantics.db.ReadGraph;
\r
25 import org.simantics.db.Resource;
\r
26 import org.simantics.db.Statement;
\r
27 import org.simantics.db.WriteGraph;
\r
28 import org.simantics.db.common.issue.StandardIssue;
\r
29 import org.simantics.db.common.primitiverequest.PossibleRelatedValueImplied2;
\r
30 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
\r
31 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
\r
32 import org.simantics.db.common.request.IsEnumeratedValue;
\r
33 import org.simantics.db.common.request.ObjectsWithType;
\r
34 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
\r
35 import org.simantics.db.common.utils.CommonDBUtils;
\r
36 import org.simantics.db.common.utils.Functions;
\r
37 import org.simantics.db.common.utils.ListUtils;
\r
38 import org.simantics.db.common.utils.Logger;
\r
39 import org.simantics.db.common.utils.NameUtils;
\r
40 import org.simantics.db.common.validation.L0Validations;
\r
41 import org.simantics.db.exception.DatabaseException;
\r
42 import org.simantics.db.exception.DoesNotContainValueException;
\r
43 import org.simantics.db.exception.NoSingleResultException;
\r
44 import org.simantics.db.layer0.exception.MissingVariableValueException;
\r
45 import org.simantics.db.layer0.exception.PendingVariableException;
\r
46 import org.simantics.db.layer0.exception.VariableException;
\r
47 import org.simantics.db.layer0.request.PossibleURI;
\r
48 import org.simantics.db.layer0.request.PropertyInfo;
\r
49 import org.simantics.db.layer0.request.PropertyInfoRequest;
\r
50 import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource;
\r
51 import org.simantics.db.layer0.scl.CompileResourceValueRequest;
\r
52 import org.simantics.db.layer0.scl.CompileValueRequest;
\r
53 import org.simantics.db.layer0.util.Layer0Utils;
\r
54 import org.simantics.db.layer0.util.PrimitiveValueParser;
\r
55 import org.simantics.db.layer0.variable.AbstractVariable;
\r
56 import org.simantics.db.layer0.variable.ChildVariableMapRequest;
\r
57 import org.simantics.db.layer0.variable.ExternalSetValue;
\r
58 import org.simantics.db.layer0.variable.PropertyVariableMapRequest;
\r
59 import org.simantics.db.layer0.variable.StandardComposedProperty;
\r
60 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
\r
61 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
\r
62 import org.simantics.db.layer0.variable.SubliteralPropertyVariable;
\r
63 import org.simantics.db.layer0.variable.SubliteralPropertyVariableDeprecated;
\r
64 import org.simantics.db.layer0.variable.ValueAccessor;
\r
65 import org.simantics.db.layer0.variable.Variable;
\r
66 import org.simantics.db.layer0.variable.VariableBuilder;
\r
67 import org.simantics.db.layer0.variable.VariableMap;
\r
68 import org.simantics.db.layer0.variable.VariableMapImpl;
\r
69 import org.simantics.db.layer0.variable.VariableNode;
\r
70 import org.simantics.db.layer0.variable.VariableNodeReadRunnable;
\r
71 import org.simantics.db.layer0.variable.VariableUtils;
\r
72 import org.simantics.db.layer0.variable.Variables;
\r
73 import org.simantics.db.layer0.variable.Variables.NodeStructure;
\r
74 import org.simantics.db.service.ClusteringSupport;
\r
75 import org.simantics.db.service.UndoRedoSupport;
\r
76 import org.simantics.issues.ontology.IssueResource;
\r
77 import org.simantics.layer0.Layer0;
\r
78 import org.simantics.scl.reflection.annotations.SCLValue;
\r
79 import org.simantics.scl.runtime.function.Function4;
\r
80 import org.simantics.scl.runtime.function.FunctionImpl1;
\r
81 import org.simantics.simulator.variable.exceptions.NodeManagerException;
\r
82 import org.simantics.utils.Development;
\r
83 import org.simantics.utils.datastructures.Pair;
\r
84 import org.simantics.utils.strings.StringInputValidator;
\r
86 import gnu.trove.map.hash.THashMap;
\r
87 import gnu.trove.set.hash.THashSet;
\r
91 public static Object standardGetValue1(ReadGraph graph, Variable context) throws DatabaseException {
\r
93 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
96 if(variable.node != null) {
\r
97 Variant value = Variables.requestNodeValue(graph, variable.node);
\r
98 if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException("");
\r
99 return value.getValue();
\r
104 if(variable.property.hasEnumerationRange) {
\r
105 Resource object = variable.getRepresents(graph);
\r
106 if(graph.sync(new IsEnumeratedValue(object))) {
\r
107 Layer0 L0 = Layer0.getInstance(graph);
\r
108 if(graph.isInstanceOf(object, L0.Literal)) {
\r
109 return graph.getValue(object);
\r
111 String label = graph.getPossibleRelatedValue2(variable.getRepresents(graph), L0.HasLabel, Bindings.STRING);
\r
112 if(label == null) label = graph.getPossibleRelatedValue(variable.getRepresents(graph), L0.HasName, Bindings.STRING);
\r
113 if(label == null) label = "<no label>";
\r
119 if (variable.isAsserted()) {
\r
120 if (variable.parentResource != null) {
\r
121 Layer0 L0 = Layer0.getInstance(graph);
\r
122 for(Resource assertion : graph.syncRequest(new ObjectsWithType(variable.parentResource, L0.Asserts, L0.Assertion))) {
\r
123 if(variable.property.predicate.equals(graph.getSingleObject(assertion, L0.HasPredicate))) {
\r
124 return graph.getRelatedValue2(assertion, L0.HasObject, variable);
\r
130 return graph.getValue2(variable.getRepresents(graph), variable);
\r
132 } catch (NoSingleResultException e) {
\r
133 throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
\r
134 } catch (DoesNotContainValueException e) {
\r
135 throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
\r
136 } catch (DatabaseException e) {
\r
137 throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
\r
142 public static Object standardGetValue2(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
143 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
146 if(variable.node != null) {
\r
148 Variant value = Variables.requestNodeValue(graph, variable.node, binding);
\r
149 if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException("");
\r
150 if(value == null) throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
151 return value.getValue(binding);
\r
152 } catch (AdaptException e) {
\r
153 throw new DatabaseException(e);
\r
159 Layer0 L0 = Layer0.getInstance(graph);
\r
161 if(variable.property.hasEnumerationRange) {
\r
162 Resource object = variable.getRepresents(graph);
\r
163 if(graph.sync(new IsEnumeratedValue(object))) {
\r
164 if(graph.isInstanceOf(object, L0.Literal)) {
\r
165 return graph.getValue(object);
\r
167 return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
\r
172 if (variable.isAsserted()) {
\r
173 if (variable.parentResource != null) {
\r
174 for(Resource assertion : graph.syncRequest(new ObjectsWithType(variable.parentResource, L0.Asserts, L0.Assertion))) {
\r
175 if(variable.property.predicate.equals(graph.getSingleObject(assertion, L0.HasPredicate))) {
\r
176 return graph.getRelatedValue2(assertion, L0.HasObject, context);
\r
182 return graph.getValue2(variable.getRepresents(graph), context, binding);
\r
184 } catch (NoSingleResultException e) {
\r
185 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
186 } catch (DoesNotContainValueException e) {
\r
187 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
188 } catch (DatabaseException e) {
\r
189 throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
\r
194 public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException {
\r
196 if(context instanceof StandardGraphPropertyVariable) {
\r
198 final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
201 if(variable.node != null) {
\r
203 final Binding binding = Layer0Utils.getDefaultBinding(graph, variable);
\r
205 final AtomicReference<Object> oldValueRef = new AtomicReference<Object>();
\r
207 variable.node.support.manager.getRealm().syncExec(new Runnable() {
\r
209 public void run() {
\r
211 oldValueRef.set(getNodeValue(variable, binding));
\r
212 setNodeValue(variable, value, binding);
\r
213 } catch (NodeManagerException e) {
\r
214 throw new RuntimeException(e);
\r
215 } catch (BindingException e) {
\r
216 throw new RuntimeException(e);
\r
220 } catch(RuntimeException e) {
\r
221 if(e.getCause() instanceof NodeManagerException || e.getCause() instanceof BindingException)
\r
222 throw new DatabaseException(e.getCause());
\r
225 } catch (InterruptedException e) {
\r
226 throw new DatabaseException(e);
\r
229 ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node,
\r
230 oldValueRef.get(), value, binding);
\r
231 graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext);
\r
238 Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
\r
239 if(modifier == null) modifier = VariableUtils.defaultInputModifier;
\r
241 modifier.apply(graph, context, value, Bindings.getBinding(value.getClass()));
\r
242 } catch (BindingConstructionException e) {
\r
243 throw new DatabaseException(e);
\r
248 public static void standardSetValue3(final WriteGraph graph, Variable context, final Object value, final Binding binding) throws DatabaseException {
\r
251 if(context instanceof StandardGraphPropertyVariable) {
\r
253 final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
256 if(variable.node != null) {
\r
260 variable.node.support.manager.getRealm().syncExec(new Runnable() {
\r
263 public void run() {
\r
265 Object oldValue = getNodeValue(variable, binding);
\r
266 setNodeValue(variable, value, binding);
\r
267 ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, oldValue, value, binding);
\r
268 graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext);
\r
269 } catch (NodeManagerException | BindingException e) {
\r
270 Logger.defaultLogError(e);
\r
279 } catch (InterruptedException e) {
\r
280 throw new DatabaseException(e);
\r
287 Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
\r
288 if(modifier == null) modifier = VariableUtils.defaultInputModifier;
\r
289 modifier.apply(graph, context, value, binding);
\r
293 public static Datatype getDatatypeFromValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
294 if (context instanceof AbstractVariable) {
\r
295 Binding defaultBinding = ((AbstractVariable)context).getPossibleDefaultBinding(graph);
\r
296 if (defaultBinding != null)
\r
297 return defaultBinding.type();
\r
300 Variant value = context.getVariantValue(graph);
\r
301 if (value.getBinding() == null)
\r
302 throw new DatabaseException("No value binding for " + context.getURI(graph));
\r
304 return value.getBinding().type();
\r
307 @SuppressWarnings("rawtypes")
\r
308 private static class DatatypeGetter implements VariableNodeReadRunnable {
\r
309 final VariableNode node;
\r
311 Exception exception;
\r
313 public DatatypeGetter(VariableNode node) {
\r
317 @SuppressWarnings("unchecked")
\r
319 public void run() {
\r
321 type = node.support.manager.getDatatype(node.node);
\r
322 } catch (NodeManagerException e) {
\r
327 public String toString() {
\r
328 return "DatatypeGetter(" + node.node + ")";
\r
332 public static Datatype standardGetDatatype(ReadGraph graph, Variable context) throws DatabaseException {
\r
333 if (context instanceof AbstractVariable) {
\r
334 final AbstractVariable variable = (AbstractVariable)context;
\r
335 if (variable.node != null) {
\r
337 DatatypeGetter request = new DatatypeGetter(variable.node);
\r
339 variable.node.support.manager.getRealm().syncExec(request);
\r
341 if (request.exception != null)
\r
342 throw new DatabaseException(request.exception);
\r
344 return request.type;
\r
345 } catch (InterruptedException e) {
\r
350 return getDatatypeFromValue(graph, context);
\r
353 // @SCLValue(type = "ValueAccessor")
\r
354 // public static ValueAccessor standardValueAccessor = new ValueAccessor() {
\r
357 // public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
358 // return standardGetValue(graph, (StandardGraphPropertyVariable)context);
\r
362 // public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
363 // return standardGetValue(graph, context, binding);
\r
367 // public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
\r
368 // standardSetValue(graph, context, value);
\r
372 // public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
\r
373 // standardSetValue(graph, context, value, binding);
\r
377 // public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
\r
378 // return standardGetDatatype(graph, context);
\r
383 @SCLValue(type = "ValueAccessor")
\r
384 public static ValueAccessor standardValueAccessor = new ValueAccessor() {
\r
387 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
388 ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
\r
389 if(accessor != null) return accessor.getValue(graph, context);
\r
391 return standardGetValue1(graph, context);
\r
395 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
396 ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
\r
397 if(accessor != null) return accessor.getValue(graph, context, binding);
\r
399 return standardGetValue2(graph, context, binding);
\r
403 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
\r
404 ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
\r
405 if(accessor != null) accessor.setValue(graph, context, value);
\r
407 standardSetValue2(graph, context, value);
\r
411 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
\r
412 ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
\r
413 if(accessor != null) accessor.setValue(graph, context, value, binding);
\r
415 standardSetValue3(graph, context, value, binding);
\r
419 public Datatype getDatatype(ReadGraph graph, Variable context)
\r
420 throws DatabaseException {
\r
421 ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
\r
422 if(accessor != null) return accessor.getDatatype(graph, context);
\r
424 return standardGetDatatype(graph, context);
\r
429 public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
430 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
\r
431 PropertyInfo graphProperty = getPossiblePropertyInfoFromContext(graph, variable, variable.resource, name);
\r
432 return getStandardChildDomainPropertyVariable(graph, context, graphProperty, name);
\r
435 public static Resource getPossiblePropertyResource(ReadGraph graph, AbstractVariable parent, Object node) throws DatabaseException {
\r
436 if(parent != null && parent.node != null && parent.node.node != null && parent.node.support != null) {
\r
437 String propertyURI = getPossiblePropertyURI(parent, node);
\r
438 if(propertyURI != null)
\r
439 return graph.getPossibleResource(propertyURI);
\r
444 public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, PropertyInfo graphProperty, String name) throws DatabaseException {
\r
445 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
\r
446 Object propertyNode = getPossibleNodeProperty(graph, variable, name, true);
\r
447 if(graphProperty != null && graphProperty.builder != null)
\r
448 return buildPropertyVariable(graph, variable, variable.resource, graphProperty, propertyNode);
\r
449 if(propertyNode != null) {
\r
450 // Fallback: try to ask property resource uri from NodeManager
\r
451 return createStandardGraphPropertyVariable(graph, variable, propertyNode);
\r
456 public static Map<String, Variable> getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
457 // Get properties with null identification
\r
458 return getStandardChildDomainPropertyVariables(graph, context, null, map);
\r
461 public static Map<String, Variable> getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
\r
463 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
\r
465 Collection<Object> nodeProperties = getPossibleNodeProperties(graph, variable);
\r
466 if(!nodeProperties.isEmpty()) {
\r
468 // Get variables for properties read from the graph
\r
469 Map<String,PropertyInfo> graphProperties = collectPropertyInfosFromContext(graph, variable, variable.resource);
\r
471 Set<String> used = new THashSet<String>(nodeProperties.size());
\r
473 map = ensureVariableMap(map, graphProperties.size() + nodeProperties.size());
\r
475 // Process NodeManager property nodes
\r
476 for(Object nodeProperty : nodeProperties) {
\r
477 String name = getNodeName(variable, nodeProperty);
\r
480 PropertyInfo graphProperty = graphProperties.get(name);
\r
481 if(graphProperty != null && graphProperty.builder != null) {
\r
482 if (classification != null && !graphProperty.hasClassification(classification)) continue;
\r
484 // Combine with identically named graph property
\r
485 map.put(name, buildPropertyVariable(graph, variable, variable.resource, graphProperty, nodeProperty));
\r
489 map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty));
\r
492 // Process graph properties
\r
493 for(PropertyInfo info : graphProperties.values()) {
\r
494 String name = info.name;
\r
495 if(used != null && used.contains(name)) continue;
\r
496 if (classification != null && !info.hasClassification(classification)) continue;
\r
497 if (info.builder != null) {
\r
498 map.put(name, buildPropertyVariable(graph, variable, variable.resource, info, null));
\r
505 if(variable.resource == null) return map;
\r
507 // Only graph properties
\r
508 Collection<Resource> predicates = graph.getPredicates(variable.resource);
\r
509 if(predicates.isEmpty()) return map;
\r
511 map = ensureVariableMap(map, predicates.size());
\r
513 // Process graph properties
\r
514 for(Resource predicate : predicates) {
\r
516 PropertyInfo info = graph.isImmutable(predicate) ?
\r
517 graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
\r
518 graph.syncRequest(new PropertyInfoRequest(predicate));
\r
520 if(!info.isHasProperty) continue;
\r
522 if (classification != null && !info.hasClassification(classification)) continue;
\r
523 if (info.builder != null) {
\r
524 map.put(info.name, buildPropertyVariable(graph, variable, variable.resource, info, null));
\r
535 @SCLValue(type = "VariableMap")
\r
536 public static VariableMap standardChildDomainProperties = new VariableMapImpl() {
\r
539 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
540 return getStandardChildDomainPropertyVariable(graph, context, name);
\r
544 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
545 return getStandardChildDomainPropertyVariables(graph, context, map);
\r
550 public static Variable getStandardPropertyDomainPropertyVariableFromValue(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
552 if(context instanceof StandardGraphPropertyVariable) {
\r
553 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
554 Resource literal = variable.getPossibleRepresents(graph);
\r
555 Object propertyNode = getPossibleNodeProperty(graph, variable, name, false);
\r
557 if(literal != null) {
\r
558 Variable result = getPossiblePropertyFromContext(graph, variable, literal, name, propertyNode);
\r
559 if(result != null) return result;
\r
562 Variable result = getPossibleSubliteralPropertyFromContext(graph, variable, name);
\r
563 if(result != null) return result;
\r
564 result = getPossiblePropertyFromContext(graph, variable, variable.property.predicate, name, propertyNode);
\r
565 if (result != null) return result;
\r
567 // Get possible property from NodeManager
\r
568 if (propertyNode != null)
\r
569 return createStandardGraphPropertyVariable(graph, variable, propertyNode);
\r
571 } else if (context instanceof StandardGraphChildVariable) {
\r
572 return standardChildDomainProperties.getVariable(graph, context, name);
\r
574 throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
\r
579 public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
581 if(context instanceof StandardGraphPropertyVariable) {
\r
582 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
583 map = collectPropertiesFromContext(graph, variable, variable.property.predicate, map);
\r
584 if (variable.parentResource != null) {
\r
585 Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
\r
586 if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, map);
\r
587 map=collectSubliteralProperties(graph, variable, map);
\r
590 // Get properties from VariableNode
\r
591 map = getStandardNodePropertyVariables(graph, context, map);
\r
593 } else if (context instanceof StandardGraphChildVariable) {
\r
594 return standardChildDomainProperties.getVariables(graph, context, map);
\r
596 throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
\r
601 public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
\r
603 if(context instanceof StandardGraphPropertyVariable) {
\r
604 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
605 map = collectPropertiesFromContext(graph, variable, variable.property.predicate, classification, map);
\r
606 if (variable.parentResource != null) {
\r
607 Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
\r
608 if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, classification, map);
\r
611 // Get properties from VariableNode
\r
612 map = getStandardNodePropertyVariables(graph, context, map);
\r
614 } else if (context instanceof StandardGraphChildVariable) {
\r
615 return standardChildDomainProperties.getVariables(graph, context, map);
\r
617 throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
\r
622 @SCLValue(type = "VariableMap")
\r
623 public static VariableMap standardPropertyDomainProperties = new VariableMapImpl() {
\r
625 VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
\r
626 Resource represents = context.getPossibleRepresents(graph);
\r
627 if(represents == null) return null;
\r
629 VariableMap map = graph.isImmutable(represents) ?
\r
630 graph.syncRequest(new PropertyVariableMapRequest(represents), TransientCacheListener.<VariableMap>instance()) :
\r
631 (VariableMap)graph.getPossibleRelatedValue2(represents, Layer0.getInstance(graph).domainProperties, represents);
\r
633 if(map == standardPropertyDomainProperties) return null;
\r
639 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
640 VariableMap valueMap = getValueVariableMap(graph, context);
\r
641 if(valueMap != null) return valueMap.getVariable(graph, context, name);
\r
642 return getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
\r
646 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
647 VariableMap valueMap = getValueVariableMap(graph, context);
\r
648 if(valueMap != null) return valueMap.getVariables(graph, context, map);
\r
649 else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, map);
\r
653 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
\r
654 VariableMap valueMap = getValueVariableMap(graph, context);
\r
655 if(valueMap != null) return valueMap.getVariables(graph, context, classification, map);
\r
656 else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, classification, map);
\r
661 public static Resource getPossibleGraphChild(ReadGraph graph, Variable variable, String name) throws DatabaseException {
\r
662 Resource resource = variable.getPossibleRepresents(graph);
\r
663 if(resource == null) return null;
\r
664 Map<String, Resource> graphChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
\r
665 return graphChildren.get(name);
\r
668 public static Map<String,Resource> getPossibleGraphChildren(ReadGraph graph, Variable variable) throws DatabaseException {
\r
669 Resource resource = variable.getPossibleRepresents(graph);
\r
670 if(resource == null) return Collections.emptyMap();
\r
671 return graph.syncRequest(new UnescapedChildMapOfResource(resource));
\r
674 public static Object getPossibleNodeChild(ReadGraph graph, Variable variable, String name) throws DatabaseException {
\r
675 if (!(variable instanceof AbstractVariable)) return null;
\r
676 VariableNode<?> node = ((AbstractVariable)variable).node;
\r
677 if(node == null) return null;
\r
678 NodeStructure structure = Variables.requestNodeStructure(graph, node);
\r
679 if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
\r
680 return structure.children.get(name);
\r
683 public static Collection<Object> getPossibleNodeChildren(ReadGraph graph, Variable variable) throws DatabaseException {
\r
684 if (!(variable instanceof AbstractVariable)) return null;
\r
685 VariableNode<?> node = ((AbstractVariable)variable).node;
\r
686 if(node == null) return Collections.emptyList();
\r
687 NodeStructure structure = Variables.requestNodeStructure(graph, node);
\r
688 if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
\r
689 return structure.children.values();
\r
692 public static Object getPossibleNodeProperty(ReadGraph graph, Variable variable, String name, boolean throwPending) throws DatabaseException {
\r
693 if (!(variable instanceof AbstractVariable)) return null;
\r
694 VariableNode<?> node = ((AbstractVariable)variable).node;
\r
695 if(node == null) return null;
\r
696 NodeStructure structure = Variables.requestNodeStructure(graph, node);
\r
697 if(throwPending && Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
\r
698 return structure.properties.get(name);
\r
701 public static Collection<Object> getPossibleNodeProperties(ReadGraph graph, Variable variable) throws DatabaseException {
\r
702 if (!(variable instanceof AbstractVariable)) return null;
\r
703 VariableNode<?> node = ((AbstractVariable)variable).node;
\r
704 if(node == null) return Collections.emptyList();
\r
705 NodeStructure structure = Variables.requestNodeStructure(graph, node);
\r
706 if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
\r
707 return structure.properties.values();
\r
710 @SuppressWarnings({ "rawtypes", "unchecked" })
\r
711 public static VariableNode build(VariableNode parent, Object node) {
\r
712 if(node == null) return null;
\r
713 return new VariableNode(parent.support, node);
\r
717 public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
718 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
\r
722 public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, Resource graphChild, String name) throws DatabaseException {
\r
723 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, graphChild, name);
\r
727 public static Map<String, Variable> getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
728 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
\r
732 public static Map<String, Variable> getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map<String,Resource> graphChildren, Map<String, Variable> map) throws DatabaseException {
\r
733 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, graphChildren, map);
\r
737 * Get a map of child Variables from a node manager-based Variable, combined with the existing variables in #map.
\r
738 * @param graph The read graph.
\r
739 * @param context The parent Variable.
\r
740 * @param map A map of variables into which the new variables are merged.
\r
741 * @return A map from variable names to instances
\r
742 * @throws DatabaseException
\r
744 public static Map<String, Variable> getStandardNodeChildVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
745 AbstractVariable variable = (AbstractVariable)context;
\r
746 if (variable.node == null) return map;
\r
748 Collection<Object> nodeChildren = getPossibleNodeChildren(graph, variable);
\r
749 if (nodeChildren.isEmpty()) return map;
\r
751 map = ensureVariableMap(map, nodeChildren.size());
\r
753 for(Object nodeChild : nodeChildren) {
\r
754 String name = getNodeName(variable, nodeChild);
\r
755 if (!map.containsKey(name))
\r
756 map.put(name, createStandardGraphChildVariable(variable, nodeChild));
\r
763 * Get a map of property Variables from a node manager-based Variable, combined with the existing variables in #map.
\r
764 * @param graph The read graph.
\r
765 * @param context The parent Variable.
\r
766 * @param map A map of variables into which the new variables are merged.
\r
767 * @return A map from variable names to instances
\r
768 * @throws DatabaseException
\r
770 public static Map<String, Variable> getStandardNodePropertyVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
771 AbstractVariable variable = (AbstractVariable)context;
\r
772 if (variable.node == null) return map;
\r
774 Collection<Object> nodeProperties = getPossibleNodeProperties(graph, variable);
\r
775 if (nodeProperties.isEmpty()) return map;
\r
777 map = ensureVariableMap(map, nodeProperties.size());
\r
779 for(Object nodeProperty : nodeProperties) {
\r
780 String name = getNodeName(variable, nodeProperty);
\r
781 if (!map.containsKey(name)) {
\r
782 map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty));
\r
789 @SCLValue(type = "VariableMap")
\r
790 public static VariableMap standardChildDomainChildren = new VariableMapImpl() {
\r
793 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
794 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
\r
798 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
799 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
\r
804 @SCLValue(type = "VariableMap")
\r
805 public static VariableMap standardPropertyDomainChildren = new VariableMapImpl() {
\r
808 * Get a possible non-standard VariableMap defined in the graph.
\r
809 * @param graph The graph
\r
810 * @param context The context node
\r
811 * @return A non-standard VariableMap instance for the context node,
\r
812 * or null, if not defined or defined as this instance.
\r
813 * @throws DatabaseException
\r
815 VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
\r
816 Resource represents = context.getPossibleRepresents(graph);
\r
817 if(represents == null) return null;
\r
818 VariableMap map = graph.syncRequest(new ChildVariableMapRequest(represents));
\r
819 if(map == standardPropertyDomainChildren) return null;
\r
824 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
825 // Delegate call to a non-standard variable map?
\r
826 VariableMap valueMap = getValueVariableMap(graph, context);
\r
827 if(valueMap != null) return valueMap.getVariable(graph, context, name);
\r
829 if(context instanceof StandardGraphPropertyVariable) {
\r
830 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
831 Datatype dt = variable.getDatatype(graph);
\r
832 if (dt instanceof ArrayType) {
\r
833 ChildReference ref = getPossibleIndexReference(name);
\r
835 return new SubliteralPropertyVariableDeprecated(variable, ref);
\r
838 // Check for a child node provided by the NodeManager
\r
839 if (variable.node != null) {
\r
840 Object childNode = getPossibleNodeChild(graph, variable, name);
\r
841 if (childNode != null)
\r
842 return createStandardGraphChildVariable(variable, childNode);
\r
844 return standardChildDomainChildren.getVariable(graph, context, name);
\r
845 } else if (context instanceof StandardGraphChildVariable) {
\r
846 return standardChildDomainChildren.getVariable(graph, context, name);
\r
848 throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
\r
853 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
854 // Delegate call to a non-standard variable map?
\r
855 VariableMap valueMap = getValueVariableMap(graph, context);
\r
856 if(valueMap != null) return valueMap.getVariables(graph, context, map);
\r
858 if(context instanceof StandardGraphPropertyVariable) {
\r
859 // Get child variables provided by the NodeManager
\r
860 Map<String, Variable> result = getStandardNodeChildVariables(graph, context, map);
\r
861 return standardChildDomainChildren.getVariables(graph, context, result);
\r
862 } else if (context instanceof StandardGraphChildVariable) {
\r
863 return standardChildDomainChildren.getVariables(graph, context, map);
\r
865 throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
\r
871 protected static ChildReference getPossibleIndexReference(String name) {
\r
872 if (name.startsWith("i-")) {
\r
874 int index = Integer.parseInt(name.substring(2));
\r
875 return new IndexReference(index);
\r
876 } catch (NumberFormatException e) {}
\r
881 protected static ValueAccessor getPossiblePropertyValueAccessor(ReadGraph graph, StandardGraphPropertyVariable variable) throws DatabaseException {
\r
882 if(variable.property == null) return null;
\r
883 return variable.property.valueAccessor;
\r
884 // return graph.syncRequest(new PropertyValueAccessorRequest(variable.property), TransientCacheAsyncListener.<ValueAccessor>instance());
\r
885 // return graph.syncRequest(new PossibleRelatedValueImplied2<ValueAccessor>(variable.property, Layer0.getInstance(graph).valueAccessor));
\r
888 public static ValueAccessor getPossibleValueValueAccessor(ReadGraph graph, Variable variable) throws DatabaseException {
\r
889 Resource value = variable.getPossibleRepresents(graph);
\r
890 if(value == null) return null;
\r
891 //return graph.syncRequest(new PropertyValueAccessorRequest(value));
\r
892 return graph.syncRequest(new PossibleRelatedValueImplied2<ValueAccessor>(value, Layer0.getInstance(graph).valueAccessor));
\r
895 public static PropertyInfo getPossiblePropertyInfoFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
\r
896 if(context == null) return null;
\r
897 Map<String, PropertyInfo> predicates = graph.syncRequest(new UnescapedPropertyMapOfResource(context));
\r
898 return predicates.get(name);
\r
901 public static Variable getPossiblePropertyFromContext(ReadGraph graph, Variable variable, Resource context, String name, Object propertyNode) throws DatabaseException {
\r
902 PropertyInfo info = getPossiblePropertyInfoFromContext(graph, variable, context, name);
\r
903 if(info == null || info.builder == null) return null;
\r
904 return buildPropertyVariable(graph, variable, context, info, propertyNode);
\r
907 public static Variable getPossibleSubliteralPropertyFromContext(ReadGraph graph, StandardGraphPropertyVariable variable, String name) throws DatabaseException {
\r
909 Resource predicate = variable.property.predicate;
\r
910 if(predicate == null) return null;
\r
912 PropertyInfo info = getPropertyInfo(graph, predicate);
\r
913 Pair<Resource, ChildReference> p = info.subliteralPredicates.get(name);
\r
914 if(p == null) return null;
\r
916 return new SubliteralPropertyVariable(graph, variable, p.first, p.second);
\r
920 public static Map<String, PropertyInfo> collectPropertyInfosFromContext(ReadGraph graph, Variable variable, Resource context) throws DatabaseException {
\r
921 if(context == null) return Collections.emptyMap();
\r
922 return graph.isImmutable(context) ?
\r
923 graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
\r
924 graph.syncRequest(new UnescapedPropertyMapOfResource(context));
\r
927 public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map<String, Variable> map) throws DatabaseException {
\r
929 Map<String,PropertyInfo> properties = graph.isImmutable(context) ?
\r
930 graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
\r
931 graph.syncRequest(new UnescapedPropertyMapOfResource(context));
\r
933 if(properties.isEmpty()) return map;
\r
935 map = ensureVariableMap(map, properties.size());
\r
937 for(PropertyInfo info : properties.values()) {
\r
938 String name = info.name;
\r
939 if (info.builder != null) {
\r
940 Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
\r
949 public static Map<String, Variable> collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map<String, Variable> map) throws DatabaseException {
\r
951 Resource predicate = variable.property.predicate;
\r
952 if(predicate == null) return map;
\r
954 PropertyInfo info = getPropertyInfo(graph, predicate);
\r
955 if(info.subliteralPredicates.isEmpty()) return map;
\r
957 map = ensureVariableMap(map, info.subliteralPredicates.size());
\r
959 for(Map.Entry<String, Pair<Resource, ChildReference>> entry : info.subliteralPredicates.entrySet()) {
\r
960 String key = entry.getKey();
\r
961 Pair<Resource, ChildReference> p = entry.getValue();
\r
962 if(map == null) map = new THashMap<String,Variable>();
\r
963 map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second));
\r
970 public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map<String, Variable> map) throws DatabaseException {
\r
972 if(graph.isImmutable(context)) {
\r
974 Map<String,PropertyInfo> properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
\r
975 for(PropertyInfo info : properties.values()) {
\r
977 if(info.classifications.contains(classification) && info.builder != null) {
\r
978 String name = info.name;
\r
979 Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
\r
980 if(map == null) map = new THashMap<String,Variable>();
\r
988 Collection<Resource> predicates = graph.getPredicates(context);
\r
990 if(predicates.isEmpty()) return map;
\r
992 map = ensureVariableMap(map, predicates.size());
\r
994 for(Resource predicate : predicates) {
\r
996 PropertyInfo info = graph.isImmutable(predicate) ?
\r
997 graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
\r
998 graph.syncRequest(new PropertyInfoRequest(predicate));
\r
1000 if(!info.isHasProperty) continue;
\r
1002 if(info.classifications.contains(classification) && info.builder != null) {
\r
1003 String name = info.name;
\r
1004 Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
\r
1005 if(map == null) map = new THashMap<String,Variable>();
\r
1017 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
\r
1018 public static String entityLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1019 if(context instanceof Resource) {
\r
1020 return NameUtils.getSafeLabel(graph, ((Resource)context));
\r
1021 } else if (context instanceof Variable) {
\r
1022 Variable parent = ((Variable)context).getParent(graph);
\r
1023 Resource represents = parent.getRepresents(graph);
\r
1024 return NameUtils.getSafeLabel(graph, represents);
\r
1026 throw new DatabaseException("Unknown context " + context);
\r
1030 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1031 public static Object listResources(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1032 return ListUtils.toList(graph, resource);
\r
1035 @SCLValue(type = "ReadGraph -> Resource -> Variable -> [String]")
\r
1036 public static List<String> standardClassifications(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
\r
1037 ArrayList<String> result = new ArrayList<String>();
\r
1038 Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph);
\r
1039 if(predicate != null) {
\r
1040 for(Resource type : graph.getTypes(predicate)) {
\r
1041 String uri = graph.getPossibleURI(type);
\r
1042 if(uri != null) result.add(uri);
\r
1048 @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
\r
1049 public static Boolean standardValidValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1050 return Boolean.TRUE;
\r
1053 @SCLValue(type = "ReadGraph -> Resource -> a -> StringInputValidator")
\r
1054 public static StringInputValidator standardValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1055 return StringInputValidator.PASS;
\r
1058 @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
\r
1059 public static Boolean standardRequiredValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1060 return Boolean.FALSE;
\r
1063 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
\r
1064 public static Boolean standardDefaultValue(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
\r
1065 Variable property = context.getParent(graph);
\r
1066 if(property instanceof StandardGraphPropertyVariable) {
\r
1067 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property;
\r
1068 if (variable.parentResource != null) {
\r
1069 Statement stm = graph.getPossibleStatement(variable.parentResource, variable.property.predicate);
\r
1070 return stm != null && stm.isAsserted(variable.parentResource);
\r
1073 return Boolean.FALSE;
\r
1076 @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
\r
1077 public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1078 return Boolean.FALSE;
\r
1081 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1082 public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1086 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1087 public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1088 return Functions.exec(graph, resource, graph, resource, context);
\r
1091 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1092 public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
\r
1093 if(context instanceof Variable) {
\r
1094 return CompileValueRequest.compileAndEvaluate(graph, (Variable)context);
\r
1095 } if (context instanceof Resource) {
\r
1096 return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter);
\r
1098 throw new IllegalStateException("Unknown context " + context);
\r
1102 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1103 public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
\r
1104 if(context instanceof Variable) {
\r
1105 return new StandardComposedProperty();
\r
1106 } if (context instanceof Resource) {
\r
1107 return new StandardComposedProperty();
\r
1109 throw new IllegalStateException("Unknown context " + context);
\r
1113 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1114 public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1116 class Validator extends FunctionImpl1<String, String> {
\r
1118 private final Datatype datatype;
\r
1120 public Validator(Datatype datatype) {
\r
1121 this.datatype = datatype;
\r
1125 public String apply(String input) {
\r
1127 if(datatype == null) return null;
\r
1131 if(datatype instanceof NumberType) {
\r
1133 Number number = (Number)PrimitiveValueParser.parse(input, datatype);
\r
1134 NumberType nt = (NumberType)datatype;
\r
1135 Range r = nt.getRange();
\r
1137 if(!r.contains(number)) return "Value is out of valid range";
\r
1142 } catch (NumberFormatException e) {
\r
1143 return "Not a valid floating-point number";
\r
1144 } catch (IllegalArgumentException e) {
\r
1145 return "Not a valid floating-point number";
\r
1152 if(context instanceof Variable) {
\r
1154 Variable variable = (Variable)context;
\r
1155 Variable property = variable.getParent(graph);
\r
1156 Datatype datatype = property.getPossibleDatatype(graph);
\r
1157 return new Validator(datatype);
\r
1159 } else if (context instanceof Resource) {
\r
1161 Layer0 L0 = Layer0.getInstance(graph);
\r
1162 Resource literal = (Resource)context;
\r
1163 Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class));
\r
1164 return new Validator(datatype);
\r
1168 return new Validator(null);
\r
1174 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
1175 public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
1177 return new FunctionImpl1<String, String>() {
\r
1180 public String apply(String input) {
\r
1182 String lower = input.toLowerCase();
\r
1183 if("true".equals(lower) || "false".equals(lower)) return null;
\r
1185 return "Not a valid boolean: " + input;
\r
1193 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource")
\r
1194 public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
\r
1195 Variable parent = context.getParent(graph);
\r
1196 if(parent instanceof StandardGraphChildVariable) {
\r
1197 StandardGraphChildVariable variable = (StandardGraphChildVariable)parent;
\r
1198 return variable.resource;
\r
1204 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
\r
1205 public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
1207 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
1209 if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
\r
1210 Layer0 L0 = Layer0.getInstance(graph);
\r
1211 return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel);
\r
1214 if (variable.parentResource == null)
\r
1215 throw new VariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").");
\r
1218 return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable);
\r
1219 } catch (NoSingleResultException e) {
\r
1220 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
1221 } catch (DoesNotContainValueException e) {
\r
1222 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
1227 @SCLValue(type = "ReadGraph -> Variable -> Binding -> a")
\r
1228 public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
1230 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
\r
1232 if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
\r
1233 Layer0 L0 = Layer0.getInstance(graph);
\r
1234 return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
\r
1237 if (variable.parentResource == null)
\r
1238 throw new VariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").");
\r
1241 return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable);
\r
1242 } catch (NoSingleResultException e) {
\r
1243 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
1244 } catch (DoesNotContainValueException e) {
\r
1245 throw new MissingVariableValueException(variable.getPossibleURI(graph));
\r
1250 @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b")
\r
1251 public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException {
\r
1253 Function4<WriteGraph, Variable, Object, Object, String> modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
\r
1254 if(modifier == null) modifier = VariableUtils.defaultInputModifier;
\r
1255 modifier.apply(graph, variable, value, binding);
\r
1260 static class L0Issue extends StandardIssue {
\r
1262 private final String description;
\r
1264 public L0Issue(String description, Resource type, Resource ... contexts) {
\r
1265 super(type, contexts);
\r
1266 this.description = description;
\r
1270 public Resource write(WriteGraph graph, Resource source) throws DatabaseException {
\r
1271 Layer0 L0 = Layer0.getInstance(graph);
\r
1272 IssueResource IR = IssueResource.getInstance(graph);
\r
1273 Resource issue = super.write(graph, source);
\r
1274 graph.claim(issue, IR.Issue_HasSeverity, IR.Severity_Fatal);
\r
1275 graph.addLiteral(issue, L0.HasDescription, L0.HasDescription_Inverse, description, Bindings.STRING);
\r
1281 private static List<Issue> reportInconsistency(ReadGraph graph, Resource subject, String description, List<Issue> issues) throws DatabaseException {
\r
1282 if(issues == null) issues = new ArrayList<Issue>();
\r
1283 System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description);
\r
1284 IssueResource IR = IssueResource.getInstance(graph);
\r
1285 issues.add(new L0Issue(description, IR.Issue, subject));
\r
1289 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
\r
1290 public static List<Issue> relationValidator(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1292 Layer0 L0 = Layer0.getInstance(graph);
\r
1294 List<Issue> issues = null;
\r
1296 for(Statement stm : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) {
\r
1297 Resource predicate = stm.getPredicate();
\r
1298 Resource object = stm.getObject();
\r
1299 if(!isRelation(graph, L0, predicate)) {
\r
1300 issues = reportInconsistency(graph, resource, "The predicate of a statement must be a relation: " + NameUtils.toString(graph, stm), issues);
\r
1302 if(graph.isInstanceOf(predicate, L0.FunctionalRelation)) {
\r
1303 if(graph.getObjects(resource, predicate).size() > 1)
\r
1304 issues = reportInconsistency(graph, resource,
\r
1306 NameUtils.getSafeName(graph, predicate)
\r
1307 + " is functional.", issues);
\r
1310 Collection<Resource> domain = graph.getObjects(predicate, L0.HasDomain);
\r
1311 if (!isInstanceOfAny(graph, resource, domain, true)) {
\r
1312 StringBuilder sb = new StringBuilder()
\r
1313 .append("The domain of ")
\r
1314 .append(NameUtils.getSafeName(graph, predicate))
\r
1315 .append(" relation is ");
\r
1316 orString(graph, sb, domain).append(".");
\r
1317 issues = reportInconsistency(graph, resource, sb.toString(), issues);
\r
1321 Collection<Resource> range = graph.getObjects(predicate, L0.HasRange);
\r
1322 if (!isInstanceOfAny(graph, object, range, true) && !graph.isInstanceOf(object, L0.SCLValue)) {
\r
1323 StringBuilder sb = new StringBuilder()
\r
1324 .append("The range of ")
\r
1325 .append(NameUtils.getSafeName(graph, predicate))
\r
1326 .append(" relation is ");
\r
1327 orString(graph, sb, range).append(" but current object is ")
\r
1328 .append(NameUtils.getSafeName(graph, object)).append(".");
\r
1329 issues = reportInconsistency(graph, resource, sb.toString(), issues);
\r
1334 return issues != null ? issues : Collections.<Issue>emptyList();
\r
1338 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
\r
1339 public static List<Issue> propertyValidator(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1341 List<Issue> issues = null;
\r
1343 Layer0 L0 = Layer0.getInstance(graph);
\r
1344 for(Statement stm : graph.getStatements(resource, L0.HasProperty)) {
\r
1345 Resource subject = stm.getSubject();
\r
1346 Resource predicate = stm.getPredicate();
\r
1347 String error = L0Validations.checkValueType(graph, subject, predicate);
\r
1348 if(error != null) issues = reportInconsistency(graph, subject, error, issues);
\r
1351 return issues != null ? issues : Collections.<Issue>emptyList();
\r
1356 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
\r
1357 public static List<Issue> valueValidator(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1359 List<Issue> issues = null;
\r
1361 Layer0 L0 = Layer0.getInstance(graph);
\r
1362 if(graph.hasValue(resource)) {
\r
1363 if(!graph.isInstanceOf(resource, L0.Literal)) {
\r
1364 issues = reportInconsistency(graph, resource,
\r
1365 "Resource has a value but it is not a literal.", issues);
\r
1368 // TODO check that the value is valid for the data type
\r
1372 if(graph.isInstanceOf(resource, L0.Literal)) {
\r
1373 issues = reportInconsistency(graph, resource,
\r
1374 "Resource is a literal but it does not have a value.", issues);
\r
1378 return issues != null ? issues : Collections.<Issue>emptyList();
\r
1383 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
\r
1384 public static List<Issue> uriValidator(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1386 List<Issue> issues = null;
\r
1388 Layer0 L0 = Layer0.getInstance(graph);
\r
1389 Resource parent = graph.getPossibleObject(resource, L0.PartOf);
\r
1390 if(parent != null) {
\r
1391 String parentURI = graph.syncRequest(new PossibleURI(parent));
\r
1392 if(parentURI != null) {
\r
1393 String name = graph.getPossibleRelatedValue(resource, L0.HasName);
\r
1394 if(name == null) {
\r
1395 issues = reportInconsistency(graph, resource, "Resource has a parent with URI but has no valid HasName.", issues);
\r
1400 return issues != null ? issues : Collections.<Issue>emptyList();
\r
1404 private static Resource getPossibleNearestClusterSet(ReadGraph graph, Resource base, Resource resource) throws DatabaseException {
\r
1406 ClusteringSupport cs = graph.getService(ClusteringSupport.class);
\r
1407 if(cs.isClusterSet(resource) && !base.equals(resource)) return resource;
\r
1409 Resource nearest = CommonDBUtils.getNearestOwner(graph, Collections.singletonList(resource));
\r
1410 if(nearest == null) return null;
\r
1412 return getPossibleNearestClusterSet(graph, base, nearest);
\r
1416 private static boolean quirks(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1418 if(!resource.isPersistent()) return true;
\r
1419 if(graph.isImmutable(resource)) return true;
\r
1420 if(resource.getResourceId() < 0x2000) return true;
\r
1426 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
\r
1427 public static List<Issue> clusterValidator(ReadGraph graph, Resource resource) throws DatabaseException {
\r
1429 if(!Development.DEVELOPMENT) return Collections.<Issue>emptyList();
\r
1431 if(quirks(graph, resource)) return Collections.<Issue>emptyList();
\r
1433 List<Issue> issues = null;
\r
1435 ClusteringSupport cs = graph.getService(ClusteringSupport.class);
\r
1436 Resource set = cs.getClusterSetOfCluster(resource);
\r
1438 if(set == null) return reportInconsistency(graph, resource, "Resource cluster is not part of any cluster set", issues);
\r
1440 Resource nearestSet = getPossibleNearestClusterSet(graph, resource, resource);
\r
1441 if(nearestSet == null) {
\r
1442 // This means that there is no owner since RootLibrary is a cluster set
\r
1443 return Collections.<Issue>emptyList();
\r
1446 if(!set.equals(nearestSet)) return reportInconsistency(graph, resource, "The cluster set of a resource is not the nearest owner set", issues);
\r
1448 return Collections.<Issue>emptyList();
\r
1452 private static boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection<Resource> types, boolean ifEmpty) throws DatabaseException {
\r
1453 if (types.isEmpty())
\r
1455 for (Resource type : types) {
\r
1456 if (graph.isInstanceOf(r, type)) {
\r
1463 private static StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection<Resource> rs) throws DatabaseException {
\r
1465 boolean first = true;
\r
1466 for (Resource r : rs) {
\r
1470 sb.append(NameUtils.getSafeName(graph, r));
\r
1476 public static boolean isRelation(ReadGraph g, Layer0 l0, Resource relation) throws DatabaseException {
\r
1477 return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo;
\r
1480 public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException {
\r
1481 return g.hasStatement(type, l0.Inherits) || type == l0.Entity;
\r
1484 public static Variable buildChildVariable(ReadGraph graph, Variable context, Resource graphChild, Object nodeChild) throws DatabaseException {
\r
1485 VariableBuilder builder = graph.adapt(graphChild, VariableBuilder.class);
\r
1486 return builder.buildChild(graph, context, build(((AbstractVariable)context).node, nodeChild), graphChild);
\r
1489 private static Variable buildPropertyVariable(ReadGraph graph, Variable variable, Resource parentResource, PropertyInfo graphProperty, Object propertyNode) throws DatabaseException {
\r
1490 VariableNode<?> node = variable instanceof AbstractVariable ? build(((AbstractVariable)variable).node, propertyNode) : null;
\r
1491 return graphProperty.builder.buildProperty(graph, variable, node, parentResource, graphProperty.predicate);
\r
1494 static StandardGraphChildVariable createStandardGraphChildVariable(
\r
1495 AbstractVariable parent, Object child) {
\r
1496 return new StandardGraphChildVariable(parent, build(parent.node, child), null);
\r
1499 private static StandardGraphPropertyVariable createStandardGraphPropertyVariable(
\r
1500 ReadGraph graph, AbstractVariable variable, Object nodeProperty) throws DatabaseException {
\r
1501 Resource propertyResource = getPossiblePropertyResource(graph, variable, nodeProperty);
\r
1502 return new StandardGraphPropertyVariable(graph, variable, build(variable.node, nodeProperty), null, propertyResource);
\r
1505 static Map<String, Variable> ensureVariableMap(
\r
1506 Map<String, Variable> map, int size) {
\r
1507 if(map == null) map = new THashMap<String,Variable>(size);
\r
1511 private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource predicate) throws DatabaseException {
\r
1512 return graph.syncRequest(new PropertyInfoRequest(predicate));
\r
1515 @SuppressWarnings("unchecked")
\r
1516 static String getNodeName(AbstractVariable parent, Object child) {
\r
1517 return parent.node.support.manager.getName(child);
\r
1520 @SuppressWarnings("unchecked")
\r
1521 private static Object getNodeValue(final AbstractVariable variable, final Binding binding) throws NodeManagerException, BindingException {
\r
1522 return variable.node.support.manager.getValue(variable.node.node, binding);
\r
1525 @SuppressWarnings("unchecked")
\r
1526 private static void setNodeValue(final AbstractVariable variable, final Object value, final Binding binding) throws NodeManagerException, BindingException {
\r
1527 variable.node.support.manager.setValue(variable.node.node, value, binding);
\r
1530 @SuppressWarnings("unchecked")
\r
1531 private static String getPossiblePropertyURI(AbstractVariable parent, Object node) {
\r
1532 return parent.node.support.manager.getPropertyURI(parent.node.node, node);
\r