]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/variables/ConnectionBrowser.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / variables / ConnectionBrowser.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.procedure.adapter.TransientCacheAsyncListener;\r
20 import org.simantics.db.common.request.BinaryRead;\r
21 import org.simantics.db.common.request.ResourceRead;\r
22 import org.simantics.db.common.request.TransientUnaryRead;\r
23 import org.simantics.db.common.utils.CommonDBUtils;\r
24 import org.simantics.db.common.utils.NameUtils;\r
25 import org.simantics.db.exception.DatabaseException;\r
26 import org.simantics.db.exception.NoSingleResultException;\r
27 import org.simantics.db.layer0.exception.MissingVariableException;\r
28 import org.simantics.db.layer0.exception.MissingVariableValueException;\r
29 import org.simantics.db.layer0.request.VariableRead;\r
30 import org.simantics.db.layer0.variable.Variable;\r
31 import org.simantics.db.service.CollectionSupport;\r
32 import org.simantics.db.service.QueryControl;\r
33 import org.simantics.layer0.Layer0;\r
34 import org.simantics.modeling.ModelingResources;\r
35 import org.simantics.structural.stubs.StructuralResource2;\r
36 import org.simantics.structural2.Functions;\r
37 import org.simantics.structural2.Functions.InterfaceResolution;\r
38 import org.simantics.structural2.queries.ConnectionSet;\r
39 import org.simantics.structural2.variables.StandardProceduralChildVariable.FixedConnection;\r
40 import org.simantics.utils.datastructures.Pair;\r
41 \r
42 public class ConnectionBrowser {\r
43 \r
44     /**\r
45      * Finds the components connected by the connection. Also connections\r
46      * in \r
47      * \r
48      * @param graph \r
49      * @param connection A connection whose related modules are searched.\r
50      * @param configuration A variable that represents the composite where the connection belongs to.\r
51      * @return A map whose keys are components and they are mapped to \r
52      *         related variables.\r
53      */\r
54     public static Collection<ResourceWithContext> findConnectedComponents(\r
55             ReadGraph graph, Resource connection, Variable configuration) \r
56             throws DatabaseException {\r
57         // Create state\r
58         ArrayList<ResourceWithContext> result = \r
59             new ArrayList<ResourceWithContext>();\r
60         THashSet<Resource> visitedConnections = new THashSet<Resource>();\r
61 \r
62         // Do actual work\r
63         findConnectedComponents(graph, connection, configuration, result,\r
64                 visitedConnections);\r
65         return result;\r
66     }\r
67 \r
68     private static void findConnectedComponents(\r
69             ReadGraph graph, Resource connection, Variable configuration,\r
70             ArrayList<ResourceWithContext> result,\r
71             THashSet<Resource> visitedConnections) throws DatabaseException {\r
72          if(visitedConnections.add(connection)) {\r
73              StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
74              Layer0 L0 = Layer0.getInstance(graph);\r
75 \r
76              // Browse related components\r
77              for(Statement stat : graph.getStatements(connection, STR.Connects)) {\r
78                  Resource component = stat.getObject();\r
79                  Resource relation = graph.getInverse(stat.getPredicate());\r
80                  //System.out.println(NameUtils.getSafeName(graph, component) + "." + NameUtils.getSafeName(graph, relation));\r
81                  Resource boundConnection = graph.getPossibleObject(relation, STR.IsBoundBy);\r
82                  Resource type = graph.getPossibleObject(component, L0.InstanceOf);\r
83                  Resource def = type != null ? graph.getPossibleObject(type, STR.IsDefinedBy) : null;\r
84                  if(boundConnection != null && def != null) {\r
85                      // The connection point is bound in component type\r
86                      Variable newContext = configuration.browsePossible(graph, component);\r
87                      Resource newComposite = getCompositeOfConnection(graph, boundConnection);\r
88                      if(newContext != null && newComposite != null) {\r
89                          newContext = browse(graph, def, newContext, newComposite);\r
90                          if (newContext != null)\r
91                              findConnectedComponents(graph, boundConnection,\r
92                                      newContext,\r
93                                      result, visitedConnections);\r
94                      }\r
95                  }\r
96                  else {\r
97                      //System.out.println("added result");\r
98                      // A primitive connection point\r
99                      Variable context = configuration.browsePossible(graph, component);\r
100                      if (context != null)\r
101                          result.add(new ResourceWithContext(component, context)); \r
102                  }\r
103              }\r
104 \r
105              // Browse over connection joins\r
106              for(Resource join : graph.getObjects(connection, STR.IsJoinedBy))\r
107                  for(Resource otherConnection : graph.getObjects(join, STR.Joins))\r
108                      if(!connection.equals(otherConnection)) {\r
109                          Resource sourceComposite = getCompositeOfConnection(graph, connection);\r
110                          Resource targetComposite = getCompositeOfConnection(graph, otherConnection);\r
111                          if (sourceComposite != null && targetComposite != null) {\r
112                              Variable sibling = browseSibling(graph, \r
113                                      sourceComposite,\r
114                                      configuration,\r
115                                      targetComposite);\r
116                              if (sibling != null)\r
117                                  findConnectedComponents(graph, otherConnection,\r
118                                          sibling, result, visitedConnections);\r
119                          }\r
120                      }\r
121 \r
122              // Browse to parents\r
123              try {\r
124                  for(Resource relation : graph.getObjects(connection, STR.Binds)) {\r
125                      Resource composite = getCompositeOfConnection(graph, connection);\r
126                      if (composite == null)\r
127                          continue;\r
128 \r
129                      Variable curConfiguration = configuration;\r
130                      while(!graph.hasStatement(composite, STR.Defines)) {\r
131                          composite = graph.getSingleObject(composite, L0.PartOf);\r
132                          curConfiguration = curConfiguration.getParent(graph);\r
133                      }\r
134                      Variable parent = curConfiguration.getParent(graph);\r
135                      Resource component = curConfiguration.getRepresents(graph);\r
136                      for(Resource c : graph.getObjects(component, relation))\r
137                          findConnectedComponents(graph, c, \r
138                                  parent, result, visitedConnections);\r
139                  }\r
140              } catch(NoSingleResultException e) {\r
141              } catch(MissingVariableException e) {\r
142              } catch(MissingVariableValueException e) {\r
143              }\r
144          }\r
145     }\r
146 \r
147     public static Collection<VariableConnectionPointDescriptor> drill(ReadGraph graph, VariableConnectionPointDescriptor pair) throws DatabaseException {\r
148 \r
149         Collection<InterfaceResolution> interfaceDescription = pair.getInterfaceDescription(graph);\r
150         if(interfaceDescription != null && interfaceDescription.size() > 0) {\r
151 \r
152                 Variable cp = pair.getVariable(graph);\r
153                 Variable context = cp.getParent(graph);\r
154                 String cpName = cp.getName(graph);\r
155 \r
156                 Collection<VariableConnectionPointDescriptor> result = new ArrayList<VariableConnectionPointDescriptor>();\r
157                 for(InterfaceResolution r : interfaceDescription) {\r
158                         if(r.interfaceName.equals(cpName)) {\r
159                                 String path = Functions.resolveInterfacePath(graph, context, r.componentName, r.connectionPoint);\r
160                                 result.add(new BrowseConnectionDescriptor(context, path));\r
161                         }\r
162                 }\r
163                 \r
164                 if(result.isEmpty()) return null;\r
165                 \r
166                 return result;\r
167                 \r
168         } else {\r
169                 return Collections.singleton(pair);\r
170         }\r
171 \r
172     }\r
173     \r
174     public static class JoinConnections extends ResourceRead<Collection<Resource>> {\r
175 \r
176                 public JoinConnections(Resource join) {\r
177                         super(join);\r
178                 }\r
179 \r
180                 @Override\r
181                 public Collection<Resource> perform(ReadGraph graph) throws DatabaseException {\r
182                 ConnectionSet cs = new ConnectionSet(graph);\r
183                 cs.addJoin(graph, resource);\r
184                 return cs.getConnections();\r
185                 }\r
186         \r
187     }\r
188 \r
189     \r
190     public static final class VariableChildren extends TransientUnaryRead<Variable, Map<Resource,Variable>> {\r
191 \r
192                 public VariableChildren(ReadGraph graph, Variable variable) throws DatabaseException {\r
193                         super(graph, variable);\r
194                 }\r
195 \r
196                 public VariableChildren(ReadGraph graph, QueryControl qc, Variable variable) throws DatabaseException {\r
197                         super(graph, qc, variable);\r
198                 }\r
199 \r
200                 @Override\r
201                 public Map<Resource, Variable> perform(ReadGraph graph, Variable parameter) throws DatabaseException {\r
202                         CollectionSupport cs = graph.getService(CollectionSupport.class);\r
203                         Map<Resource,Variable> result = cs.createMap(Variable.class);\r
204                         for(Variable child : parameter.getChildren(graph)) {\r
205                                 Resource represents = child.getPossibleRepresents(graph);\r
206                                 if(represents != null) result.put(represents, child);\r
207                         }\r
208                         return result;\r
209                 }\r
210         \r
211     }\r
212     \r
213     static Variable resolve(ReadGraph graph, Variable base, Resource component) throws DatabaseException {\r
214         Map<Resource,Variable> map = graph.syncRequest(new VariableChildren(graph, base), TransientCacheAsyncListener.<Map<Resource,Variable>>instance());\r
215         Variable result = map.get(component);\r
216         if(result != null) return result;\r
217         else {\r
218                 Layer0 L0 = Layer0.getInstance(graph);\r
219                 Resource parent = graph.getPossibleObject(component, L0.PartOf);\r
220                 if(parent == null) return null;\r
221                 Variable v = resolve(graph, base, parent);\r
222                 if (v == null) return null;\r
223                 map = graph.syncRequest(new VariableChildren(graph, v), TransientCacheAsyncListener.<Map<Resource,Variable>>instance());\r
224                 return map.get(component);\r
225         }\r
226     }\r
227     \r
228     public static class ConnectionComponentsWithAncestor extends TransientUnaryRead<Resource, List<Resource>> {\r
229 \r
230         final private List<Resource> result;\r
231 \r
232                 public ConnectionComponentsWithAncestor(ReadGraph graph, Resource conn) throws DatabaseException {\r
233                         this(graph, conn, null);\r
234                 }\r
235 \r
236         public ConnectionComponentsWithAncestor(ReadGraph graph, QueryControl qc, Resource conn, List<Resource> result) throws DatabaseException {\r
237                         super(graph, qc, conn);\r
238                         this.result = result;\r
239         }\r
240 \r
241                 public ConnectionComponentsWithAncestor(ReadGraph graph, Resource conn, List<Resource> result) throws DatabaseException {\r
242                         super(graph, conn);\r
243                         this.result = result;\r
244                 }\r
245 \r
246                 private ConnectionSet connSet(ReadGraph graph, Resource r ) throws DatabaseException {\r
247                         ConnectionSet cs = new ConnectionSet(graph);\r
248                         cs.addConnection(graph, r);\r
249                         return cs;\r
250                 }\r
251                 \r
252                 @Override\r
253                 public List<Resource> perform(ReadGraph graph, Resource resource) throws DatabaseException {\r
254                         \r
255                         if(result != null) return result;\r
256                         \r
257                         Layer0 L0 = Layer0.getInstance(graph);\r
258                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
259                         CollectionSupport colls = graph.getService(CollectionSupport.class);\r
260                         THashSet<Resource> ancestorGenerators = new THashSet<Resource>();\r
261                         Set<Resource> parts = colls.createSet();\r
262                         ConnectionSet cs = connSet(graph, resource);\r
263             for(Resource connRes : cs.getConnections()) {\r
264                 for(Statement stm : graph.getStatements(connRes, STR.Connects)) {\r
265                         Resource component = stm.getObject();\r
266                         Resource parent = graph.getPossibleObject(component, L0.PartOf);\r
267                         if(parent != null && !graph.isInstanceOf(component, ModelingResources.getInstance(graph).ReferenceElement))\r
268                                 ancestorGenerators.add(parent);\r
269                 }\r
270                 parts.add(connRes);\r
271             }\r
272             for (Resource join : cs.getJoins()) {\r
273                 parts.add(join);\r
274                 for (Resource composite : graph.getObjects(join, STR.JoinsComposite))\r
275                         ancestorGenerators.add(composite);\r
276             }\r
277             Resource ancestor = ancestorGenerators.size() == 1 ? ancestorGenerators.iterator().next() : CommonDBUtils.getNearestOwner(graph, ancestorGenerators);\r
278             \r
279             List<Resource> result = colls.createList();\r
280             result.add(ancestor);\r
281             result.addAll(colls.asSortedList(parts));\r
282             \r
283             if(parameter != WITH_PARENT) {\r
284                 for(int i=1;i<result.size();i++) {\r
285                         Resource r = result.get(i);\r
286                         // Cache 'em all\r
287                         if(!r.equals(resource))\r
288                                 graph.syncRequest(new ConnectionComponentsWithAncestor(graph, r, result), TransientCacheAsyncListener.<List<Resource>>instance());\r
289                     }\r
290             }\r
291             \r
292             return result;\r
293             \r
294                 }\r
295         \r
296     }\r
297     \r
298     public static Collection<VariableConnectionPointDescriptor> climb(ReadGraph graph, Variable child, Resource cp, String subPath_) throws DatabaseException {\r
299         \r
300         boolean isStructural = false;\r
301 \r
302         Variable curConfiguration = child.getParent(graph);\r
303 \r
304         {\r
305 \r
306                         Collection<InterfaceResolution> interfaceDescription = Functions.computeInterfacePaths(graph, curConfiguration);\r
307                 if(interfaceDescription != null) {\r
308                         isStructural = interfaceDescription != Functions.BUILTIN_STRUCTURAL_CPS;\r
309                         if(interfaceDescription.size() > 0) {\r
310                                 \r
311                                 if(subPath_ == null) {\r
312                                         \r
313                                         String childName = child.getName(graph);\r
314                                         for(InterfaceResolution r : interfaceDescription) {\r
315                                                 if(r.componentName.equals(childName) && r.connectionPoint.equals(cp)) {\r
316                                                         Variable pConn = curConfiguration.getPossibleProperty(graph, r.interfaceName);\r
317                                                         if(pConn != null) {\r
318                                                                 Resource cp2 = pConn.getPossiblePredicateResource(graph);\r
319                                                                 Collection<VariableConnectionPointDescriptor> res = climb(graph, curConfiguration, cp2, null);\r
320                                                                 if(res != null) return res;\r
321                                                         }\r
322                                                         return Collections.emptyList();\r
323                                                 }\r
324                                         }\r
325 \r
326                                 } else {\r
327                                         throw new UnsupportedOperationException("");\r
328                                 }\r
329                         }\r
330                 }\r
331 \r
332         }\r
333         \r
334         if(child instanceof StandardProceduralChildVariable) {\r
335                 \r
336                 Variable conn = child.getPossibleProperty(graph, cp);\r
337             FixedConnection fc = (FixedConnection)conn.getValue(graph);\r
338             Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(1+fc.cps.size());\r
339             result.add(new ComponentConnectionDescriptor(child, cp));// (graph, STR, curConfiguration, "/" + c.name + "#" + conn.getName(graph)));\r
340             for(Pair<String,Resource> cpzz : fc.cps) {\r
341                 if(cpzz.first == null) {\r
342                         throw new DatabaseException("Lifted connection was not resolved.");\r
343                 }\r
344                 result.add(new PairConnectionDescriptor(curConfiguration, cpzz));\r
345             }\r
346             return result;\r
347             \r
348         } else {\r
349 \r
350             Resource res = cp;\r
351             Resource represents = child.getRepresents(graph);\r
352 \r
353                 if(isStructural) {\r
354 \r
355                         Collection<Resource> conns = graph.getObjects(represents, res);\r
356                         HashSet<VariableConnectionPointDescriptor> result = new HashSet<VariableConnectionPointDescriptor>();\r
357                         for(Resource c : conns) {\r
358                                 List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, c), TransientCacheAsyncListener.<List<Resource>>instance()); \r
359                                 result.addAll(graph.syncRequest(ConnectionVariables.forStructural(graph, curConfiguration, rs)));\r
360                         }\r
361                         return result;\r
362                         \r
363                 } else {\r
364 \r
365                 Resource connection = graph.getPossibleObject(represents, res);\r
366                 if(connection != null) {\r
367                         List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, connection), TransientCacheAsyncListener.<List<Resource>>instance());\r
368                         return graph.syncRequest(ConnectionVariables.forConfiguration(graph, curConfiguration, rs));\r
369                 }\r
370                 else {\r
371                         Collection<Resource> conns = graph.getObjects(represents, res);\r
372                         HashSet<VariableConnectionPointDescriptor> result = new HashSet<VariableConnectionPointDescriptor>();\r
373                         for(Resource c : conns) {\r
374                                 List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, c), TransientCacheAsyncListener.<List<Resource>>instance()); \r
375                                 result.addAll(graph.syncRequest(ConnectionVariables.forConfiguration(graph, curConfiguration, rs)));\r
376                         }\r
377                         return result;\r
378                 }\r
379                         \r
380                 }\r
381                 \r
382         }\r
383         \r
384     }\r
385     \r
386     public static class ConnectionVariables extends BinaryRead<Variable, List<Resource>, Collection<VariableConnectionPointDescriptor>> {\r
387 \r
388         private ConnectionVariables(Variable parameter1, List<Resource> parameter2) {\r
389                         super(parameter1, parameter2);\r
390                 }\r
391 \r
392                 public static ConnectionVariables forConfiguration(ReadGraph graph, Variable configuration, List<Resource> rs) throws DatabaseException {\r
393                         return new ConnectionVariables(parent(graph, configuration, rs.get(0)), rs);\r
394                 }\r
395 \r
396                 public static ConnectionVariables forStructural(ReadGraph graph, Variable configuration, List<Resource> rs) throws DatabaseException {\r
397                         return new ConnectionVariables(configuration, rs);\r
398                 }\r
399 \r
400                 /**\r
401                  * Finds the parent variable of <code>configuration</code> that\r
402                  * represents <code>ancestor</code>.\r
403                  * \r
404                  * @param graph\r
405                  * @param configuration\r
406                  * @param ancestor\r
407                  * @return\r
408                  * @throws DatabaseException if no parent was found that represents ancestor\r
409                  */\r
410                 private static Variable parent(ReadGraph graph, Variable configuration, Resource ancestor) throws DatabaseException {\r
411                 Variable v = configuration;\r
412                 Resource represents = v.getRepresents(graph);\r
413                 while(!represents.equals(ancestor)) {\r
414                         v = v.getParent(graph);\r
415                         if (v == null) {\r
416                                         throw new DatabaseException(\r
417                                                         "parent representing ancestor not found for variable, configuration="\r
418                                                                         + safeURI(graph, configuration)\r
419                                                                         + ", ancestor="\r
420                                                                         + NameUtils.getURIOrSafeNameInternal(graph, ancestor));\r
421                         }\r
422                         represents = v.getRepresents(graph);\r
423                 }\r
424                 return v;\r
425                 }\r
426 \r
427                 @Override\r
428                 public Collection<VariableConnectionPointDescriptor> perform(ReadGraph graph) throws DatabaseException {\r
429                         if(parameter == null) return Collections.emptyList();\r
430                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
431             ArrayList<VariableConnectionPointDescriptor> result = null;\r
432             for(int i=1;i<parameter2.size();i++) {\r
433                 Resource connRes = parameter2.get(i);\r
434                 for(Statement stm : graph.getStatements(connRes, STR.Connects)) {\r
435                         Resource component = stm.getObject();\r
436                         Resource connectionPoint = graph.getInverse(stm.getPredicate());\r
437                         if(result == null) result = new ArrayList<VariableConnectionPointDescriptor>();\r
438                         result.add(new ActualConnectionDescriptor(parameter, component, connectionPoint));\r
439                 }\r
440             }\r
441             if(result == null) return Collections.emptyList();\r
442             return result;\r
443                 }\r
444         \r
445     }\r
446     \r
447     static class IsLeafType extends ResourceRead<Boolean> {\r
448 \r
449                 protected IsLeafType(Resource type) {\r
450                         super(type);\r
451                 }\r
452 \r
453                 @Override\r
454                 public Boolean perform(ReadGraph graph) throws DatabaseException {\r
455                         \r
456                         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
457 \r
458                         if(graph.isInstanceOf(resource, STR.ProceduralComponentType)) return false;\r
459                         if(graph.hasStatement(resource, STR.IsDefinedBy)) return false;\r
460                         \r
461                         return true;\r
462 \r
463                 }\r
464         \r
465     }\r
466     \r
467     static class ChildMapOfVariable extends VariableRead<Map<Resource,Variable>> {\r
468 \r
469                 public ChildMapOfVariable(Variable variable) {\r
470                         super(variable);\r
471                 }\r
472 \r
473                 @Override\r
474                 public Map<Resource, Variable> perform(ReadGraph graph) throws DatabaseException {\r
475                         HashMap<Resource,Variable> result = new HashMap<Resource,Variable>();\r
476                         for(Variable child : variable.getChildren(graph)) {\r
477                                 Resource represents = child.getPossibleRepresents(graph);\r
478                                 if(represents != null) result.put(represents, child);\r
479                         }\r
480                         return result;\r
481                 }\r
482         \r
483     }\r
484 \r
485     /**\r
486      * Given a root composite, related variable and some other component inside the composite,\r
487      * finds the related variable for that component.\r
488      */\r
489     public static Variable browse(ReadGraph graph, Resource root, Variable rootContext, Resource target) throws DatabaseException {\r
490         if(target.equals(root))\r
491             return rootContext;\r
492         else {\r
493             Layer0 L0 = Layer0.getInstance(graph);\r
494             String name = (String)graph.getPossibleRelatedValue(target, L0.HasName, Bindings.STRING);\r
495             Resource parent = graph.getPossibleObject(target, L0.PartOf);\r
496             if(name == null || parent == null)\r
497                 return null;\r
498             Variable parentVariable = browse(graph, root, rootContext, parent);\r
499             if(parentVariable == null)\r
500                 return null;\r
501             return parentVariable.getPossibleChild(graph, name);\r
502         }\r
503     }\r
504 \r
505     /**\r
506      * Finds a variable whose location related to sourceContext is the same as \r
507      * between target and source. In other words, the method solves {@code targetContext}\r
508      * in the following equations:\r
509      * <pre>\r
510      *     URI(source)        = resourceURIBase + sourceSuffix\r
511      *     URI(sourceContext) = variableURIBase + sourceSuffix\r
512      *     URI(target)        = resourceURIBase + targetSuffix\r
513      *     URI(targetContext) = variableURIBase + targetSuffix\r
514      * </pre>\r
515      */\r
516     public static Variable browseSibling(ReadGraph graph, Resource source, Variable sourceContext, Resource target) throws DatabaseException {\r
517         Layer0 L0 = Layer0.getInstance(graph);\r
518         THashMap<Resource, Variable> sourceMap = new THashMap<Resource, Variable>();\r
519         while(source != null && sourceContext != null) {\r
520             sourceMap.put(source, sourceContext);\r
521             source = graph.getPossibleObject(source, L0.PartOf);\r
522             sourceContext = sourceContext.getParent(graph);\r
523         }\r
524         return browseSibling(graph, sourceMap, target);\r
525     }\r
526 \r
527     private static Variable browseSibling(ReadGraph graph, THashMap<Resource, Variable> sourceMap, Resource target) throws DatabaseException {\r
528         Layer0 L0 = Layer0.getInstance(graph);\r
529         Variable result = sourceMap.get(target);\r
530         if(result != null)\r
531             return result;\r
532         String name = (String)graph.getPossibleRelatedValue(target, L0.HasName, Bindings.STRING);\r
533         Resource parent = graph.getPossibleObject(target, L0.PartOf);\r
534         if(name == null || parent == null)\r
535             return null;\r
536         Variable parentVariable = browseSibling(graph, sourceMap, parent);\r
537         if(parentVariable == null)\r
538             return null;\r
539         return parentVariable.getPossibleChild(graph, name);\r
540     }\r
541 \r
542     /**\r
543      * Returns the composite where the connection given as a parameter resides.\r
544      */\r
545     public static Resource getCompositeOfConnection(ReadGraph graph, Resource connection) throws DatabaseException {\r
546         Layer0 L0 = Layer0.getInstance(graph);\r
547         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
548         // First from connected components\r
549         for(Resource component : graph.getObjects(connection, STR.Connects))\r
550             for(Resource composite : graph.getObjects(component, L0.PartOf))\r
551                 return composite;\r
552         // It could be that the connection is only supported by joins (input flag -> output flag) - use diagram info TODO!!\r
553         Resource connToDiagramConn = graph.getPossibleResource("http://www.simantics.org/Modeling-1.2/ConnectionToDiagramConnection");\r
554         if(connToDiagramConn != null) {\r
555             Resource diagramConnection = graph.getPossibleObject(connection, connToDiagramConn);\r
556             if(diagramConnection != null) {\r
557                 Resource diagram = graph.getPossibleObject(diagramConnection, L0.PartOf);\r
558                 if(diagram != null) {\r
559                     Resource diagramToComposite = graph.getPossibleResource("http://www.simantics.org/Modeling-1.2/DiagramToComposite");\r
560                     if(diagramToComposite != null) {\r
561                         return graph.getPossibleObject(diagram, diagramToComposite);\r
562                     }\r
563                 }\r
564             }\r
565         }\r
566         return null;\r
567     }\r
568     \r
569         static class Flatten extends BinaryRead<Variable,Resource,Collection<VariableConnectionPointDescriptor>> {\r
570 \r
571                 public Flatten(Variable parameter1,\r
572                                 Resource parameter2) {\r
573                         super(parameter1, parameter2);\r
574                 }\r
575 \r
576                 @Override\r
577                 public Collection<VariableConnectionPointDescriptor> perform(ReadGraph graph)\r
578                                 throws DatabaseException {\r
579                         return doFlatten(graph, parameter, parameter2, null);\r
580                 }\r
581                 \r
582         }\r
583     \r
584     public static Collection<VariableConnectionPointDescriptor> flatten(ReadGraph graph, Variable child, Resource cp, Resource relationType) throws DatabaseException {\r
585 \r
586         if(relationType == null) return graph.syncRequest(new Flatten(child, cp));\r
587 \r
588         return doFlatten(graph, child, cp, relationType);\r
589 \r
590     }\r
591 \r
592         public static Collection<VariableConnectionPointDescriptor> doFlatten(ReadGraph graph, Variable child, Resource cp, Resource relationType) throws DatabaseException {\r
593         \r
594         Collection<VariableConnectionPointDescriptor> climbed = climb(graph, child, cp, null);\r
595         boolean needDrill = false;\r
596         for(VariableConnectionPointDescriptor desc : climbed) {\r
597                 if(!desc.isLeaf(graph)) {\r
598                         needDrill = true;\r
599                         break;\r
600                 }\r
601         }\r
602         \r
603         if(!needDrill) {\r
604             if(relationType != null) {\r
605                 ArrayList<VariableConnectionPointDescriptor> filtered = new ArrayList<VariableConnectionPointDescriptor>(climbed.size());\r
606                 for(VariableConnectionPointDescriptor desc : climbed)\r
607                     if(filterByRelationType(graph, desc, relationType))\r
608                         filtered.add(desc);\r
609                 return filtered;\r
610             }\r
611             return climbed;\r
612         }\r
613         \r
614         THashSet<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(climbed.size());\r
615         for(VariableConnectionPointDescriptor top : climbed) {\r
616                 Collection<VariableConnectionPointDescriptor> drilled = drill(graph, top);\r
617             if(drilled != null) {\r
618                 for(VariableConnectionPointDescriptor drill : drilled) {\r
619                         if(relationType != null) {\r
620                                 if(!filterByRelationType(graph, drill, relationType))\r
621                                         continue;\r
622                         }\r
623                         result.add(drill);\r
624                 }\r
625             }\r
626         }\r
627         return result;\r
628         \r
629     }\r
630     \r
631     private static boolean filterByRelationType(ReadGraph graph, VariableConnectionPointDescriptor desc, Resource relationType) throws DatabaseException {\r
632         Resource predicateResource = desc.getConnectionPointResource(graph);\r
633         return predicateResource != null && graph.isInstanceOf(predicateResource, relationType);\r
634     }\r
635 \r
636     private static String safeURI(ReadGraph graph, Variable v) {\r
637         if (v == null)\r
638             return "null variable";\r
639         try {\r
640             return v.getURI(graph);\r
641         } catch (DatabaseException e) {\r
642             return v.toString();\r
643         }\r
644     }\r
645 }\r