package org.simantics.db.layer0.variable; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; import org.simantics.databoard.Bindings; import org.simantics.datatypes.literal.GUID; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.exception.AssumptionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.exception.InvalidVariableException; import org.simantics.db.layer0.exception.VariableException; import org.simantics.db.layer0.function.All; import org.simantics.db.layer0.request.ClassificationsRequest; import org.simantics.db.layer0.request.VariableURI; 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; import org.simantics.simulator.variable.exceptions.NodeManagerException; public class StandardGraphChildVariable extends AbstractChildVariable { /* * Extension points * */ public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException { return null; } public Map collectSpecialChildren(ReadGraph graph, Map children) throws DatabaseException { return children; } /* * Standard implementation * */ final protected Variable parent; final public Resource resource; transient private int hash; public StandardGraphChildVariable(Variable parent, VariableNode node, Resource resource) { super(node); this.parent = parent; this.resource = resource; } @Override public void validate(ReadGraph graph) throws DatabaseException { if(!graph.hasStatement(resource)) throw new InvalidVariableException("The resource has been removed: " + resource); } @Override protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException { VariableMap map = getPossiblePropertyVariableMap(graph); if(map == null) return null; try { return map.getVariable(graph, this, name); } catch (DatabaseException e) { return null; } } @Override public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException { VariableMap map = getPossibleChildVariableMap(graph); if(map == null) return getPossibleSpecialChild(graph, name); try { Variable result = map.getVariable(graph, this, name); if(result != null) return result; else return getPossibleSpecialChild(graph, name); } catch (DatabaseException e) { return null; } } @Override public Map collectDomainProperties(ReadGraph graph, Map properties) throws DatabaseException { VariableMap map = getPossiblePropertyVariableMap(graph); if(map == null) return properties; return map.getVariables(graph, this, properties); } @Override public Collection getChildren(ReadGraph graph) throws DatabaseException { Map result = null; VariableMap map = getPossibleChildVariableMap(graph); if(map != null) result = map.getVariables(graph, this, result); result = collectSpecialChildren(graph, result); if(result == null) return Collections.emptyList(); else return result.values(); } @SuppressWarnings("unchecked") @Override public String getName(ReadGraph graph) throws DatabaseException { if(node != null) { return node.support.manager.getName(node.node); } String unescapedName = graph.getPossibleRelatedValue(resource, graph.getService(Layer0.class).HasName, Bindings.STRING); if(unescapedName == null) return "r" + resource.getResourceId(); return unescapedName; } @Override public Variable getNameVariable(ReadGraph graph) throws DatabaseException { Resource resource = (Resource) getPossibleRepresents(graph); if (resource != null) { return new StandardGraphPropertyVariable(graph, this, null, resource, Layer0.getInstance(graph).HasName); } return super.getNameVariable(graph); } @Override public String getLabel(ReadGraph graph) throws DatabaseException { if(resource == null) return getName(graph); String label = graph.getPossibleRelatedValue2(resource, graph.getService(Layer0.class).HasLabel); return label != null ? label : getName(graph); } @Override final protected Variable getLabelVariable(ReadGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); if(resource == null) return null; return new StandardGraphPropertyVariable(graph, this, L0.HasLabel); } // @Override // final public Object getSerialized(ReadGraph graph) throws DatabaseException { // Resource represents = getRepresents(graph); // if(represents != null) return represents; // else return getName(graph); // } @Override public Variable getParent(ReadGraph graph) throws DatabaseException { return parent; } @Override final public Resource getRepresents(ReadGraph graph) throws DatabaseException { if(resource == null) throw new VariableException("Variable is not represented by any resource (URI=" + getPossibleURI(graph) + ")."); return resource; // Layer0X L0X = Layer0X.getInstance(graph); // Resource represents = graph.getPossibleObject(resource, L0X.Represents); // if(represents != null) return represents; // else return resource; } @Override public Resource getPossibleRepresents(ReadGraph graph) throws DatabaseException { return resource; } @Override final public String getURI(ReadGraph graph) throws DatabaseException { try { if(parent == null) return "http:/"; String parentURI = graph.syncRequest(new VariableURI(parent), TransientCacheAsyncListener.instance()); return parentURI + Role.CHILD.getIdentifier() + encodeString(getName(graph)); } catch (AssumptionException e) { throw new InvalidVariableException(e); } } /** * All variables must have proper URIs, this is only for debugging purposes. * * @see org.simantics.db.layer0.variable.AbstractVariable#getPossibleURI(org.simantics.db.ReadGraph) */ @Override public String getPossibleURI(ReadGraph graph) throws DatabaseException { try { return getURI(graph); } catch (DatabaseException e) { return ""; } } @Override public int hashCode() { if(hash == 0) { final int prime = 31; int result = 1; result = prime * result + (parent != null ? parent.hashCode() : 0); result = prime * result + (node != null ? node.hashCode() : 0); result = prime * result + (resource != null ? resource.hashCode() : 0); hash =result; } return hash; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StandardGraphChildVariable other = (StandardGraphChildVariable) obj; if(node != null) { if(!node.equals(other.node)) return false; } else if (other.node != null) return false; if(resource != null) { if(!resource.equals(other.resource)) return false; } else if (other.resource != null) return false; if(parent != null) { if(!parent.equals(other.parent)) return false; } else if (other.parent != null) return false; return true; } @Override public T adapt(ReadGraph graph, Class clazz) throws DatabaseException { return graph.adapt(resource, clazz); } @Override public T adaptPossible(ReadGraph graph, Class clazz) throws DatabaseException { return graph.getPossibleAdapter(resource, clazz); } @Override public RVIPart getRVIPart(ReadGraph graph) throws DatabaseException { if(resource == null) return new StringRVIPart(Role.CHILD, getName(graph)); Layer0 L0 = Layer0.getInstance(graph); GUID id = graph.getPossibleRelatedValue(resource, L0.identifier, GUID.BINDING); if(id != null) return new RVI.GuidRVIPart(Role.CHILD, resource, id.mostSignificant, id.leastSignificant); else return new ResourceRVIPart(Role.CHILD, resource); } public String getIdentifier() { return getClass().getSimpleName() + "[" + resource + "]"; } protected VariableMap getPossiblePropertyVariableMap(ReadGraph graph) throws DatabaseException { if(resource == null) return All.standardChildDomainProperties; return graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).domainProperties, this); } protected VariableMap getPossibleChildVariableMap(ReadGraph graph) throws DatabaseException { if(resource == null) return All.standardChildDomainChildren; return graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).domainChildren, this); } @Override public Map collectDomainProperties(ReadGraph graph, String classification, Map properties) throws DatabaseException { VariableMap valueMap = getPossiblePropertyVariableMap(graph); if(valueMap == null) return properties; return valueMap.getVariables(graph, this, classification, properties); } @Override public Variable resolve(ReadGraph graph, RVIPart part) throws DatabaseException { Resource represents = getPossibleRepresents(graph); if (represents == null) return StandardRVIResolver.INSTANCE.getVariable(graph, this, part); RVIResolver resolver = graph.adapt(represents, RVIResolver.class); return resolver.getVariable(graph, this, part); } @Override public Variable resolvePossible(ReadGraph graph, RVIPart part) throws DatabaseException { try { return resolve(graph, part); } catch (DatabaseException e) { return null; } } @SuppressWarnings("unchecked") public Set getClassifications(ReadGraph graph) throws DatabaseException { Resource represents = getPossibleRepresents(graph); Set result = (represents != null) ? graph.syncRequest(new ClassificationsRequest(graph.getPrincipalTypes(represents))) : Collections.emptySet(); if (result.isEmpty()) { Resource type = getPossibleType(graph); if(type != null) result = graph.syncRequest(new ClassificationsRequest(Collections.singleton(type))); } if (result.isEmpty() && node != null) { try { result = node.support.manager.getClassifications(node.node); } catch(NodeManagerException e) { throw new DatabaseException(e); } } return result; } @Override public RVI getRVI(ReadGraph graph) throws DatabaseException { Resource represents = getPossibleRepresents(graph); if (represents == null) return StandardRVIResolver.INSTANCE.getRVI(graph, this); RVIResolver resolver = graph.adapt(represents, RVIResolver.class); return resolver.getRVI(graph, this); } @Override public RVI getPossibleRVI(ReadGraph graph) throws DatabaseException { Resource represents = getPossibleRepresents(graph); if (represents == null) return StandardRVIResolver.INSTANCE.getPossibleRVI(graph, this); RVIResolver resolver = graph.getPossibleAdapter(represents, RVIResolver.class); if(resolver == null) return null; return resolver.getPossibleRVI(graph, this); } @Override public Resource getPossiblePredicateResource(ReadGraph graph) throws DatabaseException { return null; } }