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