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