From: Antti Villberg Date: Mon, 20 Jan 2020 13:36:39 +0000 (+0200) Subject: Improved environment resolution for document SCL expressions X-Git-Tag: v1.43.0~123 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=e2a018d782bdeb19d418b2b06e64a028964ae2bd;p=simantics%2Fplatform.git Improved environment resolution for document SCL expressions gitlab #447 Change-Id: I4d84204eb6c2371b60c648b04e81b0cd36765f4e --- diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java index 8d364c737..1bcd91877 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java @@ -104,7 +104,7 @@ implements Read> { return DEFAULT_EXPECTED_EFFECT; } - private ExpressionEvaluator prepareEvaluator(final ReadGraph graph, final CompilationContext context, Type expectedType) throws DatabaseException { + protected ExpressionEvaluator prepareEvaluator(final ReadGraph graph, final CompilationContext context, Type expectedType) throws DatabaseException { final Variable contextVariable = new Variable("context", getContextVariableType()); LocalEnvironment localEnvironment = new AbstractLocalEnvironment() { THashMap> precalculatedVariables = new THashMap>(); @@ -156,7 +156,7 @@ implements Read> { } @SuppressWarnings("unchecked") - private Function1 eval(ExpressionEvaluator evaluator, ReadGraph graph) throws DatabaseException { + protected Function1 eval(ExpressionEvaluator evaluator, ReadGraph graph) throws DatabaseException { Object oldGraph = SCLContext.getCurrent().put("graph", graph); try { return (Function1)evaluator.eval(); diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java index 8ca55eaa5..44e2ceeee 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java @@ -1,5 +1,6 @@ package org.simantics.document.server.request; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -9,15 +10,11 @@ import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.IndexRoot; -import org.simantics.db.common.request.PossibleTypedParent; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext; -import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest; import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2; import org.simantics.db.layer0.variable.Variable; -import org.simantics.document.base.ontology.DocumentationResource; -import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EConstant; @@ -30,249 +27,258 @@ import org.simantics.scl.compiler.runtime.RuntimeEnvironment; 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.compiler.types.exceptions.MatchException; import org.simantics.scl.compiler.types.kinds.Kinds; +import org.simantics.scl.compiler.types.util.MultiFunction; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.function.Function1; +import org.simantics.scl.runtime.function.FunctionImpl1; import org.simantics.structural2.scl.ComponentTypeProperty; import org.simantics.structural2.scl.FindPossibleComponentTypeRequest; import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest; import org.simantics.utils.datastructures.Pair; -public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest { - - private final Pair componentTypeAndRoot; - private final Resource literal; - protected String possibleExpectedValueType; - - public static class CompilationContext extends AbstractExpressionCompilationContext { - public final Map propertyMap; - - public CompilationContext(RuntimeEnvironment runtimeEnvironment, - Map propertyMap) { - super(runtimeEnvironment); - this.propertyMap = propertyMap; - } - } - - private ServerSCLHandlerValueRequest(Pair componentTypeAndRoot, Resource literal, String possibleExpectedValueType) { - assert(literal != null); - this.literal = literal; - this.componentTypeAndRoot = componentTypeAndRoot; - this.possibleExpectedValueType = possibleExpectedValueType; - } - - public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException { - this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph))); - } - - public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException { - this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p)); - } - - private static Pair getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException { - Variable parent = property.getParent(graph); - Resource represents = parent.getRepresents(graph); - if(represents != null) { - Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents)); - if(type != null) { - Resource root = graph.syncRequest(new IndexRoot(type)); - return Pair.make(type, root); - } - } - parent = parent.getParent(graph); - Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph))); - return Pair.make(parent.getType(graph), root); - } - - private static Pair getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException { - if(component != null) { - Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component)); - if(type != null) { - Resource root = graph.syncRequest(new IndexRoot(type)); - return Pair.make(type, root); - } else { - Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document)); - Resource componentType = graph.getSingleType(doc); - Resource root = graph.syncRequest(new IndexRoot(doc)); - return Pair.make(componentType, root); - } - // TODO: For Antti to consider and fix later - // Introduced to handle procedural user components where component == null - } else if (literal != null) { - Resource root = graph.syncRequest(new IndexRoot(literal)); - return Pair.make(null, root); - } else { - throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null"); - } - //throw new IllegalStateException(); - } +public class ServerSCLHandlerValueRequest extends ServerSCLValueRequestBase { + + private final Pair componentTypeAndRoot; + private final Resource literal; + protected String possibleExpectedValueType; + + public static class CompilationContext extends AbstractExpressionCompilationContext { + public final Map propertyMap; + + public CompilationContext(RuntimeEnvironment runtimeEnvironment, + Map propertyMap) { + super(runtimeEnvironment); + this.propertyMap = propertyMap; + } + } + + private ServerSCLHandlerValueRequest(Pair componentTypeAndRoot, Resource literal, String possibleExpectedValueType) { + assert(literal != null); + this.literal = literal; + this.componentTypeAndRoot = componentTypeAndRoot; + this.possibleExpectedValueType = possibleExpectedValueType; + } + + public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException { + this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph))); + } + + public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException { + this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p)); + } + + private static Pair getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException { + Variable parent = property.getParent(graph); + Resource represents = parent.getRepresents(graph); + if(represents != null) { + Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents)); + if(type != null) { + Resource root = graph.syncRequest(new IndexRoot(type)); + return Pair.make(type, root); + } + } + parent = parent.getParent(graph); + Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph))); + return Pair.make(parent.getType(graph), root); + } + public static List getEffects(ReadGraph graph, Variable context) throws DatabaseException { + HandlerFn fn = (HandlerFn)compile(graph, context); + return fn.effects; + } + + public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); try { - ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context); - return req.getExpressionEffects(graph); + Function1 exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), + TransientCacheListener.instance()); + sclContext.put("graph", graph); + return exp.apply(context); } catch (DatabaseException e) { throw (DatabaseException)e; } catch (Throwable t) { throw new DatabaseException(t); + } finally { + sclContext.put("graph", oldGraph); } } - public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException { - SCLContext sclContext = SCLContext.getCurrent(); - Object oldGraph = sclContext.get("graph"); - try { - Function1 exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), - TransientCacheListener.instance()); - sclContext.put("graph", graph); - return exp.apply(context); - } catch (DatabaseException e) { - throw (DatabaseException)e; - } catch (Throwable t) { - throw new DatabaseException(t); - } finally { - sclContext.put("graph", oldGraph); - } - } - - public static Function1 compile(ReadGraph graph, Variable context) throws DatabaseException { - return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance()); - } - - public static Function1 compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException { - return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.>instance()); - } - - @Override - protected String getExpressionText(ReadGraph graph) - throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING); - return "\\context -> " + exp; - } - - protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) { - return new RuntimeEnvironmentRequest2(componentType, indexRoot) { - @Override - protected void fillEnvironmentSpecification( - EnvironmentSpecification environmentSpecification) { - } - }; - } - - @Override - protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException { - return graph.syncRequest(new UnaryRead,CompilationContext>(componentTypeAndRoot) { - @Override - public CompilationContext perform(ReadGraph graph) throws DatabaseException { - RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second)); + public static Function1 compile(ReadGraph graph, Variable context) throws DatabaseException { + return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance()); + } + + public static Function1 compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException { + return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.instance()); + } + + public static class HandlerFn extends FunctionImpl1 { + + Function1 handler; + ArrayList effects; + + HandlerFn(Function1 handler, Type type) { + try { + this.handler = handler; + this.effects = new ArrayList(); + MultiFunction mfun = Types.matchFunction(type, 1); + mfun.effect.collectConcreteEffects(this.effects); + } catch(MatchException e) { + // Should not happen! + throw new RuntimeException(e); + } + } + + @Override + public Object apply(Object p0) { + return handler.apply(p0); + } + + } + + @Override + public Function1 perform(ReadGraph graph) throws DatabaseException { + + CompilationContext context = getCompilationContext(graph); + Type expectedType = getExpectedType(graph, context); + Function1 handler = eval(prepareEvaluator(graph, context, expectedType), graph); + return new HandlerFn(handler, expectedType); + + } + + @Override + protected String getExpressionText(ReadGraph graph) + throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING); + return "\\context -> " + exp; + } + + protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) { + return new RuntimeEnvironmentRequest2(componentType, indexRoot) { + @Override + protected void fillEnvironmentSpecification( + EnvironmentSpecification environmentSpecification) { + } + }; + } + + @Override + protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException { + return graph.syncRequest(new UnaryRead,CompilationContext>(componentTypeAndRoot) { + @Override + public CompilationContext perform(ReadGraph graph) throws DatabaseException { + RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second)); Map propertyMap; if (parameter.first != null) { propertyMap = - graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), - TransientCacheListener.>instance()); + graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), + TransientCacheListener.>instance()); } else { // TODO: Antti to consider // To handle procedural user components propertyMap = Collections.emptyMap(); } -// Map propertyMap = -// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), -// TransientCacheListener.>instance()); - return new CompilationContext(runtimeEnvironment, propertyMap); - } - }); - } - - @Override - protected Type getContextVariableType() { - return VARIABLE; - } - - private static Expression accessInputVariable(Environment environment, - org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) { - SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT); - return new EApply(new EConstant(variableParentFunction), - new EApply(new EConstant(variableParentFunction), - new EVariable(contextVariable))); - } - - protected static Expression standardGetProperty( - Environment environment, - org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, - String name, - Type type) { - return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type); - } - - @Override - protected Expression getVariableAccessExpression( - ReadGraph graph, - CompilationContext context, - org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, - String name) throws DatabaseException { - ComponentTypeProperty property = context.propertyMap.get(name); - if(property != null) - return standardGetProperty( - context.runtimeEnvironment.getEnvironment(), - contextVariable, - name, - property.type == null ? Types.metaVar(Kinds.STAR) : property.type); - else { - -// if(context.propertyMap.containsKey(name)) { -// -// org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT); -// -// Environment environment = context.runtimeEnvironment.getEnvironment(); -// -//// return new EApply( -//// new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING), -// return new EApply( -// new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC), -// new EVariable(parametersVariable), -// new ELiteral(new StringConstant(name))); -// -// } - - return getSpecialVariableAccessExpression(graph, context, contextVariable, name); - - } - } - - protected Expression getSpecialVariableAccessExpression(ReadGraph graph, - CompilationContext context, - org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, - String name) throws DatabaseException { - if(name.equals("input")) { - Environment environment = context.runtimeEnvironment.getEnvironment(); - return accessInputVariable(environment, contextVariable); - } else if(name.equals("self")) - return new EVariable(contextVariable); - else - return null; - } +// Map propertyMap = +// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), +// TransientCacheListener.>instance()); + return new CompilationContext(runtimeEnvironment, propertyMap); + } + }); + } + + @Override + protected Type getContextVariableType() { + return VARIABLE; + } + + private static Expression accessInputVariable(Environment environment, + org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) { + SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT); + return new EApply(new EConstant(variableParentFunction), + new EApply(new EConstant(variableParentFunction), + new EVariable(contextVariable))); + } + + protected static Expression standardGetProperty( + Environment environment, + org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, + String name, + Type type) { + return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type); + } + + @Override + protected Expression getVariableAccessExpression( + ReadGraph graph, + CompilationContext context, + org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, + String name) throws DatabaseException { + ComponentTypeProperty property = context.propertyMap.get(name); + if(property != null) + return standardGetProperty( + context.runtimeEnvironment.getEnvironment(), + contextVariable, + name, + property.type == null ? Types.metaVar(Kinds.STAR) : property.type); + else { + +// if(context.propertyMap.containsKey(name)) { +// +// org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT); +// +// Environment environment = context.runtimeEnvironment.getEnvironment(); +// +//// return new EApply( +//// new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING), +// return new EApply( +// new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC), +// new EVariable(parametersVariable), +// new ELiteral(new StringConstant(name))); +// +// } + + return getSpecialVariableAccessExpression(graph, context, contextVariable, name); + + } + } + + protected Expression getSpecialVariableAccessExpression(ReadGraph graph, + CompilationContext context, + org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, + String name) throws DatabaseException { + if(name.equals("input")) { + Environment environment = context.runtimeEnvironment.getEnvironment(); + return accessInputVariable(environment, contextVariable); + } else if(name.equals("self")) + return new EVariable(contextVariable); + else + return null; + } @Override protected Type getExpectedType(ReadGraph graph, CompilationContext context) throws DatabaseException { return super.getExpectedType(graph, context); } - @Override - public int hashCode() { - return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj; - return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot); - } + @Override + public int hashCode() { + return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj; + return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot); + } } diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java index adff8dab5..37d60a443 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java @@ -9,16 +9,12 @@ import org.simantics.db.Resource; import org.simantics.db.Statement; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.IndexRoot; -import org.simantics.db.common.request.PossibleTypedParent; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext; -import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest; import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2; import org.simantics.db.layer0.variable.Variable; -import org.simantics.document.base.ontology.DocumentationResource; -import org.simantics.document.server.request.ServerSCLValueRequest.CompilationContext; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.constants.StringConstant; @@ -45,7 +41,7 @@ import org.simantics.utils.datastructures.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest { +public class ServerSCLValueRequest extends ServerSCLValueRequestBase { private final Pair componentTypeAndRoot; private final Resource literal; @@ -91,39 +87,9 @@ public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest< return Pair.make(parent.getType(graph), root); } - private static Pair getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException { - if(component != null) { - Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component)); - if(type != null) { - Resource root = graph.syncRequest(new IndexRoot(type)); - // System.err.println("getComponentTypeAndRoot3 " + graph.getPossibleURI(component) + " => " + graph.getPossibleURI(type) + " " + graph.getPossibleURI(root)); - return Pair.make(type, root); - } else { - Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document)); - if(doc != null) { - Resource componentType = graph.getSingleType(doc); - Resource root = graph.syncRequest(new IndexRoot(doc)); - return Pair.make(componentType, root); - } else { - //System.err.println("component = " + component); - Resource root = graph.syncRequest(new IndexRoot(component)); -// Resource componentType = graph.getSingleType(doc); - return Pair.make(null, root); - } - } - // TODO: For Antti to consider and fix later - // Introduced to handle procedural user components where component == null - } else if (literal != null) { - Resource root = graph.syncRequest(new IndexRoot(literal)); - return Pair.make(null, root); - } else { - throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null"); - } - } - public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException { SCLContext sclContext = SCLContext.getCurrent(); - Object oldGraph = sclContext.get("graph"); + Object oldGraph = sclContext.get("graph"); try { Function1 exp = compile(graph, context); sclContext.put("graph", graph); @@ -133,7 +99,7 @@ public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest< } catch (Throwable t) { throw new DatabaseException(t); } finally { - sclContext.put("graph", oldGraph); + sclContext.put("graph", oldGraph); } } diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequestBase.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequestBase.java new file mode 100644 index 000000000..9235d38f7 --- /dev/null +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequestBase.java @@ -0,0 +1,43 @@ +package org.simantics.document.server.request; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.IndexRoot; +import org.simantics.db.common.request.PossibleTypedParent; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext; +import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest; +import org.simantics.document.base.ontology.DocumentationResource; +import org.simantics.structural2.scl.FindPossibleComponentTypeRequest; +import org.simantics.utils.datastructures.Pair; + +abstract public class ServerSCLValueRequestBase extends AbstractExpressionCompilationRequest { + + static Pair getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException { + if(component != null) { + Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component)); + if(type != null) { + Resource root = graph.syncRequest(new IndexRoot(type)); + return Pair.make(type, root); + } else { + Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document)); + if(doc != null) { + Resource componentType = graph.getSingleType(doc); + Resource root = graph.syncRequest(new IndexRoot(doc)); + return Pair.make(componentType, root); + } else { + Resource root = graph.syncRequest(new IndexRoot(component)); + return Pair.make(null, root); + } + } + // TODO: For Antti to consider and fix later + // Introduced to handle procedural user components where component == null + } else if (literal != null) { + Resource root = graph.syncRequest(new IndexRoot(literal)); + return Pair.make(null, root); + } else { + throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null"); + } + } + +}