-package org.simantics.document.server.request;\r
-\r
-import java.util.Map;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
-import org.simantics.db.common.request.IndexRoot;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;\r
-import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;\r
-import org.simantics.db.layer0.util.RuntimeEnvironmentRequest;\r
-import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.document.server.request.ServerSCLValueRequest.CompilationContext;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.scl.compiler.common.names.Name;\r
-import org.simantics.scl.compiler.constants.StringConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
-import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
-import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
-import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.environment.Environment;\r
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
-import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-import org.simantics.scl.runtime.SCLContext;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.structural2.scl.ComponentTypeProperty;\r
-import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;\r
-import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest;\r
-import org.simantics.utils.datastructures.Pair;\r
-\r
-public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {\r
-\r
- private final Pair<Resource,Resource> componentTypeAndRoot;\r
- private final Resource literal;\r
-\r
- public static class CompilationContext extends AbstractExpressionCompilationContext {\r
- public final Map<String, ComponentTypeProperty> propertyMap;\r
-\r
- public CompilationContext(RuntimeEnvironment runtimeEnvironment,\r
- Map<String, ComponentTypeProperty> propertyMap) {\r
- super(runtimeEnvironment);\r
- this.propertyMap = propertyMap;\r
- }\r
- }\r
-\r
- private ServerSCLValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal) {\r
- assert(literal != null);\r
- this.literal = literal;\r
- this.componentTypeAndRoot = componentTypeAndRoot;\r
- }\r
-\r
- public ServerSCLValueRequest(ReadGraph graph, Variable context) throws DatabaseException {\r
- this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph));\r
- }\r
-\r
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException {\r
- Variable parent = property.getParent(graph);\r
- Resource represents = parent.getRepresents(graph);\r
- if(represents != null) {\r
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));\r
- if(type != null) {\r
- Resource root = graph.syncRequest(new IndexRoot(type));\r
- return Pair.make(type, root);\r
- }\r
- }\r
- parent = parent.getParent(graph);\r
- Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));\r
- return Pair.make(parent.getType(graph), root);\r
- }\r
-\r
- public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.get("graph");\r
- try {\r
- Function1<Variable,Object> exp = graph.syncRequest(new ServerSCLValueRequest(graph, context),\r
- TransientCacheListener.<Function1<Variable,Object>>instance());\r
- sclContext.put("graph", graph);\r
- return exp.apply(context);\r
- } catch (DatabaseException e) {\r
- throw (DatabaseException)e;\r
- } catch (Throwable t) {\r
- throw new DatabaseException(t);\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- }\r
- }\r
-\r
- @Override\r
- protected String getExpressionText(ReadGraph graph)\r
- throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- return graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);\r
- }\r
-\r
- protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) {\r
- return new RuntimeEnvironmentRequest2(componentType, indexRoot) {\r
- @Override\r
- protected void fillEnvironmentSpecification(\r
- EnvironmentSpecification environmentSpecification) {\r
- }\r
- };\r
- }\r
-\r
- @Override\r
- protected CompilationContext getCompilationContext(ReadGraph graph)\r
- throws DatabaseException {\r
- return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {\r
- @Override\r
- public CompilationContext perform(ReadGraph graph)\r
- throws DatabaseException {\r
- RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));\r
- Map<String, ComponentTypeProperty> propertyMap =\r
- graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),\r
- TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());\r
- return new CompilationContext(runtimeEnvironment, propertyMap);\r
- }\r
- });\r
- }\r
-\r
- @Override\r
- protected Type getContextVariableType() {\r
- return VARIABLE; \r
- }\r
-\r
- private static Expression accessInputVariable(Environment environment,\r
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {\r
- SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);\r
- return new EApply(new EConstant(variableParentFunction),\r
- new EApply(new EConstant(variableParentFunction),\r
- new EVariable(contextVariable)));\r
- }\r
-\r
- protected static Name PROPERTY_VALUE_CACHED = Name.create("Document/All", "propertyValueCached");\r
-\r
- protected static Expression getProperty(Environment environment, Expression variable, String propertyName, Type type) {\r
- return new EApply(\r
- new EConstant(environment.getValue(FROM_DYNAMIC), type),\r
- new EApply(\r
- new EConstant(environment.getValue(PROPERTY_VALUE_CACHED), Types.DYNAMIC),\r
- variable,\r
- new ELiteral(new StringConstant(propertyName))));\r
- }\r
- \r
- protected static Expression getPropertyFlexible(Environment environment, Expression variable, String propertyName, Type type) {\r
- return makeTypeFlexible(environment, getProperty(environment, variable, propertyName, type), type);\r
- }\r
- \r
- protected static Expression standardGetProperty(\r
- Environment environment,\r
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
- String name,\r
- Type type) {\r
- return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);\r
- }\r
-\r
-\r
- @Override\r
- protected Expression getVariableAccessExpression(\r
- ReadGraph graph,\r
- CompilationContext context,\r
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
- String name) throws DatabaseException {\r
- ComponentTypeProperty property = context.propertyMap.get(name);\r
- if(property != null)\r
- return standardGetProperty(\r
- context.runtimeEnvironment.getEnvironment(),\r
- contextVariable,\r
- name,\r
- property.type == null ? Types.metaVar(Kinds.STAR) : property.type);\r
- else\r
- return getSpecialVariableAccessExpression(graph, context, contextVariable, name);\r
- }\r
-\r
- protected Expression getSpecialVariableAccessExpression(ReadGraph graph,\r
- CompilationContext context,\r
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
- String name) throws DatabaseException {\r
- if(name.equals("input")) {\r
- Environment environment = context.runtimeEnvironment.getEnvironment();\r
- return accessInputVariable(environment, contextVariable);\r
- }\r
- else if(name.equals("self"))\r
- return new EVariable(contextVariable);\r
- else\r
- return null;\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- if(this == obj)\r
- return true;\r
- if(obj == null || obj.getClass() != getClass())\r
- return false;\r
- ServerSCLValueRequest other = (ServerSCLValueRequest)obj;\r
- return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);\r
- }\r
-}\r
+package org.simantics.document.server.request;
+
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+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.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.server.request.ServerSCLValueRequest.CompilationContext;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.structural2.scl.ComponentTypeProperty;
+import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;
+import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest;
+import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {
+
+ private final Pair<Resource,Resource> componentTypeAndRoot;
+ private final Resource literal;
+ protected String possibleExpectedValueType;
+
+ public static class CompilationContext extends AbstractExpressionCompilationContext {
+ public final Map<String, ComponentTypeProperty> propertyMap;
+
+ public CompilationContext(RuntimeEnvironment runtimeEnvironment,
+ Map<String, ComponentTypeProperty> propertyMap) {
+ super(runtimeEnvironment);
+ this.propertyMap = propertyMap;
+ }
+ }
+
+ private ServerSCLValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
+ assert(literal != null);
+ this.literal = literal;
+ this.componentTypeAndRoot = componentTypeAndRoot;
+ this.possibleExpectedValueType = possibleExpectedValueType;
+ }
+
+ public ServerSCLValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
+ this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context));
+ }
+
+ private static Pair<Resource,Resource> 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 Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.get("graph");
+ try {
+ Function1<Variable,Object> exp = compile(graph, context);
+ 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<Variable, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLValueRequest(graph, context), TransientCacheListener.<Function1<Variable,Object>>instance());
+ }
+
+ @Override
+ protected String getExpressionText(ReadGraph graph)
+ throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ return graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
+ }
+
+ 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<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
+ @Override
+ public CompilationContext perform(ReadGraph graph)
+ throws DatabaseException {
+ RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
+ Map<String, ComponentTypeProperty> propertyMap =
+ graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
+ TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
+ return new CompilationContext(runtimeEnvironment, propertyMap);
+ }
+ });
+ }
+
+ @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 Name PROPERTY_VALUE_CACHED = Name.create("Document/All", "propertyValueCached");
+
+ protected static Expression getProperty(Environment environment, Expression variable, String propertyName, Type type) {
+ return new EApply(
+ new EConstant(environment.getValue(FROM_DYNAMIC), type),
+ new EApply(
+ new EConstant(environment.getValue(PROPERTY_VALUE_CACHED), Types.DYNAMIC),
+ variable,
+ new ELiteral(new StringConstant(propertyName))));
+ }
+
+ protected static Expression getPropertyFlexible(Environment environment, Expression variable, String propertyName, Type type) {
+ return makeTypeFlexible(environment, getProperty(environment, variable, propertyName, type), type);
+ }
+
+ 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
+ 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 || obj.getClass() != getClass())
+ return false;
+ ServerSCLValueRequest other = (ServerSCLValueRequest)obj;
+ return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
+ }
+
+ public static Function1<Variable, Object> validate(ReadGraph graph, Variable context) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLValueValidationRequest(graph, context), TransientCacheListener.<Function1<Variable,Object>>instance());
+ }
+
+ public static class ServerSCLValueValidationRequest extends ServerSCLValueRequest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ServerSCLHandlerValueRequest.class);
+
+ public ServerSCLValueValidationRequest(ReadGraph graph, Variable context) throws DatabaseException {
+ super(graph, context);
+ }
+
+ @Override
+ protected Type getExpectedType(ReadGraph graph, CompilationContext context) throws DatabaseException {
+ if(possibleExpectedValueType != null) {
+ try {
+ return Environments.getType(context.runtimeEnvironment.getEnvironment(), possibleExpectedValueType);
+ } catch (SCLExpressionCompilationException e) {
+ LOGGER.error("Could not get type for " + String.valueOf(possibleExpectedValueType), e);
+ }
+ }
+ return super.getExpectedType(graph, context);
+ }
+ }
+}