]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/variables/StandardProceduralChildVariable.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / variables / StandardProceduralChildVariable.java
1 package org.simantics.structural2.variables;\r
2 \r
3 import gnu.trove.map.hash.THashMap;\r
4 import gnu.trove.set.hash.THashSet;\r
5 \r
6 import java.util.ArrayList;\r
7 import java.util.Collection;\r
8 import java.util.Collections;\r
9 import java.util.HashMap;\r
10 import java.util.HashSet;\r
11 import java.util.List;\r
12 import java.util.Map;\r
13 import java.util.Set;\r
14 \r
15 import org.simantics.databoard.Bindings;\r
16 import org.simantics.db.ReadGraph;\r
17 import org.simantics.db.Resource;\r
18 import org.simantics.db.Statement;\r
19 import org.simantics.db.common.utils.Logger;\r
20 import org.simantics.db.exception.DatabaseException;\r
21 import org.simantics.db.exception.NoSingleResultException;\r
22 import org.simantics.db.layer0.function.All;\r
23 import org.simantics.db.layer0.request.ClassificationsRequest;\r
24 import org.simantics.db.layer0.variable.AbstractChildVariable;\r
25 import org.simantics.db.layer0.variable.NodeSupport;\r
26 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;\r
27 import org.simantics.db.layer0.variable.StandardConstantGraphPropertyVariable;\r
28 import org.simantics.db.layer0.variable.Variable;\r
29 import org.simantics.db.layer0.variable.VariableNode;\r
30 import org.simantics.layer0.Layer0;\r
31 import org.simantics.simulator.variable.NodeManager;\r
32 import org.simantics.structural2.Functions;\r
33 import org.simantics.structural2.procedural.Connection;\r
34 import org.simantics.structural2.procedural.ConnectionPoint;\r
35 import org.simantics.structural2.procedural.Expression;\r
36 import org.simantics.structural2.procedural.Interface;\r
37 import org.simantics.structural2.procedural.Property;\r
38 import org.simantics.structural2.procedural.Terminal;\r
39 import org.simantics.utils.datastructures.Pair;\r
40 \r
41 public class StandardProceduralChildVariable extends AbstractChildVariable {\r
42 \r
43         /*\r
44          * Extension points\r
45          * \r
46          */\r
47         public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {\r
48                 return null;\r
49         }\r
50 \r
51         public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {\r
52         }\r
53 \r
54         /*\r
55          * Standard implementation\r
56          * \r
57          */\r
58         \r
59         final protected String name;\r
60         final protected Variable parent;\r
61         final private Resource type;\r
62         final private Map<String, Variable> properties;\r
63         final private List<Object> propertyIdentity;\r
64         \r
65     public static class FixedConnection implements org.simantics.structural2.variables.Connection {\r
66 \r
67                 final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();\r
68         \r
69         final private Variable parent;\r
70         \r
71         public FixedConnection(Variable parent) {\r
72             this.parent = parent;\r
73         }\r
74         \r
75         @Override\r
76         public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {\r
77                 \r
78                 Set<Variable> result = new THashSet<Variable>();\r
79             for(Pair<String,Resource> cp : cps) {\r
80                 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
81                 Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
82                 if(cp2 != null)\r
83                         for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {\r
84                                 result.add(desc.getVariable(graph));\r
85                         }\r
86                 else\r
87                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
88             }\r
89             return result;\r
90             \r
91         }\r
92         \r
93                 @Override\r
94                 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {\r
95                         \r
96                 Set<String> result = new THashSet<String>();\r
97             for(Pair<String,Resource> cp : cps) {\r
98                 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
99                 Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
100                 if(cp2 != null)\r
101                         for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {\r
102                                 result.add(desc.getURI(graph));\r
103                         }\r
104                 else\r
105                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
106             }\r
107             return result;\r
108                         \r
109                 }\r
110                 \r
111                 @Override\r
112                 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {\r
113                         \r
114                 Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();\r
115             for(Pair<String,Resource> cp : cps) {\r
116                 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); \r
117                 Variable cp2 = component.getPossibleProperty(graph, cp.second);\r
118                 if(cp2 != null)\r
119                         result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));\r
120                 else\r
121                         System.err.println("no cp " + cp.first + " for " + component.getURI(graph));\r
122             }\r
123             return result;\r
124                         \r
125                 }        \r
126 \r
127         @Override\r
128                 public int hashCode() {\r
129                         final int prime = 31;\r
130                         int result = 1;\r
131                         result = prime * result + ((cps == null) ? 0 : cps.hashCode());\r
132                         result = prime * result\r
133                                         + ((parent == null) ? 0 : parent.hashCode());\r
134                         return result;\r
135                 }\r
136 \r
137                 @Override\r
138                 public boolean equals(Object obj) {\r
139                         if (this == obj)\r
140                                 return true;\r
141                         if (obj == null)\r
142                                 return false;\r
143                         if (getClass() != obj.getClass())\r
144                                 return false;\r
145                         FixedConnection other = (FixedConnection) obj;\r
146                         if (cps == null) {\r
147                                 if (other.cps != null)\r
148                                         return false;\r
149                         } else if (!cps.equals(other.cps))\r
150                                 return false;\r
151                         if (parent == null) {\r
152                                 if (other.parent != null)\r
153                                         return false;\r
154                         } else if (!parent.equals(other.parent))\r
155                                 return false;\r
156                         return true;\r
157                 }\r
158 \r
159     }\r
160     \r
161         public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {\r
162                 super(node);\r
163                 assert name != null;\r
164         assert type != null;\r
165         this.name = name;\r
166                 this.parent = parent;\r
167                 this.type = type;\r
168                 this.properties = new THashMap<String,Variable>();\r
169                 \r
170                 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());\r
171                 propertyIdentity.addAll(properties);\r
172                 propertyIdentity.addAll(conns);\r
173                 \r
174                 Layer0 L0 = Layer0.getInstance(graph);\r
175 \r
176                 Map<String,Statement> assertedProperties = new THashMap<String, Statement>();\r
177                 for(Statement stm : graph.getAssertedStatements(type, L0.HasProperty)) {\r
178             String pn = graph.getRelatedValue(stm.getPredicate(), L0.HasName, Bindings.STRING);\r
179             assertedProperties.put(pn, stm);\r
180                 }\r
181                 \r
182         Collection<Object> nodeProperties = All.getPossibleNodeProperties(graph, (AbstractChildVariable)this);\r
183         Set<String> used = new HashSet<String>(nodeProperties.size());\r
184         for(Object nodeProperty : nodeProperties) {\r
185             @SuppressWarnings("rawtypes")\r
186             NodeSupport support = node.support;\r
187             @SuppressWarnings("rawtypes")\r
188             NodeManager manager = support.manager;\r
189             @SuppressWarnings("unchecked")\r
190             String pName = manager.getName(nodeProperty);\r
191             used.add(pName);\r
192             Statement assertedProperty = assertedProperties.get(pName); \r
193             if(assertedProperty != null) {\r
194                 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, new VariableNode(support, nodeProperty), assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));\r
195             }\r
196         }\r
197         \r
198         for(Map.Entry<String, Statement> entry : assertedProperties.entrySet()) {\r
199             String pName = entry.getKey();\r
200             if(used.contains(pName)) continue;\r
201             Statement assertedProperty = entry.getValue();\r
202             this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, null, assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));\r
203         }\r
204                 \r
205                 \r
206                 for(Property p : properties) {\r
207                     String pn = graph.getRelatedValue(p.relation, L0.HasName, Bindings.STRING);\r
208                     if(p.value == null) {\r
209                         Logger.defaultLogError("StandardProceduralChildVariable " + getURI(graph) + ": null value for property " + pn);\r
210                     } else if (p.value instanceof Expression) {\r
211                         Expression expression = (Expression)p.value;\r
212                             this.properties.put(pn, new StructuralProceduralExpressionPropertyVariable(graph, this, p.relation, expression.text) );\r
213                     } else {\r
214                             this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );\r
215                     }\r
216                         \r
217                         \r
218                 }\r
219             Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();\r
220                 for(Connection conn : conns) {\r
221                     Resource p = null;\r
222                     List<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();\r
223                     for(ConnectionPoint cp : conn.connectionPoints) {\r
224                         if(cp instanceof Terminal) {\r
225                             Terminal t = (Terminal)cp;\r
226                             if(t.component.equals(name)) {\r
227                                 p = t.relation;\r
228                                 continue;\r
229                             }\r
230                             cps.add(Pair.make(t.component, t.relation));\r
231                         }\r
232                         if(cp instanceof Interface) {\r
233                                 Interface inf = (Interface)cp;\r
234                             cps.add(new Pair<String,Resource>(null, inf.relation));\r
235                         }\r
236                     }\r
237                     if(p != null) {\r
238                         FixedConnection fc = map.get(p);\r
239                         if(fc == null) {\r
240                                 fc = new FixedConnection(parent);\r
241                                 map.put(p, fc);\r
242                         }\r
243                         fc.cps.addAll(cps);             \r
244                     }\r
245                 }\r
246                 for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {\r
247                         Resource cp = entry.getKey();\r
248             String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);\r
249                 this.properties.put(cpName, new StandardConstantGraphPropertyVariable(graph, this, cp, entry.getValue()));\r
250                 }\r
251                 \r
252         }\r
253 \r
254         @Override\r
255         public void validate(ReadGraph graph) throws DatabaseException {\r
256         }\r
257         \r
258         @Override\r
259         public Resource getType(ReadGraph graph) throws DatabaseException {\r
260             return type;\r
261         }\r
262         \r
263         @Override\r
264         public Resource getPossibleType(ReadGraph graph) throws DatabaseException {\r
265             return type;\r
266         }\r
267         \r
268         @Override\r
269         public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
270                 if (graph.isInheritedFrom(type, baseType))\r
271                         return type;\r
272                 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type");\r
273         }\r
274         \r
275         @Override\r
276         public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {\r
277                 return graph.isInheritedFrom(type, baseType) ? type : null;\r
278         }\r
279         \r
280         @Override\r
281         protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {\r
282             return properties.get(name);\r
283         }\r
284 \r
285         @Override\r
286         public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
287             return Functions.structuralChildDomainChildren.getVariable(graph, this, name);\r
288         }\r
289 \r
290         @Override\r
291         public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {\r
292                 if(!this.properties.isEmpty()) {\r
293                         if(properties == null) properties = new THashMap<String,Variable>(this.properties.size());\r
294                         properties.putAll(this.properties);\r
295                 }\r
296                 return properties;\r
297         }\r
298 \r
299         @Override\r
300         public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
301              Map<String,Variable> result = Functions.structuralChildDomainChildren.getVariables(graph, this, null);\r
302              if(result == null) return Collections.emptyList();\r
303              else return result.values();\r
304         }\r
305 \r
306         public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {\r
307                 Resource type = getPossibleType(graph);\r
308                 return (type != null)\r
309                                 ? graph.syncRequest(new ClassificationsRequest(Collections.singleton(type)))\r
310                                 : Collections.<String>emptySet();\r
311         }\r
312 \r
313         @Override\r
314         public String getName(ReadGraph graph) throws DatabaseException {\r
315             return name;\r
316         }\r
317 \r
318         @Override\r
319         public Variable getParent(ReadGraph graph) throws DatabaseException {\r
320                 return parent;\r
321         }\r
322         \r
323         @Override\r
324         final public Resource getRepresents(ReadGraph graph) throws DatabaseException {\r
325             return null;\r
326         }\r
327 \r
328         @Override\r
329         public int hashCode() {\r
330                 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);\r
331         }\r
332 \r
333         @Override\r
334         public boolean equals(Object obj) {\r
335                 \r
336                 if (this == obj)\r
337                         return true;\r
338                 if (obj == null)\r
339                         return false;\r
340                 if (getClass() != obj.getClass())\r
341                         return false;\r
342                 \r
343                 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;\r
344                 \r
345                 if(!name.equals(other.name)) return false;\r
346                 if(!type.equals(other.type)) return false;\r
347                 if(!parent.equals(other.parent)) return false;\r
348                 if(propertyIdentity != other.propertyIdentity) return false;\r
349                                 \r
350                 return true;\r
351                 \r
352         }\r
353         \r
354 }\r