X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fvariable%2FAbstractVariable.java;fp=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fvariable%2FAbstractVariable.java;h=dc88b0a7ad51b0e52cd5de5dabe91f535a282f41;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 new file mode 100644 index 000000000..dc88b0a7a --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/AbstractVariable.java @@ -0,0 +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; + } + } + +}