]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java
Merge commit '4a2d762'
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / Functions.java
1 package org.simantics.document.server;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Collections;\r
6 import java.util.List;\r
7 import java.util.Map;\r
8 import java.util.TreeMap;\r
9 \r
10 import org.simantics.Simantics;\r
11 import org.simantics.databoard.Bindings;\r
12 import org.simantics.databoard.Datatypes;\r
13 import org.simantics.databoard.binding.Binding;\r
14 import org.simantics.databoard.type.Datatype;\r
15 import org.simantics.db.ReadGraph;\r
16 import org.simantics.db.RequestProcessor;\r
17 import org.simantics.db.Resource;\r
18 import org.simantics.db.Session;\r
19 import org.simantics.db.WriteGraph;\r
20 import org.simantics.db.common.primitiverequest.Adapter;\r
21 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
22 import org.simantics.db.common.request.UnaryRead;\r
23 import org.simantics.db.common.request.UniqueRead;\r
24 import org.simantics.db.common.request.WriteResultRequest;\r
25 import org.simantics.db.common.utils.Logger;\r
26 import org.simantics.db.common.utils.NameUtils;\r
27 import org.simantics.db.exception.DatabaseException;\r
28 import org.simantics.db.layer0.function.All;\r
29 import org.simantics.db.layer0.request.ProjectModels;\r
30 import org.simantics.db.layer0.request.VariableProperty;\r
31 import org.simantics.db.layer0.request.VariableRead;\r
32 import org.simantics.db.layer0.request.VariableValue;\r
33 import org.simantics.db.layer0.variable.ConstantPropertyVariable;\r
34 import org.simantics.db.layer0.variable.ProxyChildVariable;\r
35 import org.simantics.db.layer0.variable.ProxySessionRequest;\r
36 import org.simantics.db.layer0.variable.ProxyVariables;\r
37 import org.simantics.db.layer0.variable.StandardGraphChildVariable;\r
38 import org.simantics.db.layer0.variable.Variable;\r
39 import org.simantics.db.layer0.variable.VariableMap;\r
40 import org.simantics.db.layer0.variable.VariableMapImpl;\r
41 import org.simantics.db.layer0.variable.Variables;\r
42 import org.simantics.document.base.ontology.DocumentationResource;\r
43 import org.simantics.document.server.bean.Command;\r
44 import org.simantics.document.server.bean.DataDefinition;\r
45 import org.simantics.document.server.handler.AbstractEventHandler;\r
46 import org.simantics.document.server.handler.AbstractResponseHandler;\r
47 import org.simantics.document.server.handler.EventHandler;\r
48 import org.simantics.document.server.io.CommandContext;\r
49 import org.simantics.document.server.io.CommandContextImpl;\r
50 import org.simantics.document.server.io.CommandContextMutable;\r
51 import org.simantics.document.server.io.CommandResult;\r
52 import org.simantics.document.server.request.ServerSCLHandlerValueRequest;\r
53 import org.simantics.document.server.request.ServerSCLValueRequest;\r
54 import org.simantics.document.server.serverResponse.ServerResponse;\r
55 import org.simantics.document.server.serverResponse.SuccessResponse;\r
56 import org.simantics.modeling.ModelingResources;\r
57 import org.simantics.modeling.scl.SCLRealm;\r
58 import org.simantics.modeling.scl.SCLSessionManager;\r
59 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;\r
60 import org.simantics.modeling.services.ComponentNamingStrategy;\r
61 import org.simantics.operation.Layer0X;\r
62 import org.simantics.project.IProject;\r
63 import org.simantics.scl.compiler.types.TCon;\r
64 import org.simantics.scl.compiler.types.Type;\r
65 import org.simantics.scl.compiler.types.Types;\r
66 import org.simantics.scl.reflection.annotations.SCLValue;\r
67 import org.simantics.scl.runtime.SCLContext;\r
68 import org.simantics.scl.runtime.function.Function;\r
69 import org.simantics.scl.runtime.function.Function1;\r
70 import org.simantics.scl.runtime.function.FunctionImpl1;\r
71 import org.simantics.scl.runtime.function.FunctionImpl4;\r
72 import org.simantics.scl.runtime.reporting.SCLReportingHandler;\r
73 import org.simantics.scl.runtime.tuple.Tuple;\r
74 import org.simantics.scl.runtime.tuple.Tuple0;\r
75 import org.simantics.scl.runtime.tuple.Tuple2;\r
76 import org.simantics.scl.runtime.tuple.Tuple3;\r
77 import org.simantics.scl.runtime.tuple.Tuple4;\r
78 import org.simantics.scl.runtime.tuple.Tuple5;\r
79 import org.simantics.simulation.experiment.IExperiment;\r
80 import org.simantics.simulation.ontology.SimulationResource;\r
81 import org.simantics.simulation.project.IExperimentManager;\r
82 import org.simantics.structural2.variables.Connection;\r
83 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;\r
84 \r
85 import gnu.trove.map.hash.THashMap;\r
86 \r
87 public class Functions {\r
88         \r
89     @SCLValue(type = "VariableMap")\r
90     public static VariableMap inputSpaceChildren = new VariableMapImpl() {\r
91 \r
92         private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {\r
93             Variable root = Variables.getRootVariable(graph);\r
94             return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);\r
95         }\r
96         \r
97         @Override\r
98         public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
99 \r
100             if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);\r
101             return All.standardChildDomainChildren.getVariable(graph, context, name);\r
102             \r
103         }\r
104 \r
105         @Override\r
106         public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
107 \r
108             map = All.standardChildDomainChildren.getVariables(graph, context, map);\r
109             if(map == null) map = new THashMap<String,Variable>();\r
110             map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));\r
111             return map;\r
112             \r
113         }\r
114         \r
115     };\r
116     \r
117     static class DocumentProxyChildVariable extends ProxyChildVariable {\r
118 \r
119         public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {\r
120             super(base, parent, other, name);\r
121         }\r
122     \r
123         @Override\r
124         public Variable create(Variable base, Variable parent, Variable other, String name) {\r
125             return new DocumentProxyChildVariable(base, parent, other, name);\r
126         }\r
127         \r
128         public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
129             \r
130                 if(CONTEXT_END.equals(name)) {\r
131                 if(other instanceof ProxyChildVariable) {\r
132                         // The context is also a proxy - let it do the job\r
133                     return super.getPossibleChild(graph, name);\r
134                 } else {\r
135                         return new RootVariable(this, base.getRepresents(graph));\r
136                 }\r
137                 }\r
138             \r
139             return super.getPossibleChild(graph, name);\r
140             \r
141         }\r
142         \r
143         public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
144 \r
145             Collection<Variable> result = super.getChildren(graph);\r
146             if(!(base instanceof ProxyChildVariable)) {\r
147                 result.add(new RootVariable(this, base.getRepresents(graph)));\r
148             }\r
149             return result;\r
150             \r
151         }       \r
152         \r
153     }\r
154     \r
155     static class RootVariable extends StandardGraphChildVariable {\r
156 \r
157         public RootVariable(DocumentProxyChildVariable parent, Resource resource) {\r
158             super(parent, null, resource);\r
159         }\r
160         \r
161         @Override\r
162         public String getName(ReadGraph graph) throws DatabaseException {\r
163             return ProxyChildVariable.CONTEXT_END;\r
164         }\r
165         \r
166         @SuppressWarnings("deprecation")\r
167         @Override\r
168         public Variable getNameVariable(ReadGraph graph) throws DatabaseException {\r
169             return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);\r
170         }\r
171         \r
172     }\r
173 \r
174     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
175     public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
176         Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
177         DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
178         String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);\r
179         if(uri == null) {\r
180                 // TODO HAXX - Please fix this\r
181                 // we have no URI so this probably means that someone has inserted a non-session \r
182                 // into the proxy variable => return that instead\r
183                 return session;\r
184         }\r
185         return Variables.getVariable(graph, uri);\r
186     }\r
187     \r
188     public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {\r
189         Variable session = graph.syncRequest(new ProxySessionRequest(self));\r
190         if (session == null)\r
191                 throw new DatabaseException("No state for " + self.getURI(graph));\r
192         return session.getPossibleChild(graph, "__scl__");\r
193     }\r
194     \r
195     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
196     public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
197         Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
198         if (session == null)\r
199             throw new DatabaseException("No state for " + context.getURI(graph));\r
200         return session.getPossibleChild(graph, "__scl__");\r
201     }\r
202 \r
203     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
204     public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
205         Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
206         return session.getPossibleChild(graph, "__icstate__");\r
207     }\r
208 \r
209     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
210     public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
211         return graph.syncRequest(new ProxySessionRequest(context));\r
212     }\r
213     \r
214     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
215     public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
216         // Try if experiment (run) has been used as the input\r
217         Variable var = input(graph, converter, context);\r
218         SimulationResource SR = SimulationResource.getInstance(graph);\r
219         while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {\r
220             var = var.getParent(graph);\r
221         }\r
222         \r
223         if(var != null) {\r
224             IExperiment exp = getExperiment(graph, var);\r
225             if(exp == null)\r
226                 return null;\r
227         }\r
228         \r
229         return var;\r
230     }\r
231     \r
232     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
233     public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
234         Variable var = input(graph, converter, context);\r
235         ModelingResources MOD = ModelingResources.getInstance(graph);\r
236         while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {\r
237             var = var.getParent(graph);\r
238         }\r
239         \r
240         return var;\r
241     }\r
242     \r
243     private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {\r
244         \r
245         ArrayList<Variable> result = new ArrayList<Variable>();\r
246         \r
247         DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
248 \r
249         Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);\r
250         if(broadcasted != null) result.add(broadcasted);\r
251         \r
252         for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {\r
253                 result.addAll(getBroadcasted(graph, child));\r
254         }\r
255         \r
256         return result;\r
257         \r
258     }\r
259 \r
260     private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {\r
261         \r
262         if(commandVariables.isEmpty()) return Collections.emptyList();\r
263         \r
264         String t = trigger;\r
265         TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();\r
266         \r
267         DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
268         \r
269         int count = 0;\r
270         for (Variable c : commandVariables) {\r
271                 \r
272             if(trigger == null)\r
273                 t = c.getName(graph);\r
274             \r
275             Connection conn = c.getValue(graph);\r
276             Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);\r
277             if (targetConnectionPoint != null) {\r
278                 Variable target = targetConnectionPoint.getParent(graph);\r
279                 if (target != null) {\r
280                     \r
281                     Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);\r
282                     if(enabled != null && !enabled) continue;\r
283                         \r
284                     Integer ordinal;\r
285                     if (broadcast) {\r
286                         ordinal = ++count;\r
287                     } else {\r
288                         ordinal = 1;\r
289                             try {\r
290                                 String o = c.getPossiblePropertyValue(graph, "ordinal");\r
291                                 if(o != null)\r
292                                     ordinal = Integer.parseInt(o);\r
293                             } catch (NumberFormatException e) {}\r
294                     }\r
295                     \r
296                     String constantKey = target.getPossiblePropertyValue(graph, "constantKey");\r
297                     String constantValue = target.getPossiblePropertyValue(graph, "constantValue");\r
298                     \r
299                     CommandContextMutable newConstants = (CommandContextMutable)constants; \r
300                     if(constantKey != null && constantValue != null) {\r
301                         if(!constantKey.isEmpty()) {\r
302                                 newConstants = new CommandContextImpl().merge(constants);\r
303                                 newConstants.putString(constantKey, constantValue);\r
304                         }\r
305                     }\r
306                     \r
307                     String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");\r
308                     if(requiredKey != null && !requiredKey.isEmpty()) {\r
309                         if (newConstants == constants) {\r
310                                 newConstants = new CommandContextImpl().merge(constants);\r
311                         }\r
312                                 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));\r
313                     }\r
314                     \r
315                     String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");\r
316                     if(forbiddenKey != null && !forbiddenKey.isEmpty()) {\r
317                         if (newConstants == constants) {\r
318                                 newConstants = new CommandContextImpl().merge(constants);\r
319                         }\r
320                                 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));\r
321                     }\r
322 \r
323                     if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {\r
324 \r
325                         // This is a broadcast terminal of a container\r
326                         List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);\r
327                         sequences.put(ordinal, broadcastCommands);\r
328 \r
329                     } else {\r
330 \r
331                         Command command = new Command(DocumentServerUtils.getId(graph, target), t, \r
332                                         targetConnectionPoint.getName(graph), newConstants);\r
333                         sequences.put(ordinal, Collections.singletonList(command));\r
334                         \r
335                     }\r
336 \r
337                 }\r
338             }\r
339         }\r
340 \r
341         List<Command> commands = new ArrayList<Command>();\r
342         for (List<Command> commandList : sequences.values()) {\r
343                 for (Command command : commandList) {\r
344                         commands.add(command);\r
345                 }\r
346         }\r
347         \r
348         return commands;\r
349     }\r
350 \r
351     /**\r
352      * Commands\r
353      * \r
354      * @param graph\r
355      * @param variable\r
356      * @return\r
357      * @throws DatabaseException\r
358      */\r
359     public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {\r
360         return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);\r
361     }\r
362 \r
363     /**\r
364      * Data definitions\r
365      * \r
366      * @param graph\r
367      * @param variable\r
368      * @return\r
369      * @throws DatabaseException\r
370      */\r
371     public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {\r
372         DocumentationResource DOC = DocumentationResource.getInstance(graph); \r
373         ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();\r
374         // Find data definition connections\r
375         for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {\r
376             Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);\r
377             // Find data the other end of definition connection\r
378             Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,\r
379                     dataDefinitionRelation, dataDefinitionConnection);\r
380             if (dataDefinitionProviders != null) {\r
381 \r
382                 for(Variable dataDefinitionProvider : dataDefinitionProviders) {\r
383 \r
384                     Variable dataDefinition = dataDefinitionProvider.getParent(graph);\r
385                     if (dataDefinition != null) {\r
386                         // Found other end. Is should contain ONE data\r
387 // definition connection to the actual data\r
388                         Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);\r
389                         if (dataCollection.size() == 1) {\r
390                             Variable dataRelation = dataCollection.iterator().next();\r
391                             Connection dataConnection = dataRelation.getValue(graph);\r
392                             // Find data the other end of definition connection\r
393                             Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,\r
394                                     dataRelation, dataConnection);\r
395                             if (dataConnectionPoint != null) {\r
396                                 Variable data = dataConnectionPoint.getParent(graph);\r
397                                 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);\r
398 \r
399                                 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {\r
400 \r
401                                         String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,\r
402                                                 Bindings.STRING);\r
403                                         String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,\r
404                                                 Bindings.STRING);\r
405 \r
406                                         dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
407                                                         sourceProperty, targetProperty));\r
408                                 \r
409                                 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {\r
410 \r
411                                         List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);\r
412                                         List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);\r
413 \r
414                                         for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {\r
415                                                 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
416                                                         sourcesProperty.get(i), targetsProperty.get(i)));\r
417                                         }\r
418                                 }\r
419                             }\r
420                         }\r
421                     }\r
422                 }\r
423             }\r
424         }\r
425         return dataDefinitions;\r
426     }\r
427 \r
428     @SuppressWarnings("unchecked")\r
429         private static <T> List<T> toList(Object o, Class<T> c) {\r
430         List<T> result = null;\r
431         if (o instanceof List) {\r
432                 return (List<T>)o;\r
433         } else if (o instanceof Object[]) {\r
434                 result = new ArrayList<T>(((Object[])o).length);\r
435                 for (T item : (T[])o) {\r
436                         result.add(item);\r
437                 }\r
438                 return result;\r
439         } else {\r
440                 return Collections.<T>emptyList();\r
441         }\r
442     }\r
443     \r
444     public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {\r
445         return new EventHandler() {\r
446 \r
447             @Override\r
448             public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {\r
449                 return null;\r
450             }\r
451 \r
452         };\r
453     }\r
454     \r
455     public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
456         \r
457         final Session session = graph.getSession();\r
458         \r
459         return new AbstractEventHandler() {\r
460             \r
461                         @Override\r
462                         public CommandResult handle(final CommandContext parameters) {\r
463                                 \r
464                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
465                 \r
466                 try {\r
467                         \r
468                                         String result = session.sync(new WriteResultRequest<String>() {\r
469                                             \r
470                                             @Override\r
471                                             public String perform(WriteGraph graph) throws DatabaseException {\r
472                                                 SCLContext sclContext = SCLContext.getCurrent();\r
473                                                 Object oldGraph = sclContext.put("graph", graph);\r
474                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
475                                                 try {\r
476                                                     Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
477                                                         @Override\r
478                                                         public String apply(String key) {\r
479                                                             return parameters.getString(key);\r
480                                                         }\r
481                                                     }; \r
482                                                     Object response = (String)fn.apply(variable, pf);\r
483                                                     if(response instanceof String) {\r
484                                                         return (String)response;\r
485                                                     }\r
486                                                     return null;\r
487                                                 } catch (Throwable t) {\r
488                                                     t.printStackTrace();\r
489                                                 } finally {\r
490                                                         sclContext.put("graph", oldGraph);\r
491                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
492                                                 }\r
493                                                 \r
494                                                 return null;\r
495                                                 \r
496                                             }\r
497                                             \r
498                                         });\r
499                                         \r
500                         return new SuccessResponse(result);\r
501                                         \r
502                                 } catch (Throwable e) {\r
503                                         Logger.defaultLogError(e);\r
504                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
505                                 }\r
506                 \r
507                         }\r
508             \r
509         };\r
510     }\r
511     \r
512     public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
513         \r
514         final Session session = graph.getSession();\r
515         \r
516         return new AbstractEventHandler() {\r
517             \r
518                         @Override\r
519                         public CommandResult handle(final CommandContext parameters) {\r
520                                 \r
521                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
522                 \r
523                 try {\r
524                         \r
525                                         String result = session.sync(new UniqueRead<String>() {\r
526                                             \r
527                                             @Override\r
528                                             public String perform(ReadGraph graph) throws DatabaseException {\r
529                                                 SCLContext sclContext = SCLContext.getCurrent();\r
530                                                 Object oldGraph = sclContext.put("graph", graph);\r
531                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
532                                                 try {\r
533                                                     Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
534                                                         @Override\r
535                                                         public String apply(String key) {\r
536                                                             return parameters.getString(key);\r
537                                                         }\r
538                                                     }; \r
539                                                     Object response = (String)fn.apply(variable, pf);\r
540                                                     if(response instanceof String) {\r
541                                                         return (String)response;\r
542                                                     }\r
543                                                     return null;\r
544                                                 } catch (Throwable t) {\r
545                                                     t.printStackTrace();\r
546                                                 } finally {\r
547                                                         sclContext.put("graph", oldGraph);\r
548                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
549                                                 }\r
550                                                 \r
551                                                 return null;\r
552                                                 \r
553                                             }\r
554                                             \r
555                                         });\r
556                                         \r
557                         return new SuccessResponse(result);\r
558                                         \r
559                                 } catch (Throwable e) {\r
560                                         Logger.defaultLogError(e);\r
561                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
562                                 }\r
563                 \r
564                         }\r
565             \r
566         };\r
567     }\r
568 \r
569     public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {\r
570         \r
571         final Session session = graph.getSession();\r
572         \r
573         return new AbstractEventHandler() {\r
574             \r
575                         @Override\r
576                         public CommandResult handle(final CommandContext parameters) {\r
577                                 \r
578                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
579                 \r
580                 try {\r
581                         \r
582                         CommandResult result = session.sync(new UniqueRead<CommandResult>() {\r
583                                             \r
584                                             @Override\r
585                                             public CommandResult perform(ReadGraph graph) throws DatabaseException {\r
586                                                 SCLContext sclContext = SCLContext.getCurrent();\r
587                                                 Object oldGraph = sclContext.put("graph", graph);\r
588                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
589                                                 try {\r
590                                                     Object response = fn.apply(parameters);\r
591                                                     if(response instanceof CommandResult) {\r
592                                                         return (CommandResult)response;\r
593                                                     }\r
594                                                     return null;\r
595                                                 } catch (Throwable t) {\r
596                                                     t.printStackTrace();\r
597                                                 } finally {\r
598                                                         sclContext.put("graph", oldGraph);\r
599                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
600                                                 }\r
601                                                 \r
602                                                 return null;\r
603                                                 \r
604                                             }\r
605                                             \r
606                                         });\r
607                                         \r
608                         return result;\r
609                                         \r
610                                 } catch (Throwable e) {\r
611                                         Logger.defaultLogError(e);\r
612                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
613                                 }\r
614                 \r
615                         }\r
616             \r
617         };\r
618     }\r
619 \r
620     public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {\r
621 \r
622         Variable anyFunction = self.browse(graph, ".#" + function);\r
623         if(anyFunction == null) return null;\r
624 \r
625         final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);\r
626         \r
627         final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);\r
628         String expression = anyFunction.getPropertyValue(graph, "expression");\r
629         \r
630         final Session session = graph.getSession();\r
631         \r
632         return new AbstractResponseHandler(expression) {\r
633             \r
634                 private String formatError(RequestProcessor proc, Throwable t) {\r
635                         \r
636                         try {\r
637                                 \r
638                                         return proc.syncRequest(new UniqueRead<String>() {\r
639 \r
640                                                 @Override\r
641                                                 public String perform(ReadGraph graph) throws DatabaseException {\r
642                                                         Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);\r
643                                                         String uri2 = proxy.getURI(graph);\r
644                                                         String uri = self.getParent(graph).getURI(graph);\r
645 \r
646                                                         String path = uri.substring(uri2.length());\r
647 \r
648                                                         String expr = anyFunction.getPossiblePropertyValue(graph, "expression");\r
649                                                         StringBuilder message = new StringBuilder();\r
650                                                         message.append("Handler execution failed\n");\r
651                                                         message.append(" handler=" + path + "\n");\r
652                                                         message.append(" expression=" + expr + "\n");\r
653                                                         message.append(" message=" + t.getMessage() + "\n");\r
654                                                         return message.toString();\r
655                                                 }\r
656                                                 \r
657                                         });\r
658                                         \r
659                                 } catch (DatabaseException e) {\r
660                                         \r
661                                         return e.getMessage();\r
662                                         \r
663                                 }\r
664                         \r
665                 }\r
666                 \r
667                         @Override\r
668                         public CommandResult handle(final CommandContext parameters) {\r
669                                 \r
670                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
671                 \r
672                 try {\r
673                         \r
674                         Object result = null;\r
675                         if(effects.contains(Types.WRITE_GRAPH)) {\r
676 \r
677                                 result = session.syncRequest(new WriteResultRequest<Object>() {\r
678 \r
679                                                         @Override\r
680                                                         public Object perform(WriteGraph graph)\r
681                                                                         throws DatabaseException {\r
682                                                 SCLContext sclContext = SCLContext.getCurrent();\r
683                                                 Object oldGraph = sclContext.put("graph", graph);\r
684                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
685                                                 try {\r
686                                                         Object response = fn.apply(parameters);\r
687                                                         return response;\r
688                                                 } catch (Throwable t) {\r
689                                                         return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
690                                                 } finally {\r
691                                                         sclContext.put("graph", oldGraph);\r
692                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
693                                                 }\r
694 \r
695                                                         }\r
696                                 });\r
697                                 \r
698                         } else if(effects.contains(Types.READ_GRAPH)) {\r
699 \r
700                                 result = session.sync(new UniqueRead<Object>() {\r
701 \r
702                                         @Override\r
703                                         public Object perform(ReadGraph graph) throws DatabaseException {\r
704                                                 \r
705                                                 SCLContext sclContext = SCLContext.getCurrent();\r
706                                                 Object oldGraph = sclContext.put("graph", graph);\r
707                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
708                                                 \r
709                                                 try {\r
710                                                         Object response = fn.apply(parameters);\r
711                                                         return response;\r
712                                                 } catch (Throwable t) {\r
713                                                         return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
714                                                 } finally {\r
715                                                         sclContext.put("graph", oldGraph);\r
716                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
717                                                 }\r
718                                                 \r
719                                         }\r
720                                 });\r
721 \r
722                         } else {\r
723                                 result = fn.apply(parameters);\r
724                         }\r
725 \r
726                         if (result instanceof org.simantics.document.server.serverResponse.Error) {\r
727                                 return (CommandResult)result;\r
728                         }\r
729                         \r
730                         if (result instanceof CommandResult) {\r
731                                 return (CommandResult)result;\r
732                         } else {\r
733                                 CommandContextMutable assignments = new CommandContextImpl();\r
734                                 assignments.putValue("result", result);\r
735                                 return new ServerResponse(200, "", assignments);\r
736                         }                       \r
737                                         \r
738                                 } catch (Throwable e) {\r
739                                         return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));\r
740                                 }\r
741                 \r
742                         }\r
743             \r
744         };\r
745     }\r
746     \r
747     public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {\r
748         \r
749         final Session session = graph.getSession();\r
750         \r
751         return new AbstractEventHandler() {\r
752             \r
753                         @Override\r
754                         public CommandResult handle(final CommandContext parameters) {\r
755                                 \r
756                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
757                 \r
758                 try {\r
759                         \r
760                         CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {\r
761                                             \r
762                                             @Override\r
763                                             public CommandResult perform(WriteGraph graph) throws DatabaseException {\r
764                                                 SCLContext sclContext = SCLContext.getCurrent();\r
765                                                 Object oldGraph = sclContext.put("graph", graph);\r
766                                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
767                                                 try {\r
768                                                     Object response = fn.apply(parameters);\r
769                                                     if(response instanceof CommandResult) {\r
770                                                         return (CommandResult)response;\r
771                                                     }\r
772                                                     return null;\r
773                                                 } catch (Throwable t) {\r
774                                                     t.printStackTrace();\r
775                                                 } finally {\r
776                                                         sclContext.put("graph", oldGraph);\r
777                                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
778                                                 }\r
779                                                 \r
780                                                 return null;\r
781                                                 \r
782                                             }\r
783                                             \r
784                                         });\r
785                                         \r
786                         return result;\r
787                                         \r
788                                 } catch (Throwable e) {\r
789                                         Logger.defaultLogError(e);\r
790                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
791                                 }\r
792                 \r
793                         }\r
794             \r
795         };\r
796     }\r
797 \r
798     public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {\r
799         \r
800         return new AbstractEventHandler() {\r
801             \r
802                         @Override\r
803                         public CommandResult handle(final CommandContext parameters) {\r
804                                 \r
805                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
806                 \r
807                 try {\r
808                         \r
809                         SCLContext sclContext = SCLContext.getCurrent();\r
810                         Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
811                         try {\r
812                                 Object response = fn.apply(parameters);\r
813                                 if(response instanceof CommandResult) {\r
814                                         return (CommandResult)response;\r
815                                 }\r
816                                 return null;\r
817                         } catch (Throwable t) {\r
818                                 t.printStackTrace();\r
819                         } finally {\r
820                                 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
821                         }\r
822 \r
823                         return null;\r
824                                                 \r
825                                 } catch (Throwable e) {\r
826                                         Logger.defaultLogError(e);\r
827                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
828                                 }\r
829                 \r
830                         }\r
831             \r
832         };\r
833     }\r
834 \r
835     public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {\r
836         \r
837         return new AbstractEventHandler() {\r
838             \r
839                         @Override\r
840                         public CommandResult handle(final CommandContext parameters) {\r
841                                 \r
842                 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
843                 \r
844                 try {\r
845 \r
846                         String result = "";\r
847                         \r
848                                 SCLContext sclContext = SCLContext.getCurrent();\r
849                                 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
850                                 try {\r
851                                     Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
852                                         @Override\r
853                                         public String apply(String key) {\r
854                                             return parameters.getString(key);\r
855                                         }\r
856                                     }; \r
857                                     Object response = (String)fn.apply(pf);\r
858                                     if(response instanceof String) {\r
859                                         result = (String)response;\r
860                                     }\r
861                                 } catch (Throwable t) {\r
862                                     t.printStackTrace();\r
863                                 } finally {\r
864                                         sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
865                                 }\r
866                                         \r
867                         return new SuccessResponse(result);\r
868                                         \r
869                                 } catch (Throwable e) {\r
870                                         Logger.defaultLogError(e);\r
871                                         return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
872                                 }\r
873                 \r
874                         }\r
875             \r
876         };\r
877     }\r
878 \r
879     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
880     public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
881         return ServerSCLValueRequest.compileAndEvaluate(graph, context);\r
882     }\r
883 \r
884     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
885     public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
886         return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);\r
887     }\r
888 \r
889     @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")\r
890     public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {\r
891         return createComponentNamingStrategy(graph);\r
892     }\r
893 \r
894     public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {\r
895         Layer0X L0X = Layer0X.getInstance(graph);\r
896         @SuppressWarnings({ "unchecked", "rawtypes" })\r
897         final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());\r
898         @SuppressWarnings("rawtypes")\r
899         Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {\r
900             @Override\r
901             public Object apply(ReadGraph p0, Resource p1, String p2) {\r
902                 return apply(p0, p1, p2);\r
903             }\r
904             @SuppressWarnings("unchecked")\r
905             @Override\r
906             public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {\r
907                 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);\r
908             }\r
909         };\r
910         return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);\r
911     }\r
912 \r
913     public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {\r
914         if (variable == null)\r
915             return null;\r
916 \r
917         SimulationResource SIMU = SimulationResource.getInstance(graph);\r
918 \r
919         Variable var = variable;\r
920         Resource represents = var.getRepresents(graph);\r
921         Resource activeRun = null;\r
922         if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {\r
923             activeRun = represents;\r
924         }\r
925 \r
926         IProject project = Simantics.peekProject();\r
927         if (activeRun != null && project != null) {\r
928             IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
929             if (expMan != null)\r
930                 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));\r
931         }\r
932 \r
933         return null;\r
934     }\r
935     \r
936     public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {\r
937         List<Object> list = new ArrayList<Object>();\r
938         if (tuple instanceof Tuple) {\r
939                 Collections.addAll(list, ((Tuple)tuple).toArray());\r
940         } else {\r
941                 list.add(tuple);                \r
942         }\r
943         context.putRow(key, list);\r
944         return context;\r
945     }\r
946     \r
947     public static List<Object> getTuples(CommandContext context, String key) {\r
948         List<List<Object>> rows = context.getRows(key);\r
949         List<Object> tuples = new ArrayList<Object>();\r
950         if (rows != null) {\r
951                 for (List<Object> row : rows) {\r
952                         switch (row.size()) {\r
953                         case 0: tuples.add(Tuple0.INSTANCE); break;\r
954                         case 1: tuples.add(row.get(1)); break;\r
955                         case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;\r
956                         case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;\r
957                         case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;\r
958                         case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;\r
959                         }\r
960                 }\r
961         }\r
962         return tuples;\r
963     }\r
964     \r
965     public static String printContext(CommandContext context) {\r
966         String str = context.toString();\r
967         System.err.println(str);\r
968         return str;\r
969     }\r
970     \r
971     @SCLValue(type = "AbstractEventHandler")\r
972     public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {\r
973 \r
974                 @Override\r
975                 public CommandResult handle(CommandContext context) {\r
976                         return null;\r
977                 }\r
978 \r
979     };\r
980 \r
981     public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
982         \r
983         String baseURI = base.getURI(graph);\r
984         \r
985         String selfURI = self.getURI(graph);\r
986         \r
987         String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));\r
988         String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());\r
989         String stripped = prefix + suffix;\r
990         \r
991         String relative = Variables.getRelativeRVI(baseURI, stripped); \r
992         \r
993         return Variables.getRVI(relative, ref);\r
994         \r
995     }\r
996     \r
997     public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
998         \r
999         String id = sclStateKey(graph, base, self, ref);\r
1000 \r
1001         Variable sclVar = base.getPossibleChild(graph, "__scl__");\r
1002         if(sclVar == null) return null;\r
1003         \r
1004         return sclVar.getPossibleProperty(graph, id);\r
1005         \r
1006     }\r
1007     \r
1008     public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
1009         \r
1010         Variable stateVariable = sclStateVariable(graph, base, self, ref);\r
1011         if (stateVariable != null) {\r
1012                 \r
1013                 return stateVariable.getValue(graph);\r
1014                 \r
1015         } else {\r
1016                 \r
1017                 String id = sclStateKey(graph, base, self, ref);\r
1018 \r
1019                 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");\r
1020                 realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);\r
1021                 \r
1022                 return defaultValue;\r
1023                 \r
1024         }\r
1025     }\r
1026     \r
1027     public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {\r
1028         \r
1029         String id = sclStateKey(graph, base, self, ref);\r
1030 \r
1031         SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");\r
1032         realm.getConnection().setVariable(id, getSCLType(value), value);\r
1033         realm.refreshVariablesSync();\r
1034                 \r
1035     }\r
1036     \r
1037     public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
1038         Resource project = Simantics.getProjectResource();\r
1039         Variable component = self.getParent(graph);\r
1040         Variable projectVariable = Variables.getVariable(graph, project);\r
1041         return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);\r
1042     }\r
1043     \r
1044     public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {\r
1045         Resource project = Simantics.getProjectResource();\r
1046         Variable component = self.getParent(graph);\r
1047         Variable projectVariable = Variables.getVariable(graph, project);\r
1048         setSclStateValue(graph, projectVariable, component, ref, value);\r
1049     }\r
1050     \r
1051     private static Type getSCLType(Object value) throws DatabaseException {\r
1052         Binding b = Bindings.getBindingUnchecked(value.getClass());\r
1053         Datatype t = b.type();\r
1054         if(Datatypes.STRING.equals(t)) return Types.STRING;\r
1055         if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;\r
1056         throw new DatabaseException("Type not supported");\r
1057     }\r
1058 \r
1059     public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {\r
1060         Resource project = Simantics.getProjectResource();\r
1061         ArrayList<Variable> result = new ArrayList<Variable>();\r
1062         for(Resource model : graph.syncRequest(new ProjectModels(project))) {\r
1063                 result.add(Variables.getVariable(graph, model));\r
1064         }\r
1065         return result;\r
1066     }\r
1067 \r
1068     public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {\r
1069         return var.getName(graph);\r
1070     }\r
1071     \r
1072     public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {\r
1073         Variable property = graph.syncRequest(new VariableProperty(variable, name));\r
1074         return graph.syncRequest(new VariableValue<Object>(property));\r
1075     }\r
1076 \r
1077     public static class ParentExistsRequest extends VariableRead<Boolean> {\r
1078 \r
1079                 public ParentExistsRequest(Variable parent) {\r
1080                         super(parent);\r
1081                 }\r
1082 \r
1083                 @Override\r
1084                 public Boolean perform(ReadGraph graph) throws DatabaseException {\r
1085                         \r
1086                         Variable existsProperty = variable.getPossibleProperty(graph, "exists");\r
1087                         if(existsProperty == null) return true;\r
1088                         \r
1089                         Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);\r
1090                         if (exists == null || !exists) return false;\r
1091 \r
1092                 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));\r
1093 \r
1094                 }\r
1095         \r
1096     } \r
1097 \r
1098     public static class PathExistsRequest extends VariableRead<Boolean> {\r
1099 \r
1100                 public PathExistsRequest(Variable variable) {\r
1101                         super(variable);\r
1102                 }\r
1103 \r
1104                 @Override\r
1105                 public Boolean perform(ReadGraph graph) throws DatabaseException {\r
1106                         \r
1107                         Variable widget = variable.getParent(graph);\r
1108                 \r
1109                 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");\r
1110                         if (exists == null || !exists) return false;\r
1111                 \r
1112                 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;\r
1113                 \r
1114                 DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
1115                 Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);\r
1116                 for (Variable cp : cps) {\r
1117                         \r
1118                         Connection conn = cp.getValue(graph);\r
1119                                 Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);\r
1120                                 if (otherCp != null) {\r
1121                                         Variable parentWidget = otherCp.getParent(graph);\r
1122                                         if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
1123                                                 return true;\r
1124                                         }\r
1125                                 } else {\r
1126                                         Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {\r
1127                                     @Override\r
1128                                     public Variable perform(ReadGraph graph) throws DatabaseException {\r
1129                                         DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
1130                                         Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);\r
1131 \r
1132                                                 for(VariableConnectionPointDescriptor desc : descs) {\r
1133                                                         if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {\r
1134                                                                 return desc.getVariable(graph);\r
1135                                                         }\r
1136                                                 }\r
1137                                                 return null;\r
1138                                     }\r
1139                                 });\r
1140                                         if (parentCp != null) {\r
1141                                                 Variable parentWidget = parentCp.getParent(graph);\r
1142                                                 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
1143                                                         return true;\r
1144                                                 }\r
1145                                         }\r
1146                                 }\r
1147                         }\r
1148                 \r
1149                         Resource type = widget.getType(graph);\r
1150                         return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||\r
1151                                 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());\r
1152                 }\r
1153     } \r
1154     \r
1155     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")\r
1156     public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
1157         return graph.syncRequest(new PathExistsRequest(context));\r
1158     }\r
1159     \r
1160 }