]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java
Let the request processor handle the exceptions
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / Functions.java
index 3892b50151a94b036d3a0a3460119cc3d6beaf85..0a7e004f7dcab5e75740d176100c78d59c3dfb47 100644 (file)
-package org.simantics.document.server;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.primitiverequest.Adapter;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.common.request.UniqueRead;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.function.All;\r
-import org.simantics.db.layer0.request.ProjectModels;\r
-import org.simantics.db.layer0.request.VariableProperty;\r
-import org.simantics.db.layer0.request.VariableRead;\r
-import org.simantics.db.layer0.request.VariableValue;\r
-import org.simantics.db.layer0.variable.ConstantPropertyVariable;\r
-import org.simantics.db.layer0.variable.ProxyChildVariable;\r
-import org.simantics.db.layer0.variable.ProxySessionRequest;\r
-import org.simantics.db.layer0.variable.ProxyVariables;\r
-import org.simantics.db.layer0.variable.StandardGraphChildVariable;\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.Variables;\r
-import org.simantics.document.base.ontology.DocumentationResource;\r
-import org.simantics.document.server.bean.Command;\r
-import org.simantics.document.server.bean.DataDefinition;\r
-import org.simantics.document.server.handler.AbstractEventHandler;\r
-import org.simantics.document.server.handler.AbstractResponseHandler;\r
-import org.simantics.document.server.handler.EventHandler;\r
-import org.simantics.document.server.io.CommandContext;\r
-import org.simantics.document.server.io.CommandContextImpl;\r
-import org.simantics.document.server.io.CommandContextMutable;\r
-import org.simantics.document.server.io.CommandResult;\r
-import org.simantics.document.server.request.ServerSCLHandlerValueRequest;\r
-import org.simantics.document.server.request.ServerSCLValueRequest;\r
-import org.simantics.document.server.serverResponse.ServerResponse;\r
-import org.simantics.document.server.serverResponse.SuccessResponse;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.scl.SCLRealm;\r
-import org.simantics.modeling.scl.SCLSessionManager;\r
-import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;\r
-import org.simantics.modeling.services.ComponentNamingStrategy;\r
-import org.simantics.operation.Layer0X;\r
-import org.simantics.project.IProject;\r
-import org.simantics.scl.compiler.types.TCon;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.reflection.annotations.SCLValue;\r
-import org.simantics.scl.runtime.SCLContext;\r
-import org.simantics.scl.runtime.function.Function;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.scl.runtime.function.FunctionImpl1;\r
-import org.simantics.scl.runtime.function.FunctionImpl4;\r
-import org.simantics.scl.runtime.reporting.SCLReportingHandler;\r
-import org.simantics.scl.runtime.tuple.Tuple;\r
-import org.simantics.scl.runtime.tuple.Tuple0;\r
-import org.simantics.scl.runtime.tuple.Tuple2;\r
-import org.simantics.scl.runtime.tuple.Tuple3;\r
-import org.simantics.scl.runtime.tuple.Tuple4;\r
-import org.simantics.scl.runtime.tuple.Tuple5;\r
-import org.simantics.simulation.experiment.IExperiment;\r
-import org.simantics.simulation.ontology.SimulationResource;\r
-import org.simantics.simulation.project.IExperimentManager;\r
-import org.simantics.structural2.variables.Connection;\r
-import org.simantics.structural2.variables.VariableConnectionPointDescriptor;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-public class Functions {\r
-       \r
-    @SCLValue(type = "VariableMap")\r
-    public static VariableMap inputSpaceChildren = new VariableMapImpl() {\r
-\r
-        private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {\r
-            Variable root = Variables.getRootVariable(graph);\r
-            return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);\r
-        }\r
-        \r
-        @Override\r
-        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-\r
-            if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);\r
-            return All.standardChildDomainChildren.getVariable(graph, context, name);\r
-            \r
-        }\r
-\r
-        @Override\r
-        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-\r
-            map = All.standardChildDomainChildren.getVariables(graph, context, map);\r
-            if(map == null) map = new THashMap<String,Variable>();\r
-            map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));\r
-            return map;\r
-            \r
-        }\r
-        \r
-    };\r
-    \r
-    static class DocumentProxyChildVariable extends ProxyChildVariable {\r
-\r
-        public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {\r
-            super(base, parent, other, name);\r
-        }\r
-    \r
-        @Override\r
-        public Variable create(Variable base, Variable parent, Variable other, String name) {\r
-            return new DocumentProxyChildVariable(base, parent, other, name);\r
-        }\r
-        \r
-        public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
-            \r
-               if(CONTEXT_END.equals(name)) {\r
-               if(other instanceof ProxyChildVariable) {\r
-                       // The context is also a proxy - let it do the job\r
-                    return super.getPossibleChild(graph, name);\r
-               } else {\r
-                       return new RootVariable(this, base.getRepresents(graph));\r
-               }\r
-               }\r
-            \r
-            return super.getPossibleChild(graph, name);\r
-            \r
-        }\r
-        \r
-        public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
-\r
-            Collection<Variable> result = super.getChildren(graph);\r
-            if(!(base instanceof ProxyChildVariable)) {\r
-               result.add(new RootVariable(this, base.getRepresents(graph)));\r
-            }\r
-            return result;\r
-            \r
-        }       \r
-        \r
-    }\r
-    \r
-    static class RootVariable extends StandardGraphChildVariable {\r
-\r
-        public RootVariable(DocumentProxyChildVariable parent, Resource resource) {\r
-            super(parent, null, resource);\r
-        }\r
-        \r
-        @Override\r
-        public String getName(ReadGraph graph) throws DatabaseException {\r
-            return ProxyChildVariable.CONTEXT_END;\r
-        }\r
-        \r
-        @SuppressWarnings("deprecation")\r
-        @Override\r
-        public Variable getNameVariable(ReadGraph graph) throws DatabaseException {\r
-            return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);\r
-        }\r
-        \r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-       Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
-       DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-       String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);\r
-       if(uri == null) {\r
-               // TODO HAXX - Please fix this\r
-               // we have no URI so this probably means that someone has inserted a non-session \r
-               // into the proxy variable => return that instead\r
-               return session;\r
-       }\r
-       return Variables.getVariable(graph, uri);\r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-       Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
-       return session.getPossibleChild(graph, "__scl__");\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-       Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
-       return session.getPossibleChild(graph, "__icstate__");\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-       return graph.syncRequest(new ProxySessionRequest(context));\r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-        // Try if experiment (run) has been used as the input\r
-        Variable var = input(graph, converter, context);\r
-        SimulationResource SR = SimulationResource.getInstance(graph);\r
-        while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {\r
-            var = var.getParent(graph);\r
-        }\r
-        \r
-        if(var != null) {\r
-            IExperiment exp = getExperiment(graph, var);\r
-            if(exp == null)\r
-                return null;\r
-        }\r
-        \r
-        return var;\r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-        Variable var = input(graph, converter, context);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {\r
-            var = var.getParent(graph);\r
-        }\r
-        \r
-        return var;\r
-    }\r
-    \r
-    private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {\r
-       \r
-       ArrayList<Variable> result = new ArrayList<Variable>();\r
-       \r
-        DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-\r
-       Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);\r
-       if(broadcasted != null) result.add(broadcasted);\r
-       \r
-       for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {\r
-               result.addAll(getBroadcasted(graph, child));\r
-       }\r
-       \r
-       return result;\r
-       \r
-    }\r
-\r
-    private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {\r
-       \r
-       if(commandVariables.isEmpty()) return Collections.emptyList();\r
-       \r
-        String t = trigger;\r
-        TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();\r
-        \r
-        DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-        \r
-        int count = 0;\r
-        for (Variable c : commandVariables) {\r
-               \r
-            if(trigger == null)\r
-               t = c.getName(graph);\r
-            \r
-            Connection conn = c.getValue(graph);\r
-            Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);\r
-            if (targetConnectionPoint != null) {\r
-                Variable target = targetConnectionPoint.getParent(graph);\r
-                if (target != null) {\r
-                    \r
-                    Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);\r
-                    if(enabled != null && !enabled) continue;\r
-                       \r
-                    Integer ordinal;\r
-                    if (broadcast) {\r
-                       ordinal = ++count;\r
-                    } else {\r
-                       ordinal = 1;\r
-                           try {\r
-                               String o = c.getPossiblePropertyValue(graph, "ordinal");\r
-                               if(o != null)\r
-                                   ordinal = Integer.parseInt(o);\r
-                           } catch (NumberFormatException e) {}\r
-                    }\r
-                    \r
-                    String constantKey = target.getPossiblePropertyValue(graph, "constantKey");\r
-                    String constantValue = target.getPossiblePropertyValue(graph, "constantValue");\r
-                    \r
-                    CommandContextMutable newConstants = (CommandContextMutable)constants; \r
-                    if(constantKey != null && constantValue != null) {\r
-                       if(!constantKey.isEmpty()) {\r
-                               newConstants = new CommandContextImpl().merge(constants);\r
-                               newConstants.putString(constantKey, constantValue);\r
-                       }\r
-                    }\r
-                    \r
-                    String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");\r
-                    if(requiredKey != null && !requiredKey.isEmpty()) {\r
-                       if (newConstants == constants) {\r
-                               newConstants = new CommandContextImpl().merge(constants);\r
-                       }\r
-                               newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));\r
-                    }\r
-                    \r
-                    String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");\r
-                    if(forbiddenKey != null && !forbiddenKey.isEmpty()) {\r
-                       if (newConstants == constants) {\r
-                               newConstants = new CommandContextImpl().merge(constants);\r
-                       }\r
-                               newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));\r
-                    }\r
-\r
-                    if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {\r
-\r
-                       // This is a broadcast terminal of a container\r
-                        List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);\r
-                        sequences.put(ordinal, broadcastCommands);\r
-\r
-                    } else {\r
-\r
-                       Command command = new Command(DocumentServerUtils.getId(graph, target), t, \r
-                                       targetConnectionPoint.getName(graph), newConstants);\r
-                       sequences.put(ordinal, Collections.singletonList(command));\r
-                       \r
-                    }\r
-\r
-                }\r
-            }\r
-        }\r
-\r
-        List<Command> commands = new ArrayList<Command>();\r
-        for (List<Command> commandList : sequences.values()) {\r
-               for (Command command : commandList) {\r
-                       commands.add(command);\r
-               }\r
-        }\r
-        \r
-        return commands;\r
-    }\r
-\r
-    /**\r
-     * Commands\r
-     * \r
-     * @param graph\r
-     * @param variable\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {\r
-       return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);\r
-    }\r
-\r
-    /**\r
-     * Data definitions\r
-     * \r
-     * @param graph\r
-     * @param variable\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        DocumentationResource DOC = DocumentationResource.getInstance(graph); \r
-       ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();\r
-        // Find data definition connections\r
-        for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {\r
-            Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);\r
-            // Find data the other end of definition connection\r
-            Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,\r
-                    dataDefinitionRelation, dataDefinitionConnection);\r
-            if (dataDefinitionProviders != null) {\r
-\r
-                for(Variable dataDefinitionProvider : dataDefinitionProviders) {\r
-\r
-                    Variable dataDefinition = dataDefinitionProvider.getParent(graph);\r
-                    if (dataDefinition != null) {\r
-                        // Found other end. Is should contain ONE data\r
-// definition connection to the actual data\r
-                        Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);\r
-                        if (dataCollection.size() == 1) {\r
-                            Variable dataRelation = dataCollection.iterator().next();\r
-                            Connection dataConnection = dataRelation.getValue(graph);\r
-                            // Find data the other end of definition connection\r
-                            Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,\r
-                                    dataRelation, dataConnection);\r
-                            if (dataConnectionPoint != null) {\r
-                                Variable data = dataConnectionPoint.getParent(graph);\r
-                                Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);\r
-\r
-                                if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {\r
-\r
-                                       String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,\r
-                                               Bindings.STRING);\r
-                                       String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,\r
-                                               Bindings.STRING);\r
-\r
-                                       dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
-                                                       sourceProperty, targetProperty));\r
-                                \r
-                                } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {\r
-\r
-                                       List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);\r
-                                       List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);\r
-\r
-                                       for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {\r
-                                               dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
-                                                       sourcesProperty.get(i), targetsProperty.get(i)));\r
-                                       }\r
-                                }\r
-                            }\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return dataDefinitions;\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-       private static <T> List<T> toList(Object o, Class<T> c) {\r
-       List<T> result = null;\r
-       if (o instanceof List) {\r
-               return (List<T>)o;\r
-       } else if (o instanceof Object[]) {\r
-               result = new ArrayList<T>(((Object[])o).length);\r
-               for (T item : (T[])o) {\r
-                       result.add(item);\r
-               }\r
-               return result;\r
-       } else {\r
-               return Collections.<T>emptyList();\r
-       }\r
-    }\r
-    \r
-    public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {\r
-        return new EventHandler() {\r
-\r
-            @Override\r
-            public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {\r
-                return null;\r
-            }\r
-\r
-        };\r
-    }\r
-    \r
-    public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
-        \r
-       final Session session = graph.getSession();\r
-       \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                                       String result = session.sync(new WriteResultRequest<String>() {\r
-                                           \r
-                                           @Override\r
-                                           public String perform(WriteGraph graph) throws DatabaseException {\r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               try {\r
-                                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
-                                                       @Override\r
-                                                       public String apply(String key) {\r
-                                                           return parameters.getString(key);\r
-                                                       }\r
-                                                   }; \r
-                                                   Object response = (String)fn.apply(variable, pf);\r
-                                                   if(response instanceof String) {\r
-                                                       return (String)response;\r
-                                                   }\r
-                                                   return null;\r
-                                               } catch (Throwable t) {\r
-                                                   t.printStackTrace();\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-                                               \r
-                                               return null;\r
-                                               \r
-                                           }\r
-                                           \r
-                                       });\r
-                                       \r
-                       return new SuccessResponse(result);\r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-    \r
-    public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
-        \r
-       final Session session = graph.getSession();\r
-       \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                                       String result = session.sync(new UniqueRead<String>() {\r
-                                           \r
-                                           @Override\r
-                                           public String perform(ReadGraph graph) throws DatabaseException {\r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               try {\r
-                                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
-                                                       @Override\r
-                                                       public String apply(String key) {\r
-                                                           return parameters.getString(key);\r
-                                                       }\r
-                                                   }; \r
-                                                   Object response = (String)fn.apply(variable, pf);\r
-                                                   if(response instanceof String) {\r
-                                                       return (String)response;\r
-                                                   }\r
-                                                   return null;\r
-                                               } catch (Throwable t) {\r
-                                                   t.printStackTrace();\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-                                               \r
-                                               return null;\r
-                                               \r
-                                           }\r
-                                           \r
-                                       });\r
-                                       \r
-                       return new SuccessResponse(result);\r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-\r
-    public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {\r
-        \r
-       final Session session = graph.getSession();\r
-       \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                       CommandResult result = session.sync(new UniqueRead<CommandResult>() {\r
-                                           \r
-                                           @Override\r
-                                           public CommandResult perform(ReadGraph graph) throws DatabaseException {\r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               try {\r
-                                                   Object response = fn.apply(parameters);\r
-                                                   if(response instanceof CommandResult) {\r
-                                                       return (CommandResult)response;\r
-                                                   }\r
-                                                   return null;\r
-                                               } catch (Throwable t) {\r
-                                                   t.printStackTrace();\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-                                               \r
-                                               return null;\r
-                                               \r
-                                           }\r
-                                           \r
-                                       });\r
-                                       \r
-                       return result;\r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-\r
-    public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {\r
-\r
-        Variable anyFunction = self.browse(graph, ".#" + function);\r
-        if(anyFunction == null) return null;\r
-\r
-        final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);\r
-       \r
-       final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);\r
-        String expression = anyFunction.getPropertyValue(graph, "expression");\r
-        \r
-       final Session session = graph.getSession();\r
-       \r
-        return new AbstractResponseHandler(expression) {\r
-            \r
-               private String formatError(RequestProcessor proc, Throwable t) {\r
-                       \r
-                       try {\r
-                               \r
-                                       return proc.syncRequest(new UniqueRead<String>() {\r
-\r
-                                               @Override\r
-                                               public String perform(ReadGraph graph) throws DatabaseException {\r
-                                                       Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);\r
-                                                       String uri2 = proxy.getURI(graph);\r
-                                                       String uri = self.getParent(graph).getURI(graph);\r
-\r
-                                                       String path = uri.substring(uri2.length());\r
-\r
-                                                       String expr = anyFunction.getPossiblePropertyValue(graph, "expression");\r
-                                                       StringBuilder message = new StringBuilder();\r
-                                                       message.append("Handler execution failed\n");\r
-                                                       message.append(" handler=" + path + "\n");\r
-                                                       message.append(" expression=" + expr + "\n");\r
-                                                       message.append(" message=" + t.getMessage() + "\n");\r
-                                                       return message.toString();\r
-                                               }\r
-                                               \r
-                                       });\r
-                                       \r
-                               } catch (DatabaseException e) {\r
-                                       \r
-                                       return e.getMessage();\r
-                                       \r
-                               }\r
-                       \r
-               }\r
-               \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                       Object result = null;\r
-                       if(effects.contains(Types.WRITE_GRAPH)) {\r
-\r
-                               result = session.syncRequest(new WriteResultRequest<Object>() {\r
-\r
-                                                       @Override\r
-                                                       public Object perform(WriteGraph graph)\r
-                                                                       throws DatabaseException {\r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               try {\r
-                                                       Object response = fn.apply(parameters);\r
-                                                       return response;\r
-                                               } catch (Throwable t) {\r
-                                                       return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-\r
-                                                       }\r
-                               });\r
-                               \r
-                       } else if(effects.contains(Types.READ_GRAPH)) {\r
-\r
-                               result = session.sync(new UniqueRead<Object>() {\r
-\r
-                                       @Override\r
-                                       public Object perform(ReadGraph graph) throws DatabaseException {\r
-                                               \r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               \r
-                                               try {\r
-                                                       Object response = fn.apply(parameters);\r
-                                                       return response;\r
-                                               } catch (Throwable t) {\r
-                                                       return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-                                               \r
-                                       }\r
-                               });\r
-\r
-                       } else {\r
-                               result = fn.apply(parameters);\r
-                       }\r
-\r
-                       if (result instanceof org.simantics.document.server.serverResponse.Error) {\r
-                               return (CommandResult)result;\r
-                       }\r
-                       \r
-                       if (result instanceof CommandResult) {\r
-                               return (CommandResult)result;\r
-                       } else {\r
-                               CommandContextMutable assignments = new CommandContextImpl();\r
-                               assignments.putValue("result", result);\r
-                               return new ServerResponse(200, "", assignments);\r
-                       }                       \r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));\r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-    \r
-    public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {\r
-        \r
-       final Session session = graph.getSession();\r
-       \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                       CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {\r
-                                           \r
-                                           @Override\r
-                                           public CommandResult perform(WriteGraph graph) throws DatabaseException {\r
-                                               SCLContext sclContext = SCLContext.getCurrent();\r
-                                               Object oldGraph = sclContext.put("graph", graph);\r
-                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                                               try {\r
-                                                   Object response = fn.apply(parameters);\r
-                                                   if(response instanceof CommandResult) {\r
-                                                       return (CommandResult)response;\r
-                                                   }\r
-                                                   return null;\r
-                                               } catch (Throwable t) {\r
-                                                   t.printStackTrace();\r
-                                               } finally {\r
-                                                       sclContext.put("graph", oldGraph);\r
-                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                                               }\r
-                                               \r
-                                               return null;\r
-                                               \r
-                                           }\r
-                                           \r
-                                       });\r
-                                       \r
-                       return result;\r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-\r
-    public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {\r
-        \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-                       \r
-                       SCLContext sclContext = SCLContext.getCurrent();\r
-                       Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                       try {\r
-                               Object response = fn.apply(parameters);\r
-                               if(response instanceof CommandResult) {\r
-                                       return (CommandResult)response;\r
-                               }\r
-                               return null;\r
-                       } catch (Throwable t) {\r
-                               t.printStackTrace();\r
-                       } finally {\r
-                               sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                       }\r
-\r
-                       return null;\r
-                                               \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-\r
-    public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {\r
-       \r
-        return new AbstractEventHandler() {\r
-            \r
-                       @Override\r
-                       public CommandResult handle(final CommandContext parameters) {\r
-                               \r
-                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
-                \r
-                try {\r
-\r
-                       String result = "";\r
-                       \r
-                               SCLContext sclContext = SCLContext.getCurrent();\r
-                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
-                               try {\r
-                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
-                                       @Override\r
-                                       public String apply(String key) {\r
-                                           return parameters.getString(key);\r
-                                       }\r
-                                   }; \r
-                                   Object response = (String)fn.apply(pf);\r
-                                   if(response instanceof String) {\r
-                                       result = (String)response;\r
-                                   }\r
-                               } catch (Throwable t) {\r
-                                   t.printStackTrace();\r
-                               } finally {\r
-                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
-                               }\r
-                                       \r
-                       return new SuccessResponse(result);\r
-                                       \r
-                               } catch (Throwable e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
-                               }\r
-                \r
-                       }\r
-            \r
-        };\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
-    public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-        return ServerSCLValueRequest.compileAndEvaluate(graph, context);\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
-    public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-        return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")\r
-    public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {\r
-        return createComponentNamingStrategy(graph);\r
-    }\r
-\r
-    public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {\r
-        Layer0X L0X = Layer0X.getInstance(graph);\r
-        @SuppressWarnings({ "unchecked", "rawtypes" })\r
-        final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());\r
-        @SuppressWarnings("rawtypes")\r
-        Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {\r
-            @Override\r
-            public Object apply(ReadGraph p0, Resource p1, String p2) {\r
-                return apply(p0, p1, p2);\r
-            }\r
-            @SuppressWarnings("unchecked")\r
-            @Override\r
-            public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {\r
-                return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);\r
-            }\r
-        };\r
-        return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);\r
-    }\r
-\r
-    public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {\r
-        if (variable == null)\r
-            return null;\r
-\r
-        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-\r
-        Variable var = variable;\r
-        Resource represents = var.getRepresents(graph);\r
-        Resource activeRun = null;\r
-        if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {\r
-            activeRun = represents;\r
-        }\r
-\r
-        IProject project = Simantics.peekProject();\r
-        if (activeRun != null && project != null) {\r
-            IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
-            if (expMan != null)\r
-                return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));\r
-        }\r
-\r
-        return null;\r
-    }\r
-    \r
-    public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {\r
-       List<Object> list = new ArrayList<Object>();\r
-       if (tuple instanceof Tuple) {\r
-               Collections.addAll(list, ((Tuple)tuple).toArray());\r
-       } else {\r
-               list.add(tuple);                \r
-       }\r
-       context.putRow(key, list);\r
-       return context;\r
-    }\r
-    \r
-    public static List<Object> getTuples(CommandContext context, String key) {\r
-       List<List<Object>> rows = context.getRows(key);\r
-       List<Object> tuples = new ArrayList<Object>();\r
-       if (rows != null) {\r
-               for (List<Object> row : rows) {\r
-                       switch (row.size()) {\r
-                       case 0: tuples.add(Tuple0.INSTANCE); break;\r
-                       case 1: tuples.add(row.get(1)); break;\r
-                       case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;\r
-                       case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;\r
-                       case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;\r
-                       case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;\r
-                       }\r
-               }\r
-       }\r
-       return tuples;\r
-    }\r
-    \r
-    public static String printContext(CommandContext context) {\r
-       String str = context.toString();\r
-       System.err.println(str);\r
-       return str;\r
-    }\r
-    \r
-    @SCLValue(type = "AbstractEventHandler")\r
-    public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {\r
-\r
-               @Override\r
-               public CommandResult handle(CommandContext context) {\r
-                       return null;\r
-               }\r
-\r
-    };\r
-\r
-    public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
-       \r
-       String baseURI = base.getURI(graph);\r
-       \r
-       String selfURI = self.getURI(graph);\r
-       \r
-       String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));\r
-       String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());\r
-       String stripped = prefix + suffix;\r
-       \r
-       String relative = Variables.getRelativeRVI(baseURI, stripped); \r
-       \r
-       return Variables.getRVI(relative, ref);\r
-       \r
-    }\r
-    \r
-    public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
-       \r
-       String id = sclStateKey(graph, base, self, ref);\r
-\r
-       Variable sclVar = base.getPossibleChild(graph, "__scl__");\r
-       if(sclVar == null) return null;\r
-       \r
-       return sclVar.getPossibleProperty(graph, id);\r
-       \r
-    }\r
-    \r
-    public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
-       \r
-       Variable stateVariable = sclStateVariable(graph, base, self, ref);\r
-       if (stateVariable != null) {\r
-               \r
-               return stateVariable.getValue(graph);\r
-               \r
-       } else {\r
-               \r
-               String id = sclStateKey(graph, base, self, ref);\r
-\r
-               SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");\r
-               realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);\r
-               \r
-               return defaultValue;\r
-               \r
-       }\r
-    }\r
-    \r
-    public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {\r
-       \r
-       String id = sclStateKey(graph, base, self, ref);\r
-\r
-       SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");\r
-       realm.getConnection().setVariable(id, getSCLType(value), value);\r
-       realm.refreshVariablesSync();\r
-               \r
-    }\r
-    \r
-    public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
-       Resource project = Simantics.getProjectResource();\r
-       Variable component = self.getParent(graph);\r
-       Variable projectVariable = Variables.getVariable(graph, project);\r
-       return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);\r
-    }\r
-    \r
-    public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {\r
-       Resource project = Simantics.getProjectResource();\r
-       Variable component = self.getParent(graph);\r
-       Variable projectVariable = Variables.getVariable(graph, project);\r
-       setSclStateValue(graph, projectVariable, component, ref, value);\r
-    }\r
-    \r
-    private static Type getSCLType(Object value) throws DatabaseException {\r
-       Binding b = Bindings.getBindingUnchecked(value.getClass());\r
-       Datatype t = b.type();\r
-       if(Datatypes.STRING.equals(t)) return Types.STRING;\r
-       if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;\r
-       throw new DatabaseException("Type not supported");\r
-    }\r
-\r
-    public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {\r
-       Resource project = Simantics.getProjectResource();\r
-       ArrayList<Variable> result = new ArrayList<Variable>();\r
-       for(Resource model : graph.syncRequest(new ProjectModels(project))) {\r
-               result.add(Variables.getVariable(graph, model));\r
-       }\r
-       return result;\r
-    }\r
-\r
-    public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {\r
-       return var.getName(graph);\r
-    }\r
-    \r
-    public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {\r
-       Variable property = graph.syncRequest(new VariableProperty(variable, name));\r
-       return graph.syncRequest(new VariableValue<Object>(property));\r
-    }\r
-\r
-    public static class ParentExistsRequest extends VariableRead<Boolean> {\r
-\r
-               public ParentExistsRequest(Variable parent) {\r
-                       super(parent);\r
-               }\r
-\r
-               @Override\r
-               public Boolean perform(ReadGraph graph) throws DatabaseException {\r
-                       \r
-                       Variable existsProperty = variable.getPossibleProperty(graph, "exists");\r
-                       if(existsProperty == null) return true;\r
-                       \r
-                       Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);\r
-                       if (exists == null || !exists) return false;\r
-\r
-               return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));\r
-\r
-               }\r
-       \r
-    } \r
-\r
-    public static class PathExistsRequest extends VariableRead<Boolean> {\r
-\r
-               public PathExistsRequest(Variable variable) {\r
-                       super(variable);\r
-               }\r
-\r
-               @Override\r
-               public Boolean perform(ReadGraph graph) throws DatabaseException {\r
-                       \r
-                       Variable widget = variable.getParent(graph);\r
-               \r
-               Boolean exists = widget.getPossiblePropertyValue(graph, "exists");\r
-                       if (exists == null || !exists) return false;\r
-               \r
-               if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;\r
-               \r
-               DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-               Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);\r
-               for (Variable cp : cps) {\r
-                       \r
-                       Connection conn = cp.getValue(graph);\r
-                               Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);\r
-                               if (otherCp != null) {\r
-                                       Variable parentWidget = otherCp.getParent(graph);\r
-                                       if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
-                                               return true;\r
-                                       }\r
-                               } else {\r
-                                       Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {\r
-                                   @Override\r
-                                   public Variable perform(ReadGraph graph) throws DatabaseException {\r
-                                       DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-                                       Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);\r
-\r
-                                               for(VariableConnectionPointDescriptor desc : descs) {\r
-                                                       if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {\r
-                                                               return desc.getVariable(graph);\r
-                                                       }\r
-                                               }\r
-                                               return null;\r
-                                   }\r
-                               });\r
-                                       if (parentCp != null) {\r
-                                               Variable parentWidget = parentCp.getParent(graph);\r
-                                               if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
-                                                       return true;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               \r
-                       Resource type = widget.getType(graph);\r
-                       return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||\r
-                               (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());\r
-               }\r
-    } \r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")\r
-    public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-       return graph.syncRequest(new PathExistsRequest(context));\r
-    }\r
-    \r
+package org.simantics.document.server;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.simantics.Simantics;
+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;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+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.UniqueRead;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.function.All;
+import org.simantics.db.layer0.request.ProjectModels;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.PropertyInfoRequest;
+import org.simantics.db.layer0.request.VariableProperty;
+import org.simantics.db.layer0.request.VariableRead;
+import org.simantics.db.layer0.request.VariableValueWithBinding;
+import org.simantics.db.layer0.scl.SCLDatabaseException;
+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.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;
+import org.simantics.document.server.bean.DataDefinition;
+import org.simantics.document.server.handler.AbstractEventHandler;
+import org.simantics.document.server.handler.AbstractResponseHandler;
+import org.simantics.document.server.handler.EventHandler;
+import org.simantics.document.server.io.CommandContext;
+import org.simantics.document.server.io.CommandContextImpl;
+import org.simantics.document.server.io.CommandContextMutable;
+import org.simantics.document.server.io.CommandResult;
+import org.simantics.document.server.io.IConsole;
+import org.simantics.document.server.request.NodeRequest;
+import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
+import org.simantics.document.server.request.ServerSCLValueRequest;
+import org.simantics.document.server.serverResponse.ServerResponse;
+import org.simantics.document.server.serverResponse.SuccessResponse;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.scl.SCLRealm;
+import org.simantics.modeling.scl.SCLSessionManager;
+import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
+import org.simantics.modeling.services.ComponentNamingStrategy;
+import org.simantics.operation.Layer0X;
+import org.simantics.project.IProject;
+import org.simantics.scl.compiler.module.repository.ImportFailureException;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.FunctionImpl1;
+import org.simantics.scl.runtime.function.FunctionImpl4;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
+import org.simantics.scl.runtime.tuple.Tuple;
+import org.simantics.scl.runtime.tuple.Tuple0;
+import org.simantics.scl.runtime.tuple.Tuple2;
+import org.simantics.scl.runtime.tuple.Tuple3;
+import org.simantics.scl.runtime.tuple.Tuple4;
+import org.simantics.scl.runtime.tuple.Tuple5;
+import org.simantics.simulation.experiment.IExperiment;
+import org.simantics.simulation.ontology.SimulationResource;
+import org.simantics.simulation.project.IExperimentManager;
+import org.simantics.structural2.variables.Connection;
+import org.simantics.structural2.variables.StandardProceduralChildVariable;
+import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.map.hash.THashMap;
+
+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) {
+               try {
+                       Object value = property.getValue(graph);
+                               map.put(name, new ConstantPropertyVariable(parent, name, value, null));
+               } catch (DatabaseException e) {
+                       Variable propertyExceptions = map.get(NodeRequest.PROPERTY_VALUE_EXCEPTIONS);
+                       Map<String, Exception> exceptionMap;
+                       if (propertyExceptions == null) {
+                               exceptionMap = new TreeMap<String, Exception>();
+                               propertyExceptions = new ConstantPropertyVariable(parent, NodeRequest.PROPERTY_VALUE_EXCEPTIONS, exceptionMap, null);
+                               map.put(NodeRequest.PROPERTY_VALUE_EXCEPTIONS, propertyExceptions);
+                       } else {
+                               try {
+                                               exceptionMap = propertyExceptions.getValue(graph);
+                                       } catch (DatabaseException e1) {
+                                               Logger.defaultLogError(e1);
+                                               return;
+                                       }
+                       }
+                       String label = name;
+                       try {
+                               label = property.getLabel(graph);
+                       } catch (DatabaseException e2) {
+
+                       }
+                       exceptionMap.put(label, e);
+               }
+       }
+       
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            return All.getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(final ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+            if(map == null) map = new HashMap<String,Variable>();
+
+            Variable parent = context.getParent(graph);
+
+            DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+            if(parent instanceof StandardProceduralChildVariable) {
+
+                StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent;
+                for(Variable property : procedural.getProperties(graph/*, DocumentationResource.URIs.Document_AttributeRelation*/)) {
+                    if(property instanceof StandardAssertedGraphPropertyVariable) {
+                        StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property;
+                        if("dataDefinitions".equals(ass.property.name) || "commands".equals(ass.property.name)  || "pollingFunction".equals(ass.property.name)) {
+                               storePropertyValueAndExceptions(graph, parent, ass.property.name, property, map);
+                        }
+                        continue;
+                    }
+                    Resource predicate = property.getPossiblePredicateResource(graph);
+                    if(predicate != null) {
+                        PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
+                        if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
+                               Variable prop = parent.getProperty(graph, predicate);
+                            storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
+                        }
+                    }
+                }
+
+            } else {
+
+                Resource parentRes = parent.getRepresents(graph);
+                {
+                       Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_commands);
+                       storePropertyValueAndExceptions(graph, parent, "commands", prop, map);
+                }
+
+                if (graph.getPossibleObject(parentRes, DOC.Properties_dataDefinitions) != null) {
+                       Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_dataDefinitions);
+                       storePropertyValueAndExceptions(graph, parent, "dataDefinitions", prop, map);
+                }
+                
+                DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
+                PrimitivePropertyStatementsProcedure foo = new PrimitivePropertyStatementsProcedure();
+
+                dqs.forEachDirectPersistentStatement(graph, parentRes, foo);
+
+                for(Statement stm : foo.result) {
+                    Resource predicate = stm.getPredicate();
+                    PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
+
+                    if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
+                       Variable prop = new StandardGraphPropertyVariable(graph, parent, predicate);
+                       storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
+                    } else {
+                        Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation);
+                        if(definition != null) {
+                               PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition));
+                               Variable prop = new StandardGraphPropertyVariable(graph, parent, definition);
+                            map.put(info2.name, new PrimitiveValueVariable(parent, info2.name, prop));
+                        }
+                    }
+                }
+            }
+            return map;
+
+        }
+
+    };
+
+    @SCLValue(type = "VariableMap")
+    public static VariableMap inputSpaceChildren = new VariableMapImpl() {
+
+        private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
+            Variable root = Variables.getRootVariable(graph);
+            return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
+        }
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+
+            if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
+            return All.standardChildDomainChildren.getVariable(graph, context, name);
+
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+            map = All.standardChildDomainChildren.getVariables(graph, context, map);
+            if(map == null) map = new THashMap<String,Variable>();
+            map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
+            return map;
+
+        }
+
+    };
+
+    static class DocumentProxyChildVariable extends ProxyChildVariable {
+
+        public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
+            super(base, parent, other, name);
+        }
+
+        @Override
+        public Variable create(Variable base, Variable parent, Variable other, String name) {
+            return new DocumentProxyChildVariable(base, parent, other, name);
+        }
+
+        public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
+
+               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));
+               }
+               }
+
+            return super.getPossibleChild(graph, name);
+
+        }
+
+        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;
+
+        }
+
+    }
+
+    static class RootVariable extends StandardGraphChildVariable {
+
+        public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
+            super(parent, null, resource);
+        }
+
+        @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);
+        }
+
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+       Variable session = graph.syncRequest(new ProxySessionRequest(context));
+       DocumentationResource DOC = DocumentationResource.getInstance(graph);
+       String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
+       if(uri == null) {
+               // TODO HAXX - Please fix this
+               // we have no URI so this probably means that someone has inserted a non-session 
+               // into the proxy variable => return that instead
+               return session;
+       }
+       return Variables.getVariable(graph, uri);
+    }
+
+    public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
+       Variable session = graph.syncRequest(new ProxySessionRequest(self));
+       if (session == null)
+               throw new DatabaseException("No state for " + self.getURI(graph));
+       return session.getPossibleChild(graph, "__scl__");
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+       Variable session = graph.syncRequest(new ProxySessionRequest(context));
+       if (session == null)
+           throw new DatabaseException("No state for " + context.getURI(graph));
+       return session.getPossibleChild(graph, "__scl__");
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+       Variable session = graph.syncRequest(new ProxySessionRequest(context));
+       return session.getPossibleChild(graph, "__icstate__");
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+       return graph.syncRequest(new ProxySessionRequest(context));
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+        // Try if experiment (run) has been used as the input
+        Variable var = input(graph, converter, context);
+        SimulationResource SR = SimulationResource.getInstance(graph);
+        while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
+            var = var.getParent(graph);
+        }
+
+        if(var != null) {
+            IExperiment exp = getExperiment(graph, var);
+            if(exp == null)
+                return null;
+        }
+
+        return var;
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+        Variable var = input(graph, converter, context);
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
+            var = var.getParent(graph);
+        }
+
+        return var;
+    }
+
+    private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
+
+       ArrayList<Variable> result = new ArrayList<Variable>();
+
+        DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+       Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
+       if(broadcasted != null) result.add(broadcasted);
+
+       for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
+               result.addAll(getBroadcasted(graph, child));
+       }
+
+       return result;
+
+    }
+
+    private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
+
+       if(commandVariables.isEmpty()) return Collections.emptyList();
+
+        String t = trigger;
+        TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
+
+        DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+        int count = 0;
+        for (Variable c : commandVariables) {
+
+            if(trigger == null)
+               t = c.getName(graph);
+
+            Connection conn = c.getValue(graph);
+            Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
+            if (targetConnectionPoint != null) {
+                Variable target = targetConnectionPoint.getParent(graph);
+                if (target != null) {
+
+                    Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
+                    if(enabled != null && !enabled) continue;
+
+                    Integer ordinal;
+                    if (broadcast) {
+                       ordinal = ++count;
+                    } else {
+                       ordinal = 1;
+                           try {
+                               String o = c.getPossiblePropertyValue(graph, "ordinal");
+                               if(o != null)
+                                   ordinal = Integer.parseInt(o);
+                           } catch (NumberFormatException e) {}
+                    }
+
+                    String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
+                    String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
+
+                    CommandContextMutable newConstants = (CommandContextMutable)constants; 
+                    if(constantKey != null && constantValue != null) {
+                       if(!constantKey.isEmpty()) {
+                               newConstants = new CommandContextImpl().merge(constants);
+                               newConstants.putString(constantKey, constantValue);
+                       }
+                    }
+
+                    String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
+                    if(requiredKey != null && !requiredKey.isEmpty()) {
+                       if (newConstants == constants) {
+                               newConstants = new CommandContextImpl().merge(constants);
+                       }
+                               newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
+                    }
+
+                    String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
+                    if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
+                       if (newConstants == constants) {
+                               newConstants = new CommandContextImpl().merge(constants);
+                       }
+                               newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
+                    }
+
+                    if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
+
+                       // This is a broadcast terminal of a container
+                        List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
+                        sequences.put(ordinal, broadcastCommands);
+
+                    } else {
+
+                       Command command = new Command(DocumentServerUtils.getId(graph, target), t, 
+                                       targetConnectionPoint.getName(graph), newConstants);
+                       sequences.put(ordinal, Collections.singletonList(command));
+
+                    }
+
+                }
+            }
+        }
+
+        List<Command> commands = new ArrayList<Command>();
+        for (List<Command> commandList : sequences.values()) {
+               for (Command command : commandList) {
+                       commands.add(command);
+               }
+        }
+
+        return commands;
+    }
+
+    /**
+     * Commands
+     * 
+     * @param graph
+     * @param variable
+     * @return
+     * @throws DatabaseException
+     */
+    public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
+       return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
+    }
+
+    /**
+     * Data definitions
+     * 
+     * @param graph
+     * @param variable
+     * @return
+     * @throws DatabaseException
+     */
+    public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
+        DocumentationResource DOC = DocumentationResource.getInstance(graph); 
+       ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
+        // Find data definition connections
+        for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
+            Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
+            // Find data the other end of definition connection
+            Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
+                    dataDefinitionRelation, dataDefinitionConnection);
+            if (dataDefinitionProviders != null) {
+
+                for(Variable dataDefinitionProvider : dataDefinitionProviders) {
+
+                    Variable dataDefinition = dataDefinitionProvider.getParent(graph);
+                    if (dataDefinition != null) {
+                        // Found other end. Is should contain ONE data
+// definition connection to the actual data
+                        Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
+                        if (dataCollection.size() == 1) {
+                            Variable dataRelation = dataCollection.iterator().next();
+                            Connection dataConnection = dataRelation.getValue(graph);
+                            // Find data the other end of definition connection
+                            Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
+                                    dataRelation, dataConnection);
+                            if (dataConnectionPoint != null) {
+                                Variable data = dataConnectionPoint.getParent(graph);
+                                Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
+
+                                if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
+
+                                       String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
+                                               Bindings.STRING);
+                                       String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
+                                               Bindings.STRING);
+
+                                       dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
+                                                       sourceProperty, targetProperty));
+
+                                } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
+
+                                       List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
+                                       List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
+
+                                       for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
+                                               dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
+                                                       sourcesProperty.get(i), targetsProperty.get(i)));
+                                       }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return dataDefinitions;
+    }
+
+    @SuppressWarnings("unchecked")
+       private static <T> List<T> toList(Object o, Class<T> c) {
+       List<T> result = null;
+       if (o instanceof List) {
+               return (List<T>)o;
+       } else if (o instanceof Object[]) {
+               result = new ArrayList<T>(((Object[])o).length);
+               for (T item : (T[])o) {
+                       result.add(item);
+               }
+               return result;
+       } else {
+               return Collections.<T>emptyList();
+       }
+    }
+
+    @Deprecated
+    public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
+        return new EventHandler() {
+            @Override
+            public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
+                return null;
+            }
+        };
+    }
+
+    @Deprecated
+    public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
+
+       final Session session = graph.getSession();
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                                       String result = session.sync(new WriteResultRequest<String>() {
+
+                                           @Override
+                                           public String perform(WriteGraph graph) throws DatabaseException {
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {
+                                                       @Override
+                                                       public String apply(String key) {
+                                                           return parameters.getString(key);
+                                                       }
+                                                   }; 
+                                                   Object response = (String)fn.apply(variable, pf);
+                                                   if(response instanceof String) {
+                                                       return (String)response;
+                                                   }
+                                                   return null;
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                           }
+
+                                       });
+
+                       return new SuccessResponse(result);
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+    @Deprecated
+    public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
+
+       final Session session = graph.getSession();
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                                       String result = session.sync(new UniqueRead<String>() {
+
+                                           @Override
+                                           public String perform(ReadGraph graph) throws DatabaseException {
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {
+                                                       @Override
+                                                       public String apply(String key) {
+                                                           return parameters.getString(key);
+                                                       }
+                                                   }; 
+                                                   Object response = (String)fn.apply(variable, pf);
+                                                   if(response instanceof String) {
+                                                       return (String)response;
+                                                   }
+                                                   return null;
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                           }
+
+                                       });
+
+                       return new SuccessResponse(result);
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+    @Deprecated
+    public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
+
+       final Session session = graph.getSession();
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                       CommandResult result = session.sync(new UniqueRead<CommandResult>() {
+
+                                           @Override
+                                           public CommandResult perform(ReadGraph graph) throws DatabaseException {
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                   Object response = fn.apply(parameters);
+                                                   if(response instanceof CommandResult) {
+                                                       return (CommandResult)response;
+                                                   }
+                                                   return null;
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                           }
+
+                                       });
+
+                       return result;
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+    public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
+
+        Variable anyFunction = self.browse(graph, ".#" + function);
+        if(anyFunction == null) return null;
+
+        final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
+
+       final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
+        String expression = anyFunction.getPropertyValue(graph, "expression");
+
+       final Session session = graph.getSession();
+
+        return new AbstractResponseHandler(expression) {
+
+               private String formatError(RequestProcessor proc, Throwable t) {
+
+                       try {
+
+                                       return proc.syncRequest(new UniqueRead<String>() {
+
+                                               @Override
+                                               public String perform(ReadGraph graph) throws DatabaseException {
+                                                       Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
+                                                       String uri2 = proxy.getURI(graph);
+                                                       String uri = self.getParent(graph).getURI(graph);
+
+                                                       String path = uri.substring(uri2.length());
+
+                                                       String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
+                                                       StringBuilder message = new StringBuilder();
+                                                       message.append("Handler execution failed\n");
+                                                       message.append(" handler=" + path + "\n");
+                                                       message.append(" expression=" + expr + "\n");
+                                                       message.append(" message=" + t.getMessage() + "\n");
+
+                                                       StringWriter sw = new StringWriter();
+                                                       t.printStackTrace(new PrintWriter(sw));
+                                                       message.append(" stack trace=" + sw);
+
+                                                       return message.toString();
+                                               }
+
+                                       });
+
+                               } catch (DatabaseException e) {
+
+                                       return e.getMessage();
+
+                               }
+
+               }
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                               IConsole console = parameters.getValue("__console__");
+                               SCLReportingHandler printer = (console != null) ? new ConsoleSCLReportingHandler(console)
+                                               : (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                       Object result = null;
+                       if(effects.contains(Types.WRITE_GRAPH)) {
+
+                               result = session.syncRequest(new WriteResultRequest<Object>() {
+
+                                                       @Override
+                                                       public Object perform(WriteGraph graph)
+                                                                       throws DatabaseException {
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                       return fn.apply(parameters);
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                                       }
+                               });
+
+                       } else if(effects.contains(Types.READ_GRAPH)) {
+
+                               result = session.sync(new UniqueRead<Object>() {
+
+                                       @Override
+                                       public Object perform(ReadGraph graph) throws DatabaseException {
+
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+
+                                               try {
+                                                       return fn.apply(parameters);
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                       }
+                               });
+
+                       } else {
+
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                       result = fn.apply(parameters);
+                                               } finally {
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                       }
+
+                       if (result instanceof org.simantics.document.server.serverResponse.Error) {
+                               return (CommandResult)result;
+                       }
+
+                       if (result instanceof CommandResult) {
+                               return (CommandResult)result;
+                       } else {
+                               CommandContextMutable assignments = new CommandContextImpl();
+                               assignments.putValue("result", result);
+                               return new ServerResponse(200, "", assignments);
+                       }
+
+                               } catch (Throwable e) {
+                                       return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
+                               }
+
+                       }
+
+        };
+    }
+
+    @Deprecated
+    public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
+
+       final Session session = graph.getSession();
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                       CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
+
+                                           @Override
+                                           public CommandResult perform(WriteGraph graph) throws DatabaseException {
+                                               SCLContext sclContext = SCLContext.getCurrent();
+                                               Object oldGraph = sclContext.put("graph", graph);
+                                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                                               try {
+                                                   Object response = fn.apply(parameters);
+                                                   if(response instanceof CommandResult) {
+                                                       return (CommandResult)response;
+                                                   }
+                                                   return null;
+                                               } finally {
+                                                       sclContext.put("graph", oldGraph);
+                                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                                               }
+
+                                           }
+
+                                       });
+
+                       return result;
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+
+    @Deprecated
+    public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                       SCLContext sclContext = SCLContext.getCurrent();
+                       Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                       try {
+                               Object response = fn.apply(parameters);
+                               if(response instanceof CommandResult) {
+                                       return (CommandResult)response;
+                               }
+                               return null;
+                       } finally {
+                               sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                       }
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+    @Deprecated
+    public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
+
+        return new AbstractEventHandler() {
+
+                       @Override
+                       public CommandResult handle(final CommandContext parameters) {
+
+                final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+                try {
+
+                       String result = "";
+
+                               SCLContext sclContext = SCLContext.getCurrent();
+                               Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+                               try {
+                                   Function1<String,String> pf = new FunctionImpl1<String,String>() {
+                                       @Override
+                                       public String apply(String key) {
+                                           return parameters.getString(key);
+                                       }
+                                   }; 
+                                   Object response = (String)fn.apply(pf);
+                                   if(response instanceof String) {
+                                       result = (String)response;
+                                   }
+                               } finally {
+                                       sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+                               }
+
+                       return new SuccessResponse(result);
+
+                               } catch (Throwable e) {
+                                       Logger.defaultLogError(e);
+                                       return new org.simantics.document.server.serverResponse.Error(e.getMessage()); 
+                               }
+
+                       }
+
+        };
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+    public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+        return ServerSCLValueRequest.compileAndEvaluate(graph, context);
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+    public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+        return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
+    public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
+        return createComponentNamingStrategy(graph);
+    }
+
+    public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
+        Layer0X L0X = Layer0X.getInstance(graph);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
+        @SuppressWarnings("rawtypes")
+        Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
+            @Override
+            public Object apply(ReadGraph p0, Resource p1, String p2) {
+                return apply(p0, p1, p2);
+            }
+            @SuppressWarnings("unchecked")
+            @Override
+            public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
+                return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
+            }
+        };
+        return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
+    }
+
+    public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
+        if (variable == null)
+            return null;
+
+        SimulationResource SIMU = SimulationResource.getInstance(graph);
+
+        Variable var = variable;
+        Resource represents = var.getRepresents(graph);
+        Resource activeRun = null;
+        if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
+            activeRun = represents;
+        }
+
+        IProject project = Simantics.peekProject();
+        if (activeRun != null && project != null) {
+            IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
+            if (expMan != null)
+                return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
+        }
+
+        return null;
+    }
+
+    public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
+       List<Object> list = new ArrayList<Object>();
+       if (tuple instanceof Tuple) {
+               Collections.addAll(list, ((Tuple)tuple).toArray());
+       } else {
+               list.add(tuple);
+       }
+       context.putRow(key, list);
+       return context;
+    }
+
+    public static List<Object> getTuples(CommandContext context, String key) {
+       List<List<Object>> rows = context.getRows(key);
+       List<Object> tuples = new ArrayList<Object>();
+       if (rows != null) {
+               for (List<Object> row : rows) {
+                       switch (row.size()) {
+                       case 0: tuples.add(Tuple0.INSTANCE); break;
+                       case 1: tuples.add(row.get(1)); break;
+                       case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
+                       case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
+                       case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
+                       case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
+                       }
+               }
+       }
+       return tuples;
+    }
+
+    public static String printContext(CommandContext context) {
+       return context.toString();
+    }
+
+    @SCLValue(type = "AbstractEventHandler")
+    public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
+
+               @Override
+               public CommandResult handle(CommandContext context) {
+                       return null;
+               }
+
+    };
+
+    public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
+
+       String baseURI = base.getURI(graph);
+
+       String selfURI = self.getURI(graph);
+
+       String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
+       String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
+       String stripped = prefix + suffix;
+
+       String relative = Variables.getRelativeRVI(baseURI, stripped); 
+
+       return Variables.getRVI(relative, ref);
+
+    }
+
+    public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
+
+       String id = sclStateKey(graph, base, self, ref);
+
+       Variable sclVar = base.getPossibleChild(graph, "__scl__");
+       if(sclVar == null) return null;
+
+       return sclVar.getPossibleProperty(graph, id);
+
+    }
+
+    public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
+
+       Variable stateVariable = sclStateVariable(graph, base, self, ref);
+       if (stateVariable != null) {
+
+               return stateVariable.getValue(graph);
+
+       } else {
+
+               String id = sclStateKey(graph, base, self, ref);
+
+               SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");
+               realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);
+
+               return defaultValue;
+
+       }
+    }
+
+    public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
+
+       String id = sclStateKey(graph, base, self, ref);
+
+       SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");
+       realm.getConnection().setVariable(id, getSCLType(value), value);
+       realm.refreshVariablesSync();
+
+    }
+
+    public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
+       Resource project = Simantics.getProjectResource();
+       Variable component = self.getParent(graph);
+       Variable projectVariable = Variables.getVariable(graph, project);
+       return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
+    }
+
+    public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
+       Resource project = Simantics.getProjectResource();
+       Variable component = self.getParent(graph);
+       Variable projectVariable = Variables.getVariable(graph, project);
+       setSclStateValue(graph, projectVariable, component, ref, value);
+    }
+
+    private static Type getSCLType(Object value) throws DatabaseException {
+       Binding b = Bindings.getBindingUnchecked(value.getClass());
+       Datatype t = b.type();
+       if(Datatypes.STRING.equals(t)) return Types.STRING;
+       if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
+       throw new DatabaseException("Type not supported");
+    }
+
+    public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
+       Resource project = Simantics.getProjectResource();
+       ArrayList<Variable> result = new ArrayList<Variable>();
+       for(Resource model : graph.syncRequest(new ProjectModels(project))) {
+               result.add(Variables.getVariable(graph, model));
+       }
+       return result;
+    }
+
+    public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
+       return var.getName(graph);
+    }
+
+    public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
+       Variable property = graph.syncRequest(new VariableProperty(variable, name));
+       return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
+    }
+
+    public static class ParentExistsRequest extends VariableRead<Boolean> {
+
+               public ParentExistsRequest(Variable parent) {
+                       super(parent);
+               }
+
+               @Override
+               public Boolean perform(ReadGraph graph) throws DatabaseException {
+                       
+                       Variable existsProperty = variable.getPossibleProperty(graph, "exists");
+                       if(existsProperty == null) return true;
+                       
+                       Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
+                       if (exists == null || !exists) return false;
+
+               return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
+
+               }
+
+    } 
+
+    public static class PathExistsRequest extends VariableRead<Boolean> {
+
+               public PathExistsRequest(Variable variable) {
+                       super(variable);
+               }
+
+               @Override
+               public Boolean perform(ReadGraph graph) throws DatabaseException {
+
+                       Variable widget = variable.getParent(graph);
+
+               Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
+                       if (exists == null || !exists) return false;
+
+               if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
+
+               DocumentationResource DOC = DocumentationResource.getInstance(graph);
+               Collection <Variable> cps = widget.getProperties(graph, DocumentationResource.URIs.Relations_parentRelation);
+               for (Variable cp : cps) {
+
+                       Connection conn = cp.getValue(graph);
+                               Variable otherCp = DocumentServerUtils.getPossibleChildConnectionPoint(graph, cp, conn);
+                               if (otherCp != null) {
+                                       Variable parentWidget = otherCp.getParent(graph);
+                                       if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
+                                               return true;
+                                       }
+                               } else {
+                                       Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
+                                   @Override
+                                   public Variable perform(ReadGraph graph) throws DatabaseException {
+                                       DocumentationResource DOC = DocumentationResource.getInstance(graph);
+                                       Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
+
+                                               for(VariableConnectionPointDescriptor desc : descs) {
+                                                       if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
+                                                               return desc.getVariable(graph);
+                                                       }
+                                               }
+                                               return null;
+                                   }
+                               });
+                                       if (parentCp != null) {
+                                               Variable parentWidget = parentCp.getParent(graph);
+                                               if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                       }
+
+                       Resource type = widget.getType(graph);
+                       return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
+                               (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
+               }
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
+    public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+       return graph.syncRequest(new PathExistsRequest(context));
+    }
+
+    public static String compileDocumentSCLValueExpression(ReadGraph graph, Variable context) {
+        try {
+            ServerSCLValueRequest.validate(graph, context);
+            return "";
+        } catch (Exception e) {
+            return resolveIssueMessage(e);
+        }
+    }
+    
+    private static String resolveIssueMessage(Exception e) {
+        if (e instanceof ImportFailureException)
+            return "";
+        if (e.getCause() != null && e.getCause() instanceof ImportFailureException)
+            return "";
+        if (e instanceof SCLDatabaseException) {
+            SCLDatabaseException ee = (SCLDatabaseException) e;
+            return ee.getMessage();
+        }
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("", e);
+        return e.getMessage();
+    }
+
 }
\ No newline at end of file