]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / Functions.java
diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java
new file mode 100644 (file)
index 0000000..70b9ab0
--- /dev/null
@@ -0,0 +1,847 @@
+package org.simantics.structural2;\r
+\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.error.DatatypeConstructionException;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.util.URIStringUtils;\r
+import org.simantics.db.Issue;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.issue.StandardIssue;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.request.ResourceRead;\r
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.function.All;\r
+import org.simantics.db.layer0.function.StandardChildDomainChildren;\r
+import org.simantics.db.layer0.request.PossibleModel;\r
+import org.simantics.db.layer0.request.PropertyInfo;\r
+import org.simantics.db.layer0.request.PropertyInfoRequest;\r
+import org.simantics.db.layer0.request.VariableRead;\r
+import org.simantics.db.layer0.variable.AbstractChildVariable;\r
+import org.simantics.db.layer0.variable.AbstractPropertyVariable;\r
+import org.simantics.db.layer0.variable.LazyPropertyVariable;\r
+import org.simantics.db.layer0.variable.NodeSupport;\r
+import org.simantics.db.layer0.variable.StandardGraphChildVariable;\r
+import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;\r
+import org.simantics.db.layer0.variable.ValueAccessor;\r
+import org.simantics.db.layer0.variable.ValueAccessorWithBinding;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.VariableMap;\r
+import org.simantics.db.layer0.variable.VariableMapImpl;\r
+import org.simantics.db.layer0.variable.VariableNode;\r
+import org.simantics.issues.common.IssueUtils;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.reflection.annotations.SCLValue;\r
+import org.simantics.scl.runtime.SCLContext;\r
+import org.simantics.scl.runtime.function.Function1;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.simulator.variable.NodeManager;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.structural2.procedural.Component;\r
+import org.simantics.structural2.procedural.ConnectionPoint;\r
+import org.simantics.structural2.procedural.Interface;\r
+import org.simantics.structural2.procedural.SubstructureElement;\r
+import org.simantics.structural2.procedural.Terminal;\r
+import org.simantics.structural2.queries.ConnectionComponents;\r
+import org.simantics.structural2.queries.ConnectionJoinComponents;\r
+import org.simantics.structural2.queries.ConnectionPointMapOfResource;\r
+import org.simantics.structural2.queries.PossibleConnectionPointInfo;\r
+import org.simantics.structural2.scl.CompileStructuralValueRequest;\r
+import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;\r
+import org.simantics.structural2.variables.Connection;\r
+import org.simantics.structural2.variables.ConnectionBrowser;\r
+import org.simantics.structural2.variables.StandardProceduralChildVariable;\r
+import org.simantics.structural2.variables.VariableConnectionPointDescriptor;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+public class Functions {\r
+       \r
+       @SCLValue(type="ValueAccessor")\r
+       public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {\r
+\r
+               public Binding getBinding() {\r
+                       return Bindings.STRING;\r
+               }\r
+               \r
+               @Override\r
+               public void setValue(WriteGraph graph, Variable context, Object value)\r
+                               throws DatabaseException {\r
+                       if(value == null) {\r
+                               if(getValue(graph, context) != null)\r
+                                       clearExpression(graph, context);\r
+                               return;\r
+                       }\r
+                       \r
+                       // Get all necessary data\r
+                       String expression = (String)value;\r
+                       Variable parent = context.getParent(graph);\r
+                       if(!(parent instanceof AbstractPropertyVariable)) return;\r
+                       AbstractPropertyVariable property = (AbstractPropertyVariable)parent;                   \r
+                       Resource propertyResource = property.getRepresents(graph);\r
+                       if(propertyResource == null) return;\r
+                       Resource container = property.getContainerResource(graph);\r
+                       if(container == null) return;\r
+                       Resource predicate = property.getPossiblePredicateResource(graph);\r
+                       if(predicate == null) return;                   \r
+                       Statement stat = graph.getPossibleStatement(container, predicate);                      \r
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+                       \r
+                       // Write                        \r
+                       boolean createNew = false;\r
+                       if(stat.isAsserted(container))\r
+                               createNew = true;\r
+                       else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {\r
+                               graph.deny(propertyResource);\r
+                               createNew = true;\r
+                       }\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+                       if(createNew) {\r
+                               propertyResource = graph.newResource();\r
+                               graph.claim(container, predicate, propertyResource);\r
+                               graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);                             \r
+                       }\r
+                       graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);\r
+               }\r
+\r
+               private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {\r
+                       Variable parent = context.getParent(graph);\r
+                       if(!(parent instanceof AbstractPropertyVariable)) return;\r
+                       AbstractPropertyVariable property = (AbstractPropertyVariable)parent;\r
+                       Resource container = property.getContainerResource(graph);\r
+                       if(container == null) return;\r
+                       Resource predicate = property.getPossiblePredicateResource(graph);\r
+                       if(predicate == null) return;                   \r
+                       graph.deny(container, predicate);               \r
+               }\r
+\r
+               @Override\r
+               public Object getValue(ReadGraph graph, Variable context)\r
+                               throws DatabaseException {\r
+                       Variable parent = context.getParent(graph);\r
+                       if(!(parent instanceof AbstractPropertyVariable))\r
+                               return null;\r
+                       AbstractPropertyVariable property = (AbstractPropertyVariable)parent;\r
+                       Resource propertyResource = property.getPossibleRepresents(graph);\r
+                       if(propertyResource == null) return null;\r
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+                       if(!graph.isInstanceOf(propertyResource, STR.SCLValue))\r
+                               return null;\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+                       return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);\r
+               }\r
+               \r
+       };\r
+       \r
+       static class ConnectionImpl implements Connection {\r
+\r
+               final private StandardGraphPropertyVariable connectionPoint;\r
+               \r
+               public ConnectionImpl(StandardGraphPropertyVariable connectionPoint) {\r
+                       this.connectionPoint = connectionPoint;\r
+               }\r
+               \r
+               @Override\r
+               public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+                   Set<Variable> result = new THashSet<Variable>();\r
+                   for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {\r
+                       result.add(desc.getVariable(graph));\r
+                   }\r
+                   return result;\r
+               }\r
+               \r
+               @Override\r
+               public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+                   Set<String> result = new THashSet<String>();\r
+                   for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {\r
+                       result.add(desc.getURI(graph));\r
+                   }\r
+                   return result;\r
+               }\r
+\r
+               @Override\r
+               public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {\r
+                   return ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType);\r
+               }\r
+\r
+       }\r
+       \r
+       @SCLValue(type="ValueAccessor")\r
+       public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {\r
+\r
+               @Override\r
+               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {\r
+                       throw new UnsupportedOperationException();\r
+               }\r
+               \r
+               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {\r
+                       throw new UnsupportedOperationException();\r
+               }\r
+\r
+               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {\r
+            try {\r
+               Object value = getValue(graph, context);\r
+               Binding srcBinding = Bindings.OBJECT.getContentBinding(value);\r
+                               return Bindings.adapt(value, srcBinding, binding);\r
+                       } catch (AdaptException e) {\r
+                               throw new DatabaseException(e);\r
+                       } catch (BindingException e) {\r
+                               throw new DatabaseException(e);\r
+                       }\r
+               }\r
+\r
+               @Override\r
+               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {\r
+                       StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; \r
+                       return new ConnectionImpl(variable);\r
+               }\r
+\r
+               @Override\r
+               public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {\r
+                       try {\r
+                               return Datatypes.getDatatype(Connection.class);\r
+                       } catch (DatatypeConstructionException e) {\r
+                               throw new DatabaseException(e);\r
+                       }\r
+               }\r
+               \r
+       };      \r
+\r
+\r
+       @SCLValue(type = "VariableMap")\r
+       public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {\r
+       \r
+               public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {\r
+\r
+                       Map<String, Resource> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
+                       Resource cp = connectionPoints.get(name);\r
+                       if(cp == null) return null;\r
+                       else return new StandardGraphPropertyVariable(graph, variable, cp);\r
+                       \r
+               }\r
+               \r
+               public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {\r
+                       \r
+                       if(graph.isImmutable(context)) {\r
+\r
+                               Map<String, Resource> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
+                               if(cps.size() == 0) return map;\r
+                               \r
+                               if(map == null) map = new THashMap<String,Variable>(cps.size());\r
+                               \r
+                               for(Map.Entry<String, Resource> entry : cps.entrySet()) {\r
+                                       String name = entry.getKey();\r
+                                       Resource cp = entry.getValue();\r
+                                       if(needSynchronized && !graph.isInstanceOf(cp, STR.SynchronizedConnectionRelation)) continue;\r
+                                       map.put(name, new StandardGraphPropertyVariable(graph, variable, cp));\r
+                               }\r
+                               \r
+                               return map;\r
+\r
+                       } else {\r
+                               \r
+                               Collection<Resource> predicates = graph.getPredicates(context);\r
+                               \r
+                               for(Resource predicate : predicates) {\r
+                                       \r
+                                       PropertyInfo info = graph.isImmutable(predicate) ?\r
+                                                       graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :\r
+                                                               graph.syncRequest(new PossibleConnectionPointInfo(predicate));\r
+                                                       \r
+                                       if(info != null) {\r
+                                               if(map == null) map = new THashMap<String,Variable>(4);\r
+                                               if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;\r
+                                               map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));\r
+                                       }\r
+                                       \r
+                               }\r
+\r
+                               return map;\r
+\r
+                       }\r
+                       \r
+               }\r
+\r
+               @Override\r
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+               final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+               Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);\r
+               if(cp != null) return cp;\r
+            return All.getStandardChildDomainPropertyVariable(graph, context, name);\r
+               }\r
+\r
+               @Override\r
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+               StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+               StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+               map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);\r
+            return All.getStandardChildDomainPropertyVariables(graph, context, map);\r
+               }\r
+               \r
+               public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {\r
+                       if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {\r
+                               return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);\r
+                       } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {\r
+                       StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+                       return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);\r
+                       } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {\r
+                       StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+                       return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);\r
+                       }\r
+                       return super.getVariables(graph, context, classification, map);\r
+               }\r
+               \r
+       };\r
+\r
+       static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {\r
+\r
+               public StructuralChildMapOfResource(Resource resource) {\r
+                       super(resource);\r
+               }\r
+\r
+               @Override\r
+               public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+                       Resource type = graph.getPossibleType(resource, STR.Component);\r
+                       if(type != null) {\r
+                               Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);\r
+                               if(definition != null) {\r
+                                       Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));\r
+                                       if (!map.isEmpty())\r
+                                               return map;\r
+                               } \r
+                       }\r
+                       Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));\r
+                       return directChildren;\r
+               }\r
+\r
+       }\r
+\r
+    static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {\r
+\r
+        public StructuralChildMapOfResourceT(Resource resource) {\r
+            super(resource);\r
+        }\r
+\r
+        @Override\r
+        public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
+            StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+            Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);\r
+            if(definition != null) {\r
+                Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));\r
+                if (!map.isEmpty())\r
+                    return map;\r
+            } \r
+            return Collections.emptyMap();\r
+        }\r
+\r
+    }\r
+\r
+       static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {\r
+\r
+               public StructuralRunChildMapOfResource(Resource resource) {\r
+                       super(resource);\r
+               }\r
+\r
+               public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {\r
+                       return graph.sync(new StructuralChildMapOfResource(context));\r
+               }\r
+               \r
+               @Override\r
+               public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
+\r
+                       Layer0 L0 = Layer0.getInstance(graph);\r
+                       SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+                       Resource model = graph.sync(new PossibleModel(resource));\r
+                       if(graph.isInstanceOf(model, L0.RVIContext)) {\r
+                               return fromContext(graph, model);\r
+                       }\r
+                       Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);\r
+                       if(configuration != null) {\r
+                               if(graph.isInstanceOf(configuration, L0.RVIContext)) {\r
+                                       return fromContext(graph, configuration);\r
+                               }\r
+                       }\r
+                       \r
+                       return Collections.emptyMap();\r
+                       \r
+               }\r
+               \r
+       }\r
+       \r
+       private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {\r
+           public SubstructureRequest(Variable context) {\r
+            super(context);\r
+        }\r
+\r
+        @Override\r
+        public List<SubstructureElement> perform(ReadGraph graph) {\r
+            try {\r
+                Resource type = variable.getPossibleType(graph);\r
+                if(type == null)\r
+                    return null;\r
+                return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);\r
+            } catch (Throwable t) {\r
+                t.printStackTrace();\r
+                return null;\r
+            }\r
+        }\r
+       }\r
+\r
+    public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {\r
+        StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+        final Resource type = context.getPossibleType(graph);\r
+        if(type != null) {\r
+            if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
+                return graph.syncRequest(new SubstructureRequest(context));\r
+            }\r
+        }\r
+        return null;\r
+    }  \r
+       \r
+        public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {\r
+            \r
+         if(map == null) map = new THashMap<String,Variable>();\r
+         \r
+         MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();\r
+         for(SubstructureElement sub : elements) {\r
+             if(sub instanceof org.simantics.structural2.procedural.Connection) {\r
+                 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;\r
+                 for(ConnectionPoint cp : conn.connectionPoints) {\r
+                     if(cp instanceof Terminal) {\r
+                         Terminal t = (Terminal)cp;\r
+                         conns.add(t.component, conn);\r
+                     }\r
+                 }\r
+             }\r
+         }\r
+         \r
+         Map<String,Component> proceduralChildren = new THashMap<String, Component>();\r
+         for(SubstructureElement sub : elements) {\r
+             if(sub instanceof Component) {\r
+                 Component comp = (Component)sub;\r
+                 proceduralChildren.put(comp.name, comp);\r
+             }\r
+         }\r
+         \r
+         Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);\r
+         Set<String> used = new HashSet<String>(nodeChildren.size());\r
+         for(Object nodeChild : nodeChildren) {\r
+             @SuppressWarnings("rawtypes")\r
+             NodeSupport support = ((AbstractChildVariable)context).node.support;\r
+             @SuppressWarnings("rawtypes")\r
+             NodeManager manager = support.manager;\r
+             @SuppressWarnings("unchecked")\r
+             String name = manager.getName(nodeChild);\r
+             used.add(name);\r
+             Component proceduralChild = proceduralChildren.get(name); \r
+             if(proceduralChild != null) {\r
+                 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));\r
+             }\r
+         }\r
+         \r
+         for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {\r
+             String name = entry.getKey();\r
+             if(used.contains(name)) continue;\r
+             Component proceduralChild = entry.getValue();\r
+             map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));\r
+         }\r
+         \r
+         return map;\r
+            \r
+     } \r
+        \r
+        private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {\r
+\r
+            public ProceduralSubstructureRequest(Variable variable) {\r
+                super(variable);\r
+            }\r
+\r
+            @Override\r
+            public Map<String, Variable> perform(ReadGraph graph)\r
+                    throws DatabaseException {\r
+                List<SubstructureElement> elements = getProceduralDesc(graph, variable);\r
+                if(elements != null)\r
+                    return getProcedural(graph, variable, elements, null);\r
+                else\r
+                    return null;\r
+            }\r
+        }\r
+        \r
+       \r
+       @SCLValue(type = "VariableMap")\r
+       public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {\r
+       \r
+               @Override\r
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+                       \r
+               final Resource type = context.getPossibleType(graph);\r
+               if(type != null) {\r
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+                   if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
+                           Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),\r
+                               TransientCacheListener.<Map<String,Variable>>instance());\r
+                           if(map != null) return map.get(name);\r
+                   }\r
+               }\r
+\r
+                   Resource represents = context.getPossibleRepresents(graph);\r
+            if(represents == null) {\r
+                Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));\r
+                Resource child = children.get(name);\r
+                return All.getStandardChildDomainChildVariable(graph, context, child, name);\r
+            }\r
+            Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));\r
+            Resource child = children.get(name);\r
+            return All.getStandardChildDomainChildVariable(graph, context, child, name);\r
+               }\r
+\r
+               @Override\r
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+                       \r
+               final Resource type = context.getPossibleType(graph);\r
+               if(type != null) {\r
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+                   if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
+                       Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),\r
+                                       TransientCacheListener.<Map<String,Variable>>instance());\r
+                       if(mapPrime != null) {\r
+                               if(map != null) {\r
+                                       map.putAll(mapPrime);\r
+                                       return map;\r
+                               }\r
+                               else\r
+                                       return mapPrime;\r
+                       }\r
+                   }\r
+               }\r
+            Resource represents = context.getPossibleRepresents(graph);\r
+            if(represents == null) {\r
+                Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));\r
+                return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
+            }\r
+            Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));\r
+            return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
+               }\r
+               \r
+       };\r
+       \r
+       @SCLValue(type = "VariableMap")\r
+       public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {\r
+       \r
+               @Override\r
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+                   Map<String, Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(context.getRepresents(graph)));\r
+                       Resource child = children.get(name);\r
+            return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);\r
+               }\r
+\r
+               @Override\r
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+            StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+            Map<String,Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(variable.resource));\r
+                   return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);\r
+               }\r
+               \r
+       };\r
+\r
+       @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")\r
+    public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {\r
+\r
+       StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+       HashSet<Resource> extension = new HashSet<Resource>(8);\r
+       for(Resource r : rs) {\r
+               if(graph.isInstanceOf(r, STR.Connection)) {\r
+                       extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));\r
+               }\r
+               if(graph.isInstanceOf(r, STR.ConnectionJoin)) {\r
+                       extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));\r
+               }\r
+       }\r
+\r
+       HashSet<Resource> components = new HashSet<Resource>(8);\r
+       for(Resource r : extension) {\r
+               components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));\r
+       }\r
+       \r
+       if(!extension.isEmpty()) {\r
+               ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());\r
+               result.addAll(rs);\r
+               result.addAll(extension);\r
+               result.addAll(components);\r
+               rs = result;\r
+       }\r
+       \r
+       return rs;\r
+       \r
+    }\r
+\r
+       @SCLValue(type = "ReadGraph -> Resource -> [Issue]")\r
+    public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {\r
+        \r
+               if(!graph.hasStatement(component)) return Collections.emptyList();\r
+\r
+               ArrayList<Issue> result = new ArrayList<Issue>();\r
+               \r
+               Layer0 L0 = Layer0.getInstance(graph);\r
+               StructuralResource2 sr = StructuralResource2.getInstance(graph);\r
+\r
+               Resource type = graph.getSingleType(component, sr.Component);\r
+               \r
+               Set<Resource> requiredConnections = new HashSet<Resource>();\r
+               for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {\r
+                       Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);\r
+                       if(required != null && required)\r
+                               requiredConnections.add(connectionRelation);\r
+               }\r
+               \r
+               Set<Resource> connections = new HashSet<Resource>();\r
+\r
+               for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {\r
+                       connections.add(stm.getPredicate());\r
+                       connections.addAll(graph.getSuperrelations(stm.getPredicate()));\r
+               }\r
+\r
+               for(Resource req : requiredConnections) {\r
+                       if(!connections.contains(req)) {\r
+                               result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));\r
+                       }\r
+               }\r
+\r
+               return result;\r
+        \r
+    }\r
+\r
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+    public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {\r
+       List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
+       String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);\r
+       return "'" + attributeName + "' should be connected.";\r
+    }\r
+\r
+    public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {\r
+\r
+               public InterfacePathMap(Variable context) {\r
+                       super(context);\r
+               }\r
+\r
+               @Override\r
+               public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {\r
+\r
+                       return new GraphMap<Map<String,InterfaceResolution>>() {\r
+\r
+                               @Override\r
+                               Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {\r
+                                       \r
+                                       Variable child = variable.getChild(graph, key);\r
+                                       \r
+                                       Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();\r
+                                       Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");\r
+                                       if(paths != null) {\r
+                                               for(InterfaceResolution r : paths) {\r
+                                                       childMap.put(r.interfaceName, r);\r
+                                               }\r
+                                       }\r
+                                       return childMap;\r
+\r
+                               }\r
+                               \r
+                       };\r
+                       \r
+               }\r
+       \r
+    }\r
+    \r
+    public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {\r
+       \r
+       GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());\r
+       Map<String,InterfaceResolution> childMap = map.get(graph, component);\r
+       if(childMap == null) return "";\r
+\r
+        PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());\r
+\r
+        InterfaceResolution match = childMap.get(info.name);\r
+       if(match != null) {\r
+               String comp = URIStringUtils.escape(component);\r
+               Variable newContext = context.getChild(graph, component);\r
+               return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);\r
+       } else {\r
+               return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name); \r
+       }\r
+               \r
+    }\r
+    \r
+    public static class InterfaceResolution {\r
+       \r
+       public Resource interfaceConnectionPoint;\r
+       public String interfaceName;\r
+       public String componentName;\r
+       public Resource connectionPoint;\r
+       \r
+       public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {\r
+               this.interfaceConnectionPoint = interfaceConnectionPoint;\r
+               this.interfaceName = interfaceName;\r
+               this.componentName = componentName;\r
+               this.connectionPoint = connectionPoint;\r
+       }\r
+       \r
+    }\r
+    \r
+    public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {\r
+\r
+               StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+               Resource type = variable.getPossibleType(graph);\r
+               if(type != null) {\r
+                       if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {\r
+                               ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();\r
+                               List<SubstructureElement> elements = getProceduralDesc(graph, variable); \r
+                               if(elements != null) {\r
+                                       for(SubstructureElement e : elements) {\r
+                                               if(e instanceof org.simantics.structural2.procedural.Connection) {\r
+                                                       org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;\r
+                                                       Interface inf = null;\r
+                                                       for(ConnectionPoint cp : conn.connectionPoints) {\r
+                                                               if(cp instanceof Interface) {\r
+                                                                       if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");\r
+                                                                       inf = (Interface)cp;\r
+                                                               }\r
+                                                       }\r
+                                                       if(inf != null && conn.connectionPoints.size() > 1) {\r
+                                                               Layer0 L0 = Layer0.getInstance(graph);\r
+                                                               String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );\r
+                                                               for(ConnectionPoint cp : conn.connectionPoints) {\r
+                                                                       if(cp == inf) continue;\r
+                                                                       Terminal t = (Terminal)cp;\r
+                                                                       result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               return result;\r
+                               \r
+                       }\r
+\r
+                       final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));\r
+                       if(interfaces != null) return interfaces;\r
+\r
+               }\r
+               \r
+               return BUILTIN_STRUCTURAL_CPS;\r
+       \r
+    }\r
+    \r
+    static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {\r
+\r
+               public InterfacePathRequest(Variable variable) {\r
+                       super(variable);\r
+               }\r
+               \r
+               @Override\r
+               public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {\r
+                       return computeInterfacePaths(graph, variable);\r
+               }\r
+       \r
+    }\r
+    \r
+    static class DefinedUCInterfaceMap extends ResourceRead<Collection<InterfaceResolution>> {\r
+\r
+       public DefinedUCInterfaceMap(Resource resource) {\r
+               super(resource);\r
+       }\r
+\r
+       @Override\r
+       public Collection<InterfaceResolution> perform(ReadGraph graph)\r
+                       throws DatabaseException {\r
+\r
+               StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+               Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);\r
+               if(definition != null) {\r
+                       Collection<InterfaceResolution> result = new ArrayList<InterfaceResolution>();\r
+                       Layer0 L0 = Layer0.getInstance(graph);\r
+                       for(Resource cp : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, STR.ConnectionRelation))) {\r
+                                       String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);\r
+                               for(Resource conn : graph.getObjects(cp, STR.IsBoundBy)) {\r
+                                       Statement stm = graph.getPossibleStatement(conn, STR.Connects);\r
+                                       if(stm == null) continue;\r
+                                       Resource component = stm.getObject();\r
+                                       String componentName = graph.getRelatedValue(component, L0.HasName, Bindings.STRING);\r
+                                       result.add(new InterfaceResolution(cp, cpName, componentName, graph.getInverse(stm.getPredicate())));\r
+                               }\r
+                       }\r
+                       return result;\r
+               }\r
+               return null;\r
+       }\r
+\r
+    }\r
+    \r
+    public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();\r
+\r
+       @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
+    public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
+        return CompileStructuralValueRequest.compileAndEvaluate(graph, context);\r
+    }\r
+\r
+    public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {\r
+        SCLContext sclContext = SCLContext.getCurrent();\r
+        Object oldGraph = sclContext.get("graph");\r
+        try {\r
+            Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {\r
+                protected String getExpressionText(ReadGraph graph) throws DatabaseException {\r
+                    return expression;\r
+                }\r
+            },\r
+            TransientCacheListener.<Function1<Variable,Object>>instance());\r
+            sclContext.put("graph", graph);\r
+            return exp.apply(context);\r
+        } catch (DatabaseException e) {\r
+            throw (DatabaseException)e;\r
+        } catch (Throwable t) {\r
+            throw new DatabaseException(t);\r
+        } finally {\r
+            sclContext.put("graph", oldGraph);\r
+        }\r
+    }    \r
+       \r
+       static abstract class InterfacePathProperty extends LazyPropertyVariable {\r
+               \r
+               public InterfacePathProperty(Variable parent) {\r
+                       super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);\r
+               }\r
+               \r
+               @Override\r
+               public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {\r
+                       return getValue(graph);\r
+               }\r
+               \r
+       }\r
+       \r
+       static abstract class GraphMap<Value> {\r
+               \r
+               abstract Value get(ReadGraph graph, String key) throws DatabaseException;\r
+               \r
+       }\r
+    \r
+}\r