]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/CompileSCLMonitorRequest.java
Merge branch 'feature/funcwrite'
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / CompileSCLMonitorRequest.java
1 package org.simantics.modeling.scl;
2
3 import org.simantics.databoard.Bindings;
4 import org.simantics.db.ReadGraph;
5 import org.simantics.db.Resource;
6 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
7 import org.simantics.db.common.request.IndexRoot;
8 import org.simantics.db.common.request.ResourceRead;
9 import org.simantics.db.exception.DatabaseException;
10 import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
11 import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
12 import org.simantics.db.layer0.util.RuntimeEnvironmentRequest;
13 import org.simantics.db.layer0.variable.Variable;
14 import org.simantics.layer0.Layer0;
15 import org.simantics.modeling.ComponentTypeSubstructure;
16 import org.simantics.modeling.scl.CompileSCLMonitorRequest.CompilationContext;
17 import org.simantics.scl.compiler.common.names.Name;
18 import org.simantics.scl.compiler.constants.StringConstant;
19 import org.simantics.scl.compiler.elaboration.expressions.EApply;
20 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
21 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
22 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
23 import org.simantics.scl.compiler.elaboration.expressions.Expression;
24 import org.simantics.scl.compiler.environment.Environment;
25 import org.simantics.scl.compiler.environment.Environments;
26 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
27 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
28 import org.simantics.scl.compiler.types.Type;
29 import org.simantics.scl.runtime.SCLContext;
30 import org.simantics.scl.runtime.function.Function1;
31 import org.simantics.utils.datastructures.Pair;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35
36 public class CompileSCLMonitorRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {
37
38     private static Logger LOGGER = LoggerFactory.getLogger(CompileSCLMonitorRequest.class);
39
40     protected static Name BROWSE = Name.create("Simantics/Variables", "browse");
41     protected static Name VALUE = Name.create("Simantics/Variables", "value");
42     
43     private final Resource componentType;
44     private final Resource literal;
45     private final Resource relation;
46     
47     public static class CompilationContext extends AbstractExpressionCompilationContext {
48         public final ComponentTypeSubstructure substructure;
49         
50         public CompilationContext(RuntimeEnvironment runtimeEnvironment,
51                 ComponentTypeSubstructure substructure) {
52             super(runtimeEnvironment);
53             this.substructure = substructure;
54         }
55     }
56     
57     private CompileSCLMonitorRequest(Resource componentType, Resource literal, Resource relation) {
58         this.componentType = componentType;
59         this.literal = literal;
60         this.relation = relation;
61     }
62     
63     public CompileSCLMonitorRequest(ReadGraph graph, Variable context)
64             throws DatabaseException {
65         this(context.getParent(graph).getType(graph),
66                 context.getRepresents(graph),
67                 context.getPredicateResource(graph));
68     }
69
70     public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
71         SCLContext sclContext = SCLContext.getCurrent();
72         Object oldGraph = sclContext.get("graph");
73         try {
74             Function1<Variable,Object> exp = graph.syncRequest(new CompileSCLMonitorRequest(graph, context),
75                     TransientCacheListener.<Function1<Variable,Object>>instance());
76             sclContext.put("graph", graph);
77             return exp.apply(context.getParent(graph));
78         } catch (DatabaseException e) {
79             throw (DatabaseException)e;
80         } catch (Throwable t) {
81             throw new DatabaseException(t);
82         } finally {
83             sclContext.put("graph", oldGraph);
84         }
85     }
86
87     @Override
88     protected String getExpressionText(ReadGraph graph)
89             throws DatabaseException {
90         Layer0 L0 = Layer0.getInstance(graph);
91         return graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
92     }
93     
94     @Override
95     protected Type getExpectedType(ReadGraph graph, CompilationContext context)
96             throws DatabaseException {
97         Layer0 L0 = Layer0.getInstance(graph);
98         String valueType = graph.getPossibleRelatedValue(relation, L0.RequiresValueType, Bindings.STRING);
99         if(valueType != null) {
100             try {
101                 return Environments.getType(context.runtimeEnvironment.getEnvironment(), valueType);
102             } catch (SCLExpressionCompilationException e) {
103                 LOGGER.warn("getExpectedType failed for valueType: " + valueType, e);
104             }
105         }
106         return super.getExpectedType(graph, context);
107     }
108     
109     @Override
110     protected CompilationContext getCompilationContext(ReadGraph graph)
111             throws DatabaseException {
112         return graph.syncRequest(new ResourceRead<CompilationContext>(componentType) {
113             @Override
114             public CompilationContext perform(ReadGraph graph)
115                     throws DatabaseException {
116                 Resource indexRoot = graph.syncRequest(new IndexRoot(resource));
117                 RuntimeEnvironment runtimeEnvironment = graph.syncRequest(new RuntimeEnvironmentRequest(indexRoot));
118                 return new CompilationContext(runtimeEnvironment, ComponentTypeSubstructure.forType(graph, resource));
119             }
120         });
121     }
122
123     @Override
124     protected Type getContextVariableType() {
125         return VARIABLE;
126     }
127
128     @Override
129     protected Expression getVariableAccessExpression(
130             ReadGraph graph,
131             CompilationContext context,
132             org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
133             String name) throws DatabaseException {
134         Pair<String,Type> entry = context.substructure.possibleTypedRVI(name);
135         if(entry == null)
136             return null;
137         Environment environment = context.runtimeEnvironment.getEnvironment();
138         Expression propertyVariable = new EApply(
139                 new EConstant(environment.getValue(BROWSE)),
140                 new EVariable(contextVariable),
141                 new ELiteral(new StringConstant(entry.first))
142                 );
143         return makeTypeFlexible(environment, new EApply(
144                 new EConstant(environment.getValue(VALUE), entry.second),
145                 propertyVariable
146                 ), entry.second);
147     }
148     
149     @Override
150     public int hashCode() {
151         return 31*(31*getClass().hashCode() + literal.hashCode()) + componentType.hashCode();
152     }
153     
154     @Override
155     public boolean equals(Object obj) {
156         if(this == obj)
157             return true;
158         if(obj == null || obj.getClass() != getClass())
159             return false;
160         CompileSCLMonitorRequest other = (CompileSCLMonitorRequest)obj;
161         return literal.equals(other.literal) && componentType.equals(other.componentType);
162     }
163 }