+/*******************************************************************************\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.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.PossibleModel;\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 PossibleModel(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 = getPossibleModel(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