--- /dev/null
+package org.simantics.db.layer0.variable;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Databoard;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.StringBinding;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.util.URIStringUtils;\r
+import org.simantics.datatypes.literal.GUID;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
+import org.simantics.db.common.request.PossibleIndexRoot;\r
+import org.simantics.db.common.request.PropertyMapOfResource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.AdaptionException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.exception.InvalidVariableException;\r
+import org.simantics.db.layer0.exception.MissingVariableException;\r
+import org.simantics.db.layer0.exception.MissingVariableValueException;\r
+import org.simantics.db.layer0.request.PossibleResource;\r
+import org.simantics.db.layer0.request.PropertyInfo;\r
+import org.simantics.db.layer0.request.VariableRVIRequest;\r
+import org.simantics.db.layer0.variable.RVI.GuidRVIPart;\r
+import org.simantics.db.layer0.variable.RVI.RVIPart;\r
+import org.simantics.db.layer0.variable.RVI.ResourceRVIPart;\r
+import org.simantics.db.layer0.variable.RVI.StringRVIPart;\r
+import org.simantics.db.layer0.variable.Variables.Role;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * Abstract implementation of Variable -interface.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public abstract class AbstractVariable implements Variable {\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ final public VariableNode node;\r
+\r
+ public AbstractVariable(@SuppressWarnings("rawtypes") VariableNode node) {\r
+ this.node = node;\r
+ }\r
+\r
+ /**\r
+ * Returns a variable that is not one of the standard properties listed\r
+ * in <a href="https://www.simantics.org/wiki/index.php/Org.simantics.db.layer0.variable.Variable#Standard_required_properties">specification</a>.\r
+ */\r
+ protected abstract Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException;\r
+ public abstract Variable getPossibleExtraProperty(ReadGraph graph, String name) throws DatabaseException;\r
+ public abstract Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException;\r
+ \r
+ public abstract void collectExtraProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException;\r
+ public abstract Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> map) throws DatabaseException;\r
+ public abstract Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException;\r
+ \r
+ public abstract <T> T getValue(ReadGraph graph) throws DatabaseException;\r
+ public abstract <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException;\r
+\r
+ public abstract void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException;\r
+ public abstract String getName(ReadGraph graph) throws DatabaseException;\r
+ //public abstract Object getSerialized(ReadGraph graph) throws DatabaseException;\r
+ public abstract Variable getParent(ReadGraph graph) throws DatabaseException;\r
+ public abstract Role getRole(ReadGraph graph) throws DatabaseException;\r
+ public abstract Resource getRepresents(ReadGraph graph) throws DatabaseException;\r
+ \r
+ public abstract Set<String> getClassifications(ReadGraph graph) throws DatabaseException;\r
+ \r
+ @Override\r
+ public PropertyInfo getPropertyInfo(ReadGraph graph) throws DatabaseException {\r
+ throw new DatabaseException("PropertyInfo is not available");\r
+ }\r
+ \r
+ @Override\r
+ public Resource getIndexRoot(ReadGraph graph) throws DatabaseException {\r
+ Resource represents = getPossibleRepresents(graph);\r
+ if(represents != null) return graph.syncRequest(new PossibleIndexRoot(represents));\r
+ Variable parent = getParent(graph);\r
+ if(parent == null) return null;\r
+ return parent.getIndexRoot(graph);\r
+ }\r
+ \r
+ public void validate(ReadGraph graph) throws DatabaseException {\r
+ }\r
+\r
+ public String getIdentifier() {\r
+ return getClass().getSimpleName();\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public Role getPossibleRole(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getRole(graph);\r
+ } catch (DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ protected Variable resolveChild(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ String rName = graph.getRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
+ for(Variable child : browseChildren(graph)) {\r
+ String name = child.getPossiblePropertyValue(graph, Variables.NAME, Bindings.STRING);\r
+ if(rName.equals(name)) return child;\r
+ }\r
+ throw new DatabaseException("Could not resolve child " + resource);\r
+ }\r
+ \r
+ protected Variable resolveChild(ReadGraph graph, GuidRVIPart part) throws DatabaseException {\r
+ return StandardRVIResolver.resolveChildDefault(graph, this, part);\r
+ }\r
+ \r
+ protected Variable resolveProperty(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ String rName = graph.getRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
+ for(Variable child : browseProperties(graph)) {\r
+ String name = child.getPossiblePropertyValue(graph, Variables.NAME, Bindings.STRING);\r
+ if(rName.equals(name)) return child;\r
+ }\r
+ throw new DatabaseException("Could not resolve child " + resource);\r
+ }\r
+\r
+ protected Variable resolveProperty(ReadGraph graph, GuidRVIPart part) throws DatabaseException {\r
+ return StandardRVIResolver.resolvePropertyDefault(graph, this, part);\r
+ }\r
+\r
+ protected Variable resolvePossibleChild(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ String rName = graph.getRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
+ for(Variable child : browseChildren(graph)) {\r
+ String name = child.getPossiblePropertyValue(graph, Variables.NAME, Bindings.STRING);\r
+ if(rName.equals(name)) return child;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ protected Variable resolvePossibleChild(ReadGraph graph, GuidRVIPart part) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Variable child : browseChildren(graph)) {\r
+ GUID id = child.getPossiblePropertyValue(graph, L0.identifier, GUID.BINDING);\r
+ if(id != null) {\r
+ if(id.mostSignificant == part.mostSignificant && id.leastSignificant == part.leastSignificant)\r
+ return child;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ protected Variable resolvePossibleProperty(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ String rName = graph.getRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
+ for(Variable child : browseProperties(graph)) {\r
+ String name = child.getPossiblePropertyValue(graph, Variables.NAME, Bindings.STRING);\r
+ if(rName.equals(name)) return child;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ protected Variable resolvePossibleProperty(ReadGraph graph, GuidRVIPart part) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Variable child : browseProperties(graph)) {\r
+ GUID id = child.getPossiblePropertyValue(graph, L0.identifier, GUID.BINDING);\r
+ if(id != null) {\r
+ if(id.mostSignificant == part.mostSignificant && id.leastSignificant == part.leastSignificant)\r
+ return child;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public String getLabel(ReadGraph graph) throws DatabaseException { \r
+ return getName(graph);\r
+ }\r
+ \r
+ public String getPossibleLabel(ReadGraph graph) throws DatabaseException {\r
+ Resource represents = getPossibleRepresents(graph);\r
+ if(represents == null) return null;\r
+ return graph.getPossibleRelatedValue2(represents, graph.getService(Layer0.class).HasLabel, getParent(graph), Bindings.STRING);\r
+ }\r
+\r
+ public Resource getType(ReadGraph graph) throws DatabaseException {\r
+ \r
+ Resource resource = getPossibleRepresents(graph);\r
+ if(resource == null) {\r
+ String uri = getPossiblePropertyValue(graph, "typeURI");\r
+ if(uri != null) return graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());\r
+ throw new DatabaseException("No type for " + getURI(graph));\r
+ }\r
+ return graph.getSingleType(resource);\r
+ \r
+ }\r
+ \r
+ public RVIPart getRVIPart(ReadGraph graph) throws DatabaseException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public RVI getRVI(ReadGraph graph) throws DatabaseException {\r
+ Databoard databoard = graph.getService( Databoard.class );\r
+ Binding rviBinding = databoard.getBindingUnchecked( RVI.class );\r
+ if(Variables.isContext(graph, this)) {\r
+ return RVI.empty( rviBinding );\r
+ } else {\r
+ Variable parent = getParent(graph);\r
+ if (parent == null)\r
+ // TODO: consider using a more suitable exception here to better convey the situation.\r
+ throw new MissingVariableException("no parent for variable " + this + " (URI=" + getPossibleURI(graph) + ")");\r
+ RVI base = graph.syncRequest(new VariableRVIRequest(parent));\r
+ RVIPart part = getRVIPart(graph);\r
+ return new RVIBuilder(base).append(part).toRVI();\r
+ }\r
+ }\r
+ \r
+ protected Variable getDomainProperty(ReadGraph graph, String name) throws DatabaseException {\r
+ Variable property = getPossibleDomainProperty(graph, name);\r
+ if(property == null)\r
+ throw new MissingVariableException(getIdentifier() + ": Didn't find property " + name + ".");\r
+ return property;\r
+ }\r
+ \r
+ protected void addProperty(Map<String, Variable> properties, String name, Object value, Binding binding) {\r
+ if(value != null) {\r
+ properties.put(name, new ConstantPropertyVariable(this, name, value, binding));\r
+ }\r
+ }\r
+\r
+ protected Variable getNameVariable(ReadGraph graph) throws DatabaseException {\r
+ return new ConstantPropertyVariable(this, Variables.NAME, getName(graph), Bindings.STRING);\r
+ }\r
+\r
+ protected Variable getLabelVariable(ReadGraph graph) throws DatabaseException {\r
+ return new ConstantPropertyVariable(this, Variables.LABEL, getPossibleLabel(graph), Bindings.STRING);\r
+ }\r
+\r
+ final public Collection<Variable> browseProperties(ReadGraph graph) throws DatabaseException {\r
+ return getProperties(graph);\r
+ }\r
+\r
+ private Map<String, Variable> getPropertyMap(ReadGraph graph, String classification) throws DatabaseException {\r
+ return collectDomainProperties(graph, classification, null);\r
+ }\r
+\r
+ final static class PropertyMap extends THashMap<String,Variable> {\r
+ \r
+ final private Variable variable;\r
+ \r
+ PropertyMap(Variable variable) {\r
+ this.variable = variable;\r
+ }\r
+\r
+ private Variable getTypeVariable() {\r
+ \r
+ return new AbstractConstantPropertyVariable(variable, Variables.TYPE, null) {\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getValue(ReadGraph graph) throws DatabaseException {\r
+ Resource represents = parent.getRepresents(graph);\r
+ if(represents == null) return null;\r
+ return (T)graph.getPossibleType(represents, Layer0.getInstance(graph).Entity);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {\r
+ return getValue(graph);\r
+ }\r
+ \r
+ };\r
+ }\r
+\r
+ private Variable getURIVariable() {\r
+ \r
+ return new AbstractConstantPropertyVariable(variable, Variables.URI, null) {\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getValue(ReadGraph graph) throws DatabaseException {\r
+ return (T)variable.getURI(graph);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {\r
+ return getValue(graph);\r
+ }\r
+ \r
+ };\r
+ }\r
+\r
+ public Variable get(Object key) {\r
+ Variable result = super.get(key);\r
+ if(result != null) return result;\r
+ \r
+ if(Variables.TYPE.equals(key)) return getTypeVariable();\r
+ else if(Variables.URI.equals(key)) return getURIVariable();\r
+ \r
+ return variable;\r
+ }\r
+ \r
+ }\r
+ \r
+ private Map<String, Variable> getPropertyMap(ReadGraph graph) throws DatabaseException {\r
+ PropertyMap properties = new PropertyMap(this);\r
+// Map<String, Variable> properties = new HashMap<String, Variable>();\r
+// try {\r
+// properties.put(Variables.NAME, getNameVariable(graph));\r
+// } catch (DatabaseException e) {\r
+// // A variable that has no name doesn't exist by definition.\r
+// // Therefore it can't have any properties.\r
+// return Collections.emptyMap();\r
+// }\r
+// try {\r
+// Variable labelVariable = getLabelVariable(graph);\r
+// if(labelVariable != null) properties.put(Variables.LABEL, getLabelVariable(graph));\r
+// } catch (DatabaseException e) {\r
+// // Label not absolutely mandatory.\r
+// }\r
+// addProperty(properties, Variables.TYPE, getPossibleType(graph), null);\r
+// addProperty(properties, Variables.URI, getPossibleURI(graph), Bindings.STRING);\r
+ //addProperty(properties, Variables.SERIALISED, getSerialized(graph), Bindings.STRING);\r
+ //addProperty(properties, Variables.PARENT, getParent(graph), null);\r
+// addProperty(properties, Variables.ROLE, getRole(graph), Bindings.STRING);\r
+// addProperty(properties, Variables.REPRESENTS, getPossibleRepresents(graph), null);\r
+ collectExtraProperties(graph, properties);\r
+ collectDomainProperties(graph, properties);\r
+ return properties;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<Variable> getProperties(ReadGraph graph) throws DatabaseException {\r
+ return getPropertyMap(graph).values();\r
+ }\r
+ \r
+ public Collection<Variable> getProperties(ReadGraph graph, String classification) throws DatabaseException {\r
+ Map<String,Variable> propertyMap = getPropertyMap(graph, classification);\r
+ if(propertyMap == null) return Collections.emptyList();\r
+ else return propertyMap.values();\r
+ }\r
+\r
+ @Override\r
+ public Collection<Variable> getProperties(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return getProperties(graph, uri(graph, property));\r
+ }\r
+\r
+ final public Collection<Variable> browseChildren(ReadGraph graph) throws DatabaseException {\r
+ return getChildren(graph);\r
+ }\r
+ \r
+ @Override\r
+ public Variable getPossibleProperty(ReadGraph graph, String name)\r
+ throws DatabaseException {\r
+ if(Variables.NAME.equals(name)) {\r
+ return getNameVariable(graph);\r
+ }\r
+ if(Variables.LABEL.equals(name)) {\r
+ return getLabelVariable(graph);\r
+ }\r
+ if(Variables.TYPE.equals(name)) {\r
+ Object value = getPossibleType(graph);\r
+ if(value != null)\r
+ return new ConstantPropertyVariable(this, name, value, null);\r
+ }\r
+ if(Variables.URI.equals(name)) {\r
+ // TODO: getPossibleURI or getURI?\r
+ Object value = getURI(graph);\r
+ if(value != null)\r
+ return new ConstantPropertyVariable(this, name, value, Bindings.STRING);\r
+ }\r
+// if(Variables.SERIALISED.equals(name)) {\r
+// Object value = getSerialized(graph);\r
+// if(value != null)\r
+// return new ConstantPropertyVariable(this, name, value, Bindings.STRING);\r
+// }\r
+ /*if(Variables.PARENT.equals(name)) {\r
+ Object value = getParent(graph);\r
+ if(value != null)\r
+ return new ConstantPropertyVariable(this, name, value, null);\r
+ }*/\r
+// if(Variables.ROLE.equals(name)) {\r
+// Object value = getRole(graph);\r
+// if(value != null)\r
+// return new ConstantPropertyVariable(this, name, value, null);\r
+// }\r
+// if(Variables.REPRESENTS.equals(name)) {\r
+// Object value = getRepresents(graph);\r
+// if(value != null)\r
+// return new ConstantPropertyVariable(this, name, value, null);\r
+// }\r
+ Variable extra = getPossibleExtraProperty(graph, name);\r
+ if(extra != null) return extra;\r
+ return getPossibleDomainProperty(graph, name);\r
+ }\r
+ \r
+ @Override\r
+ public Variable getPossibleProperty(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return getPossibleProperty(graph, name(graph, property));\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ protected <T> T checkNull(ReadGraph graph, Object value) throws DatabaseException {\r
+ if(value == null)\r
+ throw new MissingVariableValueException(getClass().getSimpleName() + ": Didn't find value for " + getPossibleURI(graph));\r
+ return (T)value;\r
+ }\r
+\r
+ private String name(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return graph.getRelatedValue(property, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
+ }\r
+ \r
+ private String uri(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return graph.getURI(property);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getPropertyValue(ReadGraph graph, String name) throws DatabaseException {\r
+ if(Variables.LABEL.equals(name)) return checkNull(graph, getLabel(graph));\r
+ Variable result = getDomainProperty(graph, name);\r
+ if(result != null) return result.getValue(graph);\r
+ if(Variables.NAME.equals(name)) return checkNull(graph, getName(graph));\r
+ if(Variables.TYPE.equals(name)) return checkNull(graph, getPossibleType(graph));\r
+ if(Variables.URI.equals(name)) return checkNull(graph, getURI(graph));\r
+// if(Variables.SERIALISED.equals(name)) return checkNull(graph, getSerialized(graph));\r
+// if(Variables.ROLE.equals(name)) return checkNull(graph, getRole(graph));\r
+// if(Variables.REPRESENTS.equals(name)) return checkNull(graph, getRepresents(graph));\r
+ Variable extra = getPossibleExtraProperty(graph, name);\r
+ if(extra != null) return extra.getValue(graph);\r
+ return null;\r
+ } \r
+ \r
+ @Override\r
+ public <T> T getPropertyValue(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return getPropertyValue(graph, name(graph, property));\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getPossiblePropertyValue(ReadGraph graph, String name)\r
+ throws DatabaseException {\r
+ \r
+ Variable property = getPossibleDomainProperty(graph, name);\r
+ if(property != null) return property.getPossibleValue(graph);\r
+ \r
+ if(Variables.NAME.equals(name)) return (T)getName(graph);\r
+ if(Variables.LABEL.equals(name)) return (T)getLabel(graph);\r
+ if(Variables.TYPE.equals(name)) return (T)getPossibleType(graph);\r
+ if(Variables.URI.equals(name)) return (T)getURI(graph);\r
+// if(Variables.SERIALISED.equals(name)) return (T)getSerialized(graph);\r
+// if(Variables.ROLE.equals(name)) return (T)getRole(graph);\r
+// if(Variables.REPRESENTS.equals(name)) return (T)getRepresents(graph);\r
+ \r
+ Variable extra = getPossibleExtraProperty(graph, name);\r
+ if(extra != null) return extra.getPossibleValue(graph);\r
+ \r
+ return null;\r
+ \r
+ }\r
+\r
+ @Override\r
+ public <T> T getPossiblePropertyValue(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return getPossiblePropertyValue(graph, name(graph, property));\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getPropertyValue(ReadGraph graph, String name, Binding binding)\r
+ throws DatabaseException {\r
+ if(binding instanceof StringBinding) {\r
+ StringBinding sb = (StringBinding)binding;\r
+ try {\r
+ if(Variables.NAME.equals(name)) return (T)sb.create((String)checkNull(graph, getName(graph)));\r
+ if(Variables.LABEL.equals(name)) return (T)sb.create((String)checkNull(graph, getLabel(graph)));\r
+ if(Variables.URI.equals(name)) return (T)sb.create((String)checkNull(graph, getURI(graph)));\r
+// if(Variables.SERIALISED.equals(name)) return (T)sb.create((String)checkNull(graph, getSerialized(graph)));\r
+ } catch(BindingException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+ Variable property = getPossibleExtraProperty(graph, name);\r
+ if(property != null)\r
+ return property.getValue(graph, binding);\r
+ property = getPossibleDomainProperty(graph, name);\r
+ if(property == null)\r
+ throw new MissingVariableException("Didn't find property " + name + " for " + this + ".");\r
+ return property.getValue(graph, binding);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getPropertyValue(ReadGraph graph, Resource property, Binding binding) throws DatabaseException {\r
+ return getPropertyValue(graph, name(graph, property), binding);\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getPossiblePropertyValue(ReadGraph graph, String name,\r
+ Binding binding) throws DatabaseException {\r
+ if(binding instanceof StringBinding) {\r
+ StringBinding sb = (StringBinding)binding;\r
+ try {\r
+ if(Variables.NAME.equals(name)) return (T)sb.create((String)getName(graph));\r
+ if(Variables.LABEL.equals(name)) return (T)sb.create((String)getLabel(graph));\r
+ if(Variables.URI.equals(name)) return (T)sb.create((String)getURI(graph));\r
+// if(Variables.SERIALISED.equals(name)) return (T)sb.create((String)getSerialized(graph));\r
+ } catch(BindingException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+ Variable property = getPossibleExtraProperty(graph, name);\r
+ if(property != null)\r
+ return property.getPossibleValue(graph, binding);\r
+ property = getPossibleDomainProperty(graph, name);\r
+ if(property == null)\r
+ return null;\r
+ return property.getPossibleValue(graph, binding);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getPossiblePropertyValue(ReadGraph graph, Resource property, Binding binding) throws DatabaseException {\r
+ return getPossiblePropertyValue(graph, name(graph, property), binding);\r
+ }\r
+\r
+ @Override\r
+ public void setValue(WriteGraph graph, Object value) throws DatabaseException {\r
+ try {\r
+ setValue(graph, value, Bindings.getBinding(value.getClass()));\r
+ } catch (BindingConstructionException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void setPropertyValue(WriteGraph graph, String name, Object value) throws DatabaseException {\r
+ getProperty(graph, name).setValue(graph, value);\r
+ }\r
+\r
+ @Override\r
+ public void setPropertyValue(WriteGraph graph, Resource property, Object value) throws DatabaseException {\r
+ setPropertyValue(graph, name(graph, property), value);\r
+ }\r
+\r
+ @Override\r
+ public void setPropertyValue(WriteGraph graph, String name, Object value,\r
+ Binding binding) throws DatabaseException {\r
+ getProperty(graph, name).setValue(graph, value, binding);\r
+ }\r
+\r
+ @Override\r
+ public void setPropertyValue(WriteGraph graph, Resource property, Object value, Binding binding) throws DatabaseException {\r
+ setPropertyValue(graph, name(graph, property), value, binding);\r
+ }\r
+\r
+ @Override\r
+ public Variable getChild(ReadGraph graph, String name)\r
+ throws DatabaseException {\r
+ Variable child = getPossibleChild(graph, name);\r
+ if(child == null)\r
+ throw new MissingVariableException(getURI(graph) + ": didn't find child " + name + " for " + getIdentifier() + ".");\r
+ return child;\r
+ } \r
+\r
+ @Override\r
+ public Variable getProperty(ReadGraph graph, String name) throws DatabaseException {\r
+ Variable result = getPossibleProperty(graph, name);\r
+ if(result == null)\r
+ throw new MissingVariableException(getClass().getSimpleName() + ": Didn't find property " + name + " for " + getPossibleURI(graph) + ".");\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public Variable getProperty(ReadGraph graph, Resource property) throws DatabaseException {\r
+ return getProperty(graph, name(graph, property));\r
+ }\r
+\r
+ @Override\r
+ public Variable browse(ReadGraph graph, String suffix)\r
+ throws DatabaseException {\r
+ \r
+ if(suffix.isEmpty()) \r
+ return this; \r
+ switch(suffix.charAt(0)) {\r
+ case '.': {\r
+ Variable parent = getParent(graph); \r
+ if(parent == null)\r
+ throw new MissingVariableException("Didn't find " + suffix + " for " + this + " (" + getPossibleURI(graph) + ").");\r
+ return parent.browse(graph, suffix.substring(1));\r
+ }\r
+ case '#': {\r
+ int segmentEnd = getSegmentEnd(suffix);\r
+ Variable property = getProperty(graph, \r
+ decodeString(suffix.substring(1, segmentEnd)));\r
+ if(property == null) \r
+ throw new MissingVariableException("Didn't find " + suffix + " for " + this + " (" + getPossibleURI(graph) + ").");\r
+ return property.browse(graph, suffix.substring(segmentEnd));\r
+ }\r
+ case '/': {\r
+ int segmentEnd = getSegmentEnd(suffix);\r
+ Variable child = getChild(graph, \r
+ decodeString(suffix.substring(1, segmentEnd)));\r
+ if(child == null) \r
+ throw new MissingVariableException("Didn't find " + suffix + " for " + this + " (" + getPossibleURI(graph) + ").");\r
+ return child.browse(graph, suffix.substring(segmentEnd));\r
+ }\r
+ default:\r
+ throw new MissingVariableException("Didn't find " + suffix + " for " + this + " (" + getPossibleURI(graph) + ").");\r
+ }\r
+ \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
+ @Override\r
+ public Variable browsePossible(ReadGraph graph, String suffix)\r
+ throws DatabaseException {\r
+ if(suffix.isEmpty()) \r
+ return this; \r
+ switch(suffix.charAt(0)) {\r
+ case '.': {\r
+ Variable parent = getParent(graph); \r
+ if(parent == null)\r
+ return null;\r
+ return parent.browsePossible(graph, suffix.substring(1));\r
+ }\r
+ case '#': {\r
+ int segmentEnd = getSegmentEnd(suffix);\r
+ Variable property = getPossibleProperty(graph, \r
+ decodeString(suffix.substring(1, segmentEnd)));\r
+ if(property == null) \r
+ return null;\r
+ return property.browsePossible(graph, suffix.substring(segmentEnd));\r
+ }\r
+ case '/': {\r
+ int segmentEnd = getSegmentEnd(suffix);\r
+ Variable child = getPossibleChild(graph, \r
+ decodeString(suffix.substring(1, segmentEnd)));\r
+ if(child == null) \r
+ return null;\r
+ return child.browsePossible(graph, suffix.substring(segmentEnd));\r
+ }\r
+ default:\r
+ return null;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Variable browse(ReadGraph graph, Resource config)\r
+ throws DatabaseException {\r
+ Variable variable = browsePossible(graph, config);\r
+ if(variable == null)\r
+ throw new MissingVariableException("Didn't find a variable related to " + \r
+ NameUtils.getSafeName(graph, config) + ".");\r
+ return variable;\r
+ }\r
+\r
+ @Override\r
+ public Variable browsePossible(ReadGraph graph, Resource config)\r
+ throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ String name = (String)graph.getPossibleRelatedValue(config, l0.HasName, Bindings.STRING);\r
+ if (name == null)\r
+ return null;\r
+ return getPossibleChild(graph, name);\r
+ }\r
+\r
+ @Override\r
+ public <T> T getInterface(ReadGraph graph, Class<T> clazz)\r
+ throws DatabaseException {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public String getURI(ReadGraph graph) throws DatabaseException {\r
+ validate(graph);\r
+ Variable parent = getParent(graph);\r
+ if (parent == null)\r
+ throw new InvalidVariableException(this + " has no URI");\r
+ return parent.getURI(graph) + getRole(graph).getIdentifier() + encodeString(getName(graph));\r
+ }\r
+\r
+ /**\r
+ * For debug messages.\r
+ * \r
+ * @param graph\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public String getPossibleURI(ReadGraph graph) throws DatabaseException {\r
+ Variable parent = getParent(graph);\r
+ if (parent == null)\r
+ return null;\r
+ if (parent instanceof AbstractVariable) {\r
+ String parentUri = ((AbstractVariable) parent).getPossibleURI(graph);\r
+ if (parentUri == null)\r
+ return null;\r
+ return parentUri + getRole(graph).getIdentifier() + encodeString(getName(graph));\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public <T> T getPossibleValue(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getValue(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Variant getVariantValue(ReadGraph graph) throws DatabaseException {\r
+ Binding binding = getPossibleDefaultBinding(graph);\r
+ if(binding != null) {\r
+ Object value = getValue(graph, binding);\r
+ return new Variant(binding, value);\r
+ } else {\r
+// System.err.println("no data type for " + getURI(graph));\r
+ // TODO: hackish, consider doing something else here?\r
+ Object value = getValue(graph);\r
+ try {\r
+ binding = Bindings.OBJECT.getContentBinding(value);\r
+ } catch (BindingException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ return new Variant(binding, value);\r
+ }\r
+ }\r
+ \r
+ public Variant getPossibleVariantValue(ReadGraph graph) throws DatabaseException {\r
+ Binding binding = getPossibleDefaultBinding(graph);\r
+ if(binding != null) {\r
+ Object value = getPossibleValue(graph, binding);\r
+ if(value == null) return null;\r
+ return new Variant(binding, value);\r
+ } else {\r
+ Object value = getPossibleValue(graph);\r
+ if(value == null) return null;\r
+ try {\r
+ // TODO: hackish, consider doing something else here?\r
+ binding = value != null ? Bindings.getBinding(value.getClass()) : null;\r
+ return new Variant(binding, value);\r
+ } catch (BindingConstructionException e) {\r
+ return null;\r
+ }\r
+ }\r
+ }\r
+\r
+ public <T> T getPossibleValue(ReadGraph graph, Binding binding) throws DatabaseException {\r
+ try {\r
+ return getValue(graph, binding);\r
+ } catch(MissingVariableValueException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public <T> T adapt(ReadGraph graph, Class<T> clazz) throws DatabaseException {\r
+ throw new AdaptionException(this + " does not support adaption to " + clazz);\r
+ }\r
+ \r
+ @Override\r
+ public <T> T adaptPossible(ReadGraph graph, Class<T> clazz) throws DatabaseException {\r
+ try {\r
+ return adapt(graph, clazz);\r
+ } catch (AdaptionException e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ \r
+ public static String encodeString(String string) throws DatabaseException {\r
+ if (string == null || "".equals(string)) return string;\r
+ return URIStringUtils.escape(string);\r
+ }\r
+ \r
+ public static String decodeString(String string) throws DatabaseException {\r
+ return URIStringUtils.unescape(string);\r
+ }\r
+ \r
+\r
+ protected Variable getPossiblePropertyFromContext(ReadGraph graph, Resource context, String name) throws DatabaseException {\r
+\r
+ Map<String, Resource> predicates = graph.syncRequest(new PropertyMapOfResource(context));\r
+ Resource property = predicates.get(name);\r
+ if(property == null) return null;\r
+ Resource object = graph.getSingleObject(context, property);\r
+ Variable objectAdapter = graph.getPossibleContextualAdapter(object, new ModelledVariablePropertyDescriptorImpl(this, context, property), \r
+ ModelledVariablePropertyDescriptor.class, Variable.class);\r
+ if(objectAdapter != null) return objectAdapter;\r
+ return graph.getPossibleContextualAdapter(property, new ModelledVariablePropertyDescriptorImpl(this, context, property), \r
+ ModelledVariablePropertyDescriptor.class, Variable.class);\r
+ \r
+ }\r
+ \r
+ protected Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Resource context, Map<String, Variable> properties) throws DatabaseException {\r
+\r
+ for(Map.Entry<String, Resource> entry : graph.syncRequest(new PropertyMapOfResource(context)).entrySet()) {\r
+ String name = entry.getKey();\r
+ Resource property = entry.getValue();\r
+ Resource object = graph.getSingleObject(context, property);\r
+ Variable objectAdapter = graph.getPossibleContextualAdapter(object, new ModelledVariablePropertyDescriptorImpl(this, context, property), \r
+ ModelledVariablePropertyDescriptor.class, Variable.class);\r
+ if(objectAdapter != null) {\r
+ if(objectAdapter != null) {\r
+ if(properties == null) properties = new HashMap<String,Variable>();\r
+ properties.put(name, objectAdapter);\r
+ }\r
+ } else {\r
+ Variable predicateAdapter = graph.getPossibleContextualAdapter(property, new ModelledVariablePropertyDescriptorImpl(this, context, property), \r
+ ModelledVariablePropertyDescriptor.class, Variable.class);\r
+ if(predicateAdapter != null) {\r
+ if(properties == null) properties = new HashMap<String,Variable>();\r
+ properties.put(name, predicateAdapter);\r
+ }\r
+ }\r
+\r
+ }\r
+ \r
+ return properties;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Variable resolve(ReadGraph graph, RVIPart part) throws DatabaseException {\r
+ if(part instanceof StringRVIPart) {\r
+ StringRVIPart srp = (StringRVIPart)part;\r
+ if(Role.CHILD.equals(srp.getRole())) return getChild(graph, srp.string);\r
+ else if(Role.PROPERTY.equals(srp.getRole())) return getProperty(graph, srp.string);\r
+ } else if(part instanceof ResourceRVIPart) {\r
+ ResourceRVIPart rrp = (ResourceRVIPart)part;\r
+ if(Role.CHILD.equals(rrp.getRole())) return resolveChild(graph, rrp.resource);\r
+ else if(Role.PROPERTY.equals(rrp.getRole())) return resolveProperty(graph, rrp.resource);\r
+ } else if(part instanceof GuidRVIPart) {\r
+ GuidRVIPart grp = (GuidRVIPart)part;\r
+ if(Role.CHILD.equals(grp.getRole())) return resolveChild(graph, grp);\r
+ else if(Role.PROPERTY.equals(grp.getRole())) return resolveProperty(graph, grp);\r
+ }\r
+ throw new DatabaseException("Unrecognized RVIPart: " + part);\r
+ }\r
+\r
+ @Override\r
+ public Variable resolvePossible(ReadGraph graph, RVIPart part) throws DatabaseException {\r
+ if(part instanceof StringRVIPart) {\r
+ StringRVIPart srp = (StringRVIPart)part;\r
+ if(Role.CHILD.equals(srp.getRole())) return getPossibleChild(graph, srp.string);\r
+ else if(Role.PROPERTY.equals(srp.getRole())) return getPossibleProperty(graph, srp.string);\r
+ } else if(part instanceof ResourceRVIPart) {\r
+ ResourceRVIPart rrp = (ResourceRVIPart)part;\r
+ if(Role.CHILD.equals(rrp.getRole())) return resolvePossibleChild(graph, rrp.resource);\r
+ else if(Role.PROPERTY.equals(rrp.getRole())) return resolvePossibleProperty(graph, rrp.resource);\r
+ } else if(part instanceof GuidRVIPart) {\r
+ GuidRVIPart grp = (GuidRVIPart)part;\r
+ if(Role.CHILD.equals(grp.getRole())) return resolvePossibleChild(graph, grp);\r
+ else if(Role.PROPERTY.equals(grp.getRole())) return resolvePossibleProperty(graph, grp);\r
+ }\r
+ throw new DatabaseException("Unrecognized RVIPart: " + part);\r
+ }\r
+\r
+ @Override\r
+ public Datatype getDatatype(ReadGraph graph) throws DatabaseException {\r
+ throw new DatabaseException("No data type.");\r
+ }\r
+\r
+ public Binding getDefaultBinding(ReadGraph graph) throws DatabaseException {\r
+ Datatype type = getDatatype(graph);\r
+ return Bindings.getBinding(type);\r
+ }\r
+ \r
+ public Binding getPossibleDefaultBinding(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getDefaultBinding(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Datatype getPossibleDatatype(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getDatatype(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+// public Binding getPossibleDefaultBinding(ReadGraph graph) throws DatabaseException {\r
+// \r
+// Datatype type = getPossibleDatatype(graph);\r
+// if(type == null) return null;\r
+// return Bindings.getBinding(type);\r
+//\r
+// }\r
+//\r
+// @Override\r
+// public Datatype getPossibleDatatype(ReadGraph graph) throws DatabaseException {\r
+// \r
+// Variant vt = getVariantValue(graph);\r
+// if(vt == null) return null;\r
+// Binding binding = vt.getBinding();\r
+// if(binding == null) return null;\r
+// return binding.type();\r
+//\r
+// }\r
+\r
+ @Override\r
+ public Variable getPredicate(ReadGraph graph) throws DatabaseException {\r
+ throw new DatabaseException(getClass().getSimpleName() + ": No predicate property for " + getPossibleURI(graph));\r
+ }\r
+\r
+ @Override\r
+ public Variable getPossiblePredicate(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getPredicate(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public Resource getPredicateResource(ReadGraph graph) throws DatabaseException {\r
+ Variable predicate = getPredicate(graph);\r
+ if(predicate == null) throw new DatabaseException(getClass().getSimpleName() + ": No predicate property for " + getPossibleURI(graph));\r
+ return predicate.getRepresents(graph);\r
+ }\r
+ \r
+ @Override\r
+ public Resource getPossiblePredicateResource(ReadGraph graph) throws DatabaseException {\r
+ Variable predicate = getPossiblePredicate(graph);\r
+ if(predicate == null) return null;\r
+ else return predicate.getPossibleRepresents(graph);\r
+ }\r
+\r
+ @Override\r
+ public Resource getPossibleRepresents(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getRepresents(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Resource getPossibleType(ReadGraph graph) throws DatabaseException {\r
+ Resource resource = getPossibleRepresents(graph);\r
+ if(resource == null) {\r
+ String uri = getPossiblePropertyValue(graph, "typeURI");\r
+ if(uri != null) return graph.syncRequest(new PossibleResource(uri), TransientCacheAsyncListener.<Resource>instance());\r
+ return null;\r
+ }\r
+ return graph.getPossibleObject(resource, Layer0.getInstance(graph).InstanceOf);\r
+ }\r
+\r
+ public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
+ Resource resource = getPossibleRepresents(graph);\r
+ if(resource == null) {\r
+ String uri = getPossiblePropertyValue(graph, "typeURI");\r
+ if(uri != null) return graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());\r
+ throw new DatabaseException("No type for " + getURI(graph));\r
+ }\r
+ return graph.getSingleType(resource, baseType);\r
+ }\r
+\r
+ @Override\r
+ public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
+ Resource resource = getPossibleRepresents(graph);\r
+ if(resource == null) {\r
+ String uri = getPossiblePropertyValue(graph, "typeURI");\r
+ if(uri != null) {\r
+ Resource type = graph.syncRequest(new PossibleResource(uri), TransientCacheAsyncListener.<Resource>instance());\r
+ if(type == null) return null;\r
+ if(graph.isInheritedFrom(type, baseType)) return type;\r
+ else return null;\r
+ }\r
+ return null;\r
+ }\r
+ return graph.getPossibleType(resource, baseType);\r
+ }\r
+\r
+ public Map<String, Variable> collectDomainProperties(ReadGraph graph, String classification, Map<String, Variable> map) throws DatabaseException {\r
+ Map<String,Variable> all = collectDomainProperties(graph, null);\r
+ for(Map.Entry<String, Variable> entry : all.entrySet()) {\r
+ Set<String> classifications = entry.getValue().getClassifications(graph);\r
+ if(classifications.contains(classification)) {\r
+ if(map == null) map = new HashMap<String,Variable>();\r
+ map.put(entry.getKey(), entry.getValue());\r
+ }\r
+ }\r
+ return map;\r
+ }\r
+ \r
+ @Override\r
+ public RVI getPossibleRVI(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ return getRVI(graph);\r
+ } catch(DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r