1 package org.simantics.structural2.variables;
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
15 import org.simantics.databoard.Bindings;
16 import org.simantics.db.ReadGraph;
17 import org.simantics.db.Resource;
18 import org.simantics.db.Statement;
19 import org.simantics.db.common.utils.Logger;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.exception.NoSingleResultException;
22 import org.simantics.db.layer0.function.All;
23 import org.simantics.db.layer0.request.ClassificationsRequest;
24 import org.simantics.db.layer0.variable.AbstractChildVariable;
25 import org.simantics.db.layer0.variable.NodeSupport;
26 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
27 import org.simantics.db.layer0.variable.StandardConstantGraphPropertyVariable;
28 import org.simantics.db.layer0.variable.Variable;
29 import org.simantics.db.layer0.variable.VariableNode;
30 import org.simantics.layer0.Layer0;
31 import org.simantics.simulator.variable.NodeManager;
32 import org.simantics.structural2.Functions;
33 import org.simantics.structural2.procedural.Connection;
34 import org.simantics.structural2.procedural.ConnectionPoint;
35 import org.simantics.structural2.procedural.Expression;
36 import org.simantics.structural2.procedural.Interface;
37 import org.simantics.structural2.procedural.Property;
38 import org.simantics.structural2.procedural.Terminal;
39 import org.simantics.utils.datastructures.Pair;
41 public class StandardProceduralChildVariable extends AbstractChildVariable {
47 public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
51 public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {
55 * Standard implementation
59 final protected String name;
60 final protected Variable parent;
61 final private Resource type;
62 final private Map<String, Variable> properties;
63 final private List<Object> propertyIdentity;
65 public static class FixedConnection implements org.simantics.structural2.variables.Connection {
67 final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
69 final private Variable parent;
71 public FixedConnection(Variable parent) {
76 public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
78 Set<Variable> result = new THashSet<Variable>();
79 for(Pair<String,Resource> cp : cps) {
80 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
81 Variable cp2 = component.getPossibleProperty(graph, cp.second);
83 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
84 result.add(desc.getVariable(graph));
87 System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
94 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
96 Set<String> result = new THashSet<String>();
97 for(Pair<String,Resource> cp : cps) {
98 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
99 Variable cp2 = component.getPossibleProperty(graph, cp.second);
101 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
102 result.add(desc.getURI(graph));
105 System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
112 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
114 Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();
115 for(Pair<String,Resource> cp : cps) {
116 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
117 Variable cp2 = component.getPossibleProperty(graph, cp.second);
119 result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));
121 System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
128 public int hashCode() {
129 final int prime = 31;
131 result = prime * result + ((cps == null) ? 0 : cps.hashCode());
132 result = prime * result
133 + ((parent == null) ? 0 : parent.hashCode());
138 public boolean equals(Object obj) {
143 if (getClass() != obj.getClass())
145 FixedConnection other = (FixedConnection) obj;
147 if (other.cps != null)
149 } else if (!cps.equals(other.cps))
151 if (parent == null) {
152 if (other.parent != null)
154 } else if (!parent.equals(other.parent))
161 public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
166 this.parent = parent;
168 this.properties = new THashMap<String,Variable>();
170 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());
171 propertyIdentity.addAll(properties);
172 propertyIdentity.addAll(conns);
174 Layer0 L0 = Layer0.getInstance(graph);
176 Map<String,Statement> assertedProperties = new THashMap<String, Statement>();
177 for(Statement stm : graph.getAssertedStatements(type, L0.HasProperty)) {
178 String pn = graph.getRelatedValue(stm.getPredicate(), L0.HasName, Bindings.STRING);
179 assertedProperties.put(pn, stm);
182 Collection<Object> nodeProperties = All.getPossibleNodeProperties(graph, (AbstractChildVariable)this);
183 Set<String> used = new HashSet<String>(nodeProperties.size());
184 for(Object nodeProperty : nodeProperties) {
185 @SuppressWarnings("rawtypes")
186 NodeSupport support = node.support;
187 @SuppressWarnings("rawtypes")
188 NodeManager manager = support.manager;
189 @SuppressWarnings("unchecked")
190 String pName = manager.getName(nodeProperty);
192 Statement assertedProperty = assertedProperties.get(pName);
193 if(assertedProperty != null) {
194 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, new VariableNode(support, nodeProperty), assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
198 for(Map.Entry<String, Statement> entry : assertedProperties.entrySet()) {
199 String pName = entry.getKey();
200 if(used.contains(pName)) continue;
201 Statement assertedProperty = entry.getValue();
202 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, null, assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
206 for(Property p : properties) {
207 String pn = graph.getRelatedValue(p.relation, L0.HasName, Bindings.STRING);
208 if(p.value == null) {
209 Logger.defaultLogError("StandardProceduralChildVariable " + getURI(graph) + ": null value for property " + pn);
210 } else if (p.value instanceof Expression) {
211 Expression expression = (Expression)p.value;
212 this.properties.put(pn, new StructuralProceduralExpressionPropertyVariable(graph, this, p.relation, expression.text) );
214 this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );
219 Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();
220 for(Connection conn : conns) {
222 List<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
223 for(ConnectionPoint cp : conn.connectionPoints) {
224 if(cp instanceof Terminal) {
225 Terminal t = (Terminal)cp;
226 if(t.component.equals(name)) {
230 cps.add(Pair.make(t.component, t.relation));
232 if(cp instanceof Interface) {
233 Interface inf = (Interface)cp;
234 cps.add(new Pair<String,Resource>(null, inf.relation));
238 FixedConnection fc = map.get(p);
240 fc = new FixedConnection(parent);
246 for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {
247 Resource cp = entry.getKey();
248 String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);
249 this.properties.put(cpName, new StandardConstantGraphPropertyVariable(graph, this, cp, entry.getValue()));
255 public void validate(ReadGraph graph) throws DatabaseException {
259 public Resource getType(ReadGraph graph) throws DatabaseException {
264 public Resource getPossibleType(ReadGraph graph) throws DatabaseException {
269 public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {
270 if (graph.isInheritedFrom(type, baseType))
272 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type");
276 public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
277 return graph.isInheritedFrom(type, baseType) ? type : null;
281 protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
282 return properties.get(name);
286 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
287 return Functions.structuralChildDomainChildren.getVariable(graph, this, name);
291 public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {
292 if(!this.properties.isEmpty()) {
293 if(properties == null) properties = new THashMap<String,Variable>(this.properties.size());
294 properties.putAll(this.properties);
300 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
301 Map<String,Variable> result = Functions.structuralChildDomainChildren.getVariables(graph, this, null);
302 if(result == null) return Collections.emptyList();
303 else return result.values();
306 public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
307 Resource type = getPossibleType(graph);
308 return (type != null)
309 ? graph.syncRequest(new ClassificationsRequest(Collections.singleton(type)))
310 : Collections.<String>emptySet();
314 public String getName(ReadGraph graph) throws DatabaseException {
319 public Variable getParent(ReadGraph graph) throws DatabaseException {
324 final public Resource getRepresents(ReadGraph graph) throws DatabaseException {
329 public int hashCode() {
330 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);
334 public boolean equals(Object obj) {
340 if (getClass() != obj.getClass())
343 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;
345 if(!name.equals(other.name)) return false;
346 if(!type.equals(other.type)) return false;
347 if(!parent.equals(other.parent)) return false;
348 if(propertyIdentity != other.propertyIdentity) return false;