X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Ffunction%2FAll.java;h=4e775e08a22e12597044218f138aef3cfcaf6637;hp=501e85f522ffb8b08c1f452c9a4e47058fb4f29e;hb=89b915a237d980f62d9ffe2caeb8a69170e0ce56;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java index 501e85f52..4e775e08a 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java @@ -1,1535 +1,1657 @@ -package org.simantics.db.layer0.function; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; - -import org.simantics.databoard.Bindings; -import org.simantics.databoard.accessor.reference.ChildReference; -import org.simantics.databoard.accessor.reference.IndexReference; -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.error.BindingConstructionException; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.databoard.type.ArrayType; -import org.simantics.databoard.type.Datatype; -import org.simantics.databoard.type.NumberType; -import org.simantics.databoard.util.Range; -import org.simantics.db.Issue; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Statement; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.issue.StandardIssue; -import org.simantics.db.common.primitiverequest.PossibleRelatedValueImplied2; -import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.common.procedure.adapter.TransientCacheListener; -import org.simantics.db.common.request.IsEnumeratedValue; -import org.simantics.db.common.request.ObjectsWithType; -import org.simantics.db.common.uri.UnescapedChildMapOfResource; -import org.simantics.db.common.utils.CommonDBUtils; -import org.simantics.db.common.utils.Functions; -import org.simantics.db.common.utils.ListUtils; -import org.simantics.db.common.utils.Logger; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.common.validation.L0Validations; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.exception.DoesNotContainValueException; -import org.simantics.db.exception.NoSingleResultException; -import org.simantics.db.layer0.exception.MissingVariableValueException; -import org.simantics.db.layer0.exception.PendingVariableException; -import org.simantics.db.layer0.exception.VariableException; -import org.simantics.db.layer0.request.PossibleURI; -import org.simantics.db.layer0.request.PropertyInfo; -import org.simantics.db.layer0.request.PropertyInfoRequest; -import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource; -import org.simantics.db.layer0.scl.CompileResourceValueRequest; -import org.simantics.db.layer0.scl.CompileValueRequest; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.db.layer0.util.PrimitiveValueParser; -import org.simantics.db.layer0.variable.AbstractVariable; -import org.simantics.db.layer0.variable.ChildVariableMapRequest; -import org.simantics.db.layer0.variable.ExternalSetValue; -import org.simantics.db.layer0.variable.PropertyVariableMapRequest; -import org.simantics.db.layer0.variable.StandardComposedProperty; -import org.simantics.db.layer0.variable.StandardGraphChildVariable; -import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; -import org.simantics.db.layer0.variable.SubliteralPropertyVariable; -import org.simantics.db.layer0.variable.SubliteralPropertyVariableDeprecated; -import org.simantics.db.layer0.variable.ValueAccessor; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.VariableBuilder; -import org.simantics.db.layer0.variable.VariableMap; -import org.simantics.db.layer0.variable.VariableMapImpl; -import org.simantics.db.layer0.variable.VariableNode; -import org.simantics.db.layer0.variable.VariableNodeReadRunnable; -import org.simantics.db.layer0.variable.VariableUtils; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.layer0.variable.Variables.NodeStructure; -import org.simantics.db.service.ClusteringSupport; -import org.simantics.db.service.UndoRedoSupport; -import org.simantics.issues.ontology.IssueResource; -import org.simantics.layer0.Layer0; -import org.simantics.scl.reflection.annotations.SCLValue; -import org.simantics.scl.runtime.function.Function4; -import org.simantics.scl.runtime.function.FunctionImpl1; -import org.simantics.simulator.variable.exceptions.NodeManagerException; -import org.simantics.utils.Development; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.strings.StringInputValidator; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.set.hash.THashSet; - -public class All { - - public static Object standardGetValue1(ReadGraph graph, Variable context) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node - if(variable.node != null) { - Variant value = Variables.requestNodeValue(graph, variable.node); - if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException(""); - return value.getValue(); - } - - try { - - if(variable.property.hasEnumerationRange) { - Resource object = variable.getRepresents(graph); - if(graph.sync(new IsEnumeratedValue(object))) { - Layer0 L0 = Layer0.getInstance(graph); - if(graph.isInstanceOf(object, L0.Literal)) { - return graph.getValue(object); - } else { - String label = graph.getPossibleRelatedValue2(variable.getRepresents(graph), L0.HasLabel, Bindings.STRING); - if(label == null) label = graph.getPossibleRelatedValue(variable.getRepresents(graph), L0.HasName, Bindings.STRING); - if(label == null) label = ""; - return label; - } - } - } - - if (variable.isAsserted()) { - if (variable.parentResource != null) { - Layer0 L0 = Layer0.getInstance(graph); - for(Resource assertion : graph.syncRequest(new ObjectsWithType(variable.parentResource, L0.Asserts, L0.Assertion))) { - if(variable.property.predicate.equals(graph.getSingleObject(assertion, L0.HasPredicate))) { - return graph.getRelatedValue2(assertion, L0.HasObject, variable); - } - } - } - } - - return graph.getValue2(variable.getRepresents(graph), variable); - - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DatabaseException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } - - public static Object standardGetValue2(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node - if(variable.node != null) { - try { - Variant value = Variables.requestNodeValue(graph, variable.node, binding); - if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException(""); - if(value == null) throw new MissingVariableValueException(variable.getPossibleURI(graph)); - return value.getValue(binding); - } catch (AdaptException e) { - throw new DatabaseException(e); - } - } - - try { - - Layer0 L0 = Layer0.getInstance(graph); - - if(variable.property.hasEnumerationRange) { - Resource object = variable.getRepresents(graph); - if(graph.sync(new IsEnumeratedValue(object))) { - if(graph.isInstanceOf(object, L0.Literal)) { - return graph.getValue(object); - } else { - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); - } - } - } - - if (variable.isAsserted()) { - if (variable.parentResource != null) { - for(Resource assertion : graph.syncRequest(new ObjectsWithType(variable.parentResource, L0.Asserts, L0.Assertion))) { - if(variable.property.predicate.equals(graph.getSingleObject(assertion, L0.HasPredicate))) { - return graph.getRelatedValue2(assertion, L0.HasObject, context); - } - } - } - } - - return graph.getValue2(variable.getRepresents(graph), context, binding); - - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DatabaseException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } - - public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - - final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node - if(variable.node != null) { - - final Binding binding = Layer0Utils.getDefaultBinding(graph, variable); - - final AtomicReference oldValueRef = new AtomicReference(); - try { - variable.node.support.manager.getRealm().syncExec(new Runnable() { - @Override - public void run() { - try { - oldValueRef.set(getNodeValue(variable, binding)); - setNodeValue(variable, value, binding); - } catch (NodeManagerException e) { - throw new RuntimeException(e); - } catch (BindingException e) { - throw new RuntimeException(e); - } - } - }); - } catch(RuntimeException e) { - if(e.getCause() instanceof NodeManagerException || e.getCause() instanceof BindingException) - throw new DatabaseException(e.getCause()); - else - throw e; - } catch (InterruptedException e) { - throw new DatabaseException(e); - } - - ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, - oldValueRef.get(), value, binding); - graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext); - - return; - } - - } - - Function4 modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); - if(modifier == null) modifier = VariableUtils.defaultInputModifier; - try { - modifier.apply(graph, context, value, Bindings.getBinding(value.getClass())); - } catch (BindingConstructionException e) { - throw new DatabaseException(e); - } - - } - - public static void standardSetValue3(final WriteGraph graph, Variable context, final Object value, final Binding binding) throws DatabaseException { - - // First from node - if(context instanceof StandardGraphPropertyVariable) { - - final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node - if(variable.node != null) { - - try { - - variable.node.support.manager.getRealm().syncExec(new Runnable() { - - @Override - public void run() { - try { - Object oldValue = getNodeValue(variable, binding); - setNodeValue(variable, value, binding); - ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, oldValue, value, binding); - graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext); - } catch (NodeManagerException | BindingException e) { - Logger.defaultLogError(e); - } - } - - - }); - - return; - - } catch (InterruptedException e) { - throw new DatabaseException(e); - } - - } - - } - - Function4 modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); - if(modifier == null) modifier = VariableUtils.defaultInputModifier; - modifier.apply(graph, context, value, binding); - - } - - public static Datatype getDatatypeFromValue(ReadGraph graph, Variable context) throws DatabaseException { - if (context instanceof AbstractVariable) { - Binding defaultBinding = ((AbstractVariable)context).getPossibleDefaultBinding(graph); - if (defaultBinding != null) - return defaultBinding.type(); - } - - Variant value = context.getVariantValue(graph); - if (value.getBinding() == null) - throw new DatabaseException("No value binding for " + context.getURI(graph)); - - return value.getBinding().type(); - } - - @SuppressWarnings("rawtypes") - private static class DatatypeGetter implements VariableNodeReadRunnable { - final VariableNode node; - Datatype type; - Exception exception; - - public DatatypeGetter(VariableNode node) { - this.node = node; - } - - @SuppressWarnings("unchecked") - @Override - public void run() { - try { - type = node.support.manager.getDatatype(node.node); - } catch (NodeManagerException e) { - exception = e; - } - } - @Override - public String toString() { - return "DatatypeGetter(" + node.node + ")"; - } - } - - public static Datatype standardGetDatatype(ReadGraph graph, Variable context) throws DatabaseException { - if (context instanceof AbstractVariable) { - final AbstractVariable variable = (AbstractVariable)context; - if (variable.node != null) { - try { - DatatypeGetter request = new DatatypeGetter(variable.node); - - variable.node.support.manager.getRealm().syncExec(request); - - if (request.exception != null) - throw new DatabaseException(request.exception); - - return request.type; - } catch (InterruptedException e) { - } - } - } - - return getDatatypeFromValue(graph, context); - } - -// @SCLValue(type = "ValueAccessor") -// public static ValueAccessor standardValueAccessor = new ValueAccessor() { -// -// @Override -// public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { -// return standardGetValue(graph, (StandardGraphPropertyVariable)context); -// } -// -// @Override -// public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { -// return standardGetValue(graph, context, binding); -// } -// -// @Override -// public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { -// standardSetValue(graph, context, value); -// } -// -// @Override -// public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { -// standardSetValue(graph, context, value, binding); -// } -// -// @Override -// public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException { -// return standardGetDatatype(graph, context); -// } -// -// }; - - @SCLValue(type = "ValueAccessor") - public static ValueAccessor standardValueAccessor = new ValueAccessor() { - - @Override - public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { - ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); - if(accessor != null) return accessor.getValue(graph, context); - else - return standardGetValue1(graph, context); - } - - @Override - public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); - if(accessor != null) return accessor.getValue(graph, context, binding); - else - return standardGetValue2(graph, context, binding); - } - - @Override - public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { - ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); - if(accessor != null) accessor.setValue(graph, context, value); - else - standardSetValue2(graph, context, value); - } - - @Override - public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { - ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); - if(accessor != null) accessor.setValue(graph, context, value, binding); - else - standardSetValue3(graph, context, value, binding); - } - - @Override - public Datatype getDatatype(ReadGraph graph, Variable context) - throws DatabaseException { - ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); - if(accessor != null) return accessor.getDatatype(graph, context); - else - return standardGetDatatype(graph, context); - } - - }; - - public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - PropertyInfo graphProperty = getPossiblePropertyInfoFromContext(graph, variable, variable.resource, name); - return getStandardChildDomainPropertyVariable(graph, context, graphProperty, name); - } - - public static Resource getPossiblePropertyResource(ReadGraph graph, AbstractVariable parent, Object node) throws DatabaseException { - if(parent != null && parent.node != null && parent.node.node != null && parent.node.support != null) { - String propertyURI = getPossiblePropertyURI(parent, node); - if(propertyURI != null) - return graph.getPossibleResource(propertyURI); - } - return null; - } - - public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, PropertyInfo graphProperty, String name) throws DatabaseException { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - Object propertyNode = getPossibleNodeProperty(graph, variable, name, true); - if(graphProperty != null && graphProperty.builder != null) - return buildPropertyVariable(graph, variable, variable.resource, graphProperty, propertyNode); - if(propertyNode != null) { - // Fallback: try to ask property resource uri from NodeManager - return createStandardGraphPropertyVariable(graph, variable, propertyNode); - } - return null; - } - - public static Map getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - // Get properties with null identification - return getStandardChildDomainPropertyVariables(graph, context, null, map); - } - - public static Map getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { - - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - - Collection nodeProperties = getPossibleNodeProperties(graph, variable); - if(!nodeProperties.isEmpty()) { - - // Get variables for properties read from the graph - Map graphProperties = collectPropertyInfosFromContext(graph, variable, variable.resource); - - Set used = new THashSet(nodeProperties.size()); - - map = ensureVariableMap(map, graphProperties.size() + nodeProperties.size()); - - // Process NodeManager property nodes - for(Object nodeProperty : nodeProperties) { - String name = getNodeName(variable, nodeProperty); - used.add(name); - - PropertyInfo graphProperty = graphProperties.get(name); - if(graphProperty != null && graphProperty.builder != null) { - if (classification != null && !graphProperty.hasClassification(classification)) continue; - - // Combine with identically named graph property - map.put(name, buildPropertyVariable(graph, variable, variable.resource, graphProperty, nodeProperty)); - continue; - } - - map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty)); - } - - // Process graph properties - for(PropertyInfo info : graphProperties.values()) { - String name = info.name; - if(used != null && used.contains(name)) continue; - if (classification != null && !info.hasClassification(classification)) continue; - if (info.builder != null) { - map.put(name, buildPropertyVariable(graph, variable, variable.resource, info, null)); - } - } - return map; - - } else { - - if(variable.resource == null) return map; - - // Only graph properties - Collection predicates = graph.getPredicates(variable.resource); - if(predicates.isEmpty()) return map; - - map = ensureVariableMap(map, predicates.size()); - - // Process graph properties - for(Resource predicate : predicates) { - - PropertyInfo info = graph.isImmutable(predicate) ? - graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.instance()) : - graph.syncRequest(new PropertyInfoRequest(predicate)); - - if(!info.isHasProperty) continue; - - if (classification != null && !info.hasClassification(classification)) continue; - if (info.builder != null) { - map.put(info.name, buildPropertyVariable(graph, variable, variable.resource, info, null)); - } - - } - - return map; - - } - - } - - @SCLValue(type = "VariableMap") - public static VariableMap standardChildDomainProperties = new VariableMapImpl() { - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - return getStandardChildDomainPropertyVariable(graph, context, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - return getStandardChildDomainPropertyVariables(graph, context, map); - } - - }; - - public static Variable getStandardPropertyDomainPropertyVariableFromValue(ReadGraph graph, Variable context, String name) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - Resource literal = variable.getPossibleRepresents(graph); - Object propertyNode = getPossibleNodeProperty(graph, variable, name, false); - - if(literal != null) { - Variable result = getPossiblePropertyFromContext(graph, variable, literal, name, propertyNode); - if(result != null) return result; - } - - Variable result = getPossibleSubliteralPropertyFromContext(graph, variable, name); - if(result != null) return result; - result = getPossiblePropertyFromContext(graph, variable, variable.property.predicate, name, propertyNode); - if (result != null) return result; - - // Get possible property from NodeManager - if (propertyNode != null) - return createStandardGraphPropertyVariable(graph, variable, propertyNode); - return null; - } else if (context instanceof StandardGraphChildVariable) { - return standardChildDomainProperties.getVariable(graph, context, name); - } else { - throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); - } - - } - - public static Map getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map map) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - map = collectPropertiesFromContext(graph, variable, variable.property.predicate, map); - if (variable.parentResource != null) { - Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate); - if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, map); - map=collectSubliteralProperties(graph, variable, map); - } - - // Get properties from VariableNode - map = getStandardNodePropertyVariables(graph, context, map); - return map; - } else if (context instanceof StandardGraphChildVariable) { - return standardChildDomainProperties.getVariables(graph, context, map); - } else { - throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); - } - - } - - public static Map getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - map = collectPropertiesFromContext(graph, variable, variable.property.predicate, classification, map); - if (variable.parentResource != null) { - Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate); - if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, classification, map); - } - - // Get properties from VariableNode - map = getStandardNodePropertyVariables(graph, context, map); - return map; - } else if (context instanceof StandardGraphChildVariable) { - return standardChildDomainProperties.getVariables(graph, context, map); - } else { - throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); - } - - } - - @SCLValue(type = "VariableMap") - public static VariableMap standardPropertyDomainProperties = new VariableMapImpl() { - - VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException { - Resource represents = context.getPossibleRepresents(graph); - if(represents == null) return null; - - VariableMap map = graph.isImmutable(represents) ? - graph.syncRequest(new PropertyVariableMapRequest(represents), TransientCacheListener.instance()) : - (VariableMap)graph.getPossibleRelatedValue2(represents, Layer0.getInstance(graph).domainProperties, represents); - - if(map == standardPropertyDomainProperties) return null; - else return map; - - } - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - VariableMap valueMap = getValueVariableMap(graph, context); - if(valueMap != null) return valueMap.getVariable(graph, context, name); - return getStandardPropertyDomainPropertyVariableFromValue(graph, context, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - VariableMap valueMap = getValueVariableMap(graph, context); - if(valueMap != null) return valueMap.getVariables(graph, context, map); - else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, map); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { - VariableMap valueMap = getValueVariableMap(graph, context); - if(valueMap != null) return valueMap.getVariables(graph, context, classification, map); - else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, classification, map); - } - - }; - - public static Resource getPossibleGraphChild(ReadGraph graph, Variable variable, String name) throws DatabaseException { - Resource resource = variable.getPossibleRepresents(graph); - if(resource == null) return null; - Map graphChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource)); - return graphChildren.get(name); - } - - public static Map getPossibleGraphChildren(ReadGraph graph, Variable variable) throws DatabaseException { - Resource resource = variable.getPossibleRepresents(graph); - if(resource == null) return Collections.emptyMap(); - return graph.syncRequest(new UnescapedChildMapOfResource(resource)); - } - - public static Object getPossibleNodeChild(ReadGraph graph, Variable variable, String name) throws DatabaseException { - if (!(variable instanceof AbstractVariable)) return null; - VariableNode node = ((AbstractVariable)variable).node; - if(node == null) return null; - NodeStructure structure = Variables.requestNodeStructure(graph, node); - if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); - return structure.children.get(name); - } - - public static Collection getPossibleNodeChildren(ReadGraph graph, Variable variable) throws DatabaseException { - if (!(variable instanceof AbstractVariable)) return null; - VariableNode node = ((AbstractVariable)variable).node; - if(node == null) return Collections.emptyList(); - NodeStructure structure = Variables.requestNodeStructure(graph, node); - if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); - return structure.children.values(); - } - - public static Object getPossibleNodeProperty(ReadGraph graph, Variable variable, String name, boolean throwPending) throws DatabaseException { - if (!(variable instanceof AbstractVariable)) return null; - VariableNode node = ((AbstractVariable)variable).node; - if(node == null) return null; - NodeStructure structure = Variables.requestNodeStructure(graph, node); - if(throwPending && Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); - return structure.properties.get(name); - } - - public static Collection getPossibleNodeProperties(ReadGraph graph, Variable variable) throws DatabaseException { - if (!(variable instanceof AbstractVariable)) return null; - VariableNode node = ((AbstractVariable)variable).node; - if(node == null) return Collections.emptyList(); - NodeStructure structure = Variables.requestNodeStructure(graph, node); - if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); - return structure.properties.values(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static VariableNode build(VariableNode parent, Object node) { - if(node == null) return null; - return new VariableNode(parent.support, node); - } - - @Deprecated - public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name); - } - - @Deprecated - public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, Resource graphChild, String name) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, graphChild, name); - } - - @Deprecated - public static Map getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); - } - - @Deprecated - public static Map getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map graphChildren, Map map) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, graphChildren, map); - } - - /** - * Get a map of child Variables from a node manager-based Variable, combined with the existing variables in #map. - * @param graph The read graph. - * @param context The parent Variable. - * @param map A map of variables into which the new variables are merged. - * @return A map from variable names to instances - * @throws DatabaseException - */ - public static Map getStandardNodeChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - AbstractVariable variable = (AbstractVariable)context; - if (variable.node == null) return map; - - Collection nodeChildren = getPossibleNodeChildren(graph, variable); - if (nodeChildren.isEmpty()) return map; - - map = ensureVariableMap(map, nodeChildren.size()); - - for(Object nodeChild : nodeChildren) { - String name = getNodeName(variable, nodeChild); - if (!map.containsKey(name)) - map.put(name, createStandardGraphChildVariable(variable, nodeChild)); - } - - return map; - } - - /** - * Get a map of property Variables from a node manager-based Variable, combined with the existing variables in #map. - * @param graph The read graph. - * @param context The parent Variable. - * @param map A map of variables into which the new variables are merged. - * @return A map from variable names to instances - * @throws DatabaseException - */ - public static Map getStandardNodePropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - AbstractVariable variable = (AbstractVariable)context; - if (variable.node == null) return map; - - Collection nodeProperties = getPossibleNodeProperties(graph, variable); - if (nodeProperties.isEmpty()) return map; - - map = ensureVariableMap(map, nodeProperties.size()); - - for(Object nodeProperty : nodeProperties) { - String name = getNodeName(variable, nodeProperty); - if (!map.containsKey(name)) { - map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty)); - } - } - - return map; - } - - @SCLValue(type = "VariableMap") - public static VariableMap standardChildDomainChildren = new VariableMapImpl() { - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); - } - - }; - - @SCLValue(type = "VariableMap") - public static VariableMap standardPropertyDomainChildren = new VariableMapImpl() { - - /** - * Get a possible non-standard VariableMap defined in the graph. - * @param graph The graph - * @param context The context node - * @return A non-standard VariableMap instance for the context node, - * or null, if not defined or defined as this instance. - * @throws DatabaseException - */ - VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException { - Resource represents = context.getPossibleRepresents(graph); - if(represents == null) return null; - VariableMap map = graph.syncRequest(new ChildVariableMapRequest(represents)); - if(map == standardPropertyDomainChildren) return null; - else return map; - } - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - // Delegate call to a non-standard variable map? - VariableMap valueMap = getValueVariableMap(graph, context); - if(valueMap != null) return valueMap.getVariable(graph, context, name); - - if(context instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - Datatype dt = variable.getDatatype(graph); - if (dt instanceof ArrayType) { - ChildReference ref = getPossibleIndexReference(name); - if (ref != null) - return new SubliteralPropertyVariableDeprecated(variable, ref); - } - - // Check for a child node provided by the NodeManager - if (variable.node != null) { - Object childNode = getPossibleNodeChild(graph, variable, name); - if (childNode != null) - return createStandardGraphChildVariable(variable, childNode); - } - return standardChildDomainChildren.getVariable(graph, context, name); - } else if (context instanceof StandardGraphChildVariable) { - return standardChildDomainChildren.getVariable(graph, context, name); - } else { - throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); - } - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - // Delegate call to a non-standard variable map? - VariableMap valueMap = getValueVariableMap(graph, context); - if(valueMap != null) return valueMap.getVariables(graph, context, map); - - if(context instanceof StandardGraphPropertyVariable) { - // Get child variables provided by the NodeManager - Map result = getStandardNodeChildVariables(graph, context, map); - return standardChildDomainChildren.getVariables(graph, context, result); - } else if (context instanceof StandardGraphChildVariable) { - return standardChildDomainChildren.getVariables(graph, context, map); - } else { - throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); - } - } - - }; - - protected static ChildReference getPossibleIndexReference(String name) { - if (name.startsWith("i-")) { - try { - int index = Integer.parseInt(name.substring(2)); - return new IndexReference(index); - } catch (NumberFormatException e) {} - } - return null; - } - - protected static ValueAccessor getPossiblePropertyValueAccessor(ReadGraph graph, StandardGraphPropertyVariable variable) throws DatabaseException { - if(variable.property == null) return null; - return variable.property.valueAccessor; -// return graph.syncRequest(new PropertyValueAccessorRequest(variable.property), TransientCacheAsyncListener.instance()); -// return graph.syncRequest(new PossibleRelatedValueImplied2(variable.property, Layer0.getInstance(graph).valueAccessor)); - } - - public static ValueAccessor getPossibleValueValueAccessor(ReadGraph graph, Variable variable) throws DatabaseException { - Resource value = variable.getPossibleRepresents(graph); - if(value == null) return null; - //return graph.syncRequest(new PropertyValueAccessorRequest(value)); - return graph.syncRequest(new PossibleRelatedValueImplied2(value, Layer0.getInstance(graph).valueAccessor)); - } - - public static PropertyInfo getPossiblePropertyInfoFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException { - if(context == null) return null; - Map predicates = graph.syncRequest(new UnescapedPropertyMapOfResource(context)); - return predicates.get(name); - } - - public static Variable getPossiblePropertyFromContext(ReadGraph graph, Variable variable, Resource context, String name, Object propertyNode) throws DatabaseException { - PropertyInfo info = getPossiblePropertyInfoFromContext(graph, variable, context, name); - if(info == null || info.builder == null) return null; - return buildPropertyVariable(graph, variable, context, info, propertyNode); - } - - public static Variable getPossibleSubliteralPropertyFromContext(ReadGraph graph, StandardGraphPropertyVariable variable, String name) throws DatabaseException { - - Resource predicate = variable.property.predicate; - if(predicate == null) return null; - - PropertyInfo info = getPropertyInfo(graph, predicate); - Pair p = info.subliteralPredicates.get(name); - if(p == null) return null; - - return new SubliteralPropertyVariable(graph, variable, p.first, p.second); - - } - - public static Map collectPropertyInfosFromContext(ReadGraph graph, Variable variable, Resource context) throws DatabaseException { - if(context == null) return Collections.emptyMap(); - return graph.isImmutable(context) ? - graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()) : - graph.syncRequest(new UnescapedPropertyMapOfResource(context)); - } - - public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map map) throws DatabaseException { - - Map properties = graph.isImmutable(context) ? - graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()) : - graph.syncRequest(new UnescapedPropertyMapOfResource(context)); - - if(properties.isEmpty()) return map; - - map = ensureVariableMap(map, properties.size()); - - for(PropertyInfo info : properties.values()) { - String name = info.name; - if (info.builder != null) { - Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); - map.put(name, v); - } - } - - return map; - - } - - public static Map collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map map) throws DatabaseException { - - Resource predicate = variable.property.predicate; - if(predicate == null) return map; - - PropertyInfo info = getPropertyInfo(graph, predicate); - if(info.subliteralPredicates.isEmpty()) return map; - - map = ensureVariableMap(map, info.subliteralPredicates.size()); - - for(Map.Entry> entry : info.subliteralPredicates.entrySet()) { - String key = entry.getKey(); - Pair p = entry.getValue(); - if(map == null) map = new THashMap(); - map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second)); - } - - return map; - - } - - public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map map) throws DatabaseException { - - if(graph.isImmutable(context)) { - - Map properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()); - for(PropertyInfo info : properties.values()) { - - if(info.classifications.contains(classification) && info.builder != null) { - String name = info.name; - Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); - if(map == null) map = new THashMap(); - map.put(name, v); - } - - } - - } else { - - Collection predicates = graph.getPredicates(context); - - if(predicates.isEmpty()) return map; - - map = ensureVariableMap(map, predicates.size()); - - for(Resource predicate : predicates) { - - PropertyInfo info = graph.isImmutable(predicate) ? - graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.instance()) : - graph.syncRequest(new PropertyInfoRequest(predicate)); - - if(!info.isHasProperty) continue; - - if(info.classifications.contains(classification) && info.builder != null) { - String name = info.name; - Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); - if(map == null) map = new THashMap(); - map.put(name, v); - } - - } - - } - - return map; - - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> String") - public static String entityLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - if(context instanceof Resource) { - return NameUtils.getSafeLabel(graph, ((Resource)context)); - } else if (context instanceof Variable) { - Variable parent = ((Variable)context).getParent(graph); - Resource represents = parent.getRepresents(graph); - return NameUtils.getSafeLabel(graph, represents); - } else { - throw new DatabaseException("Unknown context " + context); - } - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object listResources(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return ListUtils.toList(graph, resource); - } - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> [String]") - public static List standardClassifications(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - ArrayList result = new ArrayList(); - Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph); - if(predicate != null) { - for(Resource type : graph.getTypes(predicate)) { - String uri = graph.getPossibleURI(type); - if(uri != null) result.add(uri); - } - } - return result; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") - public static Boolean standardValidValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.TRUE; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> StringInputValidator") - public static StringInputValidator standardValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return StringInputValidator.PASS; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") - public static Boolean standardRequiredValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.FALSE; - } - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean") - public static Boolean standardDefaultValue(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - Variable property = context.getParent(graph); - if(property instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property; - if (variable.parentResource != null) { - Statement stm = graph.getPossibleStatement(variable.parentResource, variable.property.predicate); - return stm != null && stm.isAsserted(variable.parentResource); - } - } - return Boolean.FALSE; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") - public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.FALSE; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return resource; - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Functions.exec(graph, resource, graph, resource, context); - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { - return CompileValueRequest.compileAndEvaluate(graph, (Variable)context); - } if (context instanceof Resource) { - return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter); - } else { - throw new IllegalStateException("Unknown context " + context); - } - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { - return new StandardComposedProperty(); - } if (context instanceof Resource) { - return new StandardComposedProperty(); - } else { - throw new IllegalStateException("Unknown context " + context); - } - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - - class Validator extends FunctionImpl1 { - - private final Datatype datatype; - - public Validator(Datatype datatype) { - this.datatype = datatype; - } - - @Override - public String apply(String input) { - - if(datatype == null) return null; - - try { - - if(datatype instanceof NumberType) { - - Number number = (Number)PrimitiveValueParser.parse(input, datatype); - NumberType nt = (NumberType)datatype; - Range r = nt.getRange(); - if(r != null) { - if(!r.contains(number)) return "Value is out of valid range"; - } - } - return null; - - } catch (NumberFormatException e) { - return "Not a valid floating-point number"; - } catch (IllegalArgumentException e) { - return "Not a valid floating-point number"; - } - - } - - } - - if(context instanceof Variable) { - - Variable variable = (Variable)context; - Variable property = variable.getParent(graph); - Datatype datatype = property.getPossibleDatatype(graph); - return new Validator(datatype); - - } else if (context instanceof Resource) { - - Layer0 L0 = Layer0.getInstance(graph); - Resource literal = (Resource)context; - Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); - return new Validator(datatype); - - } else { - - return new Validator(null); - - } - - } - - @SCLValue(type = "ReadGraph -> Resource -> a -> b") - public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - - return new FunctionImpl1() { - - @Override - public String apply(String input) { - - String lower = input.toLowerCase(); - if("true".equals(lower) || "false".equals(lower)) return null; - - return "Not a valid boolean: " + input; - - } - - }; - - } - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource") - public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - Variable parent = context.getParent(graph); - if(parent instanceof StandardGraphChildVariable) { - StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; - return variable.resource; - } - return null; - } - - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") - public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); - } - - if (variable.parentResource == null) - throw new VariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); - - try { - return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } - - } - - @SCLValue(type = "ReadGraph -> Variable -> Binding -> a") - public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); - } - - if (variable.parentResource == null) - throw new VariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); - - try { - return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } - - } - - @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b") - public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException { - - Function4 modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); - if(modifier == null) modifier = VariableUtils.defaultInputModifier; - modifier.apply(graph, variable, value, binding); - return null; - - } - - static class L0Issue extends StandardIssue { - - private final String description; - - public L0Issue(String description, Resource type, Resource ... contexts) { - super(type, contexts); - this.description = description; - } - - @Override - public Resource write(WriteGraph graph, Resource source) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - IssueResource IR = IssueResource.getInstance(graph); - Resource issue = super.write(graph, source); - graph.claim(issue, IR.Issue_HasSeverity, IR.Severity_Fatal); - graph.addLiteral(issue, L0.HasDescription, L0.HasDescription_Inverse, description, Bindings.STRING); - return issue; - } - - } - - private static List reportInconsistency(ReadGraph graph, Resource subject, String description, List issues) throws DatabaseException { - if(issues == null) issues = new ArrayList(); - System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description); - IssueResource IR = IssueResource.getInstance(graph); - issues.add(new L0Issue(description, IR.Issue, subject)); - return issues; - } - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List relationValidator(ReadGraph graph, Resource resource) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - - List issues = null; - - for(Statement stm : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) { - Resource predicate = stm.getPredicate(); - Resource object = stm.getObject(); - if(!isRelation(graph, L0, predicate)) { - issues = reportInconsistency(graph, resource, "The predicate of a statement must be a relation: " + NameUtils.toString(graph, stm), issues); - } - if(graph.isInstanceOf(predicate, L0.FunctionalRelation)) { - if(graph.getObjects(resource, predicate).size() > 1) - issues = reportInconsistency(graph, resource, - "Relation " + - NameUtils.getSafeName(graph, predicate) - + " is functional.", issues); - } - { - Collection domain = graph.getObjects(predicate, L0.HasDomain); - if (!isInstanceOfAny(graph, resource, domain, true)) { - StringBuilder sb = new StringBuilder() - .append("The domain of ") - .append(NameUtils.getSafeName(graph, predicate)) - .append(" relation is "); - orString(graph, sb, domain).append("."); - issues = reportInconsistency(graph, resource, sb.toString(), issues); - } - } - { - Collection range = graph.getObjects(predicate, L0.HasRange); - if (!isInstanceOfAny(graph, object, range, true) && !graph.isInstanceOf(object, L0.SCLValue)) { - StringBuilder sb = new StringBuilder() - .append("The range of ") - .append(NameUtils.getSafeName(graph, predicate)) - .append(" relation is "); - orString(graph, sb, range).append(" but current object is ") - .append(NameUtils.getSafeName(graph, object)).append("."); - issues = reportInconsistency(graph, resource, sb.toString(), issues); - } - } - } - - return issues != null ? issues : Collections.emptyList(); - - } - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List propertyValidator(ReadGraph graph, Resource resource) throws DatabaseException { - - List issues = null; - - Layer0 L0 = Layer0.getInstance(graph); - for(Statement stm : graph.getStatements(resource, L0.HasProperty)) { - Resource subject = stm.getSubject(); - Resource predicate = stm.getPredicate(); - String error = L0Validations.checkValueType(graph, subject, predicate); - if(error != null) issues = reportInconsistency(graph, subject, error, issues); - } - - return issues != null ? issues : Collections.emptyList(); - - } - - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List valueValidator(ReadGraph graph, Resource resource) throws DatabaseException { - - List issues = null; - - Layer0 L0 = Layer0.getInstance(graph); - if(graph.hasValue(resource)) { - if(!graph.isInstanceOf(resource, L0.Literal)) { - issues = reportInconsistency(graph, resource, - "Resource has a value but it is not a literal.", issues); - } - else { - // TODO check that the value is valid for the data type - } - } - else { - if(graph.isInstanceOf(resource, L0.Literal)) { - issues = reportInconsistency(graph, resource, - "Resource is a literal but it does not have a value.", issues); - } - } - - return issues != null ? issues : Collections.emptyList(); - - } - - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List uriValidator(ReadGraph graph, Resource resource) throws DatabaseException { - - List issues = null; - - Layer0 L0 = Layer0.getInstance(graph); - Resource parent = graph.getPossibleObject(resource, L0.PartOf); - if(parent != null) { - String parentURI = graph.syncRequest(new PossibleURI(parent)); - if(parentURI != null) { - String name = graph.getPossibleRelatedValue(resource, L0.HasName); - if(name == null) { - issues = reportInconsistency(graph, resource, "Resource has a parent with URI but has no valid HasName.", issues); - } - } - } - - return issues != null ? issues : Collections.emptyList(); - - } - - private static Resource getPossibleNearestClusterSet(ReadGraph graph, Resource base, Resource resource) throws DatabaseException { - - ClusteringSupport cs = graph.getService(ClusteringSupport.class); - if(cs.isClusterSet(resource) && !base.equals(resource)) return resource; - - Resource nearest = CommonDBUtils.getNearestOwner(graph, Collections.singletonList(resource)); - if(nearest == null) return null; - - return getPossibleNearestClusterSet(graph, base, nearest); - - } - - private static boolean quirks(ReadGraph graph, Resource resource) throws DatabaseException { - - if(!resource.isPersistent()) return true; - if(graph.isImmutable(resource)) return true; - if(resource.getResourceId() < 0x2000) return true; - - return false; - - } - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List clusterValidator(ReadGraph graph, Resource resource) throws DatabaseException { - - if(!Development.DEVELOPMENT) return Collections.emptyList(); - - if(quirks(graph, resource)) return Collections.emptyList(); - - List issues = null; - - ClusteringSupport cs = graph.getService(ClusteringSupport.class); - Resource set = cs.getClusterSetOfCluster(resource); - - if(set == null) return reportInconsistency(graph, resource, "Resource cluster is not part of any cluster set", issues); - - Resource nearestSet = getPossibleNearestClusterSet(graph, resource, resource); - if(nearestSet == null) { - // This means that there is no owner since RootLibrary is a cluster set - return Collections.emptyList(); - } - - if(!set.equals(nearestSet)) return reportInconsistency(graph, resource, "The cluster set of a resource is not the nearest owner set", issues); - - return Collections.emptyList(); - - } - - private static boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection types, boolean ifEmpty) throws DatabaseException { - if (types.isEmpty()) - return ifEmpty; - for (Resource type : types) { - if (graph.isInstanceOf(r, type)) { - return true; - } - } - return false; - } - - private static StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection rs) throws DatabaseException { - sb.append("("); - boolean first = true; - for (Resource r : rs) { - if (!first) - sb.append(" | "); - first = false; - sb.append(NameUtils.getSafeName(graph, r)); - } - sb.append(")"); - return sb; - } - - public static boolean isRelation(ReadGraph g, Layer0 l0, Resource relation) throws DatabaseException { - return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo; - } - - public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException { - return g.hasStatement(type, l0.Inherits) || type == l0.Entity; - } - - public static Variable buildChildVariable(ReadGraph graph, Variable context, Resource graphChild, Object nodeChild) throws DatabaseException { - VariableBuilder builder = graph.adapt(graphChild, VariableBuilder.class); - return builder.buildChild(graph, context, build(((AbstractVariable)context).node, nodeChild), graphChild); - } - - private static Variable buildPropertyVariable(ReadGraph graph, Variable variable, Resource parentResource, PropertyInfo graphProperty, Object propertyNode) throws DatabaseException { - VariableNode node = variable instanceof AbstractVariable ? build(((AbstractVariable)variable).node, propertyNode) : null; - return graphProperty.builder.buildProperty(graph, variable, node, parentResource, graphProperty.predicate); - } - - static StandardGraphChildVariable createStandardGraphChildVariable( - AbstractVariable parent, Object child) { - return new StandardGraphChildVariable(parent, build(parent.node, child), null); - } - - private static StandardGraphPropertyVariable createStandardGraphPropertyVariable( - ReadGraph graph, AbstractVariable variable, Object nodeProperty) throws DatabaseException { - Resource propertyResource = getPossiblePropertyResource(graph, variable, nodeProperty); - return new StandardGraphPropertyVariable(graph, variable, build(variable.node, nodeProperty), null, propertyResource); - } - - static Map ensureVariableMap( - Map map, int size) { - if(map == null) map = new THashMap(size); - return map; - } - - private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource predicate) throws DatabaseException { - return graph.syncRequest(new PropertyInfoRequest(predicate)); - } - - @SuppressWarnings("unchecked") - static String getNodeName(AbstractVariable parent, Object child) { - return parent.node.support.manager.getName(child); - } - - @SuppressWarnings("unchecked") - private static Object getNodeValue(final AbstractVariable variable, final Binding binding) throws NodeManagerException, BindingException { - return variable.node.support.manager.getValue(variable.node.node, binding); - } - - @SuppressWarnings("unchecked") - private static void setNodeValue(final AbstractVariable variable, final Object value, final Binding binding) throws NodeManagerException, BindingException { - variable.node.support.manager.setValue(variable.node.node, value, binding); - } - - @SuppressWarnings("unchecked") - private static String getPossiblePropertyURI(AbstractVariable parent, Object node) { - return parent.node.support.manager.getPropertyURI(parent.node.node, node); - } - +package org.simantics.db.layer0.function; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.accessor.reference.ChildReference; +import org.simantics.databoard.accessor.reference.IndexReference; +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingConstructionException; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.databoard.type.ArrayType; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.NumberType; +import org.simantics.databoard.util.Range; +import org.simantics.db.Issue; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.issue.StandardIssue; +import org.simantics.db.common.primitiverequest.PossibleRelatedValueImplied2; +import org.simantics.db.common.primitiverequest.PossibleResource; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.IsEnumeratedValue; +import org.simantics.db.common.uri.UnescapedChildMapOfResource; +import org.simantics.db.common.utils.CommonDBUtils; +import org.simantics.db.common.utils.Functions; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.common.utils.Logger; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.common.utils.NearestOwnerFinder; +import org.simantics.db.common.validation.L0Validations; +import org.simantics.db.exception.AdaptionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.DoesNotContainValueException; +import org.simantics.db.exception.NoSingleResultException; +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.layer0.exception.InvalidVariableException; +import org.simantics.db.layer0.exception.MissingVariableException; +import org.simantics.db.layer0.exception.MissingVariableValueException; +import org.simantics.db.layer0.exception.PendingVariableException; +import org.simantics.db.layer0.request.PossibleURI; +import org.simantics.db.layer0.request.PropertyInfo; +import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.request.UnescapedAssertedPropertyMapOfResource; +import org.simantics.db.layer0.request.UnescapedMethodMapOfResource; +import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource; +import org.simantics.db.layer0.scl.CompileResourceValueRequest; +import org.simantics.db.layer0.scl.CompileValueRequest; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.util.PrimitiveValueParser; +import org.simantics.db.layer0.variable.AbstractVariable; +import org.simantics.db.layer0.variable.ChildVariableMapRequest; +import org.simantics.db.layer0.variable.ExternalSetValue; +import org.simantics.db.layer0.variable.PropertyVariableMapRequest; +import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable; +import org.simantics.db.layer0.variable.StandardComposedProperty; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; +import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; +import org.simantics.db.layer0.variable.SubliteralPropertyVariable; +import org.simantics.db.layer0.variable.SubliteralPropertyVariableDeprecated; +import org.simantics.db.layer0.variable.ValueAccessor; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.VariableBuilder; +import org.simantics.db.layer0.variable.VariableMap; +import org.simantics.db.layer0.variable.VariableMapImpl; +import org.simantics.db.layer0.variable.VariableNode; +import org.simantics.db.layer0.variable.VariableNodeReadRunnable; +import org.simantics.db.layer0.variable.VariableUtils; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.layer0.variable.Variables.NodeStructure; +import org.simantics.db.service.ClusteringSupport; +import org.simantics.db.service.UndoRedoSupport; +import org.simantics.issues.ontology.IssueResource; +import org.simantics.layer0.Layer0; +import org.simantics.scl.reflection.annotations.SCLValue; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function4; +import org.simantics.scl.runtime.function.FunctionImpl1; +import org.simantics.scl.runtime.function.FunctionImpl2; +import org.simantics.simulator.variable.exceptions.NodeManagerException; +import org.simantics.utils.Development; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.strings.StringInputValidator; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; + +public class All { + + public static Object standardGetValue1(ReadGraph graph, Variable context) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + // First from node + if(variable.node != null) { + Variant value = Variables.requestNodeValue(graph, variable.node); + if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException(""); + return value.getValue(); + } + + try { + + if(variable.property.hasEnumerationRange) { + Resource object = variable.getRepresents(graph); + if(graph.sync(new IsEnumeratedValue(object))) { + Layer0 L0 = Layer0.getInstance(graph); + if(graph.isInstanceOf(object, L0.Literal)) { + return graph.getValue(object); + } else { + String label = graph.getPossibleRelatedValue2(variable.getRepresents(graph), L0.HasLabel, Bindings.STRING); + if(label == null) label = graph.getPossibleRelatedValue(variable.getRepresents(graph), L0.HasName, Bindings.STRING); + if(label == null) label = ""; + return label; + } + } + } + + if (variable.isAsserted()) { + if (variable.parentResource != null) { + Map> assertions = graph.syncRequest( + new UnescapedAssertedPropertyMapOfResource(variable.parentResource), + TransientCacheAsyncListener.instance()); + + // NOTE: This optimization assumes the property + // variable's representation is the asserted object. + Resource object = variable.getPossibleRepresents(graph); + if (object != null) { + return graph.getValue2(object, variable); + } else { + for (Pair assertion : assertions.values()) { + if (assertion.first.predicate.equals(variable.property.predicate)) { + return graph.getValue2(assertion.second, variable); + } + } + } + } + } + + return graph.getValue2(variable.getRepresents(graph), variable); + + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DatabaseException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } + + public static Object standardGetValue2(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + // First from node + if(variable.node != null) { + try { + Variant value = Variables.requestNodeValue(graph, variable.node, binding); + if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException(""); + if(value == null) throw new MissingVariableValueException(variable.getPossibleURI(graph)); + return value.getValue(binding); + } catch (AdaptException e) { + throw new AdaptionException("Could not get value for " + context.getURI(graph), e); + } + } + + try { + + if(variable.property.hasEnumerationRange) { + Resource object = variable.getRepresents(graph); + if(graph.sync(new IsEnumeratedValue(object))) { + Layer0 L0 = Layer0.getInstance(graph); + if(graph.isInstanceOf(object, L0.Literal)) { + return graph.getValue(object, binding); + } else { + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); + } + } + } + + if (variable.isAsserted()) { + if (variable.parentResource != null) { + Map> assertions = graph.syncRequest( + new UnescapedAssertedPropertyMapOfResource(variable.parentResource), + TransientCacheAsyncListener.instance()); + + // NOTE: This optimization assumes the property + // variable's representation is the asserted object. + Resource object = variable.getPossibleRepresents(graph); + if (object != null) { + return graph.getValue2(object, variable, binding); + } else { + for (Pair assertion : assertions.values()) { + if (assertion.first.predicate.equals(variable.property.predicate)) { + return graph.getValue2(assertion.second, variable, binding); + } + } + } + } + } + + return graph.getValue2(variable.getRepresents(graph), context, binding); + + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph)); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph)); + } catch (DatabaseException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } + + public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException { + + if(context instanceof StandardGraphPropertyVariable) { + + final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + // First from node + if(variable.node != null) { + + final Binding binding = Layer0Utils.getDefaultBinding(graph, variable); + + final AtomicReference oldValueRef = new AtomicReference(); + try { + variable.node.support.manager.getRealm().syncExec(new Runnable() { + @Override + public void run() { + try { + oldValueRef.set(getNodeValue(variable, binding)); + setNodeValue(variable, value, binding); + } catch (NodeManagerException e) { + throw new RuntimeException(e); + } catch (BindingException e) { + throw new RuntimeException(e); + } + } + }); + } catch(RuntimeException e) { + if(e.getCause() instanceof NodeManagerException || e.getCause() instanceof BindingException) + throw new DatabaseException(e.getCause()); + else + throw e; + } catch (InterruptedException e) { + throw new DatabaseException(e); + } + + ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, + oldValueRef.get(), value, binding); + graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext); + + return; + } + + } + + Function4 modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); + if(modifier == null) modifier = VariableUtils.defaultInputModifier; + try { + modifier.apply(graph, context, value, Bindings.getBinding(value.getClass())); + } catch (BindingConstructionException e) { + throw new org.simantics.db.exception.BindingException("",e); + } + + } + + public static void standardSetValue3(final WriteGraph graph, Variable context, final Object value, final Binding binding) throws DatabaseException { + + // First from node + if(context instanceof StandardGraphPropertyVariable) { + + final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + // First from node + if(variable.node != null) { + + try { + + variable.node.support.manager.getRealm().syncExec(new Runnable() { + + @Override + public void run() { + try { + Object oldValue = getNodeValue(variable, binding); + setNodeValue(variable, value, binding); + ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, oldValue, value, binding); + graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext); + } catch (NodeManagerException | BindingException e) { + Logger.defaultLogError(e); + } + } + + + }); + + return; + + } catch (InterruptedException e) { + throw new DatabaseException(e); + } + + } + + } + + Function4 modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); + if(modifier == null) modifier = VariableUtils.defaultInputModifier; + modifier.apply(graph, context, value, binding); + + } + + public static Datatype getDatatypeFromValue(ReadGraph graph, Variable context) throws DatabaseException { + if (context instanceof AbstractVariable) { + Binding defaultBinding = ((AbstractVariable)context).getPossibleDefaultBinding(graph); + if (defaultBinding != null) + return defaultBinding.type(); + } + + Variant value = context.getVariantValue(graph); + if (value.getBinding() == null) + throw new DatabaseException("No value binding for " + context.getURI(graph)); + + return value.getBinding().type(); + } + + @SuppressWarnings("rawtypes") + private static class DatatypeGetter implements VariableNodeReadRunnable { + final VariableNode node; + Datatype type; + Exception exception; + + public DatatypeGetter(VariableNode node) { + this.node = node; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + try { + type = node.support.manager.getDatatype(node.node); + } catch (NodeManagerException e) { + exception = e; + } + } + @Override + public String toString() { + return "DatatypeGetter(" + node.node + ")"; + } + } + + public static Datatype standardGetDatatype(ReadGraph graph, Variable context) throws DatabaseException { + if (context instanceof AbstractVariable) { + final AbstractVariable variable = (AbstractVariable)context; + if (variable.node != null) { + try { + DatatypeGetter request = new DatatypeGetter(variable.node); + + variable.node.support.manager.getRealm().syncExec(request); + + if (request.exception != null) + throw new DatabaseException(request.exception); + + return request.type; + } catch (InterruptedException e) { + } + } + } + + return getDatatypeFromValue(graph, context); + } + +// @SCLValue(type = "ValueAccessor") +// public static ValueAccessor standardValueAccessor = new ValueAccessor() { +// +// @Override +// public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { +// return standardGetValue(graph, (StandardGraphPropertyVariable)context); +// } +// +// @Override +// public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { +// return standardGetValue(graph, context, binding); +// } +// +// @Override +// public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { +// standardSetValue(graph, context, value); +// } +// +// @Override +// public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { +// standardSetValue(graph, context, value, binding); +// } +// +// @Override +// public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException { +// return standardGetDatatype(graph, context); +// } +// +// }; + + @SCLValue(type = "ValueAccessor") + public static ValueAccessor standardValueAccessor = new ValueAccessor() { + + @Override + public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { + ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); + if(accessor != null) return accessor.getValue(graph, context); + else + return standardGetValue1(graph, context); + } + + @Override + public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); + if(accessor != null) return accessor.getValue(graph, context, binding); + else + return standardGetValue2(graph, context, binding); + } + + @Override + public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { + ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); + if(accessor != null) accessor.setValue(graph, context, value); + else + standardSetValue2(graph, context, value); + } + + @Override + public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { + ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); + if(accessor != null) accessor.setValue(graph, context, value, binding); + else + standardSetValue3(graph, context, value, binding); + } + + @Override + public Datatype getDatatype(ReadGraph graph, Variable context) + throws DatabaseException { + ValueAccessor accessor = getPossibleValueValueAccessor(graph, context); + if(accessor != null) return accessor.getDatatype(graph, context); + else + return standardGetDatatype(graph, context); + } + + }; + + public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + PropertyInfo graphProperty = getPossiblePropertyInfoFromContext(graph, variable, variable.resource, name); + return getStandardChildDomainPropertyVariable(graph, context, graphProperty, name); + } + + public static Resource getPossiblePropertyResource(ReadGraph graph, AbstractVariable parent, Object node) throws DatabaseException { + if(parent != null && parent.node != null && parent.node.node != null && parent.node.support != null) { + String propertyURI = getPossiblePropertyURI(parent, node); + if(propertyURI != null) + return graph.getPossibleResource(propertyURI); + } + return null; + } + + public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, PropertyInfo graphProperty, String name) throws DatabaseException { + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + Object propertyNode = getPossibleNodeProperty(graph, variable, name, true); + if(graphProperty != null && graphProperty.builder != null) + return buildPropertyVariable(graph, variable, variable.resource, graphProperty, propertyNode); + if(propertyNode != null) { + // Fallback: try to ask property resource uri from NodeManager + return createStandardGraphPropertyVariable(graph, variable, propertyNode); + } + // Final fallback: check types corresponding to + // node classification(s) and look for asserted + // properties from the URIs specified. + if (variable.node != null) { + try { + @SuppressWarnings("unchecked") + Set classifications = variable.node.support.manager.getClassifications(variable.node.node); + if (!classifications.isEmpty()) { + for (String uri : classifications) { + Resource type = graph.syncRequest( + new PossibleResource(uri), + TransientCacheAsyncListener.instance()); + if (type == null) + continue; + Map> pm = graph.syncRequest( + new UnescapedAssertedPropertyMapOfResource(type), + TransientCacheAsyncListener.instance()); + Pair pi = pm.get(name); + if (pi != null) { + return new StandardAssertedGraphPropertyVariable(graph, context, null, type, pi.first.predicate, pi.second); + } + } + } + } catch(NodeManagerException e) { + throw new DatabaseException(e); + } + } + return null; + } + + public static Map getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + // Get properties with null identification + return getStandardChildDomainPropertyVariables(graph, context, null, map); + } + + public static Map getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { + + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + + Collection nodeProperties = getPossibleNodeProperties(graph, variable); + if(!nodeProperties.isEmpty()) { + + // Get variables for properties read from the graph + Map graphProperties = collectPropertyInfosFromContext(graph, variable, variable.resource); + + Set used = new THashSet(nodeProperties.size()); + + map = ensureVariableMap(map, graphProperties.size() + nodeProperties.size()); + + // Process NodeManager property nodes + for(Object nodeProperty : nodeProperties) { + String name = getNodeName(variable, nodeProperty); + used.add(name); + + PropertyInfo graphProperty = graphProperties.get(name); + if(graphProperty != null && graphProperty.builder != null) { + if (classification != null && !graphProperty.hasClassification(classification)) continue; + + // Combine with identically named graph property + map.put(name, buildPropertyVariable(graph, variable, variable.resource, graphProperty, nodeProperty)); + continue; + } + + map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty)); + } + + // Process graph properties + for(PropertyInfo info : graphProperties.values()) { + String name = info.name; + if(used != null && used.contains(name)) continue; + if (classification != null && !info.hasClassification(classification)) continue; + if (info.builder != null) { + map.put(name, buildPropertyVariable(graph, variable, variable.resource, info, null)); + } + } + return map; + + } else { + + if(variable.resource == null) return map; + + // Only graph properties + Collection predicates = graph.getPredicates(variable.resource); + if(predicates.isEmpty()) return map; + + map = ensureVariableMap(map, predicates.size()); + + // Process graph properties + for(Resource predicate : predicates) { + + PropertyInfo info = //graph.isImmutable(predicate) ? + graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.instance());// : + //graph.syncRequest(new PropertyInfoRequest(predicate)); + + if(!info.isHasProperty) continue; + + if (classification != null && !info.hasClassification(classification)) continue; + if (info.builder != null) { + map.put(info.name, buildPropertyVariable(graph, variable, variable.resource, info, null)); + } + + } + + return map; + + } + + } + + @SCLValue(type = "VariableMap") + public static VariableMap standardChildDomainProperties = new VariableMapImpl() { + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + return getStandardChildDomainPropertyVariable(graph, context, name); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + return getStandardChildDomainPropertyVariables(graph, context, map); + } + + }; + + @SCLValue(type = "VariableMap") + public static VariableMap methodsPropertyDomainProperties = new VariableMapImpl() { + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + Variable parent = context.getParent(graph); + Resource container = parent.getPossibleRepresents(graph); + if(container == null) + return null; + Map methods = graph.syncRequest(new UnescapedMethodMapOfResource(container)); + Resource predicate = methods.get(name); + if(predicate != null) { + Layer0 L0 = Layer0.getInstance(graph); + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method)); + Resource value = graph.getSingleObject(container, predicate); + return new StandardGraphPropertyVariable(context, null, container, info, value); + } + return null; + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + Variable parent = context.getParent(graph); + Resource container = parent.getPossibleRepresents(graph); + if(container == null) + return Collections.emptyMap(); + Map methods = graph.syncRequest(new UnescapedMethodMapOfResource(container)); + for(Map.Entry entry : methods.entrySet()) { + String name = entry.getKey(); + Resource predicate = entry.getValue(); + Layer0 L0 = Layer0.getInstance(graph); + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method)); + Resource value = graph.getSingleObject(container, predicate); + if(map == null) map = new HashMap<>(); + map.put(name, new StandardGraphPropertyVariable(context, null, container, info, value)); + } + return map; + } + + }; + + public static Variable getStandardPropertyDomainPropertyVariableFromValue(ReadGraph graph, Variable context, String name) throws DatabaseException { + + if(context instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + Resource literal = variable.getPossibleRepresents(graph); + Object propertyNode = getPossibleNodeProperty(graph, variable, name, false); + + if(literal != null) { + Variable result = getPossiblePropertyFromContext(graph, variable, literal, name, propertyNode); + if(result != null) return result; + } + + Variable result = getPossibleSubliteralPropertyFromContext(graph, variable, name); + if(result != null) return result; + result = getPossiblePropertyFromContext(graph, variable, variable.property.predicate, name, propertyNode); + if (result != null) return result; + + // Get possible property from NodeManager + if (propertyNode != null) + return createStandardGraphPropertyVariable(graph, variable, propertyNode); + return null; + } else if (context instanceof StandardGraphChildVariable) { + return standardChildDomainProperties.getVariable(graph, context, name); + } else { + throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); + } + + } + + public static Map getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map map) throws DatabaseException { + + if(context instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + map = collectPropertiesFromContext(graph, variable, variable.property.predicate, map); + if (variable.parentResource != null) { + Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate); + if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, map); + map=collectSubliteralProperties(graph, variable, map); + } + + // Get properties from VariableNode + map = getStandardNodePropertyVariables(graph, context, map); + return map; + } else if (context instanceof StandardGraphChildVariable) { + return standardChildDomainProperties.getVariables(graph, context, map); + } else { + throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); + } + + } + + public static Map getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { + + if(context instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + map = collectPropertiesFromContext(graph, variable, variable.property.predicate, classification, map); + if (variable.parentResource != null) { + Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate); + if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, classification, map); + } + + // Get properties from VariableNode + map = getStandardNodePropertyVariables(graph, context, map); + return map; + } else if (context instanceof StandardGraphChildVariable) { + return standardChildDomainProperties.getVariables(graph, context, map); + } else { + throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); + } + + } + + @SCLValue(type = "VariableMap") + public static VariableMap standardPropertyDomainProperties = new VariableMapImpl() { + + VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException { + Resource represents = context.getPossibleRepresents(graph); + if(represents == null) return null; + + VariableMap map = graph.isImmutable(represents) ? + graph.syncRequest(new PropertyVariableMapRequest(represents), TransientCacheListener.instance()) : + (VariableMap)graph.getPossibleRelatedValue2(represents, Layer0.getInstance(graph).domainProperties, represents); + + if(map == standardPropertyDomainProperties) return null; + else return map; + + } + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + VariableMap valueMap = getValueVariableMap(graph, context); + if(valueMap != null) return valueMap.getVariable(graph, context, name); + return getStandardPropertyDomainPropertyVariableFromValue(graph, context, name); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + VariableMap valueMap = getValueVariableMap(graph, context); + if(valueMap != null) return valueMap.getVariables(graph, context, map); + else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, map); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { + VariableMap valueMap = getValueVariableMap(graph, context); + if(valueMap != null) return valueMap.getVariables(graph, context, classification, map); + else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, classification, map); + } + + }; + + public static Resource getPossibleGraphChild(ReadGraph graph, Variable variable, String name) throws DatabaseException { + Resource resource = variable.getPossibleRepresents(graph); + if(resource == null) return null; + Map graphChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource)); + return graphChildren.get(name); + } + + public static Map getPossibleGraphChildren(ReadGraph graph, Variable variable) throws DatabaseException { + Resource resource = variable.getPossibleRepresents(graph); + if(resource == null) return Collections.emptyMap(); + return graph.syncRequest(new UnescapedChildMapOfResource(resource)); + } + + public static Object getPossibleNodeChild(ReadGraph graph, Variable variable, String name) throws DatabaseException { + if (!(variable instanceof AbstractVariable)) return null; + VariableNode node = ((AbstractVariable)variable).node; + if(node == null) return null; + NodeStructure structure = Variables.requestNodeStructure(graph, node); + if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); + return structure.children.get(name); + } + + public static Collection getPossibleNodeChildren(ReadGraph graph, Variable variable) throws DatabaseException { + if (!(variable instanceof AbstractVariable)) return null; + VariableNode node = ((AbstractVariable)variable).node; + if(node == null) return Collections.emptyList(); + NodeStructure structure = Variables.requestNodeStructure(graph, node); + if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); + return structure.children.values(); + } + + public static Object getPossibleNodeProperty(ReadGraph graph, Variable variable, String name, boolean throwPending) throws DatabaseException { + if (!(variable instanceof AbstractVariable)) return null; + VariableNode node = ((AbstractVariable)variable).node; + if(node == null) return null; + NodeStructure structure = Variables.requestNodeStructure(graph, node); + if(throwPending && Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); + return structure.properties.get(name); + } + + public static Collection getPossibleNodeProperties(ReadGraph graph, Variable variable) throws DatabaseException { + if (!(variable instanceof AbstractVariable)) return null; + VariableNode node = ((AbstractVariable)variable).node; + if(node == null) return Collections.emptyList(); + NodeStructure structure = Variables.requestNodeStructure(graph, node); + if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException(""); + return structure.properties.values(); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static VariableNode build(VariableNode parent, Object node) { + if(node == null) return null; + return new VariableNode(parent.support, node); + } + + @Deprecated + public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name); + } + + @Deprecated + public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, Resource graphChild, String name) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, graphChild, name); + } + + @Deprecated + public static Map getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); + } + + @Deprecated + public static Map getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map graphChildren, Map map) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, graphChildren, map); + } + + /** + * Get a map of child Variables from a node manager-based Variable, combined with the existing variables in #map. + * @param graph The read graph. + * @param context The parent Variable. + * @param map A map of variables into which the new variables are merged. + * @return A map from variable names to instances + * @throws DatabaseException + */ + public static Map getStandardNodeChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + AbstractVariable variable = (AbstractVariable)context; + if (variable.node == null) return map; + + Collection nodeChildren = getPossibleNodeChildren(graph, variable); + if (nodeChildren.isEmpty()) return map; + + map = ensureVariableMap(map, nodeChildren.size()); + + for(Object nodeChild : nodeChildren) { + String name = getNodeName(variable, nodeChild); + if (!map.containsKey(name)) + map.put(name, createStandardGraphChildVariable(variable, nodeChild)); + } + + return map; + } + + /** + * Get a map of property Variables from a node manager-based Variable, combined with the existing variables in #map. + * @param graph The read graph. + * @param context The parent Variable. + * @param map A map of variables into which the new variables are merged. + * @return A map from variable names to instances + * @throws DatabaseException + */ + public static Map getStandardNodePropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + AbstractVariable variable = (AbstractVariable)context; + if (variable.node == null) return map; + + Collection nodeProperties = getPossibleNodeProperties(graph, variable); + if (nodeProperties.isEmpty()) return map; + + map = ensureVariableMap(map, nodeProperties.size()); + + for(Object nodeProperty : nodeProperties) { + String name = getNodeName(variable, nodeProperty); + if (!map.containsKey(name)) { + map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty)); + } + } + + return map; + } + + @SCLValue(type = "VariableMap") + public static VariableMap standardChildDomainChildren = new VariableMapImpl() { + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); + } + + }; + + @SCLValue(type = "VariableMap") + public static VariableMap standardPropertyDomainChildren = new VariableMapImpl() { + + /** + * Get a possible non-standard VariableMap defined in the graph. + * @param graph The graph + * @param context The context node + * @return A non-standard VariableMap instance for the context node, + * or null, if not defined or defined as this instance. + * @throws DatabaseException + */ + VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException { + Resource represents = context.getPossibleRepresents(graph); + if(represents == null) return null; + VariableMap map = graph.syncRequest(new ChildVariableMapRequest(represents)); + if(map == standardPropertyDomainChildren) return null; + else return map; + } + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + // Delegate call to a non-standard variable map? + VariableMap valueMap = getValueVariableMap(graph, context); + if(valueMap != null) return valueMap.getVariable(graph, context, name); + + if(context instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + Datatype dt = variable.getDatatype(graph); + if (dt instanceof ArrayType) { + ChildReference ref = getPossibleIndexReference(name); + if (ref != null) + return new SubliteralPropertyVariableDeprecated(variable, ref); + } + + // Check for a child node provided by the NodeManager + if (variable.node != null) { + Object childNode = getPossibleNodeChild(graph, variable, name); + if (childNode != null) + return createStandardGraphChildVariable(variable, childNode); + } + return standardChildDomainChildren.getVariable(graph, context, name); + } else if (context instanceof StandardGraphChildVariable) { + return standardChildDomainChildren.getVariable(graph, context, name); + } else { + throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); + } + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + // Delegate call to a non-standard variable map? + VariableMap valueMap = getValueVariableMap(graph, context); + if(valueMap != null) return valueMap.getVariables(graph, context, map); + + if(context instanceof StandardGraphPropertyVariable) { + // Get child variables provided by the NodeManager + Map result = getStandardNodeChildVariables(graph, context, map); + return standardChildDomainChildren.getVariables(graph, context, result); + } else if (context instanceof StandardGraphChildVariable) { + return standardChildDomainChildren.getVariables(graph, context, map); + } else { + throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName()); + } + } + + }; + + protected static ChildReference getPossibleIndexReference(String name) { + if (name.startsWith("i-")) { + try { + int index = Integer.parseInt(name.substring(2)); + return new IndexReference(index); + } catch (NumberFormatException e) {} + } + return null; + } + + protected static ValueAccessor getPossiblePropertyValueAccessor(ReadGraph graph, StandardGraphPropertyVariable variable) throws DatabaseException { + if(variable.property == null) return null; + return variable.property.valueAccessor; +// return graph.syncRequest(new PropertyValueAccessorRequest(variable.property), TransientCacheAsyncListener.instance()); +// return graph.syncRequest(new PossibleRelatedValueImplied2(variable.property, Layer0.getInstance(graph).valueAccessor)); + } + + public static ValueAccessor getPossibleValueValueAccessor(ReadGraph graph, Variable variable) throws DatabaseException { + Resource value = variable.getPossibleRepresents(graph); + if(value == null) return null; + //return graph.syncRequest(new PropertyValueAccessorRequest(value)); + return graph.syncRequest(new PossibleRelatedValueImplied2(value, Layer0.getInstance(graph).valueAccessor)); + } + + public static PropertyInfo getPossiblePropertyInfoFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException { + if(context == null) return null; + Map predicates = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheListener.instance()); + return predicates.get(name); + } + + public static Variable getPossiblePropertyFromContext(ReadGraph graph, Variable variable, Resource context, String name, Object propertyNode) throws DatabaseException { + PropertyInfo info = getPossiblePropertyInfoFromContext(graph, variable, context, name); + if(info == null || info.builder == null) return null; + return buildPropertyVariable(graph, variable, context, info, propertyNode); + } + + public static Variable getPossibleSubliteralPropertyFromContext(ReadGraph graph, StandardGraphPropertyVariable variable, String name) throws DatabaseException { + + Resource predicate = variable.property.predicate; + if(predicate == null) return null; + + PropertyInfo info = getPropertyInfo(graph, predicate); + Pair p = info.subliteralPredicates.get(name); + if(p == null) return null; + + return new SubliteralPropertyVariable(graph, variable, p.first, p.second); + + } + + public static Map collectPropertyInfosFromContext(ReadGraph graph, Variable variable, Resource context) throws DatabaseException { + if(context == null) return Collections.emptyMap(); + return graph.isImmutable(context) ? + graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()) : + graph.syncRequest(new UnescapedPropertyMapOfResource(context)); + } + + public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map map) throws DatabaseException { + + Map properties = graph.isImmutable(context) ? + graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()) : + graph.syncRequest(new UnescapedPropertyMapOfResource(context)); + + if(properties.isEmpty()) return map; + + map = ensureVariableMap(map, properties.size()); + + for(PropertyInfo info : properties.values()) { + String name = info.name; + if (info.builder != null) { + Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); + map.put(name, v); + } + } + + return map; + + } + + public static Map collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map map) throws DatabaseException { + + Resource predicate = variable.property.predicate; + if(predicate == null) return map; + + PropertyInfo info = getPropertyInfo(graph, predicate); + if(info.subliteralPredicates.isEmpty()) return map; + + map = ensureVariableMap(map, info.subliteralPredicates.size()); + + for(Map.Entry> entry : info.subliteralPredicates.entrySet()) { + String key = entry.getKey(); + Pair p = entry.getValue(); + if(map == null) map = new THashMap(); + map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second)); + } + + return map; + + } + + public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map map) throws DatabaseException { + + if(graph.isImmutable(context)) { + + Map properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()); + for(PropertyInfo info : properties.values()) { + + if(info.classifications.contains(classification) && info.builder != null) { + String name = info.name; + Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); + if(map == null) map = new THashMap(); + map.put(name, v); + } + + } + + } else { + + Collection predicates = graph.getPredicates(context); + + if(predicates.isEmpty()) return map; + + map = ensureVariableMap(map, predicates.size()); + + for(Resource predicate : predicates) { + + PropertyInfo info = graph.isImmutable(predicate) ? + graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.instance()) : + graph.syncRequest(new PropertyInfoRequest(predicate)); + + if(!info.isHasProperty) continue; + + if(info.classifications.contains(classification) && info.builder != null) { + String name = info.name; + Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate); + if(map == null) map = new THashMap(); + map.put(name, v); + } + + } + + } + + return map; + + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> String") + public static String entityLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + if(context instanceof Resource) { + return NameUtils.getSafeLabel(graph, ((Resource)context)); + } else if (context instanceof Variable) { + Variable parent = ((Variable)context).getParent(graph); + Resource represents = parent.getRepresents(graph); + return NameUtils.getSafeLabel(graph, represents); + } else { + throw new DatabaseException("Unknown context " + context); + } + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object listResources(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return ListUtils.toList(graph, resource); + } + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> [String]") + public static List standardClassifications(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { + ArrayList result = new ArrayList(); + Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph); + if(predicate != null) { + for(Resource type : graph.getTypes(predicate)) { + String uri = graph.getPossibleURI(type); + if(uri != null) result.add(uri); + } + } + return result; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") + public static Boolean standardValidValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return Boolean.TRUE; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> StringInputValidator") + public static StringInputValidator standardValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return StringInputValidator.PASS; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") + public static Boolean standardRequiredValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return Boolean.FALSE; + } + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean") + public static Boolean standardDefaultValue(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { + Variable property = context.getParent(graph); + if(property instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property; + if (variable.parentResource != null) { + Statement stm = graph.getPossibleStatement(variable.parentResource, variable.property.predicate); + return stm != null && stm.isAsserted(variable.parentResource); + } + } + return Boolean.FALSE; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") + public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return Boolean.FALSE; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return resource; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + return Functions.exec(graph, resource, graph, resource, context); + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException { + if(context instanceof Variable) { + return CompileValueRequest.compileAndEvaluate(graph, (Variable)context); + } if (context instanceof Resource) { + return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter); + } else { + throw new IllegalStateException("Unknown context " + context); + } + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException { + if(context instanceof Variable) { + return new StandardComposedProperty(); + } if (context instanceof Resource) { + return new StandardComposedProperty(); + } else { + throw new IllegalStateException("Unknown context " + context); + } + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + + class Validator extends FunctionImpl1 { + + private final Datatype datatype; + + public Validator(Datatype datatype) { + this.datatype = datatype; + } + + @Override + public String apply(String input) { + + if(datatype == null) return null; + + try { + + if(datatype instanceof NumberType) { + + Number number = (Number)PrimitiveValueParser.parse(input, datatype); + NumberType nt = (NumberType)datatype; + Range r = nt.getRange(); + if(r != null) { + if(!r.contains(number)) return "Value is out of valid range"; + } + } + return null; + + } catch (NumberFormatException e) { + return "Not a valid floating-point number"; + } catch (IllegalArgumentException e) { + return "Not a valid floating-point number"; + } + + } + + } + + if(context instanceof Variable) { + + Variable variable = (Variable)context; + Variable property = variable.getParent(graph); + Datatype datatype = property.getPossibleDatatype(graph); + return new Validator(datatype); + + } else if (context instanceof Resource) { + + Layer0 L0 = Layer0.getInstance(graph); + Resource literal = (Resource)context; + Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); + return new Validator(datatype); + + } else { + + return new Validator(null); + + } + + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { + + return new FunctionImpl1() { + + @Override + public String apply(String input) { + + String lower = input.toLowerCase(); + if("true".equals(lower) || "false".equals(lower)) return null; + + return "Not a valid boolean: " + input; + + } + + }; + + } + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource") + public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { + Variable parent = context.getParent(graph); + if(parent instanceof StandardGraphChildVariable) { + StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; + return variable.resource; + } + return null; + } + + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") + public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); + } + + if (variable.parentResource == null) + throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); + + try { + return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } + + @SCLValue(type = "ReadGraph -> Variable -> Binding -> a") + public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); + } + + if (variable.parentResource == null) + throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph)); + + try { + return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } + + @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b") + public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException { + + Function4 modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); + if(modifier == null) modifier = VariableUtils.defaultInputModifier; + modifier.apply(graph, variable, value, binding); + return null; + + } + + static class L0Issue extends StandardIssue { + + private final String description; + + public L0Issue(String description, Resource type, Resource ... contexts) { + super(type, contexts); + this.description = description; + } + + @Override + public Resource write(WriteGraph graph, Resource source) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + IssueResource IR = IssueResource.getInstance(graph); + Resource issue = super.write(graph, source); + graph.claim(issue, IR.Issue_HasSeverity, IR.Severity_Fatal); + graph.addLiteral(issue, L0.HasDescription, L0.HasDescription_Inverse, description, Bindings.STRING); + return issue; + } + + } + + private static List reportInconsistency(ReadGraph graph, Resource subject, String description, List issues) throws DatabaseException { + if(issues == null) issues = new ArrayList(); + System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description); + IssueResource IR = IssueResource.getInstance(graph); + issues.add(new L0Issue(description, IR.Issue, subject)); + return issues; + } + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List relationValidator(ReadGraph graph, Resource resource) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + + List issues = null; + + for(Statement stm : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) { + Resource predicate = stm.getPredicate(); + Resource object = stm.getObject(); + if(!isRelation(graph, L0, predicate)) { + issues = reportInconsistency(graph, resource, "The predicate of a statement must be a relation: " + NameUtils.toString(graph, stm), issues); + } + if(graph.isInstanceOf(predicate, L0.FunctionalRelation)) { + if(graph.getObjects(resource, predicate).size() > 1) + issues = reportInconsistency(graph, resource, + "Relation " + + NameUtils.getSafeName(graph, predicate) + + " is functional.", issues); + } + { + Collection domain = graph.getObjects(predicate, L0.HasDomain); + if (!isInstanceOfAny(graph, resource, domain, true)) { + StringBuilder sb = new StringBuilder() + .append("The domain of ") + .append(NameUtils.getSafeName(graph, predicate)) + .append(" relation is "); + orString(graph, sb, domain).append("."); + issues = reportInconsistency(graph, resource, sb.toString(), issues); + } + } + { + Collection range = graph.getObjects(predicate, L0.HasRange); + if (!isInstanceOfAny(graph, object, range, true) && !graph.isInstanceOf(object, L0.SCLValue)) { + StringBuilder sb = new StringBuilder() + .append("The range of ") + .append(NameUtils.getSafeName(graph, predicate)) + .append(" relation is "); + orString(graph, sb, range).append(" but current object is ") + .append(NameUtils.getSafeName(graph, object)).append("."); + issues = reportInconsistency(graph, resource, sb.toString(), issues); + } + } + } + + return issues != null ? issues : Collections.emptyList(); + + } + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List propertyValidator(ReadGraph graph, Resource resource) throws DatabaseException { + + List issues = null; + + Layer0 L0 = Layer0.getInstance(graph); + for(Statement stm : graph.getStatements(resource, L0.HasProperty)) { + Resource subject = stm.getSubject(); + Resource predicate = stm.getPredicate(); + String error = L0Validations.checkValueType(graph, subject, predicate); + if(error != null) issues = reportInconsistency(graph, subject, error, issues); + } + + return issues != null ? issues : Collections.emptyList(); + + } + + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List valueValidator(ReadGraph graph, Resource resource) throws DatabaseException { + + List issues = null; + + Layer0 L0 = Layer0.getInstance(graph); + if(graph.hasValue(resource)) { + if(!graph.isInstanceOf(resource, L0.Literal)) { + issues = reportInconsistency(graph, resource, + "Resource has a value but it is not a literal.", issues); + } + else { + // TODO check that the value is valid for the data type + } + } + else { + if(graph.isInstanceOf(resource, L0.Literal)) { + issues = reportInconsistency(graph, resource, + "Resource is a literal but it does not have a value.", issues); + } + } + + return issues != null ? issues : Collections.emptyList(); + + } + + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List uriValidator(ReadGraph graph, Resource resource) throws DatabaseException { + + List issues = null; + + Layer0 L0 = Layer0.getInstance(graph); + Resource parent = graph.getPossibleObject(resource, L0.PartOf); + if(parent != null) { + String parentURI = graph.syncRequest(new PossibleURI(parent)); + if(parentURI != null) { + String name = graph.getPossibleRelatedValue(resource, L0.HasName); + if(name == null) { + issues = reportInconsistency(graph, resource, "Resource has a parent with URI but has no valid HasName.", issues); + } + } + } + + return issues != null ? issues : Collections.emptyList(); + + } + + private static Resource getPossibleNearestClusterSet(ReadGraph graph, Resource base, Resource resource) throws DatabaseException { + + ClusteringSupport cs = graph.getService(ClusteringSupport.class); + if(cs.isClusterSet(resource) && !base.equals(resource)) return resource; + + Resource nearest = NearestOwnerFinder.getNearestOwner(graph, resource); + if(nearest == null) return null; + + return getPossibleNearestClusterSet(graph, base, nearest); + + } + + private static boolean quirks(ReadGraph graph, Resource resource) throws DatabaseException { + + if(!resource.isPersistent()) return true; + if(graph.isImmutable(resource)) return true; + if(resource.getResourceId() < 0x2000) return true; + + return false; + + } + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List clusterValidator(ReadGraph graph, Resource resource) throws DatabaseException { + + if(!Development.DEVELOPMENT) return Collections.emptyList(); + + if(quirks(graph, resource)) return Collections.emptyList(); + + List issues = null; + + ClusteringSupport cs = graph.getService(ClusteringSupport.class); + Resource set = cs.getClusterSetOfCluster(resource); + + if(set == null) return reportInconsistency(graph, resource, "Resource cluster is not part of any cluster set", issues); + + Resource nearestSet = getPossibleNearestClusterSet(graph, resource, resource); + if(nearestSet == null) { + // This means that there is no owner since RootLibrary is a cluster set + return Collections.emptyList(); + } + + if(!set.equals(nearestSet)) return reportInconsistency(graph, resource, "The cluster set of a resource is not the nearest owner set", issues); + + return Collections.emptyList(); + + } + + private static boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection types, boolean ifEmpty) throws DatabaseException { + if (types.isEmpty()) + return ifEmpty; + for (Resource type : types) { + if (graph.isInstanceOf(r, type)) { + return true; + } + } + return false; + } + + private static StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection rs) throws DatabaseException { + sb.append("("); + boolean first = true; + for (Resource r : rs) { + if (!first) + sb.append(" | "); + first = false; + sb.append(NameUtils.getSafeName(graph, r)); + } + sb.append(")"); + return sb; + } + + public static boolean isRelation(ReadGraph g, Layer0 l0, Resource relation) throws DatabaseException { + return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo; + } + + public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException { + return g.hasStatement(type, l0.Inherits) || type == l0.Entity; + } + + public static Variable buildChildVariable(ReadGraph graph, Variable context, Resource graphChild, Object nodeChild) throws DatabaseException { + VariableBuilder builder = graph.adapt(graphChild, VariableBuilder.class); + return builder.buildChild(graph, context, build(((AbstractVariable)context).node, nodeChild), graphChild); + } + + private static Variable buildPropertyVariable(ReadGraph graph, Variable variable, Resource parentResource, PropertyInfo graphProperty, Object propertyNode) throws DatabaseException { + VariableNode node = variable instanceof AbstractVariable ? build(((AbstractVariable)variable).node, propertyNode) : null; + return graphProperty.builder.buildProperty(graph, variable, node, parentResource, graphProperty.predicate); + } + + static StandardGraphChildVariable createStandardGraphChildVariable( + AbstractVariable parent, Object child) { + return new StandardGraphChildVariable(parent, build(parent.node, child), null); + } + + private static StandardGraphPropertyVariable createStandardGraphPropertyVariable( + ReadGraph graph, AbstractVariable variable, Object nodeProperty) throws DatabaseException { + Resource propertyResource = getPossiblePropertyResource(graph, variable, nodeProperty); + return new StandardGraphPropertyVariable(graph, variable, build(variable.node, nodeProperty), null, propertyResource); + } + + static Map ensureVariableMap( + Map map, int size) { + if(map == null) map = new THashMap(size); + return map; + } + + private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource predicate) throws DatabaseException { + return graph.syncRequest(new PropertyInfoRequest(predicate)); + } + + @SuppressWarnings("unchecked") + static String getNodeName(AbstractVariable parent, Object child) { + return parent.node.support.manager.getName(child); + } + + @SuppressWarnings("unchecked") + private static Object getNodeValue(final AbstractVariable variable, final Binding binding) throws NodeManagerException, BindingException { + return variable.node.support.manager.getValue(variable.node.node, binding); + } + + @SuppressWarnings("unchecked") + private static void setNodeValue(final AbstractVariable variable, final Object value, final Binding binding) throws NodeManagerException, BindingException { + variable.node.support.manager.setValue(variable.node.node, value, binding); + } + + @SuppressWarnings("unchecked") + private static String getPossiblePropertyURI(AbstractVariable parent, Object node) { + return parent.node.support.manager.getPropertyURI(parent.node.node, node); + } + + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") + public static Object defaultInstantiateUnder(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { + return new FunctionImpl2() { + public Resource apply(Resource container, Resource type) { + try { + WriteGraph graph = (WriteGraph)SCLContext.getCurrent().get("graph"); + + Layer0 L0 = Layer0.getInstance(graph); + CommonDBUtils.selectClusterSet(graph, container); + Resource result = graph.newResource(); + String name = NameUtils.findFreshInstanceName(graph, type, container); + graph.claim(result, L0.InstanceOf, type); + graph.addLiteral(result, L0.HasName, L0.NameOf, name, Bindings.STRING); + graph.claim(container, L0.ConsistsOf, L0.PartOf, result); + + return result; + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + } + }; + } + } \ No newline at end of file