]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java
Possible variable browse without URI
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / Variables.java
index e323f4f8c28bc4cb755bb38e609b7d0c6461ea44..341a496a4ff2778a3e9972cb2c0c998dbe9f6114 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.layer0.variable;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.databoard.type.NumberType;\r
-import org.simantics.databoard.util.URIStringUtils;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.PossibleIndexRoot;\r
-import org.simantics.db.common.request.TernaryRead;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.exception.MissingVariableException;\r
-import org.simantics.db.layer0.request.Model;\r
-import org.simantics.db.layer0.request.PossibleActiveVariableFromVariable;\r
-import org.simantics.db.layer0.request.PossibleVariableIndexRoot;\r
-import org.simantics.db.layer0.request.PossibleVariableModel;\r
-import org.simantics.db.layer0.request.PropertyInfo;\r
-import org.simantics.db.layer0.request.PropertyInfoRequest;\r
-import org.simantics.db.layer0.request.ResourceURIToVariable;\r
-import org.simantics.db.layer0.request.VariableIndexRoot;\r
-import org.simantics.db.layer0.request.VariableURI;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.operation.Layer0X;\r
-import org.simantics.project.ontology.ProjectResource;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.scl.runtime.function.Function2;\r
-import org.simantics.scl.runtime.function.Function3;\r
-import org.simantics.simulation.ontology.SimulationResource;\r
-import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
-import org.simantics.utils.datastructures.Pair;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-\r
-final public class Variables {\r
-\r
-    public static final Variant PENDING_NODE_VALUE = new Variant();\r
-\r
-    public static final NodeStructure PENDING_NODE_STRUCTURE = new NodeStructure(Collections.emptyMap(), Collections.emptyMap()) {\r
-        public boolean equals(Object object) {\r
-            return this == object;\r
-        }\r
-    };\r
-\r
-    public static enum Role {\r
-\r
-        CHILD("/"), PROPERTY("#");\r
-\r
-        transient final String identifier;\r
-\r
-        private Role(String identifier) {\r
-            this.identifier = identifier;\r
-        }\r
-\r
-        final public String getIdentifier() {\r
-            return identifier;\r
-        }\r
-\r
-        public static Role getRole( String identifier ) {\r
-            for (Role role : Role.values()) if (role.identifier.equals( identifier )) return role;\r
-            return null;\r
-        }\r
-\r
-    }\r
-\r
-    // use getPredicate\r
-    //final public static String PREDICATE = "PREDICATE";\r
-\r
-    @Deprecated\r
-    // use getName\r
-    final public static String NAME = "HasName";\r
-    final public static String CLASSIFICATIONS = "classifications";\r
-    final public static String EXPRESSION = "HasExpression";\r
-    final public static String INPUT_VALIDATOR = "HasInputValidator";\r
-    final public static String INPUT_MODIFIER = "HasInputModifier";\r
-    final public static String FORMATTER = "HasFormatter";\r
-\r
-    final public static String STANDARD_RESOURCE = "hasStandardResource";\r
-    //@Deprecated\r
-    // use getPresents\r
-    //final public static String REPRESENTS = "Represents";\r
-    final public static String TYPE = "Type";\r
-    final public static String URI = "URI";\r
-    /**\r
-     * @deprecated use {@link Variable#getRVI(ReadGraph)} and {@link RVI} instead.\r
-     */\r
-//    @Deprecated\r
-//    final public static String SERIALISED = "Serialised";\r
-//    @Deprecated\r
-    // use getParent\r
-    //final public static String PARENT = "Parent";\r
-    //final public static String ROLE = "Role";\r
-    //final public static String DATATYPE = "DATATYPE";\r
-    //final public static String UNIT = "UNIT";\r
-\r
-    final public static String VALID = "valid";\r
-    final public static String REQUIRED = "required";\r
-    final public static String DEFAULT = "default";\r
-    final public static String READONLY = "readOnly";\r
-    final public static String VALIDATOR = "validator";\r
-\r
-    final public static String LABEL = "HasLabel";\r
-\r
-    final public static String ENUMERATION_VALUES = "HasEnumerationValues";\r
-    final public static String CUSTOM_MODIFIER = "HasCustomModifier";\r
-\r
-    final public static String DISPLAY_COLUMN = "HasDisplayColumn";\r
-\r
-    final public static String DISPLAY_PROPERTY = "HasDisplayProperty";\r
-    final public static String DISPLAY_VALUE = "HasDisplayValue";\r
-    final public static String DISPLAY_UNIT = "HasDisplayUnit";\r
-\r
-    final public static String CONVERTED_VALUE = "convertedValue";\r
-\r
-    /**\r
-     * This property should exist for array valued property variables.\r
-     */\r
-    final public static String ARRAY_SIZE = "ARRAY_SIZE";\r
-\r
-\r
-    @Deprecated\r
-    // use etc. variable.adapt(graph, Interface.class).getResource()\r
-    final public static String RESOURCE = "Resource";\r
-    @Deprecated\r
-    final public static String CONTAINER_RESOURCE = "ContainerResource";\r
-    @Deprecated\r
-    final public static String PROPERTY_RESOURCE = "PROPERTY_RESOURCE";\r
-\r
-    @Deprecated\r
-    public final static String[] builtins = {\r
-        TYPE, RESOURCE, URI\r
-        //, SERIALISED\r
-    };\r
-\r
-    public static Variable getPossibleVariable(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        String uri = graph.getPossibleURI(resource);\r
-        return uri != null ? getPossibleVariable(graph, uri) : null;\r
-    }\r
-\r
-    public static Variable getPossibleVariable(ReadGraph graph, String uri) throws DatabaseException {\r
-        try {\r
-            return getVariable(graph, uri);\r
-        } catch (DatabaseException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    public static Variable getVariable(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        return getVariable(graph, graph.getURI(resource));\r
-    }\r
-\r
-    public static Variable getVariable(ReadGraph graph, String uri) throws DatabaseException {\r
-        try {\r
-            return graph.sync(new ResourceURIToVariable(uri));\r
-        } catch (MissingVariableException e) {\r
-            return VariableRepository.get(graph, uri);\r
-        }\r
-    }\r
-\r
-    private static int commonPrefixLength(String a, String b) {\r
-        int maxC = Math.min(a.length(), b.length());\r
-        for(int c=0;c<maxC;++c) {\r
-            if(a.charAt(c) != b.charAt(c))\r
-                return c;\r
-        }\r
-        return maxC;\r
-    }\r
-\r
-    private static boolean isSplitPos(String str, int p) {\r
-        if(p==str.length())\r
-            return true;\r
-        char c = str.charAt(p);\r
-        return c=='/' || c=='#';\r
-    }\r
-\r
-    private static int pathLength(String path) {\r
-        int count = 0;\r
-        for(int i=0;i<path.length();++i) {\r
-            char c = path.charAt(i);\r
-            if(c=='/' || c=='#')\r
-                ++count;\r
-        }\r
-        return count;\r
-    }\r
-\r
-    private static String prefixByParentPath(int parentPathLength, String suffix) {\r
-        StringBuilder b = new StringBuilder();\r
-        for(int i=0;i<parentPathLength;++i)\r
-            b.append('.');\r
-        b.append(suffix);\r
-        return b.toString();\r
-    }\r
-\r
-    public static String getRVI(ReadGraph graph, Variable base, Variable other) throws DatabaseException {\r
-        String baseURI = graph.syncRequest(new VariableURI(base));\r
-        String otherURI = graph.syncRequest(new VariableURI(other));\r
-        return getRelativeRVI(baseURI, otherURI);\r
-    }\r
-\r
-    public static String getRelativeRVI(String baseURI, String otherURI) {\r
-        int prefixLength = commonPrefixLength(baseURI, otherURI);\r
-        if(!isSplitPos(baseURI, prefixLength) || !isSplitPos(otherURI, prefixLength)) {\r
-            for(--prefixLength;prefixLength > 0 && !isSplitPos(baseURI, prefixLength);--prefixLength);\r
-        }\r
-        if(prefixLength == baseURI.length())\r
-            return otherURI.substring(prefixLength);\r
-        else \r
-            return prefixByParentPath(\r
-                    pathLength(baseURI.substring(prefixLength)), \r
-                    otherURI.substring(prefixLength));     \r
-    }\r
-\r
-    public static String getRVI2(ReadGraph graph, Variable base, Variable other) throws DatabaseException {\r
-        TObjectIntHashMap<Variable> baseLength = new TObjectIntHashMap<Variable>();\r
-        for(int depth=0;base != null;base = base.getParent(graph),++depth)\r
-            baseLength.put(base, depth);\r
-        Variable cur;\r
-        for(cur=other;!baseLength.containsKey(cur);cur=cur.getParent(graph));\r
-\r
-        // To string\r
-        String curURI = cur.getURI(graph);\r
-        String otherURI = other.getURI(graph);\r
-\r
-        return prefixByParentPath(baseLength.get(cur), otherURI.substring(curURI.length()));\r
-    }\r
-\r
-    public static String getProjectRVI(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Resource project = getProject(graph, variable);\r
-        String projectURI = graph.getURI(project);\r
-        return variable.getURI(graph).substring(projectURI.length());\r
-    }\r
-\r
-    private static int getSegmentEnd(String suffix) {\r
-        int pos;\r
-        for(pos=1;pos<suffix.length();++pos) {\r
-            char c = suffix.charAt(pos);\r
-            if(c == '/' || c == '#')\r
-                break;\r
-        }\r
-        return pos;\r
-    }\r
-\r
-    public static String getRVI(String rvi, String suffix) throws DatabaseException {\r
-        if(suffix.isEmpty()) return rvi;\r
-        switch(suffix.charAt(0)) {\r
-            case '.': {\r
-                return getRVI(URIStringUtils.getRVIParent(rvi), suffix.substring(1));\r
-            }\r
-            case '#': {\r
-                int segmentEnd = getSegmentEnd(suffix);\r
-                return getRVI(rvi + "#" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));\r
-            }\r
-            case '/': {\r
-                int segmentEnd = getSegmentEnd(suffix);\r
-                return getRVI(rvi + "/" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));\r
-            }\r
-            default:\r
-                return null;\r
-        }\r
-\r
-    }\r
-\r
-    public static Variable getRootVariable(ReadGraph graph) throws DatabaseException {\r
-        return graph.adapt(graph.getRootLibrary(), Variable.class);\r
-    }\r
-    \r
-    public static Resource getPossibleIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {\r
-       return graph.syncRequest(new PossibleVariableIndexRoot(variable));\r
-    }\r
-    \r
-    public static Resource getIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {\r
-       return graph.syncRequest(new VariableIndexRoot(variable));\r
-    }\r
-    \r
-    public static Resource getModel(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        String URI = variable.getURI(graph);\r
-        return VariablesImpl.getFirst(graph, SimulationResource.getInstance(graph).Model, URI, 8);\r
-    }\r
-\r
-    public static Resource getPossibleModel(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        return graph.syncRequest(new PossibleVariableModel(variable));\r
-    }\r
-\r
-    public static Resource getProject(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        String URI = variable.getURI(graph);\r
-        return VariablesImpl.getFirst(graph, ProjectResource.getInstance(graph).Project, URI, 8);\r
-    }\r
-\r
-    public static Variable getConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-        if(!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new Model(resource));\r
-        Resource configurationResource = graph.getSingleObject(resource, SIMU.HasConfiguration);\r
-        return Variables.getVariable(graph, configurationResource);\r
-    }\r
-\r
-    public static Resource getConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        Variable config = getConfigurationContext(graph, resource);\r
-        return config.getRepresents(graph);\r
-    }\r
-\r
-    public static Variable getConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-        Resource model = Variables.getModel(graph, variable);\r
-        Resource configurationResource = graph.getSingleObject(model, SIMU.HasConfiguration);\r
-        return Variables.getVariable(graph, configurationResource);\r
-    }\r
-\r
-    public static Resource getPossibleConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        Variable config = getPossibleConfigurationContext(graph, resource);\r
-        return config != null ? config.getPossibleRepresents(graph) : null;\r
-    }\r
-\r
-    public static Variable getPossibleConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {\r
-        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-        if (!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new PossibleIndexRoot(resource));\r
-        if (resource == null)\r
-            return null;\r
-        Resource configurationResource = graph.getPossibleObject(resource, SIMU.HasConfiguration);\r
-        if (configurationResource == null)\r
-            return null;\r
-        return Variables.getPossibleVariable(graph, configurationResource);\r
-    }\r
-\r
-    public static Variable getPossibleConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-        Resource model = getPossibleIndexRoot(graph, variable);\r
-        if (model == null)\r
-            return null;\r
-        Resource configurationResource = graph.getPossibleObject(model, SIMU.HasConfiguration);\r
-        if (configurationResource == null)\r
-            return null;\r
-        return Variables.getPossibleVariable(graph, configurationResource);\r
-    }\r
-\r
-    public static Variable getConfigurationVariable(ReadGraph graph, Resource resource, String RVI) throws DatabaseException {\r
-        Variable context = getConfigurationContext(graph, resource);\r
-        return context.browse(graph, RVI);\r
-    }\r
-    \r
-    public static Variable getConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Variable context = getConfigurationContext(graph, variable);\r
-        RVI rvi = variable.getRVI(graph);\r
-        return rvi.resolve(graph, context);\r
-    }\r
-\r
-    public static Variable getPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Variable context = getPossibleConfigurationContext(graph, variable);\r
-        if (context == null)\r
-            return null;\r
-        try {\r
-            RVI rvi = variable.getRVI(graph);\r
-            return rvi.resolvePossible(graph, context);\r
-        } catch (MissingVariableException e) {\r
-            // Ignore.\r
-            return null;\r
-        }\r
-    }\r
-\r
-    public static Datatype getDatatype(ReadGraph graph, Resource resource, RVI rvi) throws DatabaseException {\r
-        Variable var = rvi.resolve(graph, getConfigurationContext(graph, resource));\r
-        return var.getDatatype(graph);\r
-    }\r
-\r
-    @Deprecated\r
-    public static Resource getRealization(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        String URI = variable.getURI(graph);\r
-        return VariablesImpl.getFirst(graph, Layer0X.getInstance(graph).Realization, URI, 8);\r
-    }\r
-\r
-    public static boolean isContext(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Resource type = variable.getPossibleType(graph);\r
-        if(type != null) {\r
-            if(graph.isInheritedFrom(type, Layer0.getInstance(graph).RVIContext)) return true;\r
-        }\r
-        return false;\r
-    }\r
-\r
-    public static Variable getPossibleContext(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        if(isContext(graph, variable)) return variable;\r
-        Variable parent = variable.getParent(graph);\r
-        if(parent == null) return null;\r
-        return getPossibleContext(graph, parent);\r
-    }\r
-\r
-    public static Variable getContext(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Variable context = getPossibleContext(graph, variable);\r
-        if(context == null) throw new DatabaseException("No context found for " + variable.getURI(graph));\r
-        else return context;\r
-    }\r
-\r
-    public static RVI getRVI2(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        return variable.getRVI(graph);\r
-    }\r
-\r
-    public static RVI getPossibleRVI2(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        try {\r
-            return variable.getRVI(graph);\r
-        } catch (DatabaseException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    public static String getRVI(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Resource realizationResource = getRealization(graph, variable);\r
-        if (realizationResource == null)\r
-            throw new DatabaseException("No realization found for " + variable.getURI(graph));\r
-        return variable.getURI(graph).substring(graph.getURI(realizationResource).length()); \r
-    }\r
-\r
-    public static String getRVI(ReadGraph graph, Resource config) throws DatabaseException {\r
-        Variable var = getVariable(graph, config);\r
-        return getRVI(graph, var);\r
-    }\r
-\r
-    public static String getPossibleRVI(ReadGraph graph, Resource config) throws DatabaseException {\r
-        Variable var = getPossibleVariable(graph, config);\r
-        return var != null ? getPossibleRVI(graph, var) : null;\r
-    }\r
-\r
-    public static String getPossibleRVI(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        try {\r
-            return getRVI(graph, variable);\r
-        } catch (DatabaseException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    public static List<Variable> getPath(ReadGraph graph, Variable base, Variable var) throws DatabaseException {\r
-        if(!isChild(graph, base, var)) return null;\r
-        LinkedList<Variable> result = new LinkedList<Variable>();\r
-        var = var.getParent(graph);\r
-        while(!var.equals(base)) {\r
-            result.addFirst(var);\r
-            var = var.getParent(graph);\r
-        }\r
-        return result;\r
-    }\r
-\r
-    public static Variable getChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {\r
-        List<Variable> path = getPath(graph, base, var);\r
-        if(path == null || path.size() == 0) return null;\r
-        return path.get(0);\r
-    }\r
-\r
-    public static boolean isChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {\r
-        if(base.equals(var)) return false;\r
-        return var.getURI(graph).startsWith(base.getURI(graph));\r
-    }\r
-\r
-    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {\r
-        Resource current = getRealization(graph, variable);\r
-        if(current == null) throw new DatabaseException("No current realization found for variable");\r
-        return switchRealization(graph, variable, current, realization);\r
-    }\r
-\r
-    public static Variable switchPossibleContext(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {\r
-        Variable current = getPossibleContext(graph, variable);\r
-        if (current == null)\r
-            return null;\r
-        Resource currentContext = current.getPossibleRepresents(graph);\r
-        if (currentContext == null)\r
-            return null;\r
-        return switchPossibleRealization(graph, variable, currentContext, realization);\r
-    }\r
-\r
-    public static Variable switchRealization(ReadGraph graph, Variable variable, Variable realization) throws DatabaseException {\r
-        Resource current = getRealization(graph, variable);\r
-        return switchRealization(graph, variable, current, realization);\r
-    }\r
-\r
-    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {\r
-        String currentURI = graph.getURI(currentRealization);\r
-        String targetURI = graph.getURI(targetRealization);\r
-        String variableURI = variable.getURI(graph);\r
-        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());\r
-        return getVariable(graph, targetVariableURI);\r
-    }\r
-\r
-    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Variable targetRealization) throws DatabaseException {\r
-        String currentURI = graph.getURI(currentRealization);\r
-        String targetURI = targetRealization.getURI(graph);\r
-        String variableURI = variable.getURI(graph);\r
-        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());\r
-        return getVariable(graph, targetVariableURI);\r
-    }\r
-\r
-    public static Variable switchPossibleRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {\r
-        String currentURI = graph.getURI(currentRealization);\r
-        String targetURI = graph.getURI(targetRealization);\r
-        String variableURI = variable.getURI(graph);\r
-        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());\r
-        return getPossibleVariable(graph, targetVariableURI);\r
-    }\r
-\r
-    public static Variable toConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Variable config = getConfigurationContext(graph, variable);\r
-        return switchRealization(graph, variable, config);\r
-    }\r
-\r
-    public static Variable toPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {\r
-       \r
-        Resource represents = variable.getPossibleRepresents(graph);\r
-        if(represents == null) return null;\r
-        Resource config = getPossibleConfigurationContextResource(graph, represents);\r
-        if(config == null) return null;\r
-       return switchPossibleContext(graph, variable, config);\r
-\r
-    }\r
-\r
-    public static String toRVI(ReadGraph graph, List<Resource> compositePath) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        StringBuilder rvi = new StringBuilder();\r
-        for (Resource composite : compositePath) {\r
-            String name = graph.getPossibleRelatedValue(composite, L0.HasName);\r
-            if (name == null)\r
-                return null;\r
-\r
-            rvi.append('/');\r
-            String escapedName = URIStringUtils.escape(name);\r
-            rvi.append(escapedName);\r
-        }\r
-        return rvi.toString();\r
-    }\r
-\r
-    public static String appendRVI(ReadGraph graph, String modelURI, String rvi, Resource configuration) throws DatabaseException {\r
-\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        String partName = graph.getPossibleRelatedValue(configuration, L0.HasName);\r
-        if(partName == null) throw new MissingVariableException("Can not append a child corresponding to " + configuration + " to rvi '" + rvi + "' since there is no name.");\r
-        String escaped = URIStringUtils.escape(partName);\r
-        return rvi + "/" + escaped;\r
-\r
-    }\r
-\r
-    public static boolean isValid(ReadGraph graph, Variable variable) {\r
-        if(variable == null) return false;\r
-        try {\r
-            variable.getURI(graph);\r
-        } catch (DatabaseException e) {\r
-            return false;\r
-        }\r
-        return true;\r
-    }\r
-\r
-    public static Variable possibleChildWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {\r
-        Variable found = null;\r
-        for(Variable child : variable.getChildren(graph)) {\r
-            Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);\r
-            if(type != null && graph.isInheritedFrom(type, targetType)) {\r
-                if(found != null) return null;\r
-                found = child;\r
-            }\r
-        }\r
-        return found;\r
-    }\r
-\r
-    public static Collection<Variable> childrenWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {\r
-        ArrayList<Variable> result = new ArrayList<Variable>();\r
-        for(Variable child : variable.getChildren(graph)) {\r
-            Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);\r
-            if(graph.isInheritedFrom(type, targetType)) result.add(child);\r
-        }\r
-        return result;\r
-    }\r
-\r
-    public static <T> T adapt(ReadGraph graph, Variable variable, String property, Class<T> clazz) throws DatabaseException {\r
-        Resource resource = variable.getPropertyValue(graph, property);\r
-        return graph.adapt(resource, clazz);\r
-    }\r
-\r
-    public static <T> T getPossiblePropertyValue(RequestProcessor processor, Variable variable, Resource property, Binding binding) {\r
-        try {\r
-            return processor.sync(new TernaryRead<Variable,Resource,Binding,T>(variable, property, binding) {\r
-\r
-                @Override\r
-                public T perform(ReadGraph graph) throws DatabaseException {\r
-                    return parameter.getPossiblePropertyValue(graph, parameter2, parameter3);\r
-                }\r
-\r
-            });\r
-        } catch (DatabaseException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    public static Variable possibleActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        Variable activeVariable = graph.sync(new PossibleActiveVariableFromVariable(variable));\r
-        return activeVariable;\r
-    }\r
-\r
-    public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node) throws DatabaseException {\r
-        return requestNodeValue(graph, node, null);\r
-    }\r
-\r
-    public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node, final Binding binding) throws DatabaseException {\r
-       Variant value = graph.syncRequest(new NodeValueRequest(node, binding));\r
-       if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {\r
-               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.\r
-               \r
-                       ValueGetter getter = new ValueGetter(node, binding);\r
-                       try {\r
-                               node.support.manager.getRealm().syncExec(getter);\r
-                       } catch (InterruptedException e) {\r
-                               Logger.defaultLogError(e);\r
-                       }\r
-                       \r
-                       if (getter.exception != null)\r
-                               throw new DatabaseException(getter.exception);\r
-                       \r
-                       return getter.result;\r
-       }\r
-        return value; \r
-    }\r
-    \r
-    public static class NodeStructure {\r
-        // Immutable but wrapped with Collections.unmodifiableMap as an optimization\r
-        public final Map<String,Object> children;\r
-        // Immutable but not wrapped with Collections.unmodifiableMap as an optimization\r
-        public final Map<String,Object> properties;\r
-        private final int hash;\r
-\r
-        public NodeStructure(Map<String, Object> children, Map<String, Object> properties) {\r
-            this.children = children;\r
-            this.properties = properties;\r
-            this.hash = calcHash();\r
-        }\r
-\r
-        private int calcHash() {\r
-            return 31*children.hashCode() + 41*properties.hashCode();\r
-        }\r
-\r
-        @Override\r
-        public int hashCode() {\r
-            return hash;\r
-        }\r
-\r
-        @Override\r
-        public boolean equals(Object object) {\r
-            if (this == object)\r
-                return true;\r
-            else if (object == null || object == Variables.PENDING_NODE_STRUCTURE)\r
-                return false;\r
-            else if (!(object instanceof NodeStructure))\r
-                return false;\r
-            NodeStructure r = (NodeStructure)object;\r
-            return r.children.equals(children) && r.properties.equals(properties);\r
-        }\r
-    }\r
-\r
-    public static NodeStructure requestNodeStructure(ReadGraph graph, VariableNode<?> node) throws DatabaseException {\r
-        NodeStructure value = graph.syncRequest(new NodeStructureRequest(node));\r
-        if (value == null) throw new DatabaseException("External data access error");\r
-       if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {\r
-               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.\r
-               \r
-                       StructureGetter getter = new StructureGetter(node);\r
-                       try {\r
-                               node.support.manager.getRealm().syncExec(getter);\r
-                       } catch (InterruptedException e) {\r
-                               Logger.defaultLogError(e);\r
-                               throw new DatabaseException("External data access error", e);\r
-                       }\r
-                       \r
-                       if (getter.exception != null)\r
-                               throw new DatabaseException("External data access error", getter.exception);\r
-                       if (getter.result == null)\r
-                               throw new DatabaseException("External data access error");\r
-                       \r
-                       return getter.result;\r
-               \r
-       }\r
-        return value; \r
-\r
-    }\r
-    \r
-    public static String getPossibleUnit(ReadGraph graph, Variable variable) throws DatabaseException {\r
-       \r
-       try {\r
-               \r
-               Resource predicate = variable.getPossiblePredicateResource(graph);\r
-               if(predicate != null) {\r
-                       PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));\r
-                       if(info.definedUnit != null) return info.definedUnit;\r
-               }\r
-               \r
-               Variant variant = variable.getVariantValue(graph);\r
-               Binding binding = variant.getBinding();\r
-               if(binding == null) return null;\r
-               Datatype dt = binding.type();\r
-               if(!(dt instanceof NumberType)) return null;\r
-               NumberType nt = (NumberType)dt;\r
-               return nt.getUnit();\r
-               \r
-       } catch (DatabaseException e) {\r
-               return null;\r
-       }\r
-       \r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param rvi\r
-     * @param context1 primary context to use for resolving the specified RVI, must not be null\r
-     * @param context2 secondary context to use for resolving the specified RVI, may be <code>null</code>\r
-     * @return pair of variables where first is the resolved variable and second\r
-     *         is the context it was resolved with\r
-     * @throws DatabaseException\r
-     * @since 1.18.1\r
-     */\r
-    public static Pair<Variable, Variable> resolvePossible(ReadGraph graph, RVI rvi, Variable context1, Variable context2) throws DatabaseException {\r
-        Variable v = rvi.resolvePossible(graph, context1);\r
-        if (v != null)\r
-            return new Pair<>(v, context1);\r
-        if (context2 != null) {\r
-            v = rvi.resolvePossible(graph, context2);\r
-            if (v != null)\r
-                return new Pair<>(v, context2);\r
-        }\r
-        return null;\r
-    }\r
-\r
-\r
-    @SuppressWarnings("rawtypes")\r
-    private static class ValueGetter implements VariableNodeReadRunnable {\r
-\r
-        final VariableNode n;\r
-        final Binding binding;\r
-        Variant result;\r
-        Exception exception;\r
-\r
-        public ValueGetter(VariableNode n, Binding binding) {\r
-            this.n = n;\r
-            this.binding = binding;\r
-        }\r
-\r
-        @SuppressWarnings("unchecked")\r
-        @Override\r
-        public void run() {\r
-            try {\r
-                if (binding != null)\r
-                    result = new Variant(binding, n.support.manager.getValue(n.node, binding));\r
-                else\r
-                    result = n.support.manager.getValue(n.node);\r
-            } catch (Exception e) {\r
-                Logger.defaultLogError(e);\r
-                exception = e;\r
-            }\r
-        }\r
-\r
-    }\r
-\r
-    @SuppressWarnings("rawtypes")\r
-    private static class StructureGetter implements VariableNodeReadRunnable {\r
-\r
-        final VariableNode n;\r
-        NodeStructure result;\r
-        Exception exception;\r
-\r
-        public StructureGetter(VariableNode n) {\r
-            this.n = n;\r
-        }\r
-\r
-        @Override\r
-        public void run() {\r
-            try {\r
-                result = NodeStructureRequest.get(n);\r
-            } catch (NodeManagerException e) {\r
-                Logger.defaultLogError(e);\r
-                exception = e;\r
-            }\r
-        }\r
-\r
-    };\r
-\r
-    public static Variable tryGetProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {\r
-        Variable v = Variables.getPossibleVariable(graph, entity);\r
-        return v != null ? v.getPossibleProperty(graph, property) : null;\r
-    }\r
-    \r
-       public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,\r
-                       Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,\r
-                       Function1<Variable, Datatype> getDatatype) {\r
-               return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);\r
-       }\r
-\r
-    \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.layer0.variable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Databoard;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.NumberType;
+import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.request.TernaryRead;
+import org.simantics.db.common.utils.CommonDBUtils;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+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.request.Model;
+import org.simantics.db.layer0.request.PossibleActiveVariableFromVariable;
+import org.simantics.db.layer0.request.PossibleVariableIndexRoot;
+import org.simantics.db.layer0.request.PossibleVariableModel;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.PropertyInfoRequest;
+import org.simantics.db.layer0.request.ResourceURIToVariable;
+import org.simantics.db.layer0.request.VariableIndexRoot;
+import org.simantics.db.layer0.request.VariableURI;
+import org.simantics.layer0.Layer0;
+import org.simantics.operation.Layer0X;
+import org.simantics.project.ontology.ProjectResource;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.Function2;
+import org.simantics.scl.runtime.function.Function3;
+import org.simantics.simulation.ontology.SimulationResource;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.utils.datastructures.Pair;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+final public class Variables {
+
+    public static final Variant PENDING_NODE_VALUE = new Variant();
+
+    public static final NodeStructure PENDING_NODE_STRUCTURE = new NodeStructure(Collections.emptyMap(), Collections.emptyMap()) {
+        public boolean equals(Object object) {
+            return this == object;
+        }
+    };
+
+    public static enum Role {
+
+        CHILD("/"), PROPERTY("#");
+
+        transient final String identifier;
+
+        private Role(String identifier) {
+            this.identifier = identifier;
+        }
+
+        final public String getIdentifier() {
+            return identifier;
+        }
+
+        public static Role getRole( String identifier ) {
+            for (Role role : Role.values()) if (role.identifier.equals( identifier )) return role;
+            return null;
+        }
+
+    }
+
+    // use getPredicate
+    //final public static String PREDICATE = "PREDICATE";
+
+    @Deprecated
+    // use getName
+    final public static String NAME = "HasName";
+    final public static String CLASSIFICATIONS = "classifications";
+    final public static String EXPRESSION = "HasExpression";
+    final public static String INPUT_VALIDATOR = "HasInputValidator";
+    final public static String INPUT_MODIFIER = "HasInputModifier";
+    final public static String FORMATTER = "HasFormatter";
+
+    final public static String STANDARD_RESOURCE = "hasStandardResource";
+    //@Deprecated
+    // use getPresents
+    //final public static String REPRESENTS = "Represents";
+    final public static String TYPE = "Type";
+    final public static String URI = "URI";
+    /**
+     * @deprecated use {@link Variable#getRVI(ReadGraph)} and {@link RVI} instead.
+     */
+//    @Deprecated
+//    final public static String SERIALISED = "Serialised";
+//    @Deprecated
+    // use getParent
+    //final public static String PARENT = "Parent";
+    //final public static String ROLE = "Role";
+    //final public static String DATATYPE = "DATATYPE";
+    //final public static String UNIT = "UNIT";
+
+    final public static String VALID = "valid";
+    final public static String REQUIRED = "required";
+    final public static String DEFAULT = "default";
+    final public static String READONLY = "readOnly";
+    final public static String VALIDATOR = "validator";
+
+    final public static String LABEL = "HasLabel";
+
+    final public static String ENUMERATION_VALUES = "HasEnumerationValues";
+    final public static String CUSTOM_MODIFIER = "HasCustomModifier";
+
+    final public static String DISPLAY_COLUMN = "HasDisplayColumn";
+
+    final public static String DISPLAY_PROPERTY = "HasDisplayProperty";
+    final public static String DISPLAY_VALUE = "HasDisplayValue";
+    final public static String DISPLAY_UNIT = "HasDisplayUnit";
+
+    final public static String CONVERTED_VALUE = "convertedValue";
+
+    /**
+     * This property should exist for array valued property variables.
+     */
+    final public static String ARRAY_SIZE = "ARRAY_SIZE";
+
+
+    @Deprecated
+    // use etc. variable.adapt(graph, Interface.class).getResource()
+    final public static String RESOURCE = "Resource";
+    @Deprecated
+    final public static String CONTAINER_RESOURCE = "ContainerResource";
+    @Deprecated
+    final public static String PROPERTY_RESOURCE = "PROPERTY_RESOURCE";
+
+    @Deprecated
+    public final static String[] builtins = {
+        TYPE, RESOURCE, URI
+        //, SERIALISED
+    };
+
+    public static Variable getPossibleVariable(ReadGraph graph, Resource resource) throws DatabaseException {
+        String uri = graph.getPossibleURI(resource);
+        if (uri != null)
+            return getPossibleVariable(graph, uri);
+        Resource parent = CommonDBUtils.getPossibleOwner(graph, resource);
+        if (parent == null)
+            return null;
+        Variable possibleVariable = getPossibleVariable(graph, parent);
+        if (possibleVariable == null)
+            return null;
+        String possibleName = graph.getPossibleRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);
+        if (possibleName == null)
+            possibleName = VariableUtils.unnamedResourceName(resource);
+        Variable possibleChild = possibleVariable.getPossibleChild(graph, possibleName);
+        if (possibleChild != null)
+            return possibleChild;
+        for (Variable v : possibleVariable.getChildren(graph)) {
+            Resource vr = v.getPossibleRepresents(graph);
+            if (vr != null && vr.equals(resource)) {
+                return v;
+            }
+        }
+        return null;
+    }
+
+    public static Variable getPossibleVariable(ReadGraph graph, String uri) throws DatabaseException {
+        try {
+            return getVariable(graph, uri);
+        } catch (DatabaseException e) {
+            return null;
+        }
+    }
+
+    public static Variable getVariable(ReadGraph graph, Resource resource) throws DatabaseException {
+        return getVariable(graph, graph.getURI(resource));
+    }
+
+    public static Variable getVariable(ReadGraph graph, String uri) throws DatabaseException {
+        try {
+            return graph.sync(new ResourceURIToVariable(uri));
+        } catch (MissingVariableException e) {
+            return VariableRepository.get(graph, uri);
+        }
+    }
+
+    private static int commonPrefixLength(String a, String b) {
+        int maxC = Math.min(a.length(), b.length());
+        for(int c=0;c<maxC;++c) {
+            if(a.charAt(c) != b.charAt(c))
+                return c;
+        }
+        return maxC;
+    }
+
+    private static boolean isSplitPos(String str, int p) {
+        if(p==str.length())
+            return true;
+        char c = str.charAt(p);
+        return c=='/' || c=='#';
+    }
+
+    private static int pathLength(String path) {
+        int count = 0;
+        for(int i=0;i<path.length();++i) {
+            char c = path.charAt(i);
+            if(c=='/' || c=='#')
+                ++count;
+        }
+        return count;
+    }
+
+    private static String prefixByParentPath(int parentPathLength, String suffix) {
+        StringBuilder b = new StringBuilder();
+        for(int i=0;i<parentPathLength;++i)
+            b.append('.');
+        b.append(suffix);
+        return b.toString();
+    }
+
+    public static String getRVI(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
+        String baseURI = graph.syncRequest(new VariableURI(base));
+        String otherURI = graph.syncRequest(new VariableURI(other));
+        return getRelativeRVI(baseURI, otherURI);
+    }
+
+    public static String getRelativeRVI(String baseURI, String otherURI) {
+        int prefixLength = commonPrefixLength(baseURI, otherURI);
+        if(!isSplitPos(baseURI, prefixLength) || !isSplitPos(otherURI, prefixLength)) {
+            for(--prefixLength;prefixLength > 0 && !isSplitPos(baseURI, prefixLength);--prefixLength);
+        }
+        if(prefixLength == baseURI.length())
+            return otherURI.substring(prefixLength);
+        else 
+            return prefixByParentPath(
+                    pathLength(baseURI.substring(prefixLength)), 
+                    otherURI.substring(prefixLength));     
+    }
+
+    public static String getRVI2(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
+        TObjectIntHashMap<Variable> baseLength = new TObjectIntHashMap<Variable>();
+        for(int depth=0;base != null;base = base.getParent(graph),++depth)
+            baseLength.put(base, depth);
+        Variable cur;
+        for(cur=other;!baseLength.containsKey(cur);cur=cur.getParent(graph));
+
+        // To string
+        String curURI = cur.getURI(graph);
+        String otherURI = other.getURI(graph);
+
+        return prefixByParentPath(baseLength.get(cur), otherURI.substring(curURI.length()));
+    }
+
+    public static String getProjectRVI(ReadGraph graph, Variable variable) throws DatabaseException {
+        Resource project = getProject(graph, variable);
+        String projectURI = graph.getURI(project);
+        return variable.getURI(graph).substring(projectURI.length());
+    }
+
+    private static int getSegmentEnd(String suffix) {
+        int pos;
+        for(pos=1;pos<suffix.length();++pos) {
+            char c = suffix.charAt(pos);
+            if(c == '/' || c == '#')
+                break;
+        }
+        return pos;
+    }
+
+    public static String getRVI(String rvi, String suffix) throws DatabaseException {
+        if(suffix.isEmpty()) return rvi;
+        switch(suffix.charAt(0)) {
+            case '.': {
+                return getRVI(URIStringUtils.getRVIParent(rvi), suffix.substring(1));
+            }
+            case '#': {
+                int segmentEnd = getSegmentEnd(suffix);
+                return getRVI(rvi + "#" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
+            }
+            case '/': {
+                int segmentEnd = getSegmentEnd(suffix);
+                return getRVI(rvi + "/" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
+            }
+            default:
+                return null;
+        }
+
+    }
+
+    public static Variable getRootVariable(ReadGraph graph) throws DatabaseException {
+        return graph.adapt(graph.getRootLibrary(), Variable.class);
+    }
+    
+    public static Resource getPossibleIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
+       return graph.syncRequest(new PossibleVariableIndexRoot(variable));
+    }
+    
+    public static Resource getIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
+       return graph.syncRequest(new VariableIndexRoot(variable));
+    }
+    
+    public static Resource getModel(ReadGraph graph, Variable variable) throws DatabaseException {
+        String URI = variable.getURI(graph);
+        return VariablesImpl.getFirst(graph, SimulationResource.getInstance(graph).Model, URI, 8);
+    }
+
+    public static Resource getPossibleModel(ReadGraph graph, Variable variable) throws DatabaseException {
+        return graph.syncRequest(new PossibleVariableModel(variable));
+    }
+
+    public static Resource getProject(ReadGraph graph, Variable variable) throws DatabaseException {
+        String URI = variable.getURI(graph);
+        return VariablesImpl.getFirst(graph, ProjectResource.getInstance(graph).Project, URI, 8);
+    }
+
+    public static Variable getConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
+        SimulationResource SIMU = SimulationResource.getInstance(graph);
+        if(!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new Model(resource));
+        Resource configurationResource = graph.getSingleObject(resource, SIMU.HasConfiguration);
+        return Variables.getVariable(graph, configurationResource);
+    }
+
+    public static Resource getConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
+        Variable config = getConfigurationContext(graph, resource);
+        return config.getRepresents(graph);
+    }
+
+    public static Variable getConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
+        SimulationResource SIMU = SimulationResource.getInstance(graph);
+        Resource model = Variables.getModel(graph, variable);
+        Resource configurationResource = graph.getSingleObject(model, SIMU.HasConfiguration);
+        return Variables.getVariable(graph, configurationResource);
+    }
+
+    public static Resource getPossibleConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
+        Variable config = getPossibleConfigurationContext(graph, resource);
+        return config != null ? config.getPossibleRepresents(graph) : null;
+    }
+
+    public static Variable getPossibleConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
+        SimulationResource SIMU = SimulationResource.getInstance(graph);
+        if (!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new PossibleIndexRoot(resource));
+        if (resource == null)
+            return null;
+        Resource configurationResource = graph.getPossibleObject(resource, SIMU.HasConfiguration);
+        if (configurationResource == null)
+            return null;
+        return Variables.getPossibleVariable(graph, configurationResource);
+    }
+
+    public static Variable getPossibleConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
+        SimulationResource SIMU = SimulationResource.getInstance(graph);
+        Resource model = getPossibleIndexRoot(graph, variable);
+        if (model == null)
+            return null;
+        Resource configurationResource = graph.getPossibleObject(model, SIMU.HasConfiguration);
+        if (configurationResource == null)
+            return null;
+        return Variables.getPossibleVariable(graph, configurationResource);
+    }
+
+    public static Variable getConfigurationVariable(ReadGraph graph, Resource resource, String RVI) throws DatabaseException {
+        Variable context = getConfigurationContext(graph, resource);
+        return context.browse(graph, RVI);
+    }
+    
+    public static Variable getConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+        Variable context = getConfigurationContext(graph, variable);
+        RVI rvi = variable.getRVI(graph);
+        return rvi.resolve(graph, context);
+    }
+
+    public static Variable getPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+        Variable context = getPossibleConfigurationContext(graph, variable);
+        if (context == null)
+            return null;
+        try {
+            RVI rvi = variable.getRVI(graph);
+            return rvi.resolvePossible(graph, context);
+        } catch (MissingVariableException e) {
+            // Ignore.
+            return null;
+        }
+    }
+
+    public static Datatype getDatatype(ReadGraph graph, Resource resource, RVI rvi) throws DatabaseException {
+        Variable var = rvi.resolve(graph, getConfigurationContext(graph, resource));
+        return var.getDatatype(graph);
+    }
+
+    @Deprecated
+    public static Resource getRealization(ReadGraph graph, Variable variable) throws DatabaseException {
+        String URI = variable.getURI(graph);
+        return VariablesImpl.getFirst(graph, Layer0X.getInstance(graph).Realization, URI, 8);
+    }
+
+    public static boolean isContext(ReadGraph graph, Variable variable) throws DatabaseException {
+        Resource type = variable.getPossibleType(graph);
+        if(type != null) {
+            if(graph.isInheritedFrom(type, Layer0.getInstance(graph).RVIContext)) return true;
+        }
+        return false;
+    }
+
+    public static Variable getPossibleContext(ReadGraph graph, Variable variable) throws DatabaseException {
+        if(isContext(graph, variable)) return variable;
+        Variable parent = variable.getParent(graph);
+        if(parent == null) return null;
+        return getPossibleContext(graph, parent);
+    }
+
+    public static Variable getContext(ReadGraph graph, Variable variable) throws DatabaseException {
+        Variable context = getPossibleContext(graph, variable);
+        if (context == null)
+            throw new MissingVariableException("No context found for " + variable.getURI(graph), variable.getPossibleRepresents(graph));
+        else return context;
+    }
+
+    public static RVI getRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
+        return variable.getRVI(graph);
+    }
+
+    public static RVI getPossibleRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
+        try {
+            return variable.getRVI(graph);
+        } catch (DatabaseException e) {
+            return null;
+        }
+    }
+
+    public static String getRVI(ReadGraph graph, Variable variable) throws DatabaseException {
+        Resource realizationResource = getRealization(graph, variable);
+        if (realizationResource == null)
+            throw new InvalidVariableException("No realization found for " + variable.getURI(graph));
+        return variable.getURI(graph).substring(graph.getURI(realizationResource).length()); 
+    }
+
+    public static String getRVI(ReadGraph graph, Resource config) throws DatabaseException {
+        Variable var = getVariable(graph, config);
+        return getRVI(graph, var);
+    }
+
+    public static String getPossibleRVI(ReadGraph graph, Resource config) throws DatabaseException {
+        Variable var = getPossibleVariable(graph, config);
+        return var != null ? getPossibleRVI(graph, var) : null;
+    }
+
+    public static String getPossibleRVI(ReadGraph graph, Variable variable) throws DatabaseException {
+        try {
+            return getRVI(graph, variable);
+        } catch (DatabaseException e) {
+            return null;
+        }
+    }
+
+    public static List<Variable> getPath(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
+        if(!isChild(graph, base, var)) return null;
+        LinkedList<Variable> result = new LinkedList<Variable>();
+        var = var.getParent(graph);
+        while(!var.equals(base)) {
+            result.addFirst(var);
+            var = var.getParent(graph);
+        }
+        return result;
+    }
+
+    public static Variable getChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
+        List<Variable> path = getPath(graph, base, var);
+        if(path == null || path.size() == 0) return null;
+        return path.get(0);
+    }
+
+    public static boolean isChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
+        if(base.equals(var)) return false;
+        return var.getURI(graph).startsWith(base.getURI(graph));
+    }
+
+    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
+        Resource current = getRealization(graph, variable);
+        if (current == null)
+            throw new InvalidVariableException("No current realization found for variable");
+        return switchRealization(graph, variable, current, realization);
+    }
+
+    public static Variable switchPossibleContext(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
+        Variable current = getPossibleContext(graph, variable);
+        if (current == null)
+            return null;
+        Resource currentContext = current.getPossibleRepresents(graph);
+        if (currentContext == null)
+            return null;
+        return switchPossibleRealization(graph, variable, currentContext, realization);
+    }
+
+    public static Variable switchRealization(ReadGraph graph, Variable variable, Variable realization) throws DatabaseException {
+        Resource current = getRealization(graph, variable);
+        return switchRealization(graph, variable, current, realization);
+    }
+
+    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
+        String currentURI = graph.getURI(currentRealization);
+        String targetURI = graph.getURI(targetRealization);
+        String variableURI = variable.getURI(graph);
+        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
+        return getVariable(graph, targetVariableURI);
+    }
+
+    public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Variable targetRealization) throws DatabaseException {
+        String currentURI = graph.getURI(currentRealization);
+        String targetURI = targetRealization.getURI(graph);
+        String variableURI = variable.getURI(graph);
+        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
+        return getVariable(graph, targetVariableURI);
+    }
+
+    public static Variable switchPossibleRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
+        String currentURI = graph.getURI(currentRealization);
+        String targetURI = graph.getURI(targetRealization);
+        String variableURI = variable.getURI(graph);
+        String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
+        return getPossibleVariable(graph, targetVariableURI);
+    }
+
+    public static Variable toConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+        Variable config = getConfigurationContext(graph, variable);
+        return switchRealization(graph, variable, config);
+    }
+
+    public static Variable toPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+       
+        Resource represents = variable.getPossibleRepresents(graph);
+        if(represents == null) return null;
+        Resource config = getPossibleConfigurationContextResource(graph, represents);
+        if(config == null) return null;
+       return switchPossibleContext(graph, variable, config);
+
+    }
+
+    public static String toRVI(ReadGraph graph, List<Resource> compositePath) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        StringBuilder rvi = new StringBuilder();
+        for (Resource composite : compositePath) {
+            String name = graph.getPossibleRelatedValue(composite, L0.HasName);
+            if (name == null)
+                return null;
+
+            rvi.append('/');
+            String escapedName = URIStringUtils.escape(name);
+            rvi.append(escapedName);
+        }
+        return rvi.toString();
+    }
+
+    public static String appendRVI(ReadGraph graph, String modelURI, String rvi, Resource configuration) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        String partName = graph.getPossibleRelatedValue(configuration, L0.HasName);
+        if (partName == null)
+            throw new MissingVariableException("Can not append a child corresponding to " + configuration + " to rvi '"
+                    + rvi + "' since there is no name.", configuration);
+        String escaped = URIStringUtils.escape(partName);
+        return rvi + "/" + escaped;
+    }
+
+    public static boolean isValid(ReadGraph graph, Variable variable) {
+        if(variable == null) return false;
+        try {
+            variable.getURI(graph);
+        } catch (DatabaseException e) {
+            return false;
+        }
+        return true;
+    }
+
+    public static Variable possibleChildWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
+        Variable found = null;
+        for(Variable child : variable.getChildren(graph)) {
+            Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
+            if(type != null && graph.isInheritedFrom(type, targetType)) {
+                if(found != null) return null;
+                found = child;
+            }
+        }
+        return found;
+    }
+
+    public static Collection<Variable> childrenWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
+        ArrayList<Variable> result = new ArrayList<Variable>();
+        for(Variable child : variable.getChildren(graph)) {
+            Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
+            if(graph.isInheritedFrom(type, targetType)) result.add(child);
+        }
+        return result;
+    }
+
+    public static <T> T adapt(ReadGraph graph, Variable variable, String property, Class<T> clazz) throws DatabaseException {
+        Resource resource = variable.getPropertyValue(graph, property);
+        return graph.adapt(resource, clazz);
+    }
+
+    public static <T> T getPossiblePropertyValue(RequestProcessor processor, Variable variable, Resource property, Binding binding) {
+        try {
+            return processor.sync(new TernaryRead<Variable,Resource,Binding,T>(variable, property, binding) {
+
+                @Override
+                public T perform(ReadGraph graph) throws DatabaseException {
+                    return parameter.getPossiblePropertyValue(graph, parameter2, parameter3);
+                }
+
+            });
+        } catch (DatabaseException e) {
+            return null;
+        }
+    }
+
+    public static Variable possibleActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+        Variable activeVariable = graph.sync(new PossibleActiveVariableFromVariable(variable));
+        return activeVariable;
+    }
+
+    public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
+        return requestNodeValue(graph, node, null);
+    }
+
+    public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node, final Binding binding) throws DatabaseException {
+       Variant value = graph.syncRequest(new NodeValueRequest(node, binding));
+       if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {
+               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
+               
+                       ValueGetter getter = new ValueGetter(node, binding);
+                       try {
+                               node.support.manager.getRealm().syncExec(getter);
+                       } catch (InterruptedException e) {
+                               Logger.defaultLogError(e);
+                       }
+                       
+                       if (getter.exception != null)
+                               throw new MissingVariableValueException("No value for node " + node, getter.exception);
+                       
+                       return getter.result;
+       }
+        return value; 
+    }
+    
+    public static class NodeStructure {
+        // Immutable but wrapped with Collections.unmodifiableMap as an optimization
+        public final Map<String,Object> children;
+        // Immutable but not wrapped with Collections.unmodifiableMap as an optimization
+        public final Map<String,Object> properties;
+        private final int hash;
+
+        public NodeStructure(Map<String, Object> children, Map<String, Object> properties) {
+            this.children = children;
+            this.properties = properties;
+            this.hash = calcHash();
+        }
+
+        private int calcHash() {
+            return 31*children.hashCode() + 41*properties.hashCode();
+        }
+
+        @Override
+        public int hashCode() {
+            return hash;
+        }
+
+        @Override
+        public boolean equals(Object object) {
+            if (this == object)
+                return true;
+            else if (object == null || object == Variables.PENDING_NODE_STRUCTURE)
+                return false;
+            else if (!(object instanceof NodeStructure))
+                return false;
+            NodeStructure r = (NodeStructure)object;
+            return r.children.equals(children) && r.properties.equals(properties);
+        }
+    }
+
+    public static NodeStructure requestNodeStructure(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
+        NodeStructure value = graph.syncRequest(new NodeStructureRequest(node));
+        if (value == null)
+            throw new InvalidVariableException("External data access error " + String.valueOf(node));
+       if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {
+               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
+               
+                       StructureGetter getter = new StructureGetter(node);
+                       try {
+                               node.support.manager.getRealm().syncExec(getter);
+                       } catch (InterruptedException e) {
+                               Logger.defaultLogError(e);
+                               throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
+                       }
+                       
+                       if (getter.exception != null)
+                               throw new InvalidVariableException("External data access error " + String.valueOf(node), getter.exception);
+                       if (getter.result == null)
+                               throw new InvalidVariableException("External data access error " + String.valueOf(node));
+                       
+                       return getter.result;
+               
+       }
+        return value; 
+
+    }
+    
+    public static String getPossibleUnit(ReadGraph graph, Variable variable) throws DatabaseException {
+       
+       try {
+               
+               Resource predicate = variable.getPossiblePredicateResource(graph);
+               if(predicate != null) {
+                       PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
+                       if(info.definedUnit != null) return info.definedUnit;
+               }
+               
+               Variant variant = variable.getVariantValue(graph);
+               Binding binding = variant.getBinding();
+               if(binding == null) return null;
+               Datatype dt = binding.type();
+               if(!(dt instanceof NumberType)) return null;
+               NumberType nt = (NumberType)dt;
+               return nt.getUnit();
+               
+       } catch (DatabaseException e) {
+               return null;
+       }
+       
+    }
+
+    /**
+     * @param graph
+     * @param rvi
+     * @param context1 primary context to use for resolving the specified RVI, must not be null
+     * @param context2 secondary context to use for resolving the specified RVI, may be <code>null</code>
+     * @return pair of variables where first is the resolved variable and second
+     *         is the context it was resolved with
+     * @throws DatabaseException
+     * @since 1.18.1
+     */
+    public static Pair<Variable, Variable> resolvePossible(ReadGraph graph, RVI rvi, Variable context1, Variable context2) throws DatabaseException {
+        Variable v = rvi.resolvePossible(graph, context1);
+        if (v != null)
+            return new Pair<>(v, context1);
+        if (context2 != null) {
+            v = rvi.resolvePossible(graph, context2);
+            if (v != null)
+                return new Pair<>(v, context2);
+        }
+        return null;
+    }
+
+
+    @SuppressWarnings("rawtypes")
+    private static class ValueGetter implements VariableNodeReadRunnable {
+
+        final VariableNode n;
+        final Binding binding;
+        Variant result;
+        Exception exception;
+
+        public ValueGetter(VariableNode n, Binding binding) {
+            this.n = n;
+            this.binding = binding;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public void run() {
+            try {
+                if (binding != null)
+                    result = new Variant(binding, n.support.manager.getValue(n.node, binding));
+                else
+                    result = n.support.manager.getValue(n.node);
+            } catch (Exception e) {
+                Logger.defaultLogError(e);
+                exception = e;
+            }
+        }
+
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static class StructureGetter implements VariableNodeReadRunnable {
+
+        final VariableNode n;
+        NodeStructure result;
+        Exception exception;
+
+        public StructureGetter(VariableNode n) {
+            this.n = n;
+        }
+
+        @Override
+        public void run() {
+            try {
+                result = NodeStructureRequest.get(n);
+            } catch (NodeManagerException e) {
+                Logger.defaultLogError(e);
+                exception = e;
+            }
+        }
+
+    };
+
+    public static Variable tryGetProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {
+        Variable v = Variables.getPossibleVariable(graph, entity);
+        return v != null ? v.getPossibleProperty(graph, property) : null;
+    }
+    
+       public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,
+                       Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,
+                       Function1<Variable, Datatype> getDatatype) {
+               return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);
+       }
+
+    public static void setRVIProperty(WriteGraph graph, Variable variable, RVI rvi) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class );
+        Resource predicate = variable.getPredicateResource(graph);
+        Resource subject = variable.getParent(graph).getRepresents(graph);
+        graph.deny(subject, predicate);
+        graph.claimLiteral(subject, predicate, L0.RVI, rvi, rviBinding);
+    }
+
+}