]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
foobaz
authorAntti Villberg <antti.villberg@semantum.fi>
Wed, 31 Oct 2018 05:02:45 +0000 (07:02 +0200)
committerAntti Villberg <antti.villberg@semantum.fi>
Wed, 31 Oct 2018 05:02:45 +0000 (07:02 +0200)
Change-Id: I20803c442f025337535530211d638c75df5ccdb2

31 files changed:
1  2 
bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java
bundles/org.simantics.db.layer0/adapters.xml
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/CompileResourceValueRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/CompileValueRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyChildVariable.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariable.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariables.java
bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/VariableDebugger.java
bundles/org.simantics.document.base.ontology/graph/Components.pgraph
bundles/org.simantics.document.base.ontology/graph/Documentation.pgraph
bundles/org.simantics.document.base.ontology/graph/Properties.pgraph
bundles/org.simantics.document.server/adapters.xml
bundles/org.simantics.document.server/scl/Document/All.scl
bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java
bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java
bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodeRequest.java
bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java
bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java
bundles/org.simantics.layer0/graph/Layer0SCL.pgraph
bundles/org.simantics.layer0/graph/Layer0Values.pgraph
bundles/org.simantics.modeling/adapters.xml
bundles/org.simantics.structural2/src/org/simantics/structural2/ConnectionImpl2.java
bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java
bundles/org.simantics.structural2/src/org/simantics/structural2/procedural/Terminal.java
bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/Connection.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/ConnectionBrowser.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/StandardProceduralChildVariable.java

index 02877596b00d4423fac8387a31bdc73cdde76e87,02877596b00d4423fac8387a31bdc73cdde76e87..7daf9a5c36eaf6dac0882fe9a941054827044d0d
@@@ -1,13 -1,13 +1,13 @@@
  package org.simantics.db.common.request;
  
++import org.simantics.db.ComputationalValue;
++import org.simantics.db.ConverterComputationalValue;
  import org.simantics.db.ReadGraph;
  import org.simantics.db.Resource;
  import org.simantics.db.common.utils.Functions;
  import org.simantics.db.exception.DatabaseException;
  import org.simantics.db.exception.RuntimeDatabaseException;
  import org.simantics.layer0.Layer0;
--import org.simantics.scl.reflection.ReflectionUtils;
--import org.simantics.scl.reflection.ValueNotFoundException;
  import org.simantics.scl.runtime.function.FunctionImpl3;
  
  /**
@@@ -20,7 -20,7 +20,7 @@@ public class AdaptValue extends Resourc
          super(resource);
      }
  
--    private static final FunctionImpl3<ReadGraph,Resource,Object,Object> functionApplication = new FunctionImpl3<ReadGraph,Resource,Object,Object>() {
++    public static final FunctionImpl3 functionApplication = new FunctionImpl3<ReadGraph,Resource,Object,Object>() {
  
                @Override
                public Object apply(ReadGraph graph, Resource resource, Object context) {
      @Override
      public Object perform(ReadGraph graph) throws DatabaseException {
          String uri = graph.getURI(resource);        
--        try {
--                      if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication;
--            return ReflectionUtils.getValue(uri).getValue();
--        } catch (ValueNotFoundException e) {
--            throw new DatabaseException("Couldn't adapt the value " + uri, e);
--        }
++        if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication;
++        ComputationalValue ev = graph.adapt(resource, ComputationalValue.class);
++        return ev.getValue(graph, resource);
++
      }
  
  }
index 3feb22e00ebda688379b6ed7c8785b09fb8035ca,3feb22e00ebda688379b6ed7c8785b09fb8035ca..61a312e9e185f6c3429d13cc5c65f0e7dca9b667
@@@ -45,6 -45,6 +45,7 @@@ import org.simantics.databoard.type.Dat
  import org.simantics.databoard.util.binary.BinaryFile;
  import org.simantics.databoard.util.binary.RandomAccessBinary;
  import org.simantics.db.AsyncReadGraph;
++import org.simantics.db.ComputationalValue;
  import org.simantics.db.DevelopmentKeys;
  import org.simantics.db.ExternalValueSupport;
  import org.simantics.db.ReadGraph;
@@@ -181,7 -181,7 +182,6 @@@ import org.simantics.layer0.Layer0
  import org.simantics.scl.compiler.types.Type;
  import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException;
  import org.simantics.scl.reflection.ReflectionUtils;
--import org.simantics.scl.reflection.ValueNotFoundException;
  import org.simantics.scl.runtime.function.Function3;
  import org.simantics.utils.DataContainer;
  import org.simantics.utils.Development;
@@@ -6102,13 -6102,13 +6102,22 @@@ public class ReadGraphImpl implements A
                        return getValue(r, binding);
                }
        } else if(types.contains(L0.ExternalValue)) {
--              try {
--                      return (T)ReflectionUtils.getValue(getURI(r)).getValue();
--              } catch(ValueNotFoundException e) {
--                      throw new DatabaseException(e);
--              } catch(ClassCastException e) {
--                      throw new DatabaseException(e);
--              }
++            try {
++                ComputationalValue cv = adapt(r, ComputationalValue.class);
++                return cv.getValue(this, r);
++                //return (T)ReflectionUtils.getValue(getURI(r)).getValue();
++//          } catch(ValueNotFoundException e) {
++//              throw new DatabaseException(e);
++            } catch(ClassCastException e) {
++                throw new DatabaseException(e);
++            }
++//                    try {
++//                            return (T)ReflectionUtils.getValue(getURI(r)).getValue();
++//                    } catch(ValueNotFoundException e) {
++//                            throw new DatabaseException(e);
++//                    } catch(ClassCastException e) {
++//                            throw new DatabaseException(e);
++//                    }
        }
        else {
            Function3<ReadGraph,Resource,Object,T> function = requestValueFunction(r);
index 9e85e9a1bc15ab584f3522933b012ae60c468be2,9e85e9a1bc15ab584f3522933b012ae60c468be2..c2071e5c5400a00bb5b17c7367bae616dc4303d8
                </resource>
        </target>
        
++    <target interface="org.simantics.db.ComputationalValue">
++        <!-- TODO: should be ExternalValue but handle all values to minimise regressions for the time being  -->
++        <type uri="http://www.simantics.org/Layer0-0.0/Value"
++            class="org.simantics.db.layer0.adapter.ReflectionComputationalValue">
++        </type>
++        <resource uri="http://www.simantics.org/Layer0-0.0/Functions/sclValue"
++            class="org.simantics.db.layer0.adapter.SCLComputationalValue">
++        </resource>
++    </target>
++      
  </adapters>
index f93023b77ccd36a6db7d44af8d9981f4a47fc983,f93023b77ccd36a6db7d44af8d9981f4a47fc983..6f6f9b3b826512b0d1b89bdf8a94a0a740e7801e
@@@ -1186,16 -1186,16 +1186,16 @@@ public class All 
        return Functions.exec(graph, resource, graph, resource, context);
      }
  
--    @SCLValue(type = "ReadGraph -> Resource -> a -> b")
--    public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
--      if(context instanceof Variable) {
--            return CompileValueRequest.compileAndEvaluate(graph, (Variable)context);
--      } if (context instanceof Resource) {
--            return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter);
--      } else {
--              throw new IllegalStateException("Unknown context " + context);
--      }
--    }
++//    @SCLValue(type = "ReadGraph -> Resource -> a -> b")
++//    public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
++//            if(context instanceof Variable) {
++//            return CompileValueRequest.compileAndEvaluate(graph, (Variable)context);
++//            } if (context instanceof Resource) {
++//            return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter);
++//            } else {
++//                    throw new IllegalStateException("Unknown context " + context);
++//            }
++//    }
  
      @SCLValue(type = "ReadGraph -> Resource -> a -> b")
      public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
index d40f82d4dc1219055b83fe4c722edff93703d63e,d40f82d4dc1219055b83fe4c722edff93703d63e..21758a2e559d4191e2879a9a1baa0952edcc6449
@@@ -5,6 -5,6 +5,7 @@@ import java.util.List
  
  import org.simantics.databoard.Bindings;
  import org.simantics.db.ReadGraph;
++import org.simantics.db.Resource;
  import org.simantics.db.exception.DatabaseException;
  import org.simantics.db.exception.RuntimeDatabaseException;
  import org.simantics.db.request.Read;
@@@ -226,9 -226,9 +227,9 @@@ implements Read<Function1<EvaluationCon
              return base;
      }
      
--    protected static String resolveExpectedValueType(ReadGraph graph, org.simantics.db.layer0.variable.Variable context) throws DatabaseException {
++    protected static String resolveExpectedValueType(ReadGraph graph, Resource predicate) throws DatabaseException {
          Layer0 L0 = Layer0.getInstance(graph);
--        String valueType = graph.getPossibleRelatedValue(context.getPredicateResource(graph), L0.RequiresValueType, Bindings.STRING);
--        return valueType;
++        return graph.getPossibleRelatedValue(predicate, L0.RequiresValueType, Bindings.STRING);
      }
++    
  }
index c8d168f50320b547966e8bccb95d5473bf071ac5,c8d168f50320b547966e8bccb95d5473bf071ac5..e0000da7864c236ff4c7c99bcb2b271ca657cc06
@@@ -55,6 -55,6 +55,11 @@@ public class CompileResourceValueReques
          }
      }
  
++    public static Function1<Resource,Object> compile(ReadGraph graph, Resource literal) throws DatabaseException {
++        return graph.syncRequest(new CompileResourceValueRequest(literal),
++                TransientCacheListener.<Function1<Resource,Object>>instance());
++    }
++
      @Override
      protected String getExpressionText(ReadGraph graph)
              throws DatabaseException {
index e1804d790fc327c6713cc5e7bdf41b78b84c8b91,e1804d790fc327c6713cc5e7bdf41b78b84c8b91..1c82e32a4874e641b9173d340cc2452c9876e327
@@@ -66,6 -66,6 +66,23 @@@ public class CompileValueRequest extend
          }
      }
  
++    public static Function1<Variable,Object> compile(ReadGraph graph, Resource component, Resource literal, Resource predicate) throws DatabaseException {
++        SCLContext sclContext = SCLContext.getCurrent();
++        Object oldGraph = sclContext.get("graph");
++        try {
++            Function1<Variable,Object> exp = graph.syncRequest(new CompileValueRequest(component, literal, predicate),
++                    TransientCacheListener.<Function1<Variable,Object>>instance());
++            sclContext.put("graph", graph);
++            return exp;
++        } catch (DatabaseException e) {
++            throw (DatabaseException)e;
++        } catch (Throwable t) {
++            throw new DatabaseException(t);
++        } finally {
++            sclContext.put("graph", oldGraph);
++        }
++    }
++    
      @Override
      protected String getExpressionText(ReadGraph graph)
              throws DatabaseException {
index 6ee8a53845fb0f97351183e6ffa3a145f937c1ff,6ee8a53845fb0f97351183e6ffa3a145f937c1ff..89664698ac790a5a4c77baf8f16a26639ec309fc
@@@ -48,6 -48,6 +48,7 @@@ public class ProxyChildVariable extend
        }
        
      public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
++        System.err.println("other: " + other.getURI(graph) + " " + name );
        Variable otherChild = other.getPossibleChild(graph, name);
        if(otherChild == null) return null;
        return create(base, this, otherChild, name);
index fb5ea925a58f6b86b0248dca3ee7a90ab7fadeab,fb5ea925a58f6b86b0248dca3ee7a90ab7fadeab..db28afed5d452c8b5444e67e6091baf868574a86
@@@ -1,6 -1,6 +1,8 @@@
  package org.simantics.db.layer0.variable;
  
++import java.util.ArrayList;
  import java.util.Collection;
++import java.util.Collections;
  import java.util.Set;
  
  import org.simantics.databoard.binding.Binding;
@@@ -10,21 -10,21 +12,16 @@@ import org.simantics.db.ReadGraph
  import org.simantics.db.Resource;
  import org.simantics.db.WriteGraph;
  import org.simantics.db.exception.DatabaseException;
++import org.simantics.db.layer0.request.PropertyInfo;
  import org.simantics.db.layer0.variable.RVI.RVIPart;
++import org.simantics.db.layer0.variable.Variables.Role;
  
--/**
-- * @deprecated this implementation is pretty much useless, it is too
-- *             straightforward and requires extenders to override pretty much
-- *             everything in it to work correctly. Do not use.
-- * @see ValueProxyVariable
-- */
--@Deprecated
--public abstract class ProxyVariable implements Variable {
++public class ProxyVariable implements Variable {
  
      protected final Variable proxy;
      protected final Variable parent;
  
--    public ProxyVariable(Variable proxy, Variable parent) {
++    public ProxyVariable(Variable parent, Variable proxy) {
          if (proxy == null)
              throw new NullPointerException("null proxy");
          if (parent == null)
  
      @Override
      public Variable getChild(ReadGraph graph, String name) throws DatabaseException {
--        return proxy.getChild(graph, name);
++        Variable child = proxy.getChild(graph, name);
++        return ProxyVariables.tryToOwn(graph, this, child);
      }
  
      @Override
      public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
--        return proxy.getPossibleChild(graph, name);
++        Variable child = proxy.getPossibleChild(graph, name);
++        return ProxyVariables.tryToOwn(graph, this, child);
      }
  
      @Override
      public Variable getProperty(ReadGraph graph, String name) throws DatabaseException {
--        return proxy.getProperty(graph, name);
++        Variable property =  proxy.getProperty(graph, name);
++        return ProxyVariables.tryToOwn(graph, this, property);
      }
  
      @Override
--    public Variable getProperty(ReadGraph graph, Resource property) throws DatabaseException {
--        return proxy.getProperty(graph, property);
++    public Variable getProperty(ReadGraph graph, Resource property_) throws DatabaseException {
++        Variable property = proxy.getProperty(graph, property_);
++        return ProxyVariables.tryToOwn(graph, this, property);
      }
  
      @Override
      public Variable getPossibleProperty(ReadGraph graph, String name) throws DatabaseException {
--        return proxy.getPossibleProperty(graph, name);
++        Variable property =  proxy.getPossibleProperty(graph, name);
++        return ProxyVariables.tryToOwn(graph, this, property);
      }
  
      @Override
--    public Variable getPossibleProperty(ReadGraph graph, Resource property) throws DatabaseException {
--        return proxy.getPossibleProperty(graph, property);
++    public Variable getPossibleProperty(ReadGraph graph, Resource property_) throws DatabaseException {
++        Variable property = proxy.getPossibleProperty(graph, property_);
++        return ProxyVariables.tryToOwn(graph, this, property);
      }
  
      @Override
      public Collection<Variable> browseChildren(ReadGraph graph) throws DatabaseException {
--        return proxy.browseChildren(graph);
++        Collection<Variable> children = proxy.browseChildren(graph);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
--        return proxy.getChildren(graph);
++        Collection<Variable> children = proxy.getChildren(graph);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Collection<Variable> browseProperties(ReadGraph graph) throws DatabaseException {
--        return proxy.browseProperties(graph);
++        Collection<Variable> children = proxy.browseProperties(graph);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Collection<Variable> getProperties(ReadGraph graph) throws DatabaseException {
--        return proxy.getProperties(graph);
++        Collection<Variable> children = proxy.getProperties(graph);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Collection<Variable> getProperties(ReadGraph graph, String classification) throws DatabaseException {
--        return proxy.getProperties(graph, classification);
++        Collection<Variable> children = proxy.getProperties(graph, classification);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Collection<Variable> getProperties(ReadGraph graph, Resource classification) throws DatabaseException {
--        return proxy.getProperties(graph, classification);
++        Collection<Variable> children = proxy.getProperties(graph, classification);
++        if(children.isEmpty()) return Collections.emptyList();
++        Collection<Variable> result = new ArrayList<>();
++        for(Variable child : children) {
++            Variable owned = ProxyVariables.tryToOwn(graph, this, child);
++            if(owned != null) result.add(owned);
++        }
++        return result;
      }
  
      @Override
      public Variable browse(ReadGraph graph, String suffix) throws DatabaseException {
--        if (suffix.isEmpty())
--            return this;
--        return proxy.browse(graph, suffix);
++        Variable variable =  proxy.browse(graph, suffix);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
      public Variable browsePossible(ReadGraph graph, String suffix) throws DatabaseException {
--        if (suffix.isEmpty())
--            return this;
--        return proxy.browsePossible(graph, suffix);
++        Variable variable =  proxy.browsePossible(graph, suffix);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
      public Variable browse(ReadGraph graph, Resource config) throws DatabaseException {
--        return proxy.browse(graph, config);
++        Variable variable =  proxy.browse(graph, config);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
      public Variable browsePossible(ReadGraph graph, Resource config) throws DatabaseException {
--        return proxy.browsePossible(graph, config);
++        Variable variable =  proxy.browsePossible(graph, config);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
          return proxy.getURI(graph);
      }
  
--    @Override
--    public abstract int hashCode();
--
--    @Override
--    public abstract boolean equals(Object obj);
--
      @Override
      public Variable resolve(ReadGraph graph, RVIPart part) throws DatabaseException {
--        return proxy.resolve(graph, part);
++        Variable variable =  proxy.resolve(graph, part);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
      public Variable resolvePossible(ReadGraph graph, RVIPart part) throws DatabaseException {
--        return proxy.resolvePossible(graph, part);
++        Variable variable =  proxy.resolvePossible(graph, part);
++        return ProxyVariables.tryToOwn(graph, this, variable);
      }
  
      @Override
        public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
                return proxy.getPossibleType(graph, baseType);
        }
++
++    @Override
++    public PropertyInfo getPropertyInfo(ReadGraph graph) throws DatabaseException {
++        return proxy.getPropertyInfo(graph);
++    }
++
++    @Override
++    public Resource getIndexRoot(ReadGraph graph) throws DatabaseException {
++        return proxy.getIndexRoot(graph);
++    }
++
++    @Override
++    public Role getRole(ReadGraph graph) throws DatabaseException {
++        return proxy.getRole(graph);
++    }
++
++    @Override
++    public Role getPossibleRole(ReadGraph graph) throws DatabaseException {
++        return proxy.getPossibleRole(graph);
++    }
++
++    @Override
++    public int hashCode() {
++        final int prime = 31;
++        int result = 1;
++        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
++        result = prime * result + ((proxy == null) ? 0 : proxy.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;
++        ProxyVariable other = (ProxyVariable) obj;
++        if (parent == null) {
++            if (other.parent != null)
++                return false;
++        } else if (!parent.equals(other.parent))
++            return false;
++        if (proxy == null) {
++            if (other.proxy != null)
++                return false;
++        } else if (!proxy.equals(other.proxy))
++            return false;
++        return true;
++    }
++    
  }
index db552650b09c7098074bfd069b954a9b5d80ca15,db552650b09c7098074bfd069b954a9b5d80ca15..8fa9bf42628a3be5a29e12824cb87b5be4c61b2a
@@@ -4,8 -4,8 +4,24 @@@ import org.simantics.db.ReadGraph
  import org.simantics.db.exception.DatabaseException;
  
  public class ProxyVariables {
--      
--      public static Variable inputVariable(ReadGraph graph, Variable context) throws DatabaseException {
++    
++    public static Variable tryToOwn(ReadGraph graph, Variable parent, Variable variable) {
++        if(variable instanceof ProxyVariableSupport) {
++            ProxyVariableSupport pvs = (ProxyVariableSupport)variable;
++            return pvs.attachTo(graph, parent);
++        }
++        return null;
++    }
++
++    public static Variable tryToOwnRenamed(ReadGraph graph, Variable parent, Variable variable, String name) {
++        if(variable instanceof ProxyVariableSupport) {
++            ProxyVariableSupport pvs = (ProxyVariableSupport)variable;
++            return pvs.attachToRenamed(graph, parent, name);
++        }
++        return null;
++    }
++
++    public static Variable inputVariable(ReadGraph graph, Variable context) throws DatabaseException {
        Variable session = graph.syncRequest(new ProxySessionRequest(context));
        if(session == null) return null;
        String uri = session.getPossiblePropertyValue(graph, "inputURI");
index 9c02bbe2a70806dfb8833e9b7a23a12310e7a015,9c02bbe2a70806dfb8833e9b7a23a12310e7a015..08342593fe132b1b89578b645183cf52bd5239be
@@@ -694,7 -694,7 +694,7 @@@ public class VariableDebugger extends C
              content.append("<table class=\"top\">\n");
              content.append("<tr><td class=\"top_key\">URI</td><td class=\"top_value\"><span id=\"uri\">").append(uri).append("</span></td></tr>\n");
              content.append("<tr><td class=\"top_key\">RVI</td><td class=\"top_value\"><span id=\"uri\">").append(rviString).append("</span></td></tr>\n");
--            content.append("<tr><td class=\"top_key\">Class</td><td class=\"top_value\"><span id=\"class\">").append(var.getClass().getCanonicalName()).append("</span></td></tr>\n");
++            content.append("<tr><td class=\"top_key\">Class</td><td class=\"top_value\"><span id=\"class\">").append(var.getClass()).append("</span></td></tr>\n");
              content.append("<tr><td class=\"top_key\">Solver node</td><td class=\"top_value\"><span id=\"class\">").append(node).append("</span></td></tr>\n");
              content.append("</table>\n");
              content.append("</div>\n");
index 5384db0b27210f3aed2d6dc220951b3d4a78d19f,5384db0b27210f3aed2d6dc220951b3d4a78d19f..d3372b12c0bf1b3b82f117e32915bad50d1e93fb
@@@ -31,9 -31,9 +31,9 @@@ sclAttribute = COMPONENTS.sclAttribute 
                    L0.SCLValue.expression %command
                    L0.default false
  
--DOC.SCL : L0.SCLModule
--    L0.SCLModule.definition _ : L0.String
--        @L0.loadString "scl/Code.scl"
++//DOC.SCL : L0.SCLModule
++//    L0.SCLModule.definition _ : L0.String
++//        @L0.loadString "scl/Code.scl"
  
  DOC.scl : L0.Template
      @template %subject %property %expression %valueType
@@@ -49,10 -49,10 +49,13 @@@ DOC.sclValue : L0.Templat
              L0.HasValueType %valueType
  
  DOC.SCLValue <T L0.SCLValue
--  @L0.scl L0.SCLValueType.validator """\self -> compileDocumentSCLValueExpression self""" "Variable -> <ReadGraph> String"
    @L0.assert L0.ConvertsToValueWith
      DOC.Functions.sclValue : L0.ExternalValue
  
++DOC.HandlerSCLValue <T L0.SCLValue
++  @L0.assert L0.ConvertsToValueWith
++    DOC.Functions.sclHandlerValue : L0.ExternalValue
++
  /* Basic component types */
  COMPONENTS.Component <T STR.Component
      >-- COMPONENTS.Component.manualOrdinal --> L0.Integer <R L0.HasProperty
@@@ -63,9 -63,9 +66,7 @@@
      @sclAttribute PROPERTIES.commands "commandList self" "[Command]"
  
  COMPONENTS.PrimitiveComponent <T COMPONENTS.Component
--    @L0.assert PROPERTIES.primitiveProperties
--      _ : L0.Value
--        L0.domainProperties FUNCTIONS.primitiveProperties
++    @L0.sclAssertion PROPERTIES.primitiveProperties "primitiveProperties" "DocumentProperties"
  
  COMPONENTS.ParentlessComponent <T COMPONENTS.PrimitiveComponent /* Component without a parent, e.g. Root, DialogBox */
  
@@@ -84,7 -84,7 +85,7 @@@ COMPONENTS.Event <T COMPONENTS.Parentle
   
  COMPONENTS.CommandEvent <T COMPONENTS.Event
     @connectionPoint RELATIONS.data1
--   @sclAttribute PROPERTIES.dataDefinitions "dataDefinitions self" "[DataDefinition]"
++   @sclAttribute PROPERTIES.dataDefinitions "computeDataDefinitions self" "[DataDefinition]"
     @sclAttribute PROPERTIES.SCLFunction "emptyOnClick ()" "String"
  
  DOC.commandEvent : L0.Template
index 4845558ea2b21bb1a72545af5b2957f347f22496,4845558ea2b21bb1a72545af5b2957f347f22496..3089949481a7b846f8a222a5305df0cabd69e064
@@@ -12,6 -12,6 +12,11 @@@ Documentation = <http://www.simantics.o
      @L0.new
      L0.HasResourceClass "org.simantics.document.base.ontology.DocumentationResource"
  
++Documentation.SCLMain : L0.SCLModule
++    L0.SCLModule.definition """
++        include "Document/All"
++        """
++
  Documentation.connect : L0.Template
    @template %parent %relation %connection %child
      %parent
@@@ -122,13 -122,13 +127,15 @@@ Documentation.singleData : L0.Templat
      
  
  Documentation.Relations : L0.Library
++
  Documentation.Document <T Documentation.Components.Composite
      @L0.assert L0.domainChildren Documentation.Functions.inputSpaceChildren
      @L0.assert STR.Composite.namingFunction Documentation.Functions.componentNamingStrategy       
      >-- Documentation.Properties.state
--    L0.Asserts _ : L0.Assertion
++    @L0.sclAssertion Documentation.Properties.state "stateVariable self" "Variable"
++/*    L0.Asserts _ : L0.Assertion
          L0.HasPredicate Documentation.Properties.state
--        L0.HasObject FUNCTIONS.state
++        L0.HasObject FUNCTIONS.state*/
      >-- Documentation.Properties.session
      L0.Asserts _ : L0.Assertion
          L0.HasPredicate Documentation.Properties.session
index d502e3d2f2e860ed22dbdc56340c9e44954a643d,d502e3d2f2e860ed22dbdc56340c9e44954a643d..e1c71fe976a62df8b76c3a213c51418a8dbabd34
@@@ -52,7 -52,7 +52,7 @@@ PROPERTIES.model <R L0.HasProperty : L0
      ==> "Variable"
  
  PROPERTIES.primitiveProperties <R L0.HasProperty : L0.FunctionalRelation
--    ==> "String"
++    ==> "DocumentProperties"
  
  PROPERTIES.exists
      @defAttribute L0.Value
index 7a14760250c6d15b15bbf93d9be342004a35b114,7a14760250c6d15b15bbf93d9be342004a35b114..76622e38b458e8b0835a930b63ed3b00a7a05b72
      <target interface="org.simantics.db.layer0.variable.VariableBuilder">
          <type uri="http://www.simantics.org/Modeling-1.2/SCLCommandSession" class="org.simantics.document.server.state.StateVariableBuilder" />
      </target>
++    <target interface="org.simantics.db.ComputationalValue">
++        <resource uri="http://www.simantics.org/Documentation-0.0/Functions/sclValue"
++            class="org.simantics.document.server.SCLComputationalValue">
++        </resource>
++    </target>
++    <target interface="org.simantics.db.ComputationalValue">
++        <resource uri="http://www.simantics.org/Documentation-0.0/Functions/sclHandlerValue"
++            class="org.simantics.document.server.HandlerSCLComputationalValue">
++        </resource>
++    </target>
  </adapters>
index 4db639f5bf2696a389669d527bae19b035978064,4db639f5bf2696a389669d527bae19b035978064..c6967b559a3ca1377e8e74e93711d6efff72489d
@@@ -2,6 -2,6 +2,9 @@@ import "Simantics/DB
  import "Simantics/Variables"
  import "JavaBuiltin" as Java
  
++importJava "org.simantics.document.server.DocumentProperties" where
++    data DocumentProperties
++
  importJava "org.simantics.document.server.io.IConsole" where
      data IConsole
      addMessage :: IConsole -> String -> <Proc> ()
@@@ -110,6 -110,6 +113,9 @@@ importJava "org.simantics.document.serv
  
      dataDefinitions :: Variable -> <ReadGraph> [DataDefinition]
  
++    @JavaName "dataDefinitions"
++    computeDataDefinitions :: Variable -> <ReadGraph> [DataDefinition]
++    
      emptyOnClick :: () -> <ReadGraph> AbstractEventHandler
      
      writeEventHandler :: Variable -> (Variable -> (String -> Maybe String) -> <WriteGraph> String) -> <ReadGraph> AbstractEventHandler
      
      compileDocumentSCLValueExpression :: Variable -> <ReadGraph> String
      
++    primitiveProperties :: <Proc> DocumentProperties
++    
  propertyValueCached :: Serializable a => Typeable a => Variable -> String -> <ReadGraph> a
  propertyValueCached var prop = propertyValueCached_ var prop binding
      
index 5e1f5cc30e798aff45343b8f8c5f4483b6d8a9cc,5e1f5cc30e798aff45343b8f8c5f4483b6d8a9cc..95fa78da837ade7863c49f8c37306306778d1cff
@@@ -19,12 -19,12 +19,10 @@@ import org.simantics.db.layer0.variable
  import org.simantics.db.layer0.variable.Variable;
  import org.simantics.db.layer0.variable.Variables;
  import org.simantics.document.base.ontology.DocumentationResource;
--import org.simantics.document.server.Functions.RootVariable;
  import org.simantics.document.server.request.NodeRequest;
  import org.simantics.document.server.request.NodeRequestUtils;
  import org.simantics.structural2.variables.Connection;
  import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
--import org.simantics.utils.datastructures.Pair;
  import org.simantics.utils.strings.AlphanumComparator;
  
  public class DocumentServerUtils {
  
        public static Variable getPossibleOtherConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
  
--              Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
++              Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
                if(descs.size() != 2) return null;
  
                for(VariableConnectionPointDescriptor desc : descs) {
  
        public static Variable getPossibleChildConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
  
--              Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
++              Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
                if(descs.size() != 2) return null;
  
        DocumentationResource DOC = DocumentationResource.getInstance(graph);
  
        public static Variable getPossibleCommandTriggerConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
  
--              Collection<Variable> cpts = conn.getConnectionPoints(graph, null);
++              Collection<Variable> cpts = conn.getConnectionPoints(graph, connectionPoint.getParent(graph), null);
  
                Variable result = null;
                
  
                if(node == null) return "root";
                else {
--                      String uri = node.getURI(graph); 
--                      int l = uri.lastIndexOf(ProxyChildVariable.CONTEXT_END);
--                      return uri.substring(l+4);
++                  String name = node.getName(graph);
++                  if(ProxyChildVariable.CONTEXT_END.equals(name)) return "";
++                  else {
++                      String parentId = getId(graph, node.getParent(graph));
++                      if(parentId.isEmpty()) return name;
++                      else return parentId + "/" + name; 
++                  }
++                  
                }
  
        }
                return variable.getProperties(graph, DOC.Document_AttributeRelation);
        }
        
--      public static class AttributesRequest extends VariableRead<Pair<JSONObject, Collection<Variable>>> {
--
--              public AttributesRequest(Variable variable) {
--                      super(variable);
--              }
--
--              @Override
--              public Pair<JSONObject,Collection<Variable>> perform(ReadGraph graph) throws DatabaseException {
--              ArrayList<Variable> statics = new ArrayList<Variable>();
--              DocumentationResource DOC = DocumentationResource.getInstance(graph);
--              
--              Variable primitives = variable.getProperty(graph, DOC.Properties_primitiveProperties);
--              for(Variable property : primitives.getProperties(graph)) {
--                      statics.add(property);
--                      // NO SUPPORT FOR DYNAMICS AT THIS STAGE
--              }
--              
--              JSONObject staticContent = computeStatic(graph, variable, statics);
--              
--              return new Pair<JSONObject, Collection<Variable>>(staticContent, Collections.emptyList());
--              
--              }
--              
--              JSONObject computeStatic(ReadGraph graph, Variable variable, ArrayList<Variable> statics) throws DatabaseException {
--                      
--                      JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable));
--                      JSONObject object = base.clone();
--                      
--                      for(Variable attrib : statics) {
--                              String name = attrib.getName(graph);
--                              try {
--                                      if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) {
--                                      @SuppressWarnings("unchecked")
--                                              Map<String, Exception> exceptions = (Map<String, Exception>)DocumentServerUtils.getValue(graph, attrib);
--                                      
--                                      List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
--                                          if(errorList == null)
--                                              errorList = new ArrayList<String>();
--                                          
--                                  for (Map.Entry<String, Exception> entry : exceptions.entrySet()) {
--                                      String errorMessage = NodeRequestUtils.formatErrorMessage(entry.getKey(), entry.getValue());
--                                      errorList.add(errorMessage);
--                                  }
--                                      object.addJSONField(NodeRequest.ERRORS, errorList);
--                                      
--                                  } else {
--                                              Object value = DocumentServerUtils.getValue(graph, attrib);
--                                          object.addJSONField(name, value);
--                                  }
--                              } catch (Throwable t) {
--                                  List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
--                                  if(errorList == null)
--                                      errorList = new ArrayList<String>();
--                                  
--                          String errorMessage = NodeRequestUtils.formatErrorMessage(name, t);
--                          
--                                  errorList.add(errorMessage);
--                                  object.addJSONField(NodeRequest.ERRORS, errorList);
--                              }
--
--                      }
--
--                      return object;
--                      
--              }
--              
--      }
++    public static class AttributesRequest extends VariableRead<JSONObject> {
++
++        public AttributesRequest(Variable variable) {
++            super(variable);
++        }
++
++        @Override
++        public JSONObject perform(ReadGraph graph) throws DatabaseException {
++
++            DocumentationResource DOC = DocumentationResource.getInstance(graph);
++            
++            DocumentProperties properties = variable.getPropertyValue(graph, DOC.Properties_primitiveProperties); 
++            
++            return computeStatic(graph, variable, properties);
++            
++        }
++        
++        JSONObject computeStatic(ReadGraph graph, Variable variable, DocumentProperties statics) throws DatabaseException {
++            
++            JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable));
++            JSONObject object = base.clone();
++            
++            for(String name : statics.getKeys(graph, variable)) {
++                try {
++                    if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) {
++                        @SuppressWarnings("unchecked")
++                        Map<String, Exception> exceptions = (Map<String, Exception>)statics.getValue(graph, variable, name);//(Map<String, Exception>)DocumentServerUtils.getValue(graph, attrib);
++                        
++                        List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
++                        if(errorList == null)
++                            errorList = new ArrayList<String>();
++                        
++                        for (Map.Entry<String, Exception> entry : exceptions.entrySet()) {
++                            String errorMessage = NodeRequestUtils.formatErrorMessage(entry.getKey(), entry.getValue());
++                            errorList.add(errorMessage);
++                        }
++                        object.addJSONField(NodeRequest.ERRORS, errorList);
++                        
++                    } else {
++                        object.addJSONField(name, statics.getValue(graph, variable, name));
++                    }
++                } catch (Throwable t) {
++                    List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
++                    if(errorList == null)
++                        errorList = new ArrayList<String>();
++                    
++                    String errorMessage = NodeRequestUtils.formatErrorMessage(name, t);
++                    
++                    errorList.add(errorMessage);
++                    object.addJSONField(NodeRequest.ERRORS, errorList);
++                }
++
++            }
++
++            return object;
++            
++        }
++        
++    }
  
        public static Collection<Variable> getDynamicAttributes(ReadGraph graph, final DocumentationResource DOC, Variable variable) throws DatabaseException {
--      Pair<JSONObject, Collection<Variable>> attribs = graph.syncRequest(new AttributesRequest(variable));
--      return attribs.second;
++        return Collections.emptyList();
        }
        
        public static Variable getPossibleDocumentRootVariable(ReadGraph graph, Variable documentPart) throws DatabaseException {
--              if(documentPart instanceof RootVariable) return documentPart;
++          if(ProxyChildVariable.CONTEXT_END.equals(documentPart.getName(graph))) return documentPart;
                Variable parent = documentPart.getParent(graph);
                if(parent == null) return null;
                return getPossibleDocumentRootVariable(graph, parent);
index aabe7b29ffd04dbcdff684dc899f11f2bde8c19f,aabe7b29ffd04dbcdff684dc899f11f2bde8c19f..f0a7b4f472b953190978d0f241a4966743594076
@@@ -15,7 -15,7 +15,6 @@@ import org.simantics.databoard.Bindings
  import org.simantics.databoard.Datatypes;
  import org.simantics.databoard.binding.Binding;
  import org.simantics.databoard.type.Datatype;
--import org.simantics.db.AsyncReadGraph;
  import org.simantics.db.DirectStatements;
  import org.simantics.db.ReadGraph;
  import org.simantics.db.RequestProcessor;
@@@ -25,7 -25,7 +24,7 @@@ import org.simantics.db.Statement
  import org.simantics.db.WriteGraph;
  import org.simantics.db.common.primitiverequest.Adapter;
  import org.simantics.db.common.procedure.adapter.TransientCacheListener;
--import org.simantics.db.common.request.UnaryRead;
++import org.simantics.db.common.request.BinaryRead;
  import org.simantics.db.common.request.UniqueRead;
  import org.simantics.db.common.request.WriteResultRequest;
  import org.simantics.db.common.utils.Logger;
@@@ -42,15 -42,15 +41,14 @@@ import org.simantics.db.layer0.scl.SCLD
  import org.simantics.db.layer0.variable.ConstantPropertyVariable;
  import org.simantics.db.layer0.variable.ProxyChildVariable;
  import org.simantics.db.layer0.variable.ProxySessionRequest;
++import org.simantics.db.layer0.variable.ProxyVariableSupport;
  import org.simantics.db.layer0.variable.ProxyVariables;
  import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
--import org.simantics.db.layer0.variable.StandardGraphChildVariable;
  import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
  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.Variables;
--import org.simantics.db.procedure.AsyncProcedure;
  import org.simantics.db.service.DirectQuerySupport;
  import org.simantics.document.base.ontology.DocumentationResource;
  import org.simantics.document.server.bean.Command;
@@@ -107,21 -107,21 +105,6 @@@ public class Functions 
  
      private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Functions.class);
      
--    private static class PrimitivePropertyStatementsProcedure implements AsyncProcedure<DirectStatements> {
--
--        public DirectStatements result;
--
--        @Override
--        public void execute(AsyncReadGraph graph, DirectStatements result) {
--            this.result = result;
--        }
--
--        @Override
--        public void exception(AsyncReadGraph graph, Throwable throwable) {
--        }
--
--    }
--
      @SCLValue(type = "VariableMap")
      public static VariableMap primitiveProperties = new VariableMapImpl() {
        private void storePropertyValueAndExceptions(ReadGraph graph, Variable parent, String name, Variable property, Map<String, Variable> map) {
  
      };
  
++    static class StandardDocumentProperties implements DocumentProperties {
++
++        @Override
++        public Collection<String> getKeys(ReadGraph graph, Variable context) throws DatabaseException {
++            
++            DocumentationResource DOC = DocumentationResource.getInstance(graph);
++            StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
++            Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
++            return ps.keySet();
++            
++        }
++
++        @Override
++        public Object getValue(ReadGraph graph, Variable context, String key) throws DatabaseException {
++            
++            DocumentationResource DOC = DocumentationResource.getInstance(graph);
++            StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
++            Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
++            return ps.get(key).getValue(graph);
++            
++        }
++        
++    }
++    
++    public static DocumentProperties primitiveProperties() throws DatabaseException {
++        return new StandardDocumentProperties();
++    }
++    
      @SCLValue(type = "VariableMap")
      public static VariableMap inputSpaceChildren = new VariableMapImpl() {
  
          private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
--            Variable root = Variables.getRootVariable(graph);
++            System.err.println("getProxy " + context.getURI(graph));
++            //System.err.println("getProxy " + context.getParent(graph).getURI(graph));
++            Variable root = Variables.getVariable(graph, graph.getRootLibrary());   
++            //Variable parent = context.getParent(graph);
              return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
          }
  
  
      };
  
--    static class DocumentProxyChildVariable extends ProxyChildVariable {
++    static class DocumentProxyChildVariable extends ProxyChildVariable implements ProxyVariableSupport {
  
          public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
              super(base, parent, other, name);
          }
  
          public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
++            
++            System.err.println("possibleChild " + name + " for " + getURI(graph));
  
                if(CONTEXT_END.equals(name)) {
                if(other instanceof ProxyChildVariable) {
                        // The context is also a proxy - let it do the job
                      return super.getPossibleChild(graph, name);
                } else {
--                      return new RootVariable(this, base.getRepresents(graph));
++                  System.err.println("RootVariable for " + getURI(graph) + " from " + base.getURI(graph));
++                  return ProxyVariables.tryToOwnRenamed(graph, this, base, CONTEXT_END);
++                      //return new RootVariable(this, base);
                }
                }
  
  
          }
  
--        public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
--
--            Collection<Variable> result = super.getChildren(graph);
--            if(!(base instanceof ProxyChildVariable)) {
--              result.add(new RootVariable(this, base.getRepresents(graph)));
--            }
--            return result;
--
++        @Override
++        public Variable attachTo(ReadGraph graph, Variable parent) {
++            return attachToRenamed(graph, parent, name);
++        }
++        
++        @Override
++        public Variable attachToRenamed(ReadGraph graph, Variable parent, String name) {
++            if(this.parent.equals(base))
++                return new DocumentProxyChildVariable(parent, parent, other, name);
++            else
++                return new DocumentProxyChildVariable(base, parent, other, name);
          }
  
      }
  
--    static class RootVariable extends StandardGraphChildVariable {
++    /*static class RootVariable extends ProxyVariable {
  
--        public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
--            super(parent, null, resource);
++        public RootVariable(DocumentProxyChildVariable parent, Variable proxy) {
++            super(parent, proxy);
          }
  
          @Override
          public String getName(ReadGraph graph) throws DatabaseException {
              return ProxyChildVariable.CONTEXT_END;
          }
--
--        @SuppressWarnings("deprecation")
++        
          @Override
--        public Variable getNameVariable(ReadGraph graph) throws DatabaseException {
--            return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);
++        public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
++            System.err.println("Root.getPossibleChild " + name + " " + getURI(graph));
++            return super.getPossibleChild(graph, name);
++        }
++        
++        @Override
++        public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
++            System.err.println("Root.getChildren " + getURI(graph));
++            return super.getChildren(graph);
          }
  
--    }
++    }*/
  
      @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
      public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
  
      public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
        Variable property = graph.syncRequest(new VariableProperty(variable, name));
++      if(property == null)
++          System.err.println("faa");
        return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
      }
  
                                                return true;
                                        }
                                } else {
--                                      Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
++                                      Variable parentCp = graph.sync(new BinaryRead<Variable, Connection, Variable>(widget, conn) {
                                    @Override
                                    public Variable perform(ReadGraph graph) throws DatabaseException {
                                        DocumentationResource DOC = DocumentationResource.getInstance(graph);
--                                      Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
++                                      Collection<VariableConnectionPointDescriptor> descs = parameter2.getConnectionPointDescriptors(graph, parameter, null);
  
                                                for(VariableConnectionPointDescriptor desc : descs) {
                                                        if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
index d9418db9947d482fecd4daf547d85359363bea5c,d9418db9947d482fecd4daf547d85359363bea5c..2622c29946bf6cb77a64ba50c603c454e7dc146b
@@@ -17,51 -17,51 +17,18 @@@ public class NodeRequest extends Variab
  
      public static final String ERRORS = "Errors";
      public static final String PROPERTY_VALUE_EXCEPTIONS = "_PropertyValueExceptions";
--    
--      public NodeRequest(Variable node) {
--              super(node);
--      }
  
--      @SuppressWarnings("unchecked")
--    @Override
--      public JSONObject perform(ReadGraph graph) throws DatabaseException {
--
--              long s = System.nanoTime();
--
--              Pair<JSONObject, Collection<Variable>> attribs = graph.syncRequest(new AttributesRequest(variable));
--
--          JSONObject staticContent = attribs.first;
--          if(attribs.second.isEmpty()) {
--
--              if(DocumentRequest.PROFILE) {
--                      long dura = System.nanoTime()-s;
--                  if(dura > DocumentRequest.PROFILE_THRESHOLD_NODEREQUEST * 1e3) {
--                      System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
--                  }
--              }
--
--              return staticContent;
--          }
--
--          Map<String,Object> dynamicContent = graph.syncRequest(new NodeRequestDynamic(variable));
--          if(dynamicContent.isEmpty()) {
--              return staticContent;
--          }
--
--        JSONObject result = staticContent.clone();
--        result.add(dynamicContent);
++    public NodeRequest(Variable node) {
++        super(node);
++    }
  
--        if(dynamicContent.containsKey(ERRORS) || staticContent.getJSONField(ERRORS) != null) {
--            ArrayList<String> errorList = new ArrayList<>();
++    @SuppressWarnings("unchecked")
++    @Override
++    public JSONObject perform(ReadGraph graph) throws DatabaseException {
  
--            if(dynamicContent.containsKey(ERRORS))
--                errorList.addAll((List<String>)dynamicContent.get(ERRORS));
++        long s = System.nanoTime();
  
--            if(staticContent.getJSONField(ERRORS) != null)
--                errorList.addAll((List<String>)staticContent.getJSONField(ERRORS));
--
--            result.addJSONField(ERRORS, errorList);
--        }
++        JSONObject staticContent = graph.syncRequest(new AttributesRequest(variable));
  
          if(DocumentRequest.PROFILE) {
              long dura = System.nanoTime()-s;
@@@ -69,8 -69,8 +36,9 @@@
                  System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
              }
          }
--        
--        return result;
++
++
++        return staticContent;
  
      }
  
index 4a4164303613c1a2c9d963693804d727305cdb2a,4a4164303613c1a2c9d963693804d727305cdb2a..01017efffaf57af2c79906b15ae9302648af7db3
@@@ -8,12 -8,12 +8,14 @@@ import org.simantics.db.ReadGraph
  import org.simantics.db.Resource;
  import org.simantics.db.common.procedure.adapter.TransientCacheListener;
  import org.simantics.db.common.request.IndexRoot;
++import org.simantics.db.common.request.PossibleTypedParent;
++import org.simantics.db.common.request.UnaryRead;
  import org.simantics.db.exception.DatabaseException;
--import org.simantics.db.layer0.request.VariableRead;
  import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
  import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
  import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
  import org.simantics.db.layer0.variable.Variable;
++import org.simantics.document.base.ontology.DocumentationResource;
  import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;
  import org.simantics.layer0.Layer0;
  import org.simantics.scl.compiler.elaboration.expressions.EApply;
@@@ -37,7 -37,7 +39,6 @@@ import org.simantics.utils.datastructur
  
  public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {
  
--      private final Variable context;
        private final Pair<Resource,Resource> componentTypeAndRoot;
        private final Resource literal;
        protected String possibleExpectedValueType;
                }
        }
  
--      private ServerSCLHandlerValueRequest(Variable context, Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
--              assert(literal != null);
--              this.context = context;
--              this.literal = literal;
--              this.componentTypeAndRoot = componentTypeAndRoot;
--              this.possibleExpectedValueType = possibleExpectedValueType;
++      private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
++          assert(literal != null);
++          this.literal = literal;
++          this.componentTypeAndRoot = componentTypeAndRoot;
++          this.possibleExpectedValueType = possibleExpectedValueType;
        }
  
--      public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
--              this(context, getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context));
--      }
++    public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
++        this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
++    }
  
++    public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
++        this(getComponentTypeAndRoot(graph, s), o, resolveExpectedValueType(graph, p));
++    }
++      
        private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {
                Variable parent = property.getParent(graph);
                Resource represents = parent.getRepresents(graph);
                return Pair.make(parent.getType(graph), root);
        }
  
++    private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component)  throws DatabaseException {
++        if(component != null) {
++            Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
++            if(type != null) {
++                Resource root = graph.syncRequest(new IndexRoot(type));
++                return Pair.make(type, root);
++            } else {
++                Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
++                Resource componentType = graph.getSingleType(doc); 
++                Resource root = graph.syncRequest(new IndexRoot(doc));
++                return Pair.make(componentType, root);
++            }
++        }
++        throw new IllegalStateException();
++    }
  
      public static List<TCon> getEffects(ReadGraph graph, Variable context) throws DatabaseException {
          try {
                }
        }
  
++      public static Function1<Variable, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
++          return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.<Function1<Variable,Object>>instance());
++      }
++
++    public static Function1<Variable, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
++        return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.<Function1<Variable,Object>>instance());
++    }
++      
        @Override
        protected String getExpressionText(ReadGraph graph)
                        throws DatabaseException {
  
        @Override
        protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
--              
--              return graph.syncRequest(new VariableRead<CompilationContext>(context) {
--                      
--                      @Override
--                      public CompilationContext perform(ReadGraph graph) throws DatabaseException {
--                              
--                              Pair<Resource,Resource> parameter = getComponentTypeAndRoot(graph, variable);
--                              RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
--                              
--                              Map<String, ComponentTypeProperty> propertyMap =
--                                              graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
--                                                              TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
++          
++          return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
++
++              @Override
++              public CompilationContext perform(ReadGraph graph) throws DatabaseException {
++
++                  RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
++                  Map<String, ComponentTypeProperty> propertyMap =
++                          graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
++                                  TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
++                  return new CompilationContext(runtimeEnvironment, propertyMap);
++
++
++              }
++
++          });
  
--//                            Map<String, ComponentTypeProperty> result = new HashMap<String,ComponentTypeProperty>(propertyMap); 
--//                            for(DataDefinition dd : Functions.dataDefinitions(graph, variable)) {
--//                                    result.put(dd.target, null);
--//                            }
--                              
--                              return new CompilationContext(runtimeEnvironment, propertyMap);
--                              
--                      }
--                      
--              });
--              
        }
  
        @Override
          return super.getExpectedType(graph, context);
      }
  
--      @Override
--      public int hashCode() {
--              final int prime = 31;
--              int result = 1;
--              result = prime * result + ((context == null) ? 0 : context.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;
--              ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
--              if (context == null) {
--                      if (other.context != null)
--                              return false;
--              } else if (!context.equals(other.context))
--                      return false;
--              return true;
--      }
++    @Override
++    public int hashCode() {
++        return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
++    }
  
--//    @Override
--//    public int hashCode() {
--//            return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
--//    }
--//
--//    @Override
--//    public boolean equals(Object obj) {
--//            if(this == obj)
--//                    return true;
--//            if(obj == null || obj.getClass() != getClass())
--//                    return false;
--//            ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj;
--//            return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
--//    }
++    @Override
++    public boolean equals(Object obj) {
++        if (this == obj)
++            return true;
++        if (obj == null)
++            return false;
++        if (getClass() != obj.getClass())
++            return false;
++        ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
++        return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
++    }
++    
        
  }
index f9181d271073964b6082fef5119a679e8c371075,f9181d271073964b6082fef5119a679e8c371075..2f363a15150f7728fc09b31d96d6d93dec4becc9
@@@ -7,12 -7,12 +7,14 @@@ import org.simantics.db.ReadGraph
  import org.simantics.db.Resource;
  import org.simantics.db.common.procedure.adapter.TransientCacheListener;
  import org.simantics.db.common.request.IndexRoot;
++import org.simantics.db.common.request.PossibleTypedParent;
  import org.simantics.db.common.request.UnaryRead;
  import org.simantics.db.exception.DatabaseException;
  import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
  import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
  import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
  import org.simantics.db.layer0.variable.Variable;
++import org.simantics.document.base.ontology.DocumentationResource;
  import org.simantics.document.server.request.ServerSCLValueRequest.CompilationContext;
  import org.simantics.layer0.Layer0;
  import org.simantics.scl.compiler.common.names.Name;
@@@ -64,7 -64,7 +66,11 @@@ public class ServerSCLValueRequest exte
        }
  
        public ServerSCLValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
--              this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context));
++              this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
++      }
++
++      public ServerSCLValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
++          this(getComponentTypeAndRoot(graph, s), o, resolveExpectedValueType(graph, p));
        }
  
        private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {
                return Pair.make(parent.getType(graph), root);
        }
  
++    private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component)  throws DatabaseException {
++        if(component != null) {
++            Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
++            if(type != null) {
++                Resource root = graph.syncRequest(new IndexRoot(type));
++          //      System.err.println("getComponentTypeAndRoot3 " + graph.getPossibleURI(component) + " => " + graph.getPossibleURI(type) + " " + graph.getPossibleURI(root));
++                return Pair.make(type, root);
++            } else {
++                Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
++                if(doc != null) {
++                    Resource componentType = graph.getSingleType(doc);
++                    Resource root = graph.syncRequest(new IndexRoot(doc));
++                    return Pair.make(componentType, root);
++                } else {
++                    System.err.println("component = " + component);
++                    Resource root = graph.syncRequest(new IndexRoot(component));
++//                  Resource componentType = graph.getSingleType(doc);
++                    return Pair.make(null, root);
++                }
++            }
++        }
++        throw new IllegalStateException();
++    }
++      
        public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
                SCLContext sclContext = SCLContext.getCurrent();
          Object oldGraph = sclContext.get("graph");
            return graph.syncRequest(new ServerSCLValueRequest(graph, context), TransientCacheListener.<Function1<Variable,Object>>instance());
        }
  
++    public static Function1<Variable, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
++        return graph.syncRequest(new ServerSCLValueRequest(graph, s, o, p), TransientCacheListener.<Function1<Variable,Object>>instance());
++    }
++      
        @Override
        protected String getExpressionText(ReadGraph graph)
                        throws DatabaseException {
index 783f4f401f271affbd497959b5ec60e2806ee6bd,783f4f401f271affbd497959b5ec60e2806ee6bd..ec31d0350e96b2f3c5eaa44590a643bbbea3f132
@@@ -10,7 -10,7 +10,12 @@@ L0.Functions.entityLabel : L0.ExternalV
  L0.Functions.listResources : L0.ExternalValue    
  L0.Functions.resourceAsValue : L0.ExternalValue    
  L0.Functions.functionApplication : L0.ExternalValue
++
++// This was replaced by L0.Functions.sclValue to make things more uniform
  L0.Functions.computeExpression : L0.ExternalValue
++    @L0.tag L0.Deprecated
++    
++L0.Functions.sclValue : L0.ExternalValue
  L0.Functions.composedPropertyValue : L0.ExternalValue
  
  L0.Functions.standardValueAccessor : L0.ExternalValue
index c36cf60e56cffc6faf7d53cc1e7c10d2d0a3bd40,16f01a7bebfba9553314e5f12cff27648a3470c8..358aaa7e914a92ad6b89e465139fa3e6f8f8559a
@@@ -28,7 -28,7 +28,7 @@@ L0.SCLValue <T L0.Value : L0.SCLValueTy
      @L0.tag L0.Abstract
      >-- L0.SCLValue.expression --> L0.String <R L0.HasProperty : L0.TotalFunction
      >-- L0.SCLValue.environment --> L0.SCLValue.Environment <R L0.IsRelatedTo : L0.TotalFunction
--    @L0.assert L0.ConvertsToValueWith L0.Functions.computeExpression
++    @L0.assert L0.ConvertsToValueWith L0.Functions.sclValue
  
  L0.SCLValueType <T L0.Entity
      >-- L0.SCLValueType.validator ==> "Variable -> <ReadGraph> String" <R L0.HasProperty
index ff53cb579b533673483a2cfc2e33da8093905d52,ff53cb579b533673483a2cfc2e33da8093905d52..6b735a7daae95b970f963621b21bdd32e8981355
                </resource>
        </target>
  
++    <target interface="org.simantics.db.ComputationalValue">
++        <resource uri="http://www.simantics.org/Modeling-0.0/Functions/sclValue"
++            class="org.simantics.modeling.SCLComputationalValue">
++        </resource>
++    </target>
++
  </adapters>
index e4b898a6b18cccef2d66ab26c00e0ada365594da,e4b898a6b18cccef2d66ab26c00e0ada365594da..c6384ed6413dd223061383805c8ec82618d44644
@@@ -26,11 -26,11 +26,9 @@@ import gnu.trove.set.hash.THashSet
  
  public class ConnectionImpl2 implements Connection {
  
--    private final Variable component;
      private final Resource predicate;
      
--    public ConnectionImpl2(Variable component, Resource predicate) {
--        this.component = component;
++    public ConnectionImpl2(Resource predicate) {
          this.predicate = predicate;
      }
      
  
      @Override
      public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
--        Set<Variable> result = new THashSet<Variable>();
--        for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, predicate, relationType)) {
--            result.add(desc.getVariable(graph));
--        }
--        return result;
++        throw new UnsupportedOperationException();
      }
      
      @Override
      public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
++        throw new UnsupportedOperationException();
++    }
++
++    @Override
++    public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
++        throw new UnsupportedOperationException();
++    }
++
++    @Override
++    public Collection<String> getConnectionPointURIs(ReadGraph graph, Variable component, Resource relationType)
++            throws DatabaseException {
          Set<String> result = new THashSet<String>();
          for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, predicate, relationType)) {
              result.add(desc.getURI(graph));
      }
  
      @Override
--    public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
++    public Collection<Variable> getConnectionPoints(ReadGraph graph, Variable component, Resource relationType)
++            throws DatabaseException {
++        Set<Variable> result = new THashSet<Variable>();
++        for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, predicate, relationType)) {
++            result.add(desc.getVariable(graph));
++        }
++        return result;
++    }
++
++    @Override
++    public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph,
++            Variable component, Resource relationType) throws DatabaseException {
          return ConnectionBrowser.flatten(graph, component, predicate, relationType);
      }
  
index f429fdc91d104fabcaf53d6fd6c5752bdb1699ad,f429fdc91d104fabcaf53d6fd6c5752bdb1699ad..96b1c882098c7ea8dc7a622ac370bfd26402809a
@@@ -180,7 -180,7 +180,7 @@@ public class Functions 
                @Override
                public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
                        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; 
--                      return new ConnectionImpl2(context.getParent(graph), variable.property.predicate);
++                      return new ConnectionImpl(context.getParent(graph), variable.property.predicate);
                }
  
                @Override
                
        }
        
++    public static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
++
++        public StructuralChildMapOfResource(Resource resource) {
++            super(resource);
++        }
++
++        @Override
++        public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
++            StructuralResource2 STR = StructuralResource2.getInstance(graph);
++            Resource type = graph.getPossibleType(resource, STR.Component);
++            if(type != null) {
++                Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);
++                if(definition != null) {
++                    Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
++                    if (!map.isEmpty())
++                        return map;
++                } 
++            }
++            Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
++            return directChildren;
++        }
++
++    }
++
++    public static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
++
++        public StructuralChildMapOfResourceT(Resource resource) {
++            super(resource);
++        }
++
++        @Override
++        public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
++            StructuralResource2 STR = StructuralResource2.getInstance(graph);
++            Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
++            if(definition != null) {
++                Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
++                if (!map.isEmpty())
++                    return map;
++            } 
++            return Collections.emptyMap();
++        }
++
++    }
++
++    static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {
++
++        public StructuralRunChildMapOfResource(Resource resource) {
++            super(resource);
++        }
++
++        public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {
++            return graph.sync(new StructuralChildMapOfResource(context));
++        }
++        
++        @Override
++        public Map<String, 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 fromContext(graph, model);
++            }
++            Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
++            if(configuration != null) {
++                if(graph.isInstanceOf(configuration, L0.RVIContext)) {
++                    return fromContext(graph, configuration);
++                }
++            }
++            
++            return Collections.emptyMap();
++            
++        }
++        
++    }
++
        private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
            public SubstructureRequest(Variable context) {
              super(context);
index 5f07295a7d97e2930c39ef1f428f877f87a112c0,5f07295a7d97e2930c39ef1f428f877f87a112c0..96c26fa051aa4caccef3a70cee2cf50a4061b82e
@@@ -7,6 -7,6 +7,8 @@@ public class Terminal implements Connec
      public final Resource relation;
      
      public Terminal(String component, Resource relation) {
++        assert(component != null);
++        assert(relation != null);
          this.component = component;
          this.relation = relation;
      }
index 3b54c0f62c871ceff88fa8ef5cc3ac4dbc95b955,3b54c0f62c871ceff88fa8ef5cc3ac4dbc95b955..b947e995d53d49b1d0f490cd521db0a49dbe76a9
@@@ -48,6 -48,6 +48,10 @@@ public class CompileStructuralValueRequ
              sclContext.put("graph", oldGraph);
          }
      }
++      
++    public static Function1<Variable, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
++        return graph.syncRequest(new CompileStructuralValueRequest(s, o, p), TransientCacheListener.<Function1<Variable,Object>>instance());
++    }
      
      @Override
      protected String getExpressionText(ReadGraph graph)
index b404932e7a58c6d59bd98917c30dee81df36d788,b404932e7a58c6d59bd98917c30dee81df36d788..f62606996ce6c45d5868e5d92d465cbe3e922b24
@@@ -7,7 -7,7 +7,7 @@@ import org.simantics.db.Resource
  import org.simantics.db.exception.DatabaseException;
  import org.simantics.db.layer0.variable.Variable;
  
--public interface Connection {
++public interface Connection extends Connection2 {
  
      /**
       * Return absolute URIs of the connection points. An optional (may be null) relationType may be used
@@@ -21,5 -21,5 +21,5 @@@
        Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException;
        
        Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException;
--
++      
  }
index b2b92039f87f4f35870c31ed0564c624a89cec75,b2b92039f87f4f35870c31ed0564c624a89cec75..4339049ecb95a673ec202ebbd038e1d99c660fdf
@@@ -36,7 -36,7 +36,6 @@@ import org.simantics.structural2.Functi
  import org.simantics.structural2.queries.ConnectionSet;
  import org.simantics.structural2.utils.StructuralUtils;
  import org.simantics.structural2.utils.StructuralUtils.StructuralComponentClass;
--import org.simantics.structural2.variables.StandardProceduralChildVariable.FixedConnection;
  import org.simantics.utils.datastructures.Pair;
  
  import gnu.trove.map.hash.THashMap;
@@@ -338,14 -338,14 +337,9 @@@ public class ConnectionBrowser 
                
                Variable conn = child.getPossibleProperty(graph, cp);
              FixedConnection fc = (FixedConnection)conn.getValue(graph);
--            Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(1+fc.cps.size());
++            Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(1+fc.size());
              result.add(new ComponentConnectionDescriptor(child, cp));// (graph, STR, curConfiguration, "/" + c.name + "#" + conn.getName(graph)));
--            for(Pair<String,Resource> cpzz : fc.cps) {
--              if(cpzz.first == null) {
--                      throw new DatabaseException("Lifted connection was not resolved.");
--              }
--              result.add(new PairConnectionDescriptor(curConfiguration, cpzz));
--            }
++            fc.addConnectionDescriptors(graph, curConfiguration, result);
              return result;
              
          } else {
index f133adee02e3c783b7e7fe5b8dc12ef93a6a4d5a,f133adee02e3c783b7e7fe5b8dc12ef93a6a4d5a..13ef05145a818981c180b4dad865b17c6e983a57
@@@ -1,8 -1,8 +1,5 @@@
  package org.simantics.structural2.variables;
  
--import gnu.trove.map.hash.THashMap;
--import gnu.trove.set.hash.THashSet;
--
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
@@@ -39,9 -39,9 +36,11 @@@ import org.simantics.structural2.proced
  import org.simantics.utils.datastructures.Pair;
  import org.slf4j.LoggerFactory;
  
++import gnu.trove.map.hash.THashMap;
++
  public class StandardProceduralChildVariable extends AbstractChildVariable {
  
--    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StandardProceduralChildVariable.class);
++    static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StandardProceduralChildVariable.class);
        /*
         * Extension points
         * 
        final private Map<String, Variable> properties;
        final private List<Object> propertyIdentity;
        
--    public static class FixedConnection implements org.simantics.structural2.variables.Connection {
--
--              final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
--        
--        final private Variable parent;
--        
--        public FixedConnection(Variable parent) {
--            this.parent = parent;
--        }
--        
--        @Override
--        public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
--              
--              Set<Variable> result = new THashSet<Variable>();
--            for(Pair<String,Resource> cp : cps) {
--              Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); 
--              Variable cp2 = component.getPossibleProperty(graph, cp.second);
--              if(cp2 != null)
--                      for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
--                              result.add(desc.getVariable(graph));
--                      }
--                else
--                      LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
--            }
--            return result;
--            
--        }
--        
--              @Override
--              public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
--                      
--              Set<String> result = new THashSet<String>();
--            for(Pair<String,Resource> cp : cps) {
--              Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); 
--              Variable cp2 = component.getPossibleProperty(graph, cp.second);
--              if(cp2 != null)
--                      for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
--                              result.add(desc.getURI(graph));
--                      }
--                else
--                      LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
--            }
--            return result;
--                      
--              }
--              
--              @Override
--              public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
--                      
--              Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();
--            for(Pair<String,Resource> cp : cps) {
--              Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first); 
--              Variable cp2 = component.getPossibleProperty(graph, cp.second);
--              if(cp2 != null)
--                      result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));
--                else
--                      LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
--            }
--            return result;
--                      
--              }        
--
--        @Override
--              public int hashCode() {
--                      final int prime = 31;
--                      int result = 1;
--                      result = prime * result + ((cps == null) ? 0 : cps.hashCode());
--                      result = prime * result
--                                      + ((parent == null) ? 0 : parent.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;
--                      FixedConnection other = (FixedConnection) obj;
--                      if (cps == null) {
--                              if (other.cps != null)
--                                      return false;
--                      } else if (!cps.equals(other.cps))
--                              return false;
--                      if (parent == null) {
--                              if (other.parent != null)
--                                      return false;
--                      } else if (!parent.equals(other.parent))
--                              return false;
--                      return true;
--              }
--
--    }
--    
--      public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
++    public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
                super(node);
                assert name != null;
          assert type != null;
                                fc = new FixedConnection(parent);
                                map.put(p, fc);
                        }
--                      fc.cps.addAll(cps);             
++                      fc.addAll(cps);         
                    }
                }
                for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {