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.validation.L0Validations; 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.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.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 DatabaseException(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 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); } // 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)); 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); } @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); } } }; } }