--- /dev/null
+package org.simantics.structural2.variables;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.NoSingleResultException;\r
+import org.simantics.db.layer0.function.All;\r
+import org.simantics.db.layer0.request.ClassificationsRequest;\r
+import org.simantics.db.layer0.variable.AbstractChildVariable;\r
+import org.simantics.db.layer0.variable.NodeSupport;\r
+import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;\r
+import org.simantics.db.layer0.variable.StandardConstantGraphPropertyVariable;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.VariableNode;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulator.variable.NodeManager;\r
+import org.simantics.structural2.Functions;\r
+import org.simantics.structural2.procedural.Connection;\r
+import org.simantics.structural2.procedural.ConnectionPoint;\r
+import org.simantics.structural2.procedural.Expression;\r
+import org.simantics.structural2.procedural.Interface;\r
+import org.simantics.structural2.procedural.Property;\r
+import org.simantics.structural2.procedural.Terminal;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class StandardProceduralChildVariable extends AbstractChildVariable {\r
+\r
+ /*\r
+ * Extension points\r
+ * \r
+ */\r
+ public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {\r
+ return null;\r
+ }\r
+\r
+ public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {\r
+ }\r
+\r
+ /*\r
+ * Standard implementation\r
+ * \r
+ */\r
+ \r
+ final protected String name;\r
+ final protected Variable parent;\r
+ final private Resource type;\r
+ final private Map<String, Variable> properties;\r
+ final private List<Object> propertyIdentity;\r
+ \r
+ public static class FixedConnection implements org.simantics.structural2.variables.Connection {\r
+\r
+ final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();\r
+ \r
+ final private Variable parent;\r
+ \r
+ public FixedConnection(Variable parent) {\r
+ this.parent = parent;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+ \r
+ Set<Variable> result = new THashSet<Variable>();\r
+ for(Pair<String,Resource> cp : cps) {\r
+ Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
+ Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
+ if(cp2 != null)\r
+ for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {\r
+ result.add(desc.getVariable(graph));\r
+ }\r
+ else\r
+ System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
+ }\r
+ return result;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+ \r
+ Set<String> result = new THashSet<String>();\r
+ for(Pair<String,Resource> cp : cps) {\r
+ Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
+ Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
+ if(cp2 != null)\r
+ for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {\r
+ result.add(desc.getURI(graph));\r
+ }\r
+ else\r
+ System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
+ }\r
+ return result;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+ \r
+ Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();\r
+ for(Pair<String,Resource> cp : cps) {\r
+ Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
+ Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
+ if(cp2 != null)\r
+ result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));\r
+ else\r
+ System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
+ }\r
+ return result;\r
+ \r
+ } \r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((cps == null) ? 0 : cps.hashCode());\r
+ result = prime * result\r
+ + ((parent == null) ? 0 : parent.hashCode());\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ FixedConnection other = (FixedConnection) obj;\r
+ if (cps == null) {\r
+ if (other.cps != null)\r
+ return false;\r
+ } else if (!cps.equals(other.cps))\r
+ return false;\r
+ if (parent == null) {\r
+ if (other.parent != null)\r
+ return false;\r
+ } else if (!parent.equals(other.parent))\r
+ return false;\r
+ return true;\r
+ }\r
+\r
+ }\r
+ \r
+ public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {\r
+ super(node);\r
+ assert name != null;\r
+ assert type != null;\r
+ this.name = name;\r
+ this.parent = parent;\r
+ this.type = type;\r
+ this.properties = new THashMap<String,Variable>();\r
+ \r
+ this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());\r
+ propertyIdentity.addAll(properties);\r
+ propertyIdentity.addAll(conns);\r
+ \r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+\r
+ Map<String,Statement> assertedProperties = new THashMap<String, Statement>();\r
+ for(Statement stm : graph.getAssertedStatements(type, L0.HasProperty)) {\r
+ String pn = graph.getRelatedValue(stm.getPredicate(), L0.HasName, Bindings.STRING);\r
+ assertedProperties.put(pn, stm);\r
+ }\r
+ \r
+ Collection<Object> nodeProperties = All.getPossibleNodeProperties(graph, (AbstractChildVariable)this);\r
+ Set<String> used = new HashSet<String>(nodeProperties.size());\r
+ for(Object nodeProperty : nodeProperties) {\r
+ @SuppressWarnings("rawtypes")\r
+ NodeSupport support = node.support;\r
+ @SuppressWarnings("rawtypes")\r
+ NodeManager manager = support.manager;\r
+ @SuppressWarnings("unchecked")\r
+ String pName = manager.getName(nodeProperty);\r
+ used.add(pName);\r
+ Statement assertedProperty = assertedProperties.get(pName); \r
+ if(assertedProperty != null) {\r
+ this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, new VariableNode(support, nodeProperty), assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));\r
+ }\r
+ }\r
+ \r
+ for(Map.Entry<String, Statement> entry : assertedProperties.entrySet()) {\r
+ String pName = entry.getKey();\r
+ if(used.contains(pName)) continue;\r
+ Statement assertedProperty = entry.getValue();\r
+ this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, null, assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));\r
+ }\r
+ \r
+ \r
+ for(Property p : properties) {\r
+ String pn = graph.getRelatedValue(p.relation, L0.HasName, Bindings.STRING);\r
+ if(p.value == null) {\r
+ Logger.defaultLogError("StandardProceduralChildVariable " + getURI(graph) + ": null value for property " + pn);\r
+ } else if (p.value instanceof Expression) {\r
+ Expression expression = (Expression)p.value;\r
+ this.properties.put(pn, new StructuralProceduralExpressionPropertyVariable(graph, this, p.relation, expression.text) );\r
+ } else {\r
+ this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );\r
+ }\r
+ \r
+ \r
+ }\r
+ Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();\r
+ for(Connection conn : conns) {\r
+ Resource p = null;\r
+ List<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();\r
+ for(ConnectionPoint cp : conn.connectionPoints) {\r
+ if(cp instanceof Terminal) {\r
+ Terminal t = (Terminal)cp;\r
+ if(t.component.equals(name)) {\r
+ p = t.relation;\r
+ continue;\r
+ }\r
+ cps.add(Pair.make(t.component, t.relation));\r
+ }\r
+ if(cp instanceof Interface) {\r
+ Interface inf = (Interface)cp;\r
+ cps.add(new Pair<String,Resource>(null, inf.relation));\r
+ }\r
+ }\r
+ if(p != null) {\r
+ FixedConnection fc = map.get(p);\r
+ if(fc == null) {\r
+ fc = new FixedConnection(parent);\r
+ map.put(p, fc);\r
+ }\r
+ fc.cps.addAll(cps); \r
+ }\r
+ }\r
+ for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {\r
+ Resource cp = entry.getKey();\r
+ String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);\r
+ this.properties.put(cpName, new StandardConstantGraphPropertyVariable(graph, this, cp, entry.getValue()));\r
+ }\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void validate(ReadGraph graph) throws DatabaseException {\r
+ }\r
+ \r
+ @Override\r
+ public Resource getType(ReadGraph graph) throws DatabaseException {\r
+ return type;\r
+ }\r
+ \r
+ @Override\r
+ public Resource getPossibleType(ReadGraph graph) throws DatabaseException {\r
+ return type;\r
+ }\r
+ \r
+ @Override\r
+ public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
+ if (graph.isInheritedFrom(type, baseType))\r
+ return type;\r
+ throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type");\r
+ }\r
+ \r
+ @Override\r
+ public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
+ return graph.isInheritedFrom(type, baseType) ? type : null;\r
+ }\r
+ \r
+ @Override\r
+ protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {\r
+ return properties.get(name);\r
+ }\r
+\r
+ @Override\r
+ public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
+ return Functions.structuralChildDomainChildren.getVariable(graph, this, name);\r
+ }\r
+\r
+ @Override\r
+ public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {\r
+ if(!this.properties.isEmpty()) {\r
+ if(properties == null) properties = new THashMap<String,Variable>(this.properties.size());\r
+ properties.putAll(this.properties);\r
+ }\r
+ return properties;\r
+ }\r
+\r
+ @Override\r
+ public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
+ Map<String,Variable> result = Functions.structuralChildDomainChildren.getVariables(graph, this, null);\r
+ if(result == null) return Collections.emptyList();\r
+ else return result.values();\r
+ }\r
+\r
+ public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {\r
+ Resource type = getPossibleType(graph);\r
+ return (type != null)\r
+ ? graph.syncRequest(new ClassificationsRequest(Collections.singleton(type)))\r
+ : Collections.<String>emptySet();\r
+ }\r
+\r
+ @Override\r
+ public String getName(ReadGraph graph) throws DatabaseException {\r
+ return name;\r
+ }\r
+\r
+ @Override\r
+ public Variable getParent(ReadGraph graph) throws DatabaseException {\r
+ return parent;\r
+ }\r
+ \r
+ @Override\r
+ final public Resource getRepresents(ReadGraph graph) throws DatabaseException {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ \r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ \r
+ StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;\r
+ \r
+ if(!name.equals(other.name)) return false;\r
+ if(!type.equals(other.type)) return false;\r
+ if(!parent.equals(other.parent)) return false;\r
+ if(propertyIdentity != other.propertyIdentity) return false;\r
+ \r
+ return true;\r
+ \r
+ }\r
+ \r
+}\r