]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/variables/StandardProceduralChildVariable.java
0db9d7033df415da9800f5924bd2d836f343274c
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / variables / StandardProceduralChildVariable.java
1 package org.simantics.structural2.variables;
2
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
5
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;
12 import java.util.Map;
13 import java.util.Set;
14
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;
40
41 public class StandardProceduralChildVariable extends AbstractChildVariable {
42
43         /*
44          * Extension points
45          * 
46          */
47         public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
48                 return null;
49         }
50
51         public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {
52         }
53
54         /*
55          * Standard implementation
56          * 
57          */
58         
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;
64         
65     public static class FixedConnection implements org.simantics.structural2.variables.Connection {
66
67                 final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
68         
69         final private Variable parent;
70         
71         public FixedConnection(Variable parent) {
72             this.parent = parent;
73         }
74         
75         @Override
76         public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
77                 
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);
82                 if(cp2 != null)
83                         for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
84                                 result.add(desc.getVariable(graph));
85                         }
86                 else
87                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
88             }
89             return result;
90             
91         }
92         
93                 @Override
94                 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
95                         
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);
100                 if(cp2 != null)
101                         for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
102                                 result.add(desc.getURI(graph));
103                         }
104                 else
105                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
106             }
107             return result;
108                         
109                 }
110                 
111                 @Override
112                 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
113                         
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);
118                 if(cp2 != null)
119                         result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));
120                 else
121                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));
122             }
123             return result;
124                         
125                 }        
126
127         @Override
128                 public int hashCode() {
129                         final int prime = 31;
130                         int result = 1;
131                         result = prime * result + ((cps == null) ? 0 : cps.hashCode());
132                         result = prime * result
133                                         + ((parent == null) ? 0 : parent.hashCode());
134                         return result;
135                 }
136
137                 @Override
138                 public boolean equals(Object obj) {
139                         if (this == obj)
140                                 return true;
141                         if (obj == null)
142                                 return false;
143                         if (getClass() != obj.getClass())
144                                 return false;
145                         FixedConnection other = (FixedConnection) obj;
146                         if (cps == null) {
147                                 if (other.cps != null)
148                                         return false;
149                         } else if (!cps.equals(other.cps))
150                                 return false;
151                         if (parent == null) {
152                                 if (other.parent != null)
153                                         return false;
154                         } else if (!parent.equals(other.parent))
155                                 return false;
156                         return true;
157                 }
158
159     }
160     
161         public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
162                 super(node);
163                 assert name != null;
164         assert type != null;
165         this.name = name;
166                 this.parent = parent;
167                 this.type = type;
168                 this.properties = new THashMap<String,Variable>();
169                 
170                 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());
171                 propertyIdentity.addAll(properties);
172                 propertyIdentity.addAll(conns);
173                 
174                 Layer0 L0 = Layer0.getInstance(graph);
175
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);
180                 }
181                 
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);
191             used.add(pName);
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()));
195             }
196         }
197         
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()));
203         }
204                 
205                 
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) );
213                     } else {
214                             this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );
215                     }
216                         
217                         
218                 }
219             Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();
220                 for(Connection conn : conns) {
221                     Resource p = null;
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)) {
227                                 p = t.relation;
228                                 continue;
229                             }
230                             cps.add(Pair.make(t.component, t.relation));
231                         }
232                         if(cp instanceof Interface) {
233                                 Interface inf = (Interface)cp;
234                             cps.add(new Pair<String,Resource>(null, inf.relation));
235                         }
236                     }
237                     if(p != null) {
238                         FixedConnection fc = map.get(p);
239                         if(fc == null) {
240                                 fc = new FixedConnection(parent);
241                                 map.put(p, fc);
242                         }
243                         fc.cps.addAll(cps);             
244                     }
245                 }
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()));
250                 }
251                 
252         }
253
254         @Override
255         public void validate(ReadGraph graph) throws DatabaseException {
256         }
257         
258         @Override
259         public Resource getType(ReadGraph graph) throws DatabaseException {
260             return type;
261         }
262         
263         @Override
264         public Resource getPossibleType(ReadGraph graph) throws DatabaseException {
265             return type;
266         }
267         
268         @Override
269         public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {
270                 if (graph.isInheritedFrom(type, baseType))
271                         return type;
272                 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type");
273         }
274         
275         @Override
276         public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
277                 return graph.isInheritedFrom(type, baseType) ? type : null;
278         }
279         
280         @Override
281         protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
282             return properties.get(name);
283         }
284
285         @Override
286         public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
287             return Functions.structuralChildDomainChildren.getVariable(graph, this, name);
288         }
289
290         @Override
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);
295                 }
296                 return properties;
297         }
298
299         @Override
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();
304         }
305
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();
311         }
312
313         @Override
314         public String getName(ReadGraph graph) throws DatabaseException {
315             return name;
316         }
317
318         @Override
319         public Variable getParent(ReadGraph graph) throws DatabaseException {
320                 return parent;
321         }
322         
323         @Override
324         final public Resource getRepresents(ReadGraph graph) throws DatabaseException {
325             return null;
326         }
327
328         @Override
329         public int hashCode() {
330                 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);
331         }
332
333         @Override
334         public boolean equals(Object obj) {
335                 
336                 if (this == obj)
337                         return true;
338                 if (obj == null)
339                         return false;
340                 if (getClass() != obj.getClass())
341                         return false;
342                 
343                 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;
344                 
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;
349                                 
350                 return true;
351                 
352         }
353         
354 }