Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / request / ServerSCLHandlerValueRequest.java
1 package org.simantics.document.server.request;\r
2 \r
3 import java.util.HashMap;\r
4 import java.util.List;\r
5 import java.util.Map;\r
6 \r
7 import org.simantics.databoard.Bindings;\r
8 import org.simantics.db.ReadGraph;\r
9 import org.simantics.db.Resource;\r
10 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
11 import org.simantics.db.common.request.IndexRoot;\r
12 import org.simantics.db.exception.DatabaseException;\r
13 import org.simantics.db.layer0.request.VariableRead;\r
14 import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;\r
15 import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;\r
16 import org.simantics.db.layer0.util.RuntimeEnvironmentRequest;\r
17 import org.simantics.db.layer0.variable.Variable;\r
18 import org.simantics.document.server.Functions;\r
19 import org.simantics.document.server.bean.DataDefinition;\r
20 import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;\r
21 import org.simantics.layer0.Layer0;\r
22 import org.simantics.scl.compiler.constants.StringConstant;\r
23 import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
24 import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
25 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
26 import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
27 import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
28 import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
29 import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
30 import org.simantics.scl.compiler.environment.Environment;\r
31 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
32 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
33 import org.simantics.scl.compiler.types.TCon;\r
34 import org.simantics.scl.compiler.types.Type;\r
35 import org.simantics.scl.compiler.types.Types;\r
36 import org.simantics.scl.compiler.types.kinds.Kinds;\r
37 import org.simantics.scl.runtime.SCLContext;\r
38 import org.simantics.scl.runtime.function.Function1;\r
39 import org.simantics.structural2.scl.ComponentTypeProperty;\r
40 import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;\r
41 import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest;\r
42 import org.simantics.utils.datastructures.Pair;\r
43 \r
44 public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {\r
45 \r
46         private final Variable context;\r
47         private final Pair<Resource,Resource> componentTypeAndRoot;\r
48         private final Resource literal;\r
49 \r
50         public static class CompilationContext extends AbstractExpressionCompilationContext {\r
51                 public final Map<String, ComponentTypeProperty> propertyMap;\r
52 \r
53                 public CompilationContext(RuntimeEnvironment runtimeEnvironment,\r
54                                 Map<String, ComponentTypeProperty> propertyMap) {\r
55                         super(runtimeEnvironment);\r
56                         this.propertyMap = propertyMap;\r
57                 }\r
58         }\r
59 \r
60         private ServerSCLHandlerValueRequest(Variable context, Pair<Resource,Resource> componentTypeAndRoot, Resource literal) {\r
61                 assert(literal != null);\r
62                 this.context = context;\r
63                 this.literal = literal;\r
64                 this.componentTypeAndRoot = componentTypeAndRoot;\r
65         }\r
66 \r
67         public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {\r
68                 this(context, getComponentTypeAndRoot(graph, context), context.getRepresents(graph));\r
69         }\r
70 \r
71         private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {\r
72                 Variable parent = property.getParent(graph);\r
73                 Resource represents = parent.getRepresents(graph);\r
74                 if(represents != null) {\r
75                         Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));\r
76                         if(type != null) {\r
77                                 Resource root = graph.syncRequest(new IndexRoot(type));\r
78                                 return Pair.make(type, root);\r
79                         }\r
80                 }\r
81                 parent = parent.getParent(graph);\r
82                 Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));\r
83                 return Pair.make(parent.getType(graph), root);\r
84         }\r
85 \r
86 \r
87     public static List<TCon> getEffects(ReadGraph graph, Variable context) throws DatabaseException {\r
88         try {\r
89                 ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context);\r
90                 return req.getExpressionEffects(graph);\r
91         } catch (DatabaseException e) {\r
92             throw (DatabaseException)e;\r
93         } catch (Throwable t) {\r
94             throw new DatabaseException(t);\r
95         }\r
96     }\r
97 \r
98         public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {\r
99                 SCLContext sclContext = SCLContext.getCurrent();\r
100         Object oldGraph = sclContext.get("graph");\r
101                 try {\r
102                         Function1<Variable,Object> exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context),\r
103                                         TransientCacheListener.<Function1<Variable,Object>>instance());\r
104                         sclContext.put("graph", graph);\r
105                         return exp.apply(context);\r
106                 } catch (DatabaseException e) {\r
107                         throw (DatabaseException)e;\r
108                 } catch (Throwable t) {\r
109                         throw new DatabaseException(t);\r
110                 } finally {\r
111             sclContext.put("graph", oldGraph);\r
112                 }\r
113         }\r
114 \r
115         @Override\r
116         protected String getExpressionText(ReadGraph graph)\r
117                         throws DatabaseException {\r
118                 Layer0 L0 = Layer0.getInstance(graph);\r
119                 String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);\r
120                 return "\\context -> " + exp;\r
121         }\r
122 \r
123         protected RuntimeEnvironmentRequest getRuntimeEnvironmentRequest(Resource indexRoot) {\r
124                 return new RuntimeEnvironmentRequest(indexRoot) {\r
125                         @Override\r
126                         protected void fillEnvironmentSpecification(\r
127                                         EnvironmentSpecification environmentSpecification) {\r
128                         }\r
129                 };\r
130         }\r
131 \r
132         @Override\r
133         protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {\r
134                 \r
135                 return graph.syncRequest(new VariableRead<CompilationContext>(context) {\r
136                         \r
137                         @Override\r
138                         public CompilationContext perform(ReadGraph graph) throws DatabaseException {\r
139                                 \r
140                                 Pair<Resource,Resource> parameter = getComponentTypeAndRoot(graph, variable);\r
141                                 RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.second));\r
142                                 \r
143                                 Map<String, ComponentTypeProperty> propertyMap =\r
144                                                 graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),\r
145                                                                 TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());\r
146 \r
147 //                              Map<String, ComponentTypeProperty> result = new HashMap<String,ComponentTypeProperty>(propertyMap); \r
148 //                              for(DataDefinition dd : Functions.dataDefinitions(graph, variable)) {\r
149 //                                      result.put(dd.target, null);\r
150 //                              }\r
151                                 \r
152                                 return new CompilationContext(runtimeEnvironment, propertyMap);\r
153                                 \r
154                         }\r
155                         \r
156                 });\r
157                 \r
158         }\r
159 \r
160         @Override\r
161         protected Type getContextVariableType() {\r
162                 return VARIABLE; \r
163         }\r
164 \r
165         private static Expression accessInputVariable(Environment environment,\r
166                         org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {\r
167                 SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);\r
168                 return new EApply(new EConstant(variableParentFunction),\r
169                                 new EApply(new EConstant(variableParentFunction),\r
170                                                 new EVariable(contextVariable)));\r
171         }\r
172 \r
173         protected static Expression standardGetProperty(\r
174                         Environment environment,\r
175                         org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
176                         String name,\r
177                         Type type) {\r
178                 return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);\r
179         }\r
180 \r
181         @Override\r
182         protected Expression getVariableAccessExpression(\r
183                         ReadGraph graph,\r
184                         CompilationContext context,\r
185                         org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
186                         String name) throws DatabaseException {\r
187                 ComponentTypeProperty property = context.propertyMap.get(name);\r
188                 if(property != null)\r
189                         return standardGetProperty(\r
190                                         context.runtimeEnvironment.getEnvironment(),\r
191                                         contextVariable,\r
192                                         name,\r
193                                         property.type == null ? Types.metaVar(Kinds.STAR) : property.type);\r
194                 else {\r
195                         \r
196 //                      if(context.propertyMap.containsKey(name)) {\r
197 //                              \r
198 //                              org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT);\r
199 //                              \r
200 //                              Environment environment = context.runtimeEnvironment.getEnvironment();\r
201 //                              \r
202 ////                            return new EApply(\r
203 ////                            new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING),\r
204 //                              return new EApply(\r
205 //                                      new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC),\r
206 //                                      new EVariable(parametersVariable),\r
207 //                                      new ELiteral(new StringConstant(name)));\r
208 //                              \r
209 //                      }\r
210                         \r
211                         return getSpecialVariableAccessExpression(graph, context, contextVariable, name);\r
212                         \r
213                 }\r
214         }\r
215 \r
216         protected Expression getSpecialVariableAccessExpression(ReadGraph graph,\r
217                         CompilationContext context,\r
218                         org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,\r
219                         String name) throws DatabaseException {\r
220                 if(name.equals("input")) {\r
221                         Environment environment = context.runtimeEnvironment.getEnvironment();\r
222                         return accessInputVariable(environment, contextVariable);\r
223                 } else if(name.equals("self"))\r
224                         return new EVariable(contextVariable);\r
225                 else\r
226                         return null;\r
227         }\r
228 \r
229         @Override\r
230         public int hashCode() {\r
231                 final int prime = 31;\r
232                 int result = 1;\r
233                 result = prime * result + ((context == null) ? 0 : context.hashCode());\r
234                 return result;\r
235         }\r
236 \r
237         @Override\r
238         public boolean equals(Object obj) {\r
239                 if (this == obj)\r
240                         return true;\r
241                 if (obj == null)\r
242                         return false;\r
243                 if (getClass() != obj.getClass())\r
244                         return false;\r
245                 ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;\r
246                 if (context == null) {\r
247                         if (other.context != null)\r
248                                 return false;\r
249                 } else if (!context.equals(other.context))\r
250                         return false;\r
251                 return true;\r
252         }\r
253 \r
254 //      @Override\r
255 //      public int hashCode() {\r
256 //              return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();\r
257 //      }\r
258 //\r
259 //      @Override\r
260 //      public boolean equals(Object obj) {\r
261 //              if(this == obj)\r
262 //                      return true;\r
263 //              if(obj == null || obj.getClass() != getClass())\r
264 //                      return false;\r
265 //              ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj;\r
266 //              return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);\r
267 //      }\r
268         \r
269 }\r