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.AsyncReadGraph;
19 import org.simantics.db.DirectStatements;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.RequestProcessor;
22 import org.simantics.db.Resource;
23 import org.simantics.db.Session;
24 import org.simantics.db.Statement;
25 import org.simantics.db.WriteGraph;
26 import org.simantics.db.common.primitiverequest.Adapter;
27 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
28 import org.simantics.db.common.request.UnaryRead;
29 import org.simantics.db.common.request.UniqueRead;
30 import org.simantics.db.common.request.WriteResultRequest;
31 import org.simantics.db.common.utils.Logger;
32 import org.simantics.db.common.utils.NameUtils;
33 import org.simantics.db.exception.DatabaseException;
34 import org.simantics.db.layer0.function.All;
35 import org.simantics.db.layer0.request.ProjectModels;
36 import org.simantics.db.layer0.request.PropertyInfo;
37 import org.simantics.db.layer0.request.PropertyInfoRequest;
38 import org.simantics.db.layer0.request.VariableProperty;
39 import org.simantics.db.layer0.request.VariableRead;
40 import org.simantics.db.layer0.request.VariableValueWithBinding;
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.ProxyVariables;
45 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
46 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
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.procedure.AsyncProcedure;
53 import org.simantics.db.service.DirectQuerySupport;
54 import org.simantics.document.base.ontology.DocumentationResource;
55 import org.simantics.document.server.bean.Command;
56 import org.simantics.document.server.bean.DataDefinition;
57 import org.simantics.document.server.handler.AbstractEventHandler;
58 import org.simantics.document.server.handler.AbstractResponseHandler;
59 import org.simantics.document.server.handler.EventHandler;
60 import org.simantics.document.server.io.CommandContext;
61 import org.simantics.document.server.io.CommandContextImpl;
62 import org.simantics.document.server.io.CommandContextMutable;
63 import org.simantics.document.server.io.CommandResult;
64 import org.simantics.document.server.io.IConsole;
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.modeling.ModelingResources;
70 import org.simantics.modeling.scl.SCLRealm;
71 import org.simantics.modeling.scl.SCLSessionManager;
72 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
73 import org.simantics.modeling.services.ComponentNamingStrategy;
74 import org.simantics.operation.Layer0X;
75 import org.simantics.project.IProject;
76 import org.simantics.scl.compiler.types.TCon;
77 import org.simantics.scl.compiler.types.Type;
78 import org.simantics.scl.compiler.types.Types;
79 import org.simantics.scl.reflection.annotations.SCLValue;
80 import org.simantics.scl.runtime.SCLContext;
81 import org.simantics.scl.runtime.function.Function;
82 import org.simantics.scl.runtime.function.Function1;
83 import org.simantics.scl.runtime.function.FunctionImpl1;
84 import org.simantics.scl.runtime.function.FunctionImpl4;
85 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
86 import org.simantics.scl.runtime.tuple.Tuple;
87 import org.simantics.scl.runtime.tuple.Tuple0;
88 import org.simantics.scl.runtime.tuple.Tuple2;
89 import org.simantics.scl.runtime.tuple.Tuple3;
90 import org.simantics.scl.runtime.tuple.Tuple4;
91 import org.simantics.scl.runtime.tuple.Tuple5;
92 import org.simantics.simulation.experiment.IExperiment;
93 import org.simantics.simulation.ontology.SimulationResource;
94 import org.simantics.simulation.project.IExperimentManager;
95 import org.simantics.structural2.variables.Connection;
96 import org.simantics.structural2.variables.StandardProceduralChildVariable;
97 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
99 import gnu.trove.map.hash.THashMap;
101 public class Functions {
103 private static class PrimitivePropertyStatementsProcedure implements AsyncProcedure<DirectStatements> {
105 public DirectStatements result;
108 public void execute(AsyncReadGraph graph, DirectStatements result) {
109 this.result = result;
113 public void exception(AsyncReadGraph graph, Throwable throwable) {
118 @SCLValue(type = "VariableMap")
119 public static VariableMap primitiveProperties = new VariableMapImpl() {
122 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
123 return All.getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
127 public Map<String, Variable> getVariables(final ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
129 Variable parent = context.getParent(graph);
131 DocumentationResource DOC = DocumentationResource.getInstance(graph);
133 if(parent instanceof StandardProceduralChildVariable) {
135 StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent;
136 for(Variable property : procedural.getProperties(graph/*, DocumentationResource.URIs.Document_AttributeRelation*/)) {
137 if(property instanceof StandardAssertedGraphPropertyVariable) {
138 StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property;
139 if("datadefinitions".equals(ass.property.name) || "commands".equals(ass.property.name) || "pollingFunction".equals(ass.property.name)) {
140 Object value = property.getPossibleValue(graph);
141 if(value != null) map.put(ass.property.name, new ConstantPropertyVariable(parent, ass.property.name, value, null));
145 Resource predicate = property.getPossiblePredicateResource(graph);
146 if(predicate != null) {
147 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
148 if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
149 Variable prop = parent.getProperty(graph, predicate);
150 Object value = prop.getValue(graph);
151 if(map == null) map = new HashMap<String,Variable>();
152 map.put(info.name, new ConstantPropertyVariable(parent, info.name, value, null));
159 DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
160 PrimitivePropertyStatementsProcedure foo = new PrimitivePropertyStatementsProcedure();
162 dqs.forEachDirectPersistentStatement(graph, parent.getRepresents(graph), foo);
164 for(Statement stm : foo.result) {
165 Resource predicate = stm.getPredicate();
166 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
168 if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
169 if(map == null) map = new HashMap<String,Variable>();
170 Variable prop = new StandardGraphPropertyVariable(graph, parent, predicate);
171 Object value = prop.getValue(graph);
172 map.put(info.name, new ConstantPropertyVariable(parent, info.name, value, null));
174 Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation);
175 if(definition != null) {
176 if(map == null) map = new HashMap<String,Variable>();
178 PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition));
179 Variable prop = new StandardGraphPropertyVariable(graph, parent, definition);
180 map.put(info2.name, new PrimitiveValueVariable(parent, info2.name, prop));
181 } catch (DatabaseException e) {
182 Logger.defaultLogError(e);
188 Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_dataDefinitions);
189 Object value = prop.getPossibleValue(graph);
190 if(value != null) map.put("dataDefinitions", new ConstantPropertyVariable(parent, "dataDefinitions", value, null));
191 prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_commands);
192 value = prop.getPossibleValue(graph);
193 if(value != null) map.put("commands", new ConstantPropertyVariable(parent, "commands", value, null));
197 if(map == null) return Collections.emptyMap();
205 @SCLValue(type = "VariableMap")
206 public static VariableMap inputSpaceChildren = new VariableMapImpl() {
208 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
209 Variable root = Variables.getRootVariable(graph);
210 return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
214 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
216 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
217 return All.standardChildDomainChildren.getVariable(graph, context, name);
222 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
224 map = All.standardChildDomainChildren.getVariables(graph, context, map);
225 if(map == null) map = new THashMap<String,Variable>();
226 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
233 static class DocumentProxyChildVariable extends ProxyChildVariable {
235 public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
236 super(base, parent, other, name);
240 public Variable create(Variable base, Variable parent, Variable other, String name) {
241 return new DocumentProxyChildVariable(base, parent, other, name);
244 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
246 if(CONTEXT_END.equals(name)) {
247 if(other instanceof ProxyChildVariable) {
248 // The context is also a proxy - let it do the job
249 return super.getPossibleChild(graph, name);
251 return new RootVariable(this, base.getRepresents(graph));
255 return super.getPossibleChild(graph, name);
259 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
261 Collection<Variable> result = super.getChildren(graph);
262 if(!(base instanceof ProxyChildVariable)) {
263 result.add(new RootVariable(this, base.getRepresents(graph)));
271 static class RootVariable extends StandardGraphChildVariable {
273 public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
274 super(parent, null, resource);
278 public String getName(ReadGraph graph) throws DatabaseException {
279 return ProxyChildVariable.CONTEXT_END;
282 @SuppressWarnings("deprecation")
284 public Variable getNameVariable(ReadGraph graph) throws DatabaseException {
285 return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);
290 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
291 public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
292 Variable session = graph.syncRequest(new ProxySessionRequest(context));
293 DocumentationResource DOC = DocumentationResource.getInstance(graph);
294 String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
296 // TODO HAXX - Please fix this
297 // we have no URI so this probably means that someone has inserted a non-session
298 // into the proxy variable => return that instead
301 return Variables.getVariable(graph, uri);
304 public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
305 Variable session = graph.syncRequest(new ProxySessionRequest(self));
307 throw new DatabaseException("No state for " + self.getURI(graph));
308 return session.getPossibleChild(graph, "__scl__");
311 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
312 public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
313 Variable session = graph.syncRequest(new ProxySessionRequest(context));
315 throw new DatabaseException("No state for " + context.getURI(graph));
316 return session.getPossibleChild(graph, "__scl__");
319 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
320 public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
321 Variable session = graph.syncRequest(new ProxySessionRequest(context));
322 return session.getPossibleChild(graph, "__icstate__");
325 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
326 public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
327 return graph.syncRequest(new ProxySessionRequest(context));
330 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
331 public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
332 // Try if experiment (run) has been used as the input
333 Variable var = input(graph, converter, context);
334 SimulationResource SR = SimulationResource.getInstance(graph);
335 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
336 var = var.getParent(graph);
340 IExperiment exp = getExperiment(graph, var);
348 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
349 public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
350 Variable var = input(graph, converter, context);
351 ModelingResources MOD = ModelingResources.getInstance(graph);
352 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
353 var = var.getParent(graph);
359 private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
361 ArrayList<Variable> result = new ArrayList<Variable>();
363 DocumentationResource DOC = DocumentationResource.getInstance(graph);
365 Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
366 if(broadcasted != null) result.add(broadcasted);
368 for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
369 result.addAll(getBroadcasted(graph, child));
376 private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
378 if(commandVariables.isEmpty()) return Collections.emptyList();
381 TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
383 DocumentationResource DOC = DocumentationResource.getInstance(graph);
386 for (Variable c : commandVariables) {
389 t = c.getName(graph);
391 Connection conn = c.getValue(graph);
392 Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
393 if (targetConnectionPoint != null) {
394 Variable target = targetConnectionPoint.getParent(graph);
395 if (target != null) {
397 Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
398 if(enabled != null && !enabled) continue;
406 String o = c.getPossiblePropertyValue(graph, "ordinal");
408 ordinal = Integer.parseInt(o);
409 } catch (NumberFormatException e) {}
412 String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
413 String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
415 CommandContextMutable newConstants = (CommandContextMutable)constants;
416 if(constantKey != null && constantValue != null) {
417 if(!constantKey.isEmpty()) {
418 newConstants = new CommandContextImpl().merge(constants);
419 newConstants.putString(constantKey, constantValue);
423 String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
424 if(requiredKey != null && !requiredKey.isEmpty()) {
425 if (newConstants == constants) {
426 newConstants = new CommandContextImpl().merge(constants);
428 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
431 String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
432 if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
433 if (newConstants == constants) {
434 newConstants = new CommandContextImpl().merge(constants);
436 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
439 if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
441 // This is a broadcast terminal of a container
442 List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
443 sequences.put(ordinal, broadcastCommands);
447 Command command = new Command(DocumentServerUtils.getId(graph, target), t,
448 targetConnectionPoint.getName(graph), newConstants);
449 sequences.put(ordinal, Collections.singletonList(command));
457 List<Command> commands = new ArrayList<Command>();
458 for (List<Command> commandList : sequences.values()) {
459 for (Command command : commandList) {
460 commands.add(command);
473 * @throws DatabaseException
475 public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
476 return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
485 * @throws DatabaseException
487 public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
488 DocumentationResource DOC = DocumentationResource.getInstance(graph);
489 ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
490 // Find data definition connections
491 for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
492 Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
493 // Find data the other end of definition connection
494 Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
495 dataDefinitionRelation, dataDefinitionConnection);
496 if (dataDefinitionProviders != null) {
498 for(Variable dataDefinitionProvider : dataDefinitionProviders) {
500 Variable dataDefinition = dataDefinitionProvider.getParent(graph);
501 if (dataDefinition != null) {
502 // Found other end. Is should contain ONE data
503 // definition connection to the actual data
504 Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
505 if (dataCollection.size() == 1) {
506 Variable dataRelation = dataCollection.iterator().next();
507 Connection dataConnection = dataRelation.getValue(graph);
508 // Find data the other end of definition connection
509 Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
510 dataRelation, dataConnection);
511 if (dataConnectionPoint != null) {
512 Variable data = dataConnectionPoint.getParent(graph);
513 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
515 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
517 String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
519 String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
522 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
523 sourceProperty, targetProperty));
525 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
527 List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
528 List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
530 for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
531 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
532 sourcesProperty.get(i), targetsProperty.get(i)));
541 return dataDefinitions;
544 @SuppressWarnings("unchecked")
545 private static <T> List<T> toList(Object o, Class<T> c) {
546 List<T> result = null;
547 if (o instanceof List) {
549 } else if (o instanceof Object[]) {
550 result = new ArrayList<T>(((Object[])o).length);
551 for (T item : (T[])o) {
556 return Collections.<T>emptyList();
560 public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
561 return new EventHandler() {
563 public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
569 public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
571 final Session session = graph.getSession();
573 return new AbstractEventHandler() {
576 public CommandResult handle(final CommandContext parameters) {
578 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
582 String result = session.sync(new WriteResultRequest<String>() {
585 public String perform(WriteGraph graph) throws DatabaseException {
586 SCLContext sclContext = SCLContext.getCurrent();
587 Object oldGraph = sclContext.put("graph", graph);
588 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
590 Function1<String,String> pf = new FunctionImpl1<String,String>() {
592 public String apply(String key) {
593 return parameters.getString(key);
596 Object response = (String)fn.apply(variable, pf);
597 if(response instanceof String) {
598 return (String)response;
601 } catch (Throwable t) {
604 sclContext.put("graph", oldGraph);
605 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
614 return new SuccessResponse(result);
616 } catch (Throwable e) {
617 Logger.defaultLogError(e);
618 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
626 public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
628 final Session session = graph.getSession();
630 return new AbstractEventHandler() {
633 public CommandResult handle(final CommandContext parameters) {
635 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
639 String result = session.sync(new UniqueRead<String>() {
642 public String perform(ReadGraph graph) throws DatabaseException {
643 SCLContext sclContext = SCLContext.getCurrent();
644 Object oldGraph = sclContext.put("graph", graph);
645 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
647 Function1<String,String> pf = new FunctionImpl1<String,String>() {
649 public String apply(String key) {
650 return parameters.getString(key);
653 Object response = (String)fn.apply(variable, pf);
654 if(response instanceof String) {
655 return (String)response;
658 } catch (Throwable t) {
661 sclContext.put("graph", oldGraph);
662 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
671 return new SuccessResponse(result);
673 } catch (Throwable e) {
674 Logger.defaultLogError(e);
675 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
683 public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
685 final Session session = graph.getSession();
687 return new AbstractEventHandler() {
690 public CommandResult handle(final CommandContext parameters) {
692 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
696 CommandResult result = session.sync(new UniqueRead<CommandResult>() {
699 public CommandResult perform(ReadGraph graph) throws DatabaseException {
700 SCLContext sclContext = SCLContext.getCurrent();
701 Object oldGraph = sclContext.put("graph", graph);
702 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
704 Object response = fn.apply(parameters);
705 if(response instanceof CommandResult) {
706 return (CommandResult)response;
709 } catch (Throwable t) {
712 sclContext.put("graph", oldGraph);
713 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
724 } catch (Throwable e) {
725 Logger.defaultLogError(e);
726 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
734 public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
736 Variable anyFunction = self.browse(graph, ".#" + function);
737 if(anyFunction == null) return null;
739 final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
741 final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
742 String expression = anyFunction.getPropertyValue(graph, "expression");
744 final Session session = graph.getSession();
746 return new AbstractResponseHandler(expression) {
748 private String formatError(RequestProcessor proc, Throwable t) {
752 return proc.syncRequest(new UniqueRead<String>() {
755 public String perform(ReadGraph graph) throws DatabaseException {
756 Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
757 String uri2 = proxy.getURI(graph);
758 String uri = self.getParent(graph).getURI(graph);
760 String path = uri.substring(uri2.length());
762 String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
763 StringBuilder message = new StringBuilder();
764 message.append("Handler execution failed\n");
765 message.append(" handler=" + path + "\n");
766 message.append(" expression=" + expr + "\n");
767 message.append(" message=" + t.getMessage() + "\n");
769 StringWriter sw = new StringWriter();
770 t.printStackTrace(new PrintWriter(sw));
771 message.append(" stack trace=" + sw);
773 return message.toString();
778 } catch (DatabaseException e) {
780 return e.getMessage();
787 public CommandResult handle(final CommandContext parameters) {
789 IConsole console = parameters.getValue("__console__");
790 SCLReportingHandler printer = (console != null) ? new ConsoleSCLReportingHandler(console)
791 : (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
795 Object result = null;
796 if(effects.contains(Types.WRITE_GRAPH)) {
798 result = session.syncRequest(new WriteResultRequest<Object>() {
801 public Object perform(WriteGraph graph)
802 throws DatabaseException {
803 SCLContext sclContext = SCLContext.getCurrent();
804 Object oldGraph = sclContext.put("graph", graph);
805 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
807 Object response = fn.apply(parameters);
809 } catch (Throwable t) {
810 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
812 sclContext.put("graph", oldGraph);
813 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
819 } else if(effects.contains(Types.READ_GRAPH)) {
821 result = session.sync(new UniqueRead<Object>() {
824 public Object perform(ReadGraph graph) throws DatabaseException {
826 SCLContext sclContext = SCLContext.getCurrent();
827 Object oldGraph = sclContext.put("graph", graph);
828 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
831 Object response = fn.apply(parameters);
833 } catch (Throwable t) {
834 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
836 sclContext.put("graph", oldGraph);
837 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
845 SCLContext sclContext = SCLContext.getCurrent();
846 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
848 result = fn.apply(parameters);
850 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
855 if (result instanceof org.simantics.document.server.serverResponse.Error) {
856 return (CommandResult)result;
859 if (result instanceof CommandResult) {
860 return (CommandResult)result;
862 CommandContextMutable assignments = new CommandContextImpl();
863 assignments.putValue("result", result);
864 return new ServerResponse(200, "", assignments);
867 } catch (Throwable e) {
868 return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
876 public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
878 final Session session = graph.getSession();
880 return new AbstractEventHandler() {
883 public CommandResult handle(final CommandContext parameters) {
885 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
889 CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
892 public CommandResult perform(WriteGraph graph) throws DatabaseException {
893 SCLContext sclContext = SCLContext.getCurrent();
894 Object oldGraph = sclContext.put("graph", graph);
895 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
897 Object response = fn.apply(parameters);
898 if(response instanceof CommandResult) {
899 return (CommandResult)response;
902 } catch (Throwable t) {
905 sclContext.put("graph", oldGraph);
906 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
917 } catch (Throwable e) {
918 Logger.defaultLogError(e);
919 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
927 public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
929 return new AbstractEventHandler() {
932 public CommandResult handle(final CommandContext parameters) {
934 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
938 SCLContext sclContext = SCLContext.getCurrent();
939 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
941 Object response = fn.apply(parameters);
942 if(response instanceof CommandResult) {
943 return (CommandResult)response;
946 } catch (Throwable t) {
949 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
954 } catch (Throwable e) {
955 Logger.defaultLogError(e);
956 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
964 public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
966 return new AbstractEventHandler() {
969 public CommandResult handle(final CommandContext parameters) {
971 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
977 SCLContext sclContext = SCLContext.getCurrent();
978 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
980 Function1<String,String> pf = new FunctionImpl1<String,String>() {
982 public String apply(String key) {
983 return parameters.getString(key);
986 Object response = (String)fn.apply(pf);
987 if(response instanceof String) {
988 result = (String)response;
990 } catch (Throwable t) {
993 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
996 return new SuccessResponse(result);
998 } catch (Throwable e) {
999 Logger.defaultLogError(e);
1000 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
1008 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1009 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1010 return ServerSCLValueRequest.compileAndEvaluate(graph, context);
1013 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1014 public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1015 return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
1018 @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
1019 public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
1020 return createComponentNamingStrategy(graph);
1023 public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
1024 Layer0X L0X = Layer0X.getInstance(graph);
1025 @SuppressWarnings({ "unchecked", "rawtypes" })
1026 final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
1027 @SuppressWarnings("rawtypes")
1028 Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
1030 public Object apply(ReadGraph p0, Resource p1, String p2) {
1031 return apply(p0, p1, p2);
1033 @SuppressWarnings("unchecked")
1035 public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
1036 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
1039 return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
1042 public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
1043 if (variable == null)
1046 SimulationResource SIMU = SimulationResource.getInstance(graph);
1048 Variable var = variable;
1049 Resource represents = var.getRepresents(graph);
1050 Resource activeRun = null;
1051 if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
1052 activeRun = represents;
1055 IProject project = Simantics.peekProject();
1056 if (activeRun != null && project != null) {
1057 IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
1059 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
1065 public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
1066 List<Object> list = new ArrayList<Object>();
1067 if (tuple instanceof Tuple) {
1068 Collections.addAll(list, ((Tuple)tuple).toArray());
1072 context.putRow(key, list);
1076 public static List<Object> getTuples(CommandContext context, String key) {
1077 List<List<Object>> rows = context.getRows(key);
1078 List<Object> tuples = new ArrayList<Object>();
1080 for (List<Object> row : rows) {
1081 switch (row.size()) {
1082 case 0: tuples.add(Tuple0.INSTANCE); break;
1083 case 1: tuples.add(row.get(1)); break;
1084 case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
1085 case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
1086 case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
1087 case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
1094 public static String printContext(CommandContext context) {
1095 return context.toString();
1098 @SCLValue(type = "AbstractEventHandler")
1099 public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
1102 public CommandResult handle(CommandContext context) {
1108 public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1110 String baseURI = base.getURI(graph);
1112 String selfURI = self.getURI(graph);
1114 String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
1115 String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
1116 String stripped = prefix + suffix;
1118 String relative = Variables.getRelativeRVI(baseURI, stripped);
1120 return Variables.getRVI(relative, ref);
1124 public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1126 String id = sclStateKey(graph, base, self, ref);
1128 Variable sclVar = base.getPossibleChild(graph, "__scl__");
1129 if(sclVar == null) return null;
1131 return sclVar.getPossibleProperty(graph, id);
1135 public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
1137 Variable stateVariable = sclStateVariable(graph, base, self, ref);
1138 if (stateVariable != null) {
1140 return stateVariable.getValue(graph);
1144 String id = sclStateKey(graph, base, self, ref);
1146 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");
1147 realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);
1149 return defaultValue;
1154 public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
1156 String id = sclStateKey(graph, base, self, ref);
1158 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");
1159 realm.getConnection().setVariable(id, getSCLType(value), value);
1160 realm.refreshVariablesSync();
1164 public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
1165 Resource project = Simantics.getProjectResource();
1166 Variable component = self.getParent(graph);
1167 Variable projectVariable = Variables.getVariable(graph, project);
1168 return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
1171 public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
1172 Resource project = Simantics.getProjectResource();
1173 Variable component = self.getParent(graph);
1174 Variable projectVariable = Variables.getVariable(graph, project);
1175 setSclStateValue(graph, projectVariable, component, ref, value);
1178 private static Type getSCLType(Object value) throws DatabaseException {
1179 Binding b = Bindings.getBindingUnchecked(value.getClass());
1180 Datatype t = b.type();
1181 if(Datatypes.STRING.equals(t)) return Types.STRING;
1182 if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
1183 throw new DatabaseException("Type not supported");
1186 public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
1187 Resource project = Simantics.getProjectResource();
1188 ArrayList<Variable> result = new ArrayList<Variable>();
1189 for(Resource model : graph.syncRequest(new ProjectModels(project))) {
1190 result.add(Variables.getVariable(graph, model));
1195 public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
1196 return var.getName(graph);
1199 public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
1200 Variable property = graph.syncRequest(new VariableProperty(variable, name));
1201 return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
1204 public static class ParentExistsRequest extends VariableRead<Boolean> {
1206 public ParentExistsRequest(Variable parent) {
1211 public Boolean perform(ReadGraph graph) throws DatabaseException {
1213 Variable existsProperty = variable.getPossibleProperty(graph, "exists");
1214 if(existsProperty == null) return true;
1216 Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
1217 if (exists == null || !exists) return false;
1219 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
1225 public static class PathExistsRequest extends VariableRead<Boolean> {
1227 public PathExistsRequest(Variable variable) {
1232 public Boolean perform(ReadGraph graph) throws DatabaseException {
1234 Variable widget = variable.getParent(graph);
1236 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
1237 if (exists == null || !exists) return false;
1239 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
1241 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1242 Collection <Variable> cps = widget.getProperties(graph, DocumentationResource.URIs.Relations_parentRelation);
1243 for (Variable cp : cps) {
1245 Connection conn = cp.getValue(graph);
1246 Variable otherCp = DocumentServerUtils.getPossibleChildConnectionPoint(graph, cp, conn);
1247 if (otherCp != null) {
1248 Variable parentWidget = otherCp.getParent(graph);
1249 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1253 Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
1255 public Variable perform(ReadGraph graph) throws DatabaseException {
1256 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1257 Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
1259 for(VariableConnectionPointDescriptor desc : descs) {
1260 if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
1261 return desc.getVariable(graph);
1267 if (parentCp != null) {
1268 Variable parentWidget = parentCp.getParent(graph);
1269 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1276 Resource type = widget.getType(graph);
1277 return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
1278 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
1282 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
1283 public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1284 return graph.syncRequest(new PathExistsRequest(context));