]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java
Merge "Some Acorn improvements"
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / Functions.java
1 package org.simantics.structural2;\r
2 \r
3 \r
4 import java.util.ArrayList;\r
5 import java.util.Collection;\r
6 import java.util.Collections;\r
7 import java.util.HashSet;\r
8 import java.util.List;\r
9 import java.util.Map;\r
10 import java.util.Set;\r
11 \r
12 import org.simantics.databoard.Bindings;\r
13 import org.simantics.databoard.Datatypes;\r
14 import org.simantics.databoard.adapter.AdaptException;\r
15 import org.simantics.databoard.binding.Binding;\r
16 import org.simantics.databoard.binding.error.BindingException;\r
17 import org.simantics.databoard.binding.error.DatatypeConstructionException;\r
18 import org.simantics.databoard.type.Datatype;\r
19 import org.simantics.databoard.util.URIStringUtils;\r
20 import org.simantics.db.Issue;\r
21 import org.simantics.db.ReadGraph;\r
22 import org.simantics.db.Resource;\r
23 import org.simantics.db.Statement;\r
24 import org.simantics.db.WriteGraph;\r
25 import org.simantics.db.common.issue.StandardIssue;\r
26 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
27 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
28 import org.simantics.db.common.request.ObjectsWithType;\r
29 import org.simantics.db.common.request.PossibleIndexRoot;\r
30 import org.simantics.db.common.request.ResourceRead;\r
31 import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
32 import org.simantics.db.exception.DatabaseException;\r
33 import org.simantics.db.layer0.function.All;\r
34 import org.simantics.db.layer0.function.StandardChildDomainChildren;\r
35 import org.simantics.db.layer0.request.PropertyInfo;\r
36 import org.simantics.db.layer0.request.PropertyInfoRequest;\r
37 import org.simantics.db.layer0.request.VariableRead;\r
38 import org.simantics.db.layer0.variable.AbstractChildVariable;\r
39 import org.simantics.db.layer0.variable.AbstractPropertyVariable;\r
40 import org.simantics.db.layer0.variable.LazyPropertyVariable;\r
41 import org.simantics.db.layer0.variable.NodeSupport;\r
42 import org.simantics.db.layer0.variable.StandardGraphChildVariable;\r
43 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;\r
44 import org.simantics.db.layer0.variable.ValueAccessor;\r
45 import org.simantics.db.layer0.variable.ValueAccessorWithBinding;\r
46 import org.simantics.db.layer0.variable.Variable;\r
47 import org.simantics.db.layer0.variable.VariableMap;\r
48 import org.simantics.db.layer0.variable.VariableMapImpl;\r
49 import org.simantics.db.layer0.variable.VariableNode;\r
50 import org.simantics.issues.common.IssueUtils;\r
51 import org.simantics.layer0.Layer0;\r
52 import org.simantics.scl.reflection.annotations.SCLValue;\r
53 import org.simantics.scl.runtime.SCLContext;\r
54 import org.simantics.scl.runtime.function.Function1;\r
55 import org.simantics.simulation.ontology.SimulationResource;\r
56 import org.simantics.simulator.variable.NodeManager;\r
57 import org.simantics.structural.stubs.StructuralResource2;\r
58 import org.simantics.structural2.procedural.Component;\r
59 import org.simantics.structural2.procedural.ConnectionPoint;\r
60 import org.simantics.structural2.procedural.Interface;\r
61 import org.simantics.structural2.procedural.SubstructureElement;\r
62 import org.simantics.structural2.procedural.Terminal;\r
63 import org.simantics.structural2.queries.ConnectionComponents;\r
64 import org.simantics.structural2.queries.ConnectionJoinComponents;\r
65 import org.simantics.structural2.queries.ConnectionPointMapOfResource;\r
66 import org.simantics.structural2.queries.PossibleConnectionPointInfo;\r
67 import org.simantics.structural2.scl.CompileStructuralValueRequest;\r
68 import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;\r
69 import org.simantics.structural2.variables.Connection;\r
70 import org.simantics.structural2.variables.ConnectionBrowser;\r
71 import org.simantics.structural2.variables.StandardProceduralChildVariable;\r
72 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;\r
73 import org.simantics.utils.datastructures.MapList;\r
74 \r
75 import gnu.trove.map.hash.THashMap;\r
76 import gnu.trove.set.hash.THashSet;\r
77 \r
78 public class Functions {\r
79         \r
80         @SCLValue(type="ValueAccessor")\r
81         public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {\r
82 \r
83                 public Binding getBinding() {\r
84                         return Bindings.STRING;\r
85                 }\r
86                 \r
87                 @Override\r
88                 public void setValue(WriteGraph graph, Variable context, Object value)\r
89                                 throws DatabaseException {\r
90                         if(value == null) {\r
91                                 if(getValue(graph, context) != null)\r
92                                         clearExpression(graph, context);\r
93                                 return;\r
94                         }\r
95                         \r
96                         // Get all necessary data\r
97                         String expression = (String)value;\r
98                         Variable parent = context.getParent(graph);\r
99                         if(!(parent instanceof AbstractPropertyVariable)) return;\r
100                         AbstractPropertyVariable property = (AbstractPropertyVariable)parent;                   \r
101                         Resource propertyResource = property.getRepresents(graph);\r
102                         if(propertyResource == null) return;\r
103                         Resource container = property.getContainerResource(graph);\r
104                         if(container == null) return;\r
105                         Resource predicate = property.getPossiblePredicateResource(graph);\r
106                         if(predicate == null) return;                   \r
107                         Statement stat = graph.getPossibleStatement(container, predicate);                      \r
108                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
109                         \r
110                         // Write                        \r
111                         boolean createNew = false;\r
112                         if(stat.isAsserted(container))\r
113                                 createNew = true;\r
114                         else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {\r
115                                 graph.deny(propertyResource);\r
116                                 createNew = true;\r
117                         }\r
118             Layer0 L0 = Layer0.getInstance(graph);\r
119                         if(createNew) {\r
120                                 propertyResource = graph.newResource();\r
121                                 graph.claim(container, predicate, propertyResource);\r
122                                 graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);                             \r
123                         }\r
124                         graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);\r
125                 }\r
126 \r
127                 private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {\r
128                         Variable parent = context.getParent(graph);\r
129                         if(!(parent instanceof AbstractPropertyVariable)) return;\r
130                         AbstractPropertyVariable property = (AbstractPropertyVariable)parent;\r
131                         Resource container = property.getContainerResource(graph);\r
132                         if(container == null) return;\r
133                         Resource predicate = property.getPossiblePredicateResource(graph);\r
134                         if(predicate == null) return;                   \r
135                         graph.deny(container, predicate);               \r
136                 }\r
137 \r
138                 @Override\r
139                 public Object getValue(ReadGraph graph, Variable context)\r
140                                 throws DatabaseException {\r
141                         Variable parent = context.getParent(graph);\r
142                         if(!(parent instanceof AbstractPropertyVariable))\r
143                                 return null;\r
144                         AbstractPropertyVariable property = (AbstractPropertyVariable)parent;\r
145                         Resource propertyResource = property.getPossibleRepresents(graph);\r
146                         if(propertyResource == null) return null;\r
147                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
148                         if(!graph.isInstanceOf(propertyResource, STR.SCLValue))\r
149                                 return null;\r
150             Layer0 L0 = Layer0.getInstance(graph);\r
151                         return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);\r
152                 }\r
153                 \r
154         };\r
155         \r
156         static class ConnectionImpl implements Connection {\r
157 \r
158                 final private StandardGraphPropertyVariable connectionPoint;\r
159                 \r
160                 public ConnectionImpl(StandardGraphPropertyVariable connectionPoint) {\r
161                         this.connectionPoint = connectionPoint;\r
162                 }\r
163                 \r
164                 @Override\r
165                 public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {\r
166                     Set<Variable> result = new THashSet<Variable>();\r
167                     for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {\r
168                         result.add(desc.getVariable(graph));\r
169                     }\r
170                     return result;\r
171                 }\r
172                 \r
173                 @Override\r
174                 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {\r
175                     Set<String> result = new THashSet<String>();\r
176                     for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {\r
177                         result.add(desc.getURI(graph));\r
178                     }\r
179                     return result;\r
180                 }\r
181 \r
182                 @Override\r
183                 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {\r
184                     return ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType);\r
185                 }\r
186 \r
187         }\r
188         \r
189         @SCLValue(type="ValueAccessor")\r
190         public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {\r
191 \r
192                 @Override\r
193                 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {\r
194                         throw new UnsupportedOperationException();\r
195                 }\r
196                 \r
197                 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {\r
198                         throw new UnsupportedOperationException();\r
199                 }\r
200 \r
201                 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {\r
202             try {\r
203                 Object value = getValue(graph, context);\r
204                 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);\r
205                                 return Bindings.adapt(value, srcBinding, binding);\r
206                         } catch (AdaptException e) {\r
207                                 throw new DatabaseException(e);\r
208                         } catch (BindingException e) {\r
209                                 throw new DatabaseException(e);\r
210                         }\r
211                 }\r
212 \r
213                 @Override\r
214                 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {\r
215                         StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; \r
216                         return new ConnectionImpl(variable);\r
217                 }\r
218 \r
219                 @Override\r
220                 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {\r
221                         try {\r
222                                 return Datatypes.getDatatype(Connection.class);\r
223                         } catch (DatatypeConstructionException e) {\r
224                                 throw new DatabaseException(e);\r
225                         }\r
226                 }\r
227                 \r
228         };      \r
229 \r
230 \r
231         @SCLValue(type = "VariableMap")\r
232         public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {\r
233         \r
234                 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {\r
235 \r
236                         Map<String, Resource> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
237                         Resource cp = connectionPoints.get(name);\r
238                         if(cp == null) return null;\r
239                         else return new StandardGraphPropertyVariable(graph, variable, cp);\r
240                         \r
241                 }\r
242                 \r
243                 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {\r
244                         \r
245                         if(graph.isImmutable(context)) {\r
246 \r
247                                 Map<String, Resource> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
248                                 if(cps.size() == 0) return map;\r
249                                 \r
250                                 if(map == null) map = new THashMap<String,Variable>(cps.size());\r
251                                 \r
252                                 for(Map.Entry<String, Resource> entry : cps.entrySet()) {\r
253                                         String name = entry.getKey();\r
254                                         Resource cp = entry.getValue();\r
255                                         if(needSynchronized && !graph.isInstanceOf(cp, STR.SynchronizedConnectionRelation)) continue;\r
256                                         map.put(name, new StandardGraphPropertyVariable(graph, variable, cp));\r
257                                 }\r
258                                 \r
259                                 return map;\r
260 \r
261                         } else {\r
262                                 \r
263                                 Collection<Resource> predicates = graph.getPredicates(context);\r
264                                 \r
265                                 for(Resource predicate : predicates) {\r
266                                         \r
267                                         PropertyInfo info = graph.isImmutable(predicate) ?\r
268                                                         graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :\r
269                                                                 graph.syncRequest(new PossibleConnectionPointInfo(predicate));\r
270                                                         \r
271                                         if(info != null) {\r
272                                                 if(map == null) map = new THashMap<String,Variable>(4);\r
273                                                 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;\r
274                                                 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));\r
275                                         }\r
276                                         \r
277                                 }\r
278 \r
279                                 return map;\r
280 \r
281                         }\r
282                         \r
283                 }\r
284 \r
285                 @Override\r
286                 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
287                 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
288                 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);\r
289                 if(cp != null) return cp;\r
290             return All.getStandardChildDomainPropertyVariable(graph, context, name);\r
291                 }\r
292 \r
293                 @Override\r
294                 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
295                 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
296                 StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
297                 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);\r
298             return All.getStandardChildDomainPropertyVariables(graph, context, map);\r
299                 }\r
300                 \r
301                 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {\r
302                         if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {\r
303                                 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);\r
304                         } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {\r
305                         StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
306                         return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);\r
307                         } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {\r
308                         StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
309                         return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);\r
310                         }\r
311                         return super.getVariables(graph, context, classification, map);\r
312                 }\r
313                 \r
314         };\r
315 \r
316         static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {\r
317 \r
318                 public StructuralChildMapOfResource(Resource resource) {\r
319                         super(resource);\r
320                 }\r
321 \r
322                 @Override\r
323                 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
324                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
325                         Resource type = graph.getPossibleType(resource, STR.Component);\r
326                         if(type != null) {\r
327                                 Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);\r
328                                 if(definition != null) {\r
329                                         Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));\r
330                                         if (!map.isEmpty())\r
331                                                 return map;\r
332                                 } \r
333                         }\r
334                         Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));\r
335                         return directChildren;\r
336                 }\r
337 \r
338         }\r
339 \r
340     static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {\r
341 \r
342         public StructuralChildMapOfResourceT(Resource resource) {\r
343             super(resource);\r
344         }\r
345 \r
346         @Override\r
347         public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
348             StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
349             Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);\r
350             if(definition != null) {\r
351                 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));\r
352                 if (!map.isEmpty())\r
353                     return map;\r
354             } \r
355             return Collections.emptyMap();\r
356         }\r
357 \r
358     }\r
359 \r
360         static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {\r
361 \r
362                 public StructuralRunChildMapOfResource(Resource resource) {\r
363                         super(resource);\r
364                 }\r
365 \r
366                 public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {\r
367                         return graph.sync(new StructuralChildMapOfResource(context));\r
368                 }\r
369                 \r
370                 @Override\r
371                 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
372 \r
373                         Layer0 L0 = Layer0.getInstance(graph);\r
374                         SimulationResource SIMU = SimulationResource.getInstance(graph);\r
375                         Resource model = graph.sync(new PossibleIndexRoot(resource));\r
376                         if(graph.isInstanceOf(model, L0.RVIContext)) {\r
377                                 return fromContext(graph, model);\r
378                         }\r
379                         Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);\r
380                         if(configuration != null) {\r
381                                 if(graph.isInstanceOf(configuration, L0.RVIContext)) {\r
382                                         return fromContext(graph, configuration);\r
383                                 }\r
384                         }\r
385                         \r
386                         return Collections.emptyMap();\r
387                         \r
388                 }\r
389                 \r
390         }\r
391         \r
392         private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {\r
393             public SubstructureRequest(Variable context) {\r
394             super(context);\r
395         }\r
396 \r
397         @Override\r
398         public List<SubstructureElement> perform(ReadGraph graph) {\r
399             try {\r
400                 Resource type = variable.getPossibleType(graph);\r
401                 if(type == null)\r
402                     return null;\r
403                 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);\r
404             } catch (Throwable t) {\r
405                 t.printStackTrace();\r
406                 return null;\r
407             }\r
408         }\r
409         }\r
410 \r
411     public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {\r
412         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
413         final Resource type = context.getPossibleType(graph);\r
414         if(type != null) {\r
415             if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
416                 return graph.syncRequest(new SubstructureRequest(context));\r
417             }\r
418         }\r
419         return null;\r
420     }  \r
421         \r
422          public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {\r
423              \r
424          if(map == null) map = new THashMap<String,Variable>();\r
425          \r
426          MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();\r
427          for(SubstructureElement sub : elements) {\r
428              if(sub instanceof org.simantics.structural2.procedural.Connection) {\r
429                  org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;\r
430                  for(ConnectionPoint cp : conn.connectionPoints) {\r
431                      if(cp instanceof Terminal) {\r
432                          Terminal t = (Terminal)cp;\r
433                          conns.add(t.component, conn);\r
434                      }\r
435                  }\r
436              }\r
437          }\r
438          \r
439          Map<String,Component> proceduralChildren = new THashMap<String, Component>();\r
440          for(SubstructureElement sub : elements) {\r
441              if(sub instanceof Component) {\r
442                  Component comp = (Component)sub;\r
443                  proceduralChildren.put(comp.name, comp);\r
444              }\r
445          }\r
446          \r
447          Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);\r
448          Set<String> used = new HashSet<String>(nodeChildren.size());\r
449          for(Object nodeChild : nodeChildren) {\r
450              @SuppressWarnings("rawtypes")\r
451              NodeSupport support = ((AbstractChildVariable)context).node.support;\r
452              @SuppressWarnings("rawtypes")\r
453              NodeManager manager = support.manager;\r
454              @SuppressWarnings("unchecked")\r
455              String name = manager.getName(nodeChild);\r
456              used.add(name);\r
457              Component proceduralChild = proceduralChildren.get(name); \r
458              if(proceduralChild != null) {\r
459                  map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));\r
460              }\r
461          }\r
462          \r
463          for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {\r
464              String name = entry.getKey();\r
465              if(used.contains(name)) continue;\r
466              Component proceduralChild = entry.getValue();\r
467              map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));\r
468          }\r
469          \r
470          return map;\r
471              \r
472      }  \r
473          \r
474          private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {\r
475 \r
476              public ProceduralSubstructureRequest(Variable variable) {\r
477                  super(variable);\r
478              }\r
479 \r
480              @Override\r
481              public Map<String, Variable> perform(ReadGraph graph)\r
482                      throws DatabaseException {\r
483                  List<SubstructureElement> elements = getProceduralDesc(graph, variable);\r
484                  if(elements != null)\r
485                      return getProcedural(graph, variable, elements, null);\r
486                  else\r
487                      return null;\r
488              }\r
489          }\r
490          \r
491         \r
492         @SCLValue(type = "VariableMap")\r
493         public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {\r
494         \r
495                 @Override\r
496                 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
497                         \r
498                 final Resource type = context.getPossibleType(graph);\r
499                 if(type != null) {\r
500                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
501                     if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
502                             Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),\r
503                                 TransientCacheListener.<Map<String,Variable>>instance());\r
504                             if(map != null) return map.get(name);\r
505                     }\r
506                 }\r
507 \r
508                     Resource represents = context.getPossibleRepresents(graph);\r
509             if(represents == null) {\r
510                 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));\r
511                 Resource child = children.get(name);\r
512                 return All.getStandardChildDomainChildVariable(graph, context, child, name);\r
513             }\r
514             Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));\r
515             Resource child = children.get(name);\r
516             return All.getStandardChildDomainChildVariable(graph, context, child, name);\r
517                 }\r
518 \r
519                 @Override\r
520                 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
521                         \r
522                 final Resource type = context.getPossibleType(graph);\r
523                 if(type != null) {\r
524                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
525                     if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
526                         Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),\r
527                                         TransientCacheListener.<Map<String,Variable>>instance());\r
528                         if(mapPrime != null) {\r
529                                 if(map != null) {\r
530                                         map.putAll(mapPrime);\r
531                                         return map;\r
532                                 }\r
533                                 else\r
534                                         return mapPrime;\r
535                         }\r
536                     }\r
537                 }\r
538             Resource represents = context.getPossibleRepresents(graph);\r
539             if(represents == null) {\r
540                 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));\r
541                 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
542             }\r
543             Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));\r
544             return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
545                 }\r
546                 \r
547         };\r
548         \r
549         @SCLValue(type = "VariableMap")\r
550         public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {\r
551         \r
552                 @Override\r
553                 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
554                     Map<String, Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(context.getRepresents(graph)));\r
555                         Resource child = children.get(name);\r
556             return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);\r
557                 }\r
558 \r
559                 @Override\r
560                 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
561             StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
562             Map<String,Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(variable.resource));\r
563                     return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
564                 }\r
565                 \r
566         };\r
567 \r
568         @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")\r
569     public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {\r
570 \r
571         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
572         HashSet<Resource> extension = new HashSet<Resource>(8);\r
573         for(Resource r : rs) {\r
574                 if(graph.isInstanceOf(r, STR.Connection)) {\r
575                         extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));\r
576                 }\r
577                 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {\r
578                         extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));\r
579                 }\r
580         }\r
581 \r
582         HashSet<Resource> components = new HashSet<Resource>(8);\r
583         for(Resource r : extension) {\r
584                 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));\r
585         }\r
586         \r
587         if(!extension.isEmpty()) {\r
588                 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());\r
589                 result.addAll(rs);\r
590                 result.addAll(extension);\r
591                 result.addAll(components);\r
592                 rs = result;\r
593         }\r
594         \r
595         return rs;\r
596         \r
597     }\r
598 \r
599         @SCLValue(type = "ReadGraph -> Resource -> [Issue]")\r
600     public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {\r
601         \r
602                 if(!graph.hasStatement(component)) return Collections.emptyList();\r
603 \r
604                 ArrayList<Issue> result = new ArrayList<Issue>();\r
605                 \r
606                 Layer0 L0 = Layer0.getInstance(graph);\r
607                 StructuralResource2 sr = StructuralResource2.getInstance(graph);\r
608 \r
609                 Resource type = graph.getSingleType(component, sr.Component);\r
610                 \r
611                 Set<Resource> requiredConnections = new HashSet<Resource>();\r
612                 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {\r
613                         Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);\r
614                         if(required != null && required)\r
615                                 requiredConnections.add(connectionRelation);\r
616                 }\r
617                 \r
618                 Set<Resource> connections = new HashSet<Resource>();\r
619 \r
620                 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {\r
621                         connections.add(stm.getPredicate());\r
622                         connections.addAll(graph.getSuperrelations(stm.getPredicate()));\r
623                 }\r
624 \r
625                 for(Resource req : requiredConnections) {\r
626                         if(!connections.contains(req)) {\r
627                                 result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));\r
628                         }\r
629                 }\r
630 \r
631                 return result;\r
632         \r
633     }\r
634 \r
635     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
636     public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {\r
637         List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
638         String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);\r
639         return "'" + attributeName + "' should be connected.";\r
640     }\r
641 \r
642     public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {\r
643 \r
644                 public InterfacePathMap(Variable context) {\r
645                         super(context);\r
646                 }\r
647 \r
648                 @Override\r
649                 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {\r
650 \r
651                         return new GraphMap<Map<String,InterfaceResolution>>() {\r
652 \r
653                                 @Override\r
654                                 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {\r
655                                         \r
656                                         Variable child = variable.getChild(graph, key);\r
657                                         \r
658                                         Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();\r
659                                         Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");\r
660                                         if(paths != null) {\r
661                                                 for(InterfaceResolution r : paths) {\r
662                                                         childMap.put(r.interfaceName, r);\r
663                                                 }\r
664                                         }\r
665                                         return childMap;\r
666 \r
667                                 }\r
668                                 \r
669                         };\r
670                         \r
671                 }\r
672         \r
673     }\r
674     \r
675     public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {\r
676         \r
677         GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());\r
678         Map<String,InterfaceResolution> childMap = map.get(graph, component);\r
679         if(childMap == null) return "";\r
680 \r
681         PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());\r
682 \r
683         InterfaceResolution match = childMap.get(info.name);\r
684         if(match != null) {\r
685                 String comp = URIStringUtils.escape(component);\r
686                 Variable newContext = context.getChild(graph, component);\r
687                 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);\r
688         } else {\r
689                 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name); \r
690         }\r
691                 \r
692     }\r
693     \r
694     public static class InterfaceResolution {\r
695         \r
696         public Resource interfaceConnectionPoint;\r
697         public String interfaceName;\r
698         public String componentName;\r
699         public Resource connectionPoint;\r
700         \r
701         public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {\r
702                 this.interfaceConnectionPoint = interfaceConnectionPoint;\r
703                 this.interfaceName = interfaceName;\r
704                 this.componentName = componentName;\r
705                 this.connectionPoint = connectionPoint;\r
706         }\r
707         \r
708     }\r
709     \r
710     public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {\r
711 \r
712                 StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
713                 Resource type = variable.getPossibleType(graph);\r
714                 if(type != null) {\r
715                         if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
716                                 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();\r
717                                 List<SubstructureElement> elements = getProceduralDesc(graph, variable); \r
718                                 if(elements != null) {\r
719                                         for(SubstructureElement e : elements) {\r
720                                                 if(e instanceof org.simantics.structural2.procedural.Connection) {\r
721                                                         org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;\r
722                                                         Interface inf = null;\r
723                                                         for(ConnectionPoint cp : conn.connectionPoints) {\r
724                                                                 if(cp instanceof Interface) {\r
725                                                                         if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");\r
726                                                                         inf = (Interface)cp;\r
727                                                                 }\r
728                                                         }\r
729                                                         if(inf != null && conn.connectionPoints.size() > 1) {\r
730                                                                 Layer0 L0 = Layer0.getInstance(graph);\r
731                                                                 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );\r
732                                                                 for(ConnectionPoint cp : conn.connectionPoints) {\r
733                                                                         if(cp == inf) continue;\r
734                                                                         Terminal t = (Terminal)cp;\r
735                                                                         result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));\r
736                                                                 }\r
737                                                         }\r
738                                                 }\r
739                                         }\r
740                                 }\r
741 \r
742                                 return result;\r
743                                 \r
744                         }\r
745 \r
746                         final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));\r
747                         if(interfaces != null) return interfaces;\r
748 \r
749                 }\r
750                 \r
751                 return BUILTIN_STRUCTURAL_CPS;\r
752         \r
753     }\r
754     \r
755     static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {\r
756 \r
757                 public InterfacePathRequest(Variable variable) {\r
758                         super(variable);\r
759                 }\r
760                 \r
761                 @Override\r
762                 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {\r
763                         return computeInterfacePaths(graph, variable);\r
764                 }\r
765         \r
766     }\r
767     \r
768     static class DefinedUCInterfaceMap extends ResourceRead<Collection<InterfaceResolution>> {\r
769 \r
770         public DefinedUCInterfaceMap(Resource resource) {\r
771                 super(resource);\r
772         }\r
773 \r
774         @Override\r
775         public Collection<InterfaceResolution> perform(ReadGraph graph)\r
776                         throws DatabaseException {\r
777 \r
778                 StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
779                 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);\r
780                 if(definition != null) {\r
781                         Collection<InterfaceResolution> result = new ArrayList<InterfaceResolution>();\r
782                         Layer0 L0 = Layer0.getInstance(graph);\r
783                         for(Resource cp : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, STR.ConnectionRelation))) {\r
784                                         String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);\r
785                                 for(Resource conn : graph.getObjects(cp, STR.IsBoundBy)) {\r
786                                         Statement stm = graph.getPossibleStatement(conn, STR.Connects);\r
787                                         if(stm == null) continue;\r
788                                         Resource component = stm.getObject();\r
789                                         String componentName = graph.getRelatedValue(component, L0.HasName, Bindings.STRING);\r
790                                         result.add(new InterfaceResolution(cp, cpName, componentName, graph.getInverse(stm.getPredicate())));\r
791                                 }\r
792                         }\r
793                         return result;\r
794                 }\r
795                 return null;\r
796         }\r
797 \r
798     }\r
799     \r
800     public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();\r
801 \r
802         @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
803     public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
804         return CompileStructuralValueRequest.compileAndEvaluate(graph, context);\r
805     }\r
806 \r
807     public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {\r
808         SCLContext sclContext = SCLContext.getCurrent();\r
809         Object oldGraph = sclContext.get("graph");\r
810         try {\r
811             Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {\r
812                 protected String getExpressionText(ReadGraph graph) throws DatabaseException {\r
813                     return expression;\r
814                 }\r
815             },\r
816             TransientCacheListener.<Function1<Variable,Object>>instance());\r
817             sclContext.put("graph", graph);\r
818             return exp.apply(context);\r
819         } catch (DatabaseException e) {\r
820             throw (DatabaseException)e;\r
821         } catch (Throwable t) {\r
822             throw new DatabaseException(t);\r
823         } finally {\r
824             sclContext.put("graph", oldGraph);\r
825         }\r
826     }    \r
827         \r
828         static abstract class InterfacePathProperty extends LazyPropertyVariable {\r
829                 \r
830                 public InterfacePathProperty(Variable parent) {\r
831                         super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);\r
832                 }\r
833                 \r
834                 @Override\r
835                 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {\r
836                         return getValue(graph);\r
837                 }\r
838                 \r
839         }\r
840         \r
841         static abstract class GraphMap<Value> {\r
842                 \r
843                 abstract Value get(ReadGraph graph, String key) throws DatabaseException;\r
844                 \r
845         }\r
846     \r
847 }\r