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;
10 import java.util.TreeMap;
12 import org.simantics.Simantics;
13 import org.simantics.databoard.Bindings;
14 import org.simantics.databoard.Datatypes;
15 import org.simantics.databoard.binding.Binding;
16 import org.simantics.databoard.type.Datatype;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.RequestProcessor;
19 import org.simantics.db.Resource;
20 import org.simantics.db.Session;
21 import org.simantics.db.WriteGraph;
22 import org.simantics.db.common.primitiverequest.Adapter;
23 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
24 import org.simantics.db.common.request.UnaryRead;
25 import org.simantics.db.common.request.UniqueRead;
26 import org.simantics.db.common.request.WriteResultRequest;
27 import org.simantics.db.common.utils.Logger;
28 import org.simantics.db.common.utils.NameUtils;
29 import org.simantics.db.exception.DatabaseException;
30 import org.simantics.db.layer0.function.All;
31 import org.simantics.db.layer0.request.ProjectModels;
32 import org.simantics.db.layer0.request.VariableProperty;
33 import org.simantics.db.layer0.request.VariableRead;
34 import org.simantics.db.layer0.request.VariableValueWithBinding;
35 import org.simantics.db.layer0.variable.ConstantPropertyVariable;
36 import org.simantics.db.layer0.variable.ProxyChildVariable;
37 import org.simantics.db.layer0.variable.ProxySessionRequest;
38 import org.simantics.db.layer0.variable.ProxyVariables;
39 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
40 import org.simantics.db.layer0.variable.Variable;
41 import org.simantics.db.layer0.variable.VariableMap;
42 import org.simantics.db.layer0.variable.VariableMapImpl;
43 import org.simantics.db.layer0.variable.Variables;
44 import org.simantics.document.base.ontology.DocumentationResource;
45 import org.simantics.document.server.bean.Command;
46 import org.simantics.document.server.bean.DataDefinition;
47 import org.simantics.document.server.handler.AbstractEventHandler;
48 import org.simantics.document.server.handler.AbstractResponseHandler;
49 import org.simantics.document.server.handler.EventHandler;
50 import org.simantics.document.server.io.CommandContext;
51 import org.simantics.document.server.io.CommandContextImpl;
52 import org.simantics.document.server.io.CommandContextMutable;
53 import org.simantics.document.server.io.CommandResult;
54 import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
55 import org.simantics.document.server.request.ServerSCLValueRequest;
56 import org.simantics.document.server.serverResponse.ServerResponse;
57 import org.simantics.document.server.serverResponse.SuccessResponse;
58 import org.simantics.modeling.ModelingResources;
59 import org.simantics.modeling.scl.SCLRealm;
60 import org.simantics.modeling.scl.SCLSessionManager;
61 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
62 import org.simantics.modeling.services.ComponentNamingStrategy;
63 import org.simantics.operation.Layer0X;
64 import org.simantics.project.IProject;
65 import org.simantics.scl.compiler.types.TCon;
66 import org.simantics.scl.compiler.types.Type;
67 import org.simantics.scl.compiler.types.Types;
68 import org.simantics.scl.reflection.annotations.SCLValue;
69 import org.simantics.scl.runtime.SCLContext;
70 import org.simantics.scl.runtime.function.Function;
71 import org.simantics.scl.runtime.function.Function1;
72 import org.simantics.scl.runtime.function.FunctionImpl1;
73 import org.simantics.scl.runtime.function.FunctionImpl4;
74 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
75 import org.simantics.scl.runtime.tuple.Tuple;
76 import org.simantics.scl.runtime.tuple.Tuple0;
77 import org.simantics.scl.runtime.tuple.Tuple2;
78 import org.simantics.scl.runtime.tuple.Tuple3;
79 import org.simantics.scl.runtime.tuple.Tuple4;
80 import org.simantics.scl.runtime.tuple.Tuple5;
81 import org.simantics.simulation.experiment.IExperiment;
82 import org.simantics.simulation.ontology.SimulationResource;
83 import org.simantics.simulation.project.IExperimentManager;
84 import org.simantics.structural2.variables.Connection;
85 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
87 import gnu.trove.map.hash.THashMap;
89 public class Functions {
91 @SCLValue(type = "VariableMap")
92 public static VariableMap inputSpaceChildren = new VariableMapImpl() {
94 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
95 Variable root = Variables.getRootVariable(graph);
96 return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
100 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
102 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
103 return All.standardChildDomainChildren.getVariable(graph, context, name);
108 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
110 map = All.standardChildDomainChildren.getVariables(graph, context, map);
111 if(map == null) map = new THashMap<String,Variable>();
112 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
119 static class DocumentProxyChildVariable extends ProxyChildVariable {
121 public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
122 super(base, parent, other, name);
126 public Variable create(Variable base, Variable parent, Variable other, String name) {
127 return new DocumentProxyChildVariable(base, parent, other, name);
130 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
132 if(CONTEXT_END.equals(name)) {
133 if(other instanceof ProxyChildVariable) {
134 // The context is also a proxy - let it do the job
135 return super.getPossibleChild(graph, name);
137 return new RootVariable(this, base.getRepresents(graph));
141 return super.getPossibleChild(graph, name);
145 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
147 Collection<Variable> result = super.getChildren(graph);
148 if(!(base instanceof ProxyChildVariable)) {
149 result.add(new RootVariable(this, base.getRepresents(graph)));
157 static class RootVariable extends StandardGraphChildVariable {
159 public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
160 super(parent, null, resource);
164 public String getName(ReadGraph graph) throws DatabaseException {
165 return ProxyChildVariable.CONTEXT_END;
168 @SuppressWarnings("deprecation")
170 public Variable getNameVariable(ReadGraph graph) throws DatabaseException {
171 return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);
176 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
177 public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
178 Variable session = graph.syncRequest(new ProxySessionRequest(context));
179 DocumentationResource DOC = DocumentationResource.getInstance(graph);
180 String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
182 // TODO HAXX - Please fix this
183 // we have no URI so this probably means that someone has inserted a non-session
184 // into the proxy variable => return that instead
187 return Variables.getVariable(graph, uri);
190 public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
191 Variable session = graph.syncRequest(new ProxySessionRequest(self));
193 throw new DatabaseException("No state for " + self.getURI(graph));
194 return session.getPossibleChild(graph, "__scl__");
197 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
198 public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
199 Variable session = graph.syncRequest(new ProxySessionRequest(context));
201 throw new DatabaseException("No state for " + context.getURI(graph));
202 return session.getPossibleChild(graph, "__scl__");
205 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
206 public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
207 Variable session = graph.syncRequest(new ProxySessionRequest(context));
208 return session.getPossibleChild(graph, "__icstate__");
211 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
212 public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
213 return graph.syncRequest(new ProxySessionRequest(context));
216 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
217 public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
218 // Try if experiment (run) has been used as the input
219 Variable var = input(graph, converter, context);
220 SimulationResource SR = SimulationResource.getInstance(graph);
221 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
222 var = var.getParent(graph);
226 IExperiment exp = getExperiment(graph, var);
234 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
235 public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
236 Variable var = input(graph, converter, context);
237 ModelingResources MOD = ModelingResources.getInstance(graph);
238 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
239 var = var.getParent(graph);
245 private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
247 ArrayList<Variable> result = new ArrayList<Variable>();
249 DocumentationResource DOC = DocumentationResource.getInstance(graph);
251 Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
252 if(broadcasted != null) result.add(broadcasted);
254 for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
255 result.addAll(getBroadcasted(graph, child));
262 private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
264 if(commandVariables.isEmpty()) return Collections.emptyList();
267 TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
269 DocumentationResource DOC = DocumentationResource.getInstance(graph);
272 for (Variable c : commandVariables) {
275 t = c.getName(graph);
277 Connection conn = c.getValue(graph);
278 Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
279 if (targetConnectionPoint != null) {
280 Variable target = targetConnectionPoint.getParent(graph);
281 if (target != null) {
283 Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
284 if(enabled != null && !enabled) continue;
292 String o = c.getPossiblePropertyValue(graph, "ordinal");
294 ordinal = Integer.parseInt(o);
295 } catch (NumberFormatException e) {}
298 String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
299 String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
301 CommandContextMutable newConstants = (CommandContextMutable)constants;
302 if(constantKey != null && constantValue != null) {
303 if(!constantKey.isEmpty()) {
304 newConstants = new CommandContextImpl().merge(constants);
305 newConstants.putString(constantKey, constantValue);
309 String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
310 if(requiredKey != null && !requiredKey.isEmpty()) {
311 if (newConstants == constants) {
312 newConstants = new CommandContextImpl().merge(constants);
314 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
317 String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
318 if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
319 if (newConstants == constants) {
320 newConstants = new CommandContextImpl().merge(constants);
322 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
325 if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
327 // This is a broadcast terminal of a container
328 List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
329 sequences.put(ordinal, broadcastCommands);
333 Command command = new Command(DocumentServerUtils.getId(graph, target), t,
334 targetConnectionPoint.getName(graph), newConstants);
335 sequences.put(ordinal, Collections.singletonList(command));
343 List<Command> commands = new ArrayList<Command>();
344 for (List<Command> commandList : sequences.values()) {
345 for (Command command : commandList) {
346 commands.add(command);
359 * @throws DatabaseException
361 public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
362 return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
371 * @throws DatabaseException
373 public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
374 DocumentationResource DOC = DocumentationResource.getInstance(graph);
375 ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
376 // Find data definition connections
377 for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
378 Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
379 // Find data the other end of definition connection
380 Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
381 dataDefinitionRelation, dataDefinitionConnection);
382 if (dataDefinitionProviders != null) {
384 for(Variable dataDefinitionProvider : dataDefinitionProviders) {
386 Variable dataDefinition = dataDefinitionProvider.getParent(graph);
387 if (dataDefinition != null) {
388 // Found other end. Is should contain ONE data
389 // definition connection to the actual data
390 Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
391 if (dataCollection.size() == 1) {
392 Variable dataRelation = dataCollection.iterator().next();
393 Connection dataConnection = dataRelation.getValue(graph);
394 // Find data the other end of definition connection
395 Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
396 dataRelation, dataConnection);
397 if (dataConnectionPoint != null) {
398 Variable data = dataConnectionPoint.getParent(graph);
399 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
401 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
403 String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
405 String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
408 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
409 sourceProperty, targetProperty));
411 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
413 List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
414 List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
416 for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
417 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
418 sourcesProperty.get(i), targetsProperty.get(i)));
427 return dataDefinitions;
430 @SuppressWarnings("unchecked")
431 private static <T> List<T> toList(Object o, Class<T> c) {
432 List<T> result = null;
433 if (o instanceof List) {
435 } else if (o instanceof Object[]) {
436 result = new ArrayList<T>(((Object[])o).length);
437 for (T item : (T[])o) {
442 return Collections.<T>emptyList();
446 public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
447 return new EventHandler() {
450 public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
457 public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
459 final Session session = graph.getSession();
461 return new AbstractEventHandler() {
464 public CommandResult handle(final CommandContext parameters) {
466 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
470 String result = session.sync(new WriteResultRequest<String>() {
473 public String perform(WriteGraph graph) throws DatabaseException {
474 SCLContext sclContext = SCLContext.getCurrent();
475 Object oldGraph = sclContext.put("graph", graph);
476 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
478 Function1<String,String> pf = new FunctionImpl1<String,String>() {
480 public String apply(String key) {
481 return parameters.getString(key);
484 Object response = (String)fn.apply(variable, pf);
485 if(response instanceof String) {
486 return (String)response;
489 } catch (Throwable t) {
492 sclContext.put("graph", oldGraph);
493 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
502 return new SuccessResponse(result);
504 } catch (Throwable e) {
505 Logger.defaultLogError(e);
506 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
514 public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
516 final Session session = graph.getSession();
518 return new AbstractEventHandler() {
521 public CommandResult handle(final CommandContext parameters) {
523 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
527 String result = session.sync(new UniqueRead<String>() {
530 public String perform(ReadGraph graph) throws DatabaseException {
531 SCLContext sclContext = SCLContext.getCurrent();
532 Object oldGraph = sclContext.put("graph", graph);
533 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
535 Function1<String,String> pf = new FunctionImpl1<String,String>() {
537 public String apply(String key) {
538 return parameters.getString(key);
541 Object response = (String)fn.apply(variable, pf);
542 if(response instanceof String) {
543 return (String)response;
546 } catch (Throwable t) {
549 sclContext.put("graph", oldGraph);
550 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
559 return new SuccessResponse(result);
561 } catch (Throwable e) {
562 Logger.defaultLogError(e);
563 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
571 public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
573 final Session session = graph.getSession();
575 return new AbstractEventHandler() {
578 public CommandResult handle(final CommandContext parameters) {
580 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
584 CommandResult result = session.sync(new UniqueRead<CommandResult>() {
587 public CommandResult perform(ReadGraph graph) throws DatabaseException {
588 SCLContext sclContext = SCLContext.getCurrent();
589 Object oldGraph = sclContext.put("graph", graph);
590 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
592 Object response = fn.apply(parameters);
593 if(response instanceof CommandResult) {
594 return (CommandResult)response;
597 } catch (Throwable t) {
600 sclContext.put("graph", oldGraph);
601 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
612 } catch (Throwable e) {
613 Logger.defaultLogError(e);
614 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
622 public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
624 Variable anyFunction = self.browse(graph, ".#" + function);
625 if(anyFunction == null) return null;
627 final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
629 final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
630 String expression = anyFunction.getPropertyValue(graph, "expression");
632 final Session session = graph.getSession();
634 return new AbstractResponseHandler(expression) {
636 private String formatError(RequestProcessor proc, Throwable t) {
640 return proc.syncRequest(new UniqueRead<String>() {
643 public String perform(ReadGraph graph) throws DatabaseException {
644 Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
645 String uri2 = proxy.getURI(graph);
646 String uri = self.getParent(graph).getURI(graph);
648 String path = uri.substring(uri2.length());
650 String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
651 StringBuilder message = new StringBuilder();
652 message.append("Handler execution failed\n");
653 message.append(" handler=" + path + "\n");
654 message.append(" expression=" + expr + "\n");
655 message.append(" message=" + t.getMessage() + "\n");
657 StringWriter sw = new StringWriter();
658 t.printStackTrace(new PrintWriter(sw));
659 message.append(" stack trace=" + sw);
661 return message.toString();
666 } catch (DatabaseException e) {
668 return e.getMessage();
675 public CommandResult handle(final CommandContext parameters) {
677 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
681 Object result = null;
682 if(effects.contains(Types.WRITE_GRAPH)) {
684 result = session.syncRequest(new WriteResultRequest<Object>() {
687 public Object perform(WriteGraph graph)
688 throws DatabaseException {
689 SCLContext sclContext = SCLContext.getCurrent();
690 Object oldGraph = sclContext.put("graph", graph);
691 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
693 Object response = fn.apply(parameters);
695 } catch (Throwable t) {
696 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
698 sclContext.put("graph", oldGraph);
699 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
705 } else if(effects.contains(Types.READ_GRAPH)) {
707 result = session.sync(new UniqueRead<Object>() {
710 public Object perform(ReadGraph graph) throws DatabaseException {
712 SCLContext sclContext = SCLContext.getCurrent();
713 Object oldGraph = sclContext.put("graph", graph);
714 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
717 Object response = fn.apply(parameters);
719 } catch (Throwable t) {
720 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
722 sclContext.put("graph", oldGraph);
723 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
730 result = fn.apply(parameters);
733 if (result instanceof org.simantics.document.server.serverResponse.Error) {
734 return (CommandResult)result;
737 if (result instanceof CommandResult) {
738 return (CommandResult)result;
740 CommandContextMutable assignments = new CommandContextImpl();
741 assignments.putValue("result", result);
742 return new ServerResponse(200, "", assignments);
745 } catch (Throwable e) {
746 return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
754 public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
756 final Session session = graph.getSession();
758 return new AbstractEventHandler() {
761 public CommandResult handle(final CommandContext parameters) {
763 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
767 CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
770 public CommandResult perform(WriteGraph graph) throws DatabaseException {
771 SCLContext sclContext = SCLContext.getCurrent();
772 Object oldGraph = sclContext.put("graph", graph);
773 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
775 Object response = fn.apply(parameters);
776 if(response instanceof CommandResult) {
777 return (CommandResult)response;
780 } catch (Throwable t) {
783 sclContext.put("graph", oldGraph);
784 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
795 } catch (Throwable e) {
796 Logger.defaultLogError(e);
797 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
805 public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
807 return new AbstractEventHandler() {
810 public CommandResult handle(final CommandContext parameters) {
812 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
816 SCLContext sclContext = SCLContext.getCurrent();
817 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
819 Object response = fn.apply(parameters);
820 if(response instanceof CommandResult) {
821 return (CommandResult)response;
824 } catch (Throwable t) {
827 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
832 } catch (Throwable e) {
833 Logger.defaultLogError(e);
834 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
842 public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
844 return new AbstractEventHandler() {
847 public CommandResult handle(final CommandContext parameters) {
849 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
855 SCLContext sclContext = SCLContext.getCurrent();
856 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
858 Function1<String,String> pf = new FunctionImpl1<String,String>() {
860 public String apply(String key) {
861 return parameters.getString(key);
864 Object response = (String)fn.apply(pf);
865 if(response instanceof String) {
866 result = (String)response;
868 } catch (Throwable t) {
871 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
874 return new SuccessResponse(result);
876 } catch (Throwable e) {
877 Logger.defaultLogError(e);
878 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
886 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
887 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
888 return ServerSCLValueRequest.compileAndEvaluate(graph, context);
891 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
892 public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
893 return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
896 @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
897 public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
898 return createComponentNamingStrategy(graph);
901 public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
902 Layer0X L0X = Layer0X.getInstance(graph);
903 @SuppressWarnings({ "unchecked", "rawtypes" })
904 final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
905 @SuppressWarnings("rawtypes")
906 Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
908 public Object apply(ReadGraph p0, Resource p1, String p2) {
909 return apply(p0, p1, p2);
911 @SuppressWarnings("unchecked")
913 public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
914 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
917 return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
920 public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
921 if (variable == null)
924 SimulationResource SIMU = SimulationResource.getInstance(graph);
926 Variable var = variable;
927 Resource represents = var.getRepresents(graph);
928 Resource activeRun = null;
929 if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
930 activeRun = represents;
933 IProject project = Simantics.peekProject();
934 if (activeRun != null && project != null) {
935 IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
937 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
943 public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
944 List<Object> list = new ArrayList<Object>();
945 if (tuple instanceof Tuple) {
946 Collections.addAll(list, ((Tuple)tuple).toArray());
950 context.putRow(key, list);
954 public static List<Object> getTuples(CommandContext context, String key) {
955 List<List<Object>> rows = context.getRows(key);
956 List<Object> tuples = new ArrayList<Object>();
958 for (List<Object> row : rows) {
959 switch (row.size()) {
960 case 0: tuples.add(Tuple0.INSTANCE); break;
961 case 1: tuples.add(row.get(1)); break;
962 case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
963 case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
964 case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
965 case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
972 public static String printContext(CommandContext context) {
973 String str = context.toString();
974 System.err.println(str);
978 @SCLValue(type = "AbstractEventHandler")
979 public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
982 public CommandResult handle(CommandContext context) {
988 public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
990 String baseURI = base.getURI(graph);
992 String selfURI = self.getURI(graph);
994 String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
995 String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
996 String stripped = prefix + suffix;
998 String relative = Variables.getRelativeRVI(baseURI, stripped);
1000 return Variables.getRVI(relative, ref);
1004 public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1006 String id = sclStateKey(graph, base, self, ref);
1008 Variable sclVar = base.getPossibleChild(graph, "__scl__");
1009 if(sclVar == null) return null;
1011 return sclVar.getPossibleProperty(graph, id);
1015 public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
1017 Variable stateVariable = sclStateVariable(graph, base, self, ref);
1018 if (stateVariable != null) {
1020 return stateVariable.getValue(graph);
1024 String id = sclStateKey(graph, base, self, ref);
1026 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");
1027 realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);
1029 return defaultValue;
1034 public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
1036 String id = sclStateKey(graph, base, self, ref);
1038 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");
1039 realm.getConnection().setVariable(id, getSCLType(value), value);
1040 realm.refreshVariablesSync();
1044 public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
1045 Resource project = Simantics.getProjectResource();
1046 Variable component = self.getParent(graph);
1047 Variable projectVariable = Variables.getVariable(graph, project);
1048 return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
1051 public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
1052 Resource project = Simantics.getProjectResource();
1053 Variable component = self.getParent(graph);
1054 Variable projectVariable = Variables.getVariable(graph, project);
1055 setSclStateValue(graph, projectVariable, component, ref, value);
1058 private static Type getSCLType(Object value) throws DatabaseException {
1059 Binding b = Bindings.getBindingUnchecked(value.getClass());
1060 Datatype t = b.type();
1061 if(Datatypes.STRING.equals(t)) return Types.STRING;
1062 if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
1063 throw new DatabaseException("Type not supported");
1066 public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
1067 Resource project = Simantics.getProjectResource();
1068 ArrayList<Variable> result = new ArrayList<Variable>();
1069 for(Resource model : graph.syncRequest(new ProjectModels(project))) {
1070 result.add(Variables.getVariable(graph, model));
1075 public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
1076 return var.getName(graph);
1079 public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
1080 Variable property = graph.syncRequest(new VariableProperty(variable, name));
1081 return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
1084 public static class ParentExistsRequest extends VariableRead<Boolean> {
1086 public ParentExistsRequest(Variable parent) {
1091 public Boolean perform(ReadGraph graph) throws DatabaseException {
1093 Variable existsProperty = variable.getPossibleProperty(graph, "exists");
1094 if(existsProperty == null) return true;
1096 Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
1097 if (exists == null || !exists) return false;
1099 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
1105 public static class PathExistsRequest extends VariableRead<Boolean> {
1107 public PathExistsRequest(Variable variable) {
1112 public Boolean perform(ReadGraph graph) throws DatabaseException {
1114 Variable widget = variable.getParent(graph);
1116 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
1117 if (exists == null || !exists) return false;
1119 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
1121 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1122 Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);
1123 for (Variable cp : cps) {
1125 Connection conn = cp.getValue(graph);
1126 Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);
1127 if (otherCp != null) {
1128 Variable parentWidget = otherCp.getParent(graph);
1129 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1133 Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
1135 public Variable perform(ReadGraph graph) throws DatabaseException {
1136 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1137 Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
1139 for(VariableConnectionPointDescriptor desc : descs) {
1140 if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
1141 return desc.getVariable(graph);
1147 if (parentCp != null) {
1148 Variable parentWidget = parentCp.getParent(graph);
1149 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1156 Resource type = widget.getType(graph);
1157 return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
1158 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
1162 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
1163 public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1164 return graph.syncRequest(new PathExistsRequest(context));