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