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