1 package org.simantics.document.server;
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;
11 import java.util.TreeMap;
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.TransientCacheAsyncListener;
27 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
28 import org.simantics.db.common.request.BinaryRead;
29 import org.simantics.db.common.request.ResourceRead;
30 import org.simantics.db.common.request.UniqueRead;
31 import org.simantics.db.common.request.WriteResultRequest;
32 import org.simantics.db.common.utils.Logger;
33 import org.simantics.db.common.utils.NameUtils;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.db.layer0.function.All;
36 import org.simantics.db.layer0.request.ProjectModels;
37 import org.simantics.db.layer0.request.PropertyInfo;
38 import org.simantics.db.layer0.request.PropertyInfoRequest;
39 import org.simantics.db.layer0.request.VariableProperty;
40 import org.simantics.db.layer0.request.VariableRead;
41 import org.simantics.db.layer0.request.VariableValueWithBinding;
42 import org.simantics.db.layer0.scl.SCLDatabaseException;
43 import org.simantics.db.layer0.variable.ConstantPropertyVariable;
44 import org.simantics.db.layer0.variable.ProxyChildVariable;
45 import org.simantics.db.layer0.variable.ProxySessionRequest;
46 import org.simantics.db.layer0.variable.ProxyVariableSupport;
47 import org.simantics.db.layer0.variable.ProxyVariables;
48 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
49 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
50 import org.simantics.db.layer0.variable.Variable;
51 import org.simantics.db.layer0.variable.VariableMap;
52 import org.simantics.db.layer0.variable.VariableMapImpl;
53 import org.simantics.db.layer0.variable.Variables;
54 import org.simantics.db.service.DirectQuerySupport;
55 import org.simantics.document.base.ontology.DocumentationResource;
56 import org.simantics.document.server.bean.Command;
57 import org.simantics.document.server.bean.DataDefinition;
58 import org.simantics.document.server.handler.AbstractEventHandler;
59 import org.simantics.document.server.handler.AbstractResponseHandler;
60 import org.simantics.document.server.handler.EventHandler;
61 import org.simantics.document.server.io.CommandContext;
62 import org.simantics.document.server.io.CommandContextImpl;
63 import org.simantics.document.server.io.CommandContextMutable;
64 import org.simantics.document.server.io.CommandResult;
65 import org.simantics.document.server.io.IConsole;
66 import org.simantics.document.server.request.NodeRequest;
67 import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
68 import org.simantics.document.server.request.ServerSCLValueRequest;
69 import org.simantics.document.server.serverResponse.ServerResponse;
70 import org.simantics.document.server.serverResponse.SuccessResponse;
71 import org.simantics.document.server.state.StateNodeManager;
72 import org.simantics.document.server.state.StateRealm;
73 import org.simantics.document.server.state.StateSessionManager;
74 import org.simantics.modeling.ModelingResources;
75 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
76 import org.simantics.modeling.services.ComponentNamingStrategy;
77 import org.simantics.operation.Layer0X;
78 import org.simantics.project.IProject;
79 import org.simantics.scl.compiler.module.repository.ImportFailureException;
80 import org.simantics.scl.compiler.types.TCon;
81 import org.simantics.scl.compiler.types.Type;
82 import org.simantics.scl.compiler.types.Types;
83 import org.simantics.scl.reflection.annotations.SCLValue;
84 import org.simantics.scl.runtime.SCLContext;
85 import org.simantics.scl.runtime.function.Function;
86 import org.simantics.scl.runtime.function.Function1;
87 import org.simantics.scl.runtime.function.FunctionImpl1;
88 import org.simantics.scl.runtime.function.FunctionImpl4;
89 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
90 import org.simantics.scl.runtime.tuple.Tuple;
91 import org.simantics.scl.runtime.tuple.Tuple0;
92 import org.simantics.scl.runtime.tuple.Tuple2;
93 import org.simantics.scl.runtime.tuple.Tuple3;
94 import org.simantics.scl.runtime.tuple.Tuple4;
95 import org.simantics.scl.runtime.tuple.Tuple5;
96 import org.simantics.simulation.experiment.IExperiment;
97 import org.simantics.simulation.ontology.SimulationResource;
98 import org.simantics.simulation.project.IExperimentManager;
99 import org.simantics.structural2.variables.Connection;
100 import org.simantics.structural2.variables.StandardProceduralChildVariable;
101 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
102 import org.slf4j.LoggerFactory;
104 import gnu.trove.map.hash.THashMap;
106 public class Functions {
108 private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Functions.class);
110 @SCLValue(type = "VariableMap")
111 public static VariableMap primitiveProperties = new VariableMapImpl() {
112 private void storePropertyValueAndExceptions(ReadGraph graph, Variable parent, String name, Variable property, Map<String, Variable> map) {
114 Object value = property.getValue(graph);
115 map.put(name, new ConstantPropertyVariable(parent, name, value, null));
116 } catch (DatabaseException e) {
117 Variable propertyExceptions = map.get(NodeRequest.PROPERTY_VALUE_EXCEPTIONS);
118 Map<String, Exception> exceptionMap;
119 if (propertyExceptions == null) {
120 exceptionMap = new TreeMap<String, Exception>();
121 propertyExceptions = new ConstantPropertyVariable(parent, NodeRequest.PROPERTY_VALUE_EXCEPTIONS, exceptionMap, null);
122 map.put(NodeRequest.PROPERTY_VALUE_EXCEPTIONS, propertyExceptions);
125 exceptionMap = propertyExceptions.getValue(graph);
126 } catch (DatabaseException e1) {
127 Logger.defaultLogError(e1);
133 label = property.getLabel(graph);
134 } catch (DatabaseException e2) {
137 exceptionMap.put(label, e);
142 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
143 return All.getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
147 public Map<String, Variable> getVariables(final ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
149 if(map == null) map = new HashMap<String,Variable>();
151 Variable parent = context.getParent(graph);
153 DocumentationResource DOC = DocumentationResource.getInstance(graph);
155 if(parent instanceof StandardProceduralChildVariable) {
157 StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent;
158 for(Variable property : procedural.getProperties(graph/*, DocumentationResource.URIs.Document_AttributeRelation*/)) {
159 if(property instanceof StandardAssertedGraphPropertyVariable) {
160 StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property;
161 if("dataDefinitions".equals(ass.property.name) || "commands".equals(ass.property.name) || "pollingFunction".equals(ass.property.name)) {
162 storePropertyValueAndExceptions(graph, parent, ass.property.name, property, map);
166 Resource predicate = property.getPossiblePredicateResource(graph);
167 if(predicate != null) {
168 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
169 if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
170 Variable prop = parent.getProperty(graph, predicate);
171 storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
178 Resource parentRes = parent.getRepresents(graph);
180 Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_commands);
181 storePropertyValueAndExceptions(graph, parent, "commands", prop, map);
184 if (graph.getPossibleObject(parentRes, DOC.Properties_dataDefinitions) != null) {
185 Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_dataDefinitions);
186 storePropertyValueAndExceptions(graph, parent, "dataDefinitions", prop, map);
189 DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
190 //PrimitivePropertyStatementsProcedure foo = new PrimitivePropertyStatementsProcedure();
192 DirectStatements ds = dqs.getDirectPersistentStatements(graph, parentRes);
194 for(Statement stm : ds) {
195 Resource predicate = stm.getPredicate();
196 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
198 if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
199 Variable prop = new StandardGraphPropertyVariable(graph, parent, predicate);
200 storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
202 Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation);
203 if(definition != null) {
204 PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition));
205 Variable prop = new StandardGraphPropertyVariable(graph, parent, definition);
206 map.put(info2.name, new PrimitiveValueVariable(parent, info2.name, prop));
217 static class DocumentPropertyKeys extends ResourceRead<List<String>> {
219 protected DocumentPropertyKeys(Resource resource) {
224 public List<String> perform(ReadGraph graph) throws DatabaseException {
226 List<String> result = new ArrayList<>();
228 DocumentationResource DOC = DocumentationResource.getInstance(graph);
230 if(graph.hasStatement(resource, DOC.Properties_commands))
231 result.add("commands");
232 if(graph.hasStatement(resource, DOC.Properties_dataDefinitions))
233 result.add("dataDefinitions");
235 DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
236 DirectStatements ds = dqs.getDirectPersistentStatements(graph, resource);
238 for(Statement stm : ds) {
240 Resource predicate = stm.getPredicate();
241 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
243 if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
244 result.add(info.name);
246 Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation);
247 if(definition != null) {
248 PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition));
249 result.add(info2.name);
260 static class StandardDocumentProperties implements DocumentProperties {
263 public Collection<String> getKeys(ReadGraph graph, Variable parent) throws DatabaseException {
265 if(parent instanceof StandardProceduralChildVariable) {
267 StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent;
268 List<String> result = new ArrayList<>();
269 for(Variable property : procedural.getProperties(graph)) {
270 if(property instanceof StandardAssertedGraphPropertyVariable) {
271 StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property;
272 if("dataDefinitions".equals(ass.property.name) || "commands".equals(ass.property.name) || "pollingFunction".equals(ass.property.name)) {
273 result.add(ass.property.name);
277 Resource predicate = property.getPossiblePredicateResource(graph);
278 if(predicate != null) {
279 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
280 if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
281 result.add(info.name);
290 Resource parentRes = parent.getRepresents(graph);
291 return graph.syncRequest(new DocumentPropertyKeys(parentRes), TransientCacheAsyncListener.instance());
298 public Object getValue(ReadGraph graph, Variable context, String key) throws DatabaseException {
299 return context.getPropertyValue(graph, key);
304 public static DocumentProperties primitiveProperties() throws DatabaseException {
305 return new StandardDocumentProperties();
308 @SCLValue(type = "VariableMap")
309 public static VariableMap inputSpaceChildren = new VariableMapImpl() {
311 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
312 Variable root = Variables.getRootVariable(graph);
313 return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
317 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
319 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
320 return All.standardChildDomainChildren.getVariable(graph, context, name);
325 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
327 map = All.standardChildDomainChildren.getVariables(graph, context, map);
328 if(map == null) map = new THashMap<String,Variable>();
329 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
336 static class DocumentProxyChildVariable extends ProxyChildVariable implements ProxyVariableSupport {
338 public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
339 super(base, parent, other, name);
343 public Variable create(Variable base, Variable parent, Variable other, String name) {
344 return new DocumentProxyChildVariable(base, parent, other, name);
347 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
349 if(CONTEXT_END.equals(name)) {
350 if(other instanceof ProxyChildVariable) {
351 // The context is also a proxy - let it do the job
352 return super.getPossibleChild(graph, name);
354 return ProxyVariables.tryToOwnRenamed(graph, this, base, CONTEXT_END);
358 return super.getPossibleChild(graph, name);
363 public Variable attachTo(ReadGraph graph, Variable parent) {
364 return attachToRenamed(graph, parent, name);
368 public Variable attachToRenamed(ReadGraph graph, Variable parent, String name) {
369 if(this.parent.equals(base))
370 return new DocumentProxyChildVariable(parent, parent, other, name);
372 return new DocumentProxyChildVariable(base, parent, other, name);
377 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
378 public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
379 Variable session = graph.syncRequest(new ProxySessionRequest(context));
380 DocumentationResource DOC = DocumentationResource.getInstance(graph);
381 String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
383 // TODO HAXX - Please fix this
384 // we have no URI so this probably means that someone has inserted a non-session
385 // into the proxy variable => return that instead
388 return Variables.getVariable(graph, uri);
391 public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
392 Variable session = graph.syncRequest(new ProxySessionRequest(self));
394 throw new DatabaseException("No state for " + self.getURI(graph));
395 return session.getPossibleChild(graph, "__scl__");
398 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
399 public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
400 Variable session = graph.syncRequest(new ProxySessionRequest(context));
402 throw new DatabaseException("No state for " + context.getURI(graph));
403 return session.getPossibleChild(graph, "__scl__");
406 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
407 public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
408 Variable session = graph.syncRequest(new ProxySessionRequest(context));
409 return session.getPossibleChild(graph, "__icstate__");
412 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
413 public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
414 return graph.syncRequest(new ProxySessionRequest(context));
417 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
418 public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
419 // Try if experiment (run) has been used as the input
420 Variable var = input(graph, converter, context);
421 SimulationResource SR = SimulationResource.getInstance(graph);
422 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
423 var = var.getParent(graph);
427 IExperiment exp = getExperiment(graph, var);
435 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
436 public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
437 Variable var = input(graph, converter, context);
438 ModelingResources MOD = ModelingResources.getInstance(graph);
439 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
440 var = var.getParent(graph);
446 private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
448 ArrayList<Variable> result = new ArrayList<Variable>();
450 DocumentationResource DOC = DocumentationResource.getInstance(graph);
452 Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
453 if(broadcasted != null) result.add(broadcasted);
455 for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
456 result.addAll(getBroadcasted(graph, child));
463 private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
465 if(commandVariables.isEmpty()) return Collections.emptyList();
468 TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
470 DocumentationResource DOC = DocumentationResource.getInstance(graph);
473 for (Variable c : commandVariables) {
476 t = c.getName(graph);
478 Connection conn = c.getValue(graph);
479 Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
480 if (targetConnectionPoint != null) {
481 Variable target = targetConnectionPoint.getParent(graph);
482 if (target != null) {
484 Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
485 if(enabled != null && !enabled) continue;
493 String o = c.getPossiblePropertyValue(graph, "ordinal");
495 ordinal = Integer.parseInt(o);
496 } catch (NumberFormatException e) {}
499 String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
500 String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
502 CommandContextMutable newConstants = (CommandContextMutable)constants;
503 if(constantKey != null && constantValue != null) {
504 if(!constantKey.isEmpty()) {
505 newConstants = new CommandContextImpl().merge(constants);
506 newConstants.putString(constantKey, constantValue);
510 String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
511 if(requiredKey != null && !requiredKey.isEmpty()) {
512 if (newConstants == constants) {
513 newConstants = new CommandContextImpl().merge(constants);
515 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
518 String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
519 if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
520 if (newConstants == constants) {
521 newConstants = new CommandContextImpl().merge(constants);
523 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
526 if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
528 // This is a broadcast terminal of a container
529 List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
530 sequences.put(ordinal, broadcastCommands);
534 Command command = new Command(DocumentServerUtils.getId(graph, target), t,
535 targetConnectionPoint.getName(graph), newConstants);
536 sequences.put(ordinal, Collections.singletonList(command));
544 List<Command> commands = new ArrayList<Command>();
545 for (List<Command> commandList : sequences.values()) {
546 for (Command command : commandList) {
547 commands.add(command);
560 * @throws DatabaseException
562 public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
563 return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
572 * @throws DatabaseException
574 public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
575 DocumentationResource DOC = DocumentationResource.getInstance(graph);
576 ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
577 // Find data definition connections
578 for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
579 Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
580 // Find data the other end of definition connection
581 Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
582 dataDefinitionRelation, dataDefinitionConnection);
583 if (dataDefinitionProviders != null) {
585 for(Variable dataDefinitionProvider : dataDefinitionProviders) {
587 Variable dataDefinition = dataDefinitionProvider.getParent(graph);
588 if (dataDefinition != null) {
589 // Found other end. Is should contain ONE data
590 // definition connection to the actual data
591 Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
592 if (dataCollection.size() == 1) {
593 Variable dataRelation = dataCollection.iterator().next();
594 Connection dataConnection = dataRelation.getValue(graph);
595 // Find data the other end of definition connection
596 Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
597 dataRelation, dataConnection);
598 if (dataConnectionPoint != null) {
599 Variable data = dataConnectionPoint.getParent(graph);
600 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
602 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
604 String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
606 String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
609 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
610 sourceProperty, targetProperty));
612 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
614 List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
615 List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
617 for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
618 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
619 sourcesProperty.get(i), targetsProperty.get(i)));
628 return dataDefinitions;
631 @SuppressWarnings("unchecked")
632 private static <T> List<T> toList(Object o, Class<T> c) {
633 List<T> result = null;
634 if (o instanceof List) {
636 } else if (o instanceof Object[]) {
637 result = new ArrayList<T>(((Object[])o).length);
638 for (T item : (T[])o) {
643 return Collections.<T>emptyList();
648 public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
649 return new EventHandler() {
651 public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
658 public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
660 final Session session = graph.getSession();
662 return new AbstractEventHandler() {
665 public CommandResult handle(final CommandContext parameters) {
667 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
671 String result = session.sync(new WriteResultRequest<String>() {
674 public String perform(WriteGraph graph) throws DatabaseException {
675 SCLContext sclContext = SCLContext.getCurrent();
676 Object oldGraph = sclContext.put("graph", graph);
677 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
679 Function1<String,String> pf = new FunctionImpl1<String,String>() {
681 public String apply(String key) {
682 return parameters.getString(key);
685 Object response = (String)fn.apply(variable, pf);
686 if(response instanceof String) {
687 return (String)response;
691 sclContext.put("graph", oldGraph);
692 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
699 return new SuccessResponse(result);
701 } catch (Throwable e) {
702 Logger.defaultLogError(e);
703 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
712 public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
714 final Session session = graph.getSession();
716 return new AbstractEventHandler() {
719 public CommandResult handle(final CommandContext parameters) {
721 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
725 String result = session.sync(new UniqueRead<String>() {
728 public String perform(ReadGraph graph) throws DatabaseException {
729 SCLContext sclContext = SCLContext.getCurrent();
730 Object oldGraph = sclContext.put("graph", graph);
731 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
733 Function1<String,String> pf = new FunctionImpl1<String,String>() {
735 public String apply(String key) {
736 return parameters.getString(key);
739 Object response = (String)fn.apply(variable, pf);
740 if(response instanceof String) {
741 return (String)response;
745 sclContext.put("graph", oldGraph);
746 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
753 return new SuccessResponse(result);
755 } catch (Throwable e) {
756 Logger.defaultLogError(e);
757 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
766 public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
768 final Session session = graph.getSession();
770 return new AbstractEventHandler() {
773 public CommandResult handle(final CommandContext parameters) {
775 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
779 CommandResult result = session.sync(new UniqueRead<CommandResult>() {
782 public CommandResult perform(ReadGraph graph) throws DatabaseException {
783 SCLContext sclContext = SCLContext.getCurrent();
784 Object oldGraph = sclContext.put("graph", graph);
785 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
787 Object response = fn.apply(parameters);
788 if(response instanceof CommandResult) {
789 return (CommandResult)response;
793 sclContext.put("graph", oldGraph);
794 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
803 } catch (Throwable e) {
804 Logger.defaultLogError(e);
805 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
813 public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
815 Variable anyFunction = self.browse(graph, ".#" + function);
816 if(anyFunction == null) return null;
818 final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
820 Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
821 //String expression = anyFunction.getPropertyValue(graph, "expression");
823 final Session session = graph.getSession();
825 return new AbstractResponseHandler(fn) {
827 private String formatError(RequestProcessor proc, Throwable t) {
831 return proc.syncRequest(new UniqueRead<String>() {
834 public String perform(ReadGraph graph) throws DatabaseException {
835 Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
836 String uri2 = proxy.getURI(graph);
837 String uri = self.getParent(graph).getURI(graph);
839 String path = uri.substring(uri2.length());
841 String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
842 StringBuilder message = new StringBuilder();
843 message.append("Handler execution failed\n");
844 message.append(" handler=" + path + "\n");
845 message.append(" expression=" + expr + "\n");
846 message.append(" message=" + t.getMessage() + "\n");
848 StringWriter sw = new StringWriter();
849 t.printStackTrace(new PrintWriter(sw));
850 message.append(" stack trace=" + sw);
852 return message.toString();
857 } catch (DatabaseException e) {
859 return e.getMessage();
866 public CommandResult handle(final CommandContext parameters) {
868 IConsole console = parameters.getValue("__console__");
869 SCLReportingHandler printer = (console != null) ? new ConsoleSCLReportingHandler(console)
870 : (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
874 Object result = null;
875 if(effects.contains(Types.WRITE_GRAPH)) {
877 result = session.syncRequest(new WriteResultRequest<Object>() {
880 public Object perform(WriteGraph graph)
881 throws DatabaseException {
882 SCLContext sclContext = SCLContext.getCurrent();
883 Object oldGraph = sclContext.put("graph", graph);
884 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
886 return fn.apply(parameters);
888 sclContext.put("graph", oldGraph);
889 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
895 } else if(effects.contains(Types.READ_GRAPH)) {
897 result = session.sync(new UniqueRead<Object>() {
900 public Object perform(ReadGraph graph) throws DatabaseException {
902 SCLContext sclContext = SCLContext.getCurrent();
903 Object oldGraph = sclContext.put("graph", graph);
904 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
907 return fn.apply(parameters);
909 sclContext.put("graph", oldGraph);
910 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
918 SCLContext sclContext = SCLContext.getCurrent();
919 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
921 result = fn.apply(parameters);
923 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
928 if (result instanceof org.simantics.document.server.serverResponse.Error) {
929 return (CommandResult)result;
932 if (result instanceof CommandResult) {
933 return (CommandResult)result;
935 CommandContextMutable assignments = new CommandContextImpl();
936 assignments.putValue("result", result);
937 return new ServerResponse(200, "", assignments);
940 } catch (Throwable e) {
941 return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
950 public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
952 final Session session = graph.getSession();
954 return new AbstractEventHandler() {
957 public CommandResult handle(final CommandContext parameters) {
959 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
963 CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
966 public CommandResult perform(WriteGraph graph) throws DatabaseException {
967 SCLContext sclContext = SCLContext.getCurrent();
968 Object oldGraph = sclContext.put("graph", graph);
969 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
971 Object response = fn.apply(parameters);
972 if(response instanceof CommandResult) {
973 return (CommandResult)response;
977 sclContext.put("graph", oldGraph);
978 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
987 } catch (Throwable e) {
988 Logger.defaultLogError(e);
989 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
999 public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
1001 return new AbstractEventHandler() {
1004 public CommandResult handle(final CommandContext parameters) {
1006 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
1010 SCLContext sclContext = SCLContext.getCurrent();
1011 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
1013 Object response = fn.apply(parameters);
1014 if(response instanceof CommandResult) {
1015 return (CommandResult)response;
1019 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
1022 } catch (Throwable e) {
1023 Logger.defaultLogError(e);
1024 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
1033 public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
1035 return new AbstractEventHandler() {
1038 public CommandResult handle(final CommandContext parameters) {
1040 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
1046 SCLContext sclContext = SCLContext.getCurrent();
1047 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
1049 Function1<String,String> pf = new FunctionImpl1<String,String>() {
1051 public String apply(String key) {
1052 return parameters.getString(key);
1055 Object response = (String)fn.apply(pf);
1056 if(response instanceof String) {
1057 result = (String)response;
1060 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
1063 return new SuccessResponse(result);
1065 } catch (Throwable e) {
1066 Logger.defaultLogError(e);
1067 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
1075 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1076 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1077 return ServerSCLValueRequest.compileAndEvaluate(graph, context);
1080 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1081 public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1082 return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
1085 @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
1086 public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
1087 return createComponentNamingStrategy(graph);
1090 public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
1091 Layer0X L0X = Layer0X.getInstance(graph);
1092 @SuppressWarnings({ "unchecked", "rawtypes" })
1093 final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
1094 @SuppressWarnings("rawtypes")
1095 Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
1097 public Object apply(ReadGraph p0, Resource p1, String p2) {
1098 return apply(p0, p1, p2);
1100 @SuppressWarnings("unchecked")
1102 public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
1103 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
1106 return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
1109 public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
1110 if (variable == null)
1113 SimulationResource SIMU = SimulationResource.getInstance(graph);
1115 Variable var = variable;
1116 Resource represents = var.getRepresents(graph);
1117 Resource activeRun = null;
1118 if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
1119 activeRun = represents;
1122 IProject project = Simantics.peekProject();
1123 if (activeRun != null && project != null) {
1124 IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
1126 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
1132 public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
1133 List<Object> list = new ArrayList<Object>();
1134 if (tuple instanceof Tuple) {
1135 Collections.addAll(list, ((Tuple)tuple).toArray());
1139 context.putRow(key, list);
1143 public static List<Object> getTuples(CommandContext context, String key) {
1144 List<List<Object>> rows = context.getRows(key);
1145 List<Object> tuples = new ArrayList<Object>();
1147 for (List<Object> row : rows) {
1148 switch (row.size()) {
1149 case 0: tuples.add(Tuple0.INSTANCE); break;
1150 case 1: tuples.add(row.get(1)); break;
1151 case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
1152 case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
1153 case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
1154 case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
1161 public static String printContext(CommandContext context) {
1162 return context.toString();
1165 @SCLValue(type = "AbstractEventHandler")
1166 public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
1169 public CommandResult handle(CommandContext context) {
1175 public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1177 String baseURI = base.getURI(graph);
1179 String selfURI = self.getURI(graph);
1181 String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
1182 String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
1183 String stripped = prefix + suffix;
1185 String relative = Variables.getRelativeRVI(baseURI, stripped);
1187 return Variables.getRVI(relative, ref);
1191 public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1193 String id = sclStateKey(graph, base, self, ref);
1195 Variable sclVar = base.getPossibleChild(graph, "__scl__");
1196 if(sclVar == null) return null;
1198 return sclVar.getPossibleProperty(graph, id);
1202 public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
1204 Variable stateVariable = sclStateVariable(graph, base, self, ref);
1205 if (stateVariable != null) {
1207 return stateVariable.getValue(graph);
1211 return defaultValue;
1216 public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
1218 String id = sclStateKey(graph, base, self, ref);
1220 StateRealm realm = (StateRealm) StateSessionManager.getInstance().getOrCreateRealm(graph, base.getURI(graph)+"/__scl__");
1221 StateNodeManager nodeManager = (StateNodeManager) realm.getNodeManager();
1222 nodeManager.setState(id, value);
1226 public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
1227 Resource project = Simantics.getProjectResource();
1228 Variable component = self.getParent(graph);
1229 Variable projectVariable = Variables.getVariable(graph, project);
1230 return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
1233 public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
1234 Resource project = Simantics.getProjectResource();
1235 Variable component = self.getParent(graph);
1236 Variable projectVariable = Variables.getVariable(graph, project);
1237 setSclStateValue(graph, projectVariable, component, ref, value);
1240 private static Type getSCLType(Object value) throws DatabaseException {
1241 Binding b = Bindings.getBindingUnchecked(value.getClass());
1242 Datatype t = b.type();
1243 if(Datatypes.STRING.equals(t)) return Types.STRING;
1244 if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
1245 throw new DatabaseException("Type not supported");
1248 public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
1249 Resource project = Simantics.getProjectResource();
1250 ArrayList<Variable> result = new ArrayList<Variable>();
1251 for(Resource model : graph.syncRequest(new ProjectModels(project))) {
1252 result.add(Variables.getVariable(graph, model));
1257 public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
1258 return var.getName(graph);
1261 public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
1262 Variable property = graph.syncRequest(new VariableProperty(variable, name));
1263 return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
1266 public static class ParentExistsRequest extends VariableRead<Boolean> {
1268 public ParentExistsRequest(Variable parent) {
1273 public Boolean perform(ReadGraph graph) throws DatabaseException {
1275 Variable existsProperty = variable.getPossibleProperty(graph, "exists");
1276 if(existsProperty == null) return true;
1278 Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
1279 if (exists == null || !exists) return false;
1281 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
1287 public static class PathExistsRequest extends VariableRead<Boolean> {
1289 public PathExistsRequest(Variable variable) {
1294 public Boolean perform(ReadGraph graph) throws DatabaseException {
1296 Variable widget = variable.getParent(graph);
1298 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
1299 if (exists == null || !exists) return false;
1301 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
1303 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1304 Collection <Variable> cps = widget.getProperties(graph, DocumentationResource.URIs.Relations_parentRelation);
1305 for (Variable cp : cps) {
1307 Connection conn = cp.getValue(graph);
1308 Variable otherCp = DocumentServerUtils.getPossibleChildConnectionPoint(graph, cp, conn);
1309 if (otherCp != null) {
1310 Variable parentWidget = otherCp.getParent(graph);
1311 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1315 Variable parentCp = graph.sync(new BinaryRead<Variable, Connection, Variable>(widget, conn) {
1317 public Variable perform(ReadGraph graph) throws DatabaseException {
1318 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1319 Collection<VariableConnectionPointDescriptor> descs = parameter2.getConnection2().getConnectionPointDescriptors(graph, parameter, null);
1321 for(VariableConnectionPointDescriptor desc : descs) {
1322 if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
1323 return desc.getVariable(graph);
1329 if (parentCp != null) {
1330 Variable parentWidget = parentCp.getParent(graph);
1331 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1338 Resource type = widget.getType(graph);
1339 return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
1340 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
1344 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
1345 public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1346 return graph.syncRequest(new PathExistsRequest(context));
1349 public static String compileDocumentSCLValueExpression(ReadGraph graph, Variable context) {
1351 ServerSCLValueRequest.validate(graph, context);
1353 } catch (Exception e) {
1354 return resolveIssueMessage(e);
1358 private static String resolveIssueMessage(Exception e) {
1359 if (e instanceof ImportFailureException)
1361 if (e.getCause() != null && e.getCause() instanceof ImportFailureException)
1363 if (e instanceof SCLDatabaseException) {
1364 SCLDatabaseException ee = (SCLDatabaseException) e;
1365 return ee.getMessage();
1367 if (LOGGER.isDebugEnabled())
1368 LOGGER.debug("", e);
1369 return e.getMessage();