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