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.TransientCacheListener;
27 import org.simantics.db.common.request.BinaryRead;
28 import org.simantics.db.common.request.UniqueRead;
29 import org.simantics.db.common.request.WriteResultRequest;
30 import org.simantics.db.common.utils.Logger;
31 import org.simantics.db.common.utils.NameUtils;
32 import org.simantics.db.exception.DatabaseException;
33 import org.simantics.db.layer0.function.All;
34 import org.simantics.db.layer0.request.ProjectModels;
35 import org.simantics.db.layer0.request.PropertyInfo;
36 import org.simantics.db.layer0.request.PropertyInfoRequest;
37 import org.simantics.db.layer0.request.VariableProperty;
38 import org.simantics.db.layer0.request.VariableRead;
39 import org.simantics.db.layer0.request.VariableValueWithBinding;
40 import org.simantics.db.layer0.scl.SCLDatabaseException;
41 import org.simantics.db.layer0.variable.ConstantPropertyVariable;
42 import org.simantics.db.layer0.variable.ProxyChildVariable;
43 import org.simantics.db.layer0.variable.ProxySessionRequest;
44 import org.simantics.db.layer0.variable.ProxyVariableSupport;
45 import org.simantics.db.layer0.variable.ProxyVariables;
46 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
47 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
48 import org.simantics.db.layer0.variable.Variable;
49 import org.simantics.db.layer0.variable.VariableMap;
50 import org.simantics.db.layer0.variable.VariableMapImpl;
51 import org.simantics.db.layer0.variable.Variables;
52 import org.simantics.db.service.DirectQuerySupport;
53 import org.simantics.document.base.ontology.DocumentationResource;
54 import org.simantics.document.server.bean.Command;
55 import org.simantics.document.server.bean.DataDefinition;
56 import org.simantics.document.server.handler.AbstractEventHandler;
57 import org.simantics.document.server.handler.AbstractResponseHandler;
58 import org.simantics.document.server.handler.EventHandler;
59 import org.simantics.document.server.io.CommandContext;
60 import org.simantics.document.server.io.CommandContextImpl;
61 import org.simantics.document.server.io.CommandContextMutable;
62 import org.simantics.document.server.io.CommandResult;
63 import org.simantics.document.server.io.IConsole;
64 import org.simantics.document.server.request.NodeRequest;
65 import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
66 import org.simantics.document.server.request.ServerSCLValueRequest;
67 import org.simantics.document.server.serverResponse.ServerResponse;
68 import org.simantics.document.server.serverResponse.SuccessResponse;
69 import org.simantics.document.server.state.StateNodeManager;
70 import org.simantics.document.server.state.StateRealm;
71 import org.simantics.document.server.state.StateSessionManager;
72 import org.simantics.modeling.ModelingResources;
73 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
74 import org.simantics.modeling.services.ComponentNamingStrategy;
75 import org.simantics.operation.Layer0X;
76 import org.simantics.project.IProject;
77 import org.simantics.scl.compiler.module.repository.ImportFailureException;
78 import org.simantics.scl.compiler.types.TCon;
79 import org.simantics.scl.compiler.types.Type;
80 import org.simantics.scl.compiler.types.Types;
81 import org.simantics.scl.reflection.annotations.SCLValue;
82 import org.simantics.scl.runtime.SCLContext;
83 import org.simantics.scl.runtime.function.Function;
84 import org.simantics.scl.runtime.function.Function1;
85 import org.simantics.scl.runtime.function.FunctionImpl1;
86 import org.simantics.scl.runtime.function.FunctionImpl4;
87 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
88 import org.simantics.scl.runtime.tuple.Tuple;
89 import org.simantics.scl.runtime.tuple.Tuple0;
90 import org.simantics.scl.runtime.tuple.Tuple2;
91 import org.simantics.scl.runtime.tuple.Tuple3;
92 import org.simantics.scl.runtime.tuple.Tuple4;
93 import org.simantics.scl.runtime.tuple.Tuple5;
94 import org.simantics.simulation.experiment.IExperiment;
95 import org.simantics.simulation.ontology.SimulationResource;
96 import org.simantics.simulation.project.IExperimentManager;
97 import org.simantics.structural2.variables.Connection;
98 import org.simantics.structural2.variables.StandardProceduralChildVariable;
99 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
100 import org.slf4j.LoggerFactory;
102 import gnu.trove.map.hash.THashMap;
104 public class Functions {
106 private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Functions.class);
108 @SCLValue(type = "VariableMap")
109 public static VariableMap primitiveProperties = new VariableMapImpl() {
110 private void storePropertyValueAndExceptions(ReadGraph graph, Variable parent, String name, Variable property, Map<String, Variable> map) {
112 Object value = property.getValue(graph);
113 map.put(name, new ConstantPropertyVariable(parent, name, value, null));
114 } catch (DatabaseException e) {
115 Variable propertyExceptions = map.get(NodeRequest.PROPERTY_VALUE_EXCEPTIONS);
116 Map<String, Exception> exceptionMap;
117 if (propertyExceptions == null) {
118 exceptionMap = new TreeMap<String, Exception>();
119 propertyExceptions = new ConstantPropertyVariable(parent, NodeRequest.PROPERTY_VALUE_EXCEPTIONS, exceptionMap, null);
120 map.put(NodeRequest.PROPERTY_VALUE_EXCEPTIONS, propertyExceptions);
123 exceptionMap = propertyExceptions.getValue(graph);
124 } catch (DatabaseException e1) {
125 Logger.defaultLogError(e1);
131 label = property.getLabel(graph);
132 } catch (DatabaseException e2) {
135 exceptionMap.put(label, e);
140 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
141 return All.getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
145 public Map<String, Variable> getVariables(final ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
147 if(map == null) map = new HashMap<String,Variable>();
149 Variable parent = context.getParent(graph);
151 DocumentationResource DOC = DocumentationResource.getInstance(graph);
153 if(parent instanceof StandardProceduralChildVariable) {
155 StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent;
156 for(Variable property : procedural.getProperties(graph/*, DocumentationResource.URIs.Document_AttributeRelation*/)) {
157 if(property instanceof StandardAssertedGraphPropertyVariable) {
158 StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property;
159 if("dataDefinitions".equals(ass.property.name) || "commands".equals(ass.property.name) || "pollingFunction".equals(ass.property.name)) {
160 storePropertyValueAndExceptions(graph, parent, ass.property.name, property, map);
164 Resource predicate = property.getPossiblePredicateResource(graph);
165 if(predicate != null) {
166 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
167 if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
168 Variable prop = parent.getProperty(graph, predicate);
169 storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
176 Resource parentRes = parent.getRepresents(graph);
178 Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_commands);
179 storePropertyValueAndExceptions(graph, parent, "commands", prop, map);
182 if (graph.getPossibleObject(parentRes, DOC.Properties_dataDefinitions) != null) {
183 Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_dataDefinitions);
184 storePropertyValueAndExceptions(graph, parent, "dataDefinitions", prop, map);
187 DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
188 //PrimitivePropertyStatementsProcedure foo = new PrimitivePropertyStatementsProcedure();
190 DirectStatements ds = dqs.getDirectPersistentStatements(graph, parentRes);
192 for(Statement stm : ds) {
193 Resource predicate = stm.getPredicate();
194 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
196 if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) {
197 Variable prop = new StandardGraphPropertyVariable(graph, parent, predicate);
198 storePropertyValueAndExceptions(graph, parent, info.name, prop, map);
200 Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation);
201 if(definition != null) {
202 PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition));
203 Variable prop = new StandardGraphPropertyVariable(graph, parent, definition);
204 map.put(info2.name, new PrimitiveValueVariable(parent, info2.name, prop));
215 static class StandardDocumentProperties implements DocumentProperties {
218 public Collection<String> getKeys(ReadGraph graph, Variable context) throws DatabaseException {
220 DocumentationResource DOC = DocumentationResource.getInstance(graph);
221 StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
222 Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
228 public Object getValue(ReadGraph graph, Variable context, String key) throws DatabaseException {
230 DocumentationResource DOC = DocumentationResource.getInstance(graph);
231 StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
232 Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
233 return ps.get(key).getValue(graph);
239 public static DocumentProperties primitiveProperties() throws DatabaseException {
240 return new StandardDocumentProperties();
243 @SCLValue(type = "VariableMap")
244 public static VariableMap inputSpaceChildren = new VariableMapImpl() {
246 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
247 Variable root = Variables.getRootVariable(graph);
248 return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
252 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
254 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
255 return All.standardChildDomainChildren.getVariable(graph, context, name);
260 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
262 map = All.standardChildDomainChildren.getVariables(graph, context, map);
263 if(map == null) map = new THashMap<String,Variable>();
264 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
271 static class DocumentProxyChildVariable extends ProxyChildVariable implements ProxyVariableSupport {
273 public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
274 super(base, parent, other, name);
278 public Variable create(Variable base, Variable parent, Variable other, String name) {
279 return new DocumentProxyChildVariable(base, parent, other, name);
282 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
284 if(CONTEXT_END.equals(name)) {
285 if(other instanceof ProxyChildVariable) {
286 // The context is also a proxy - let it do the job
287 return super.getPossibleChild(graph, name);
289 return ProxyVariables.tryToOwnRenamed(graph, this, base, CONTEXT_END);
293 return super.getPossibleChild(graph, name);
298 public Variable attachTo(ReadGraph graph, Variable parent) {
299 return attachToRenamed(graph, parent, name);
303 public Variable attachToRenamed(ReadGraph graph, Variable parent, String name) {
304 if(this.parent.equals(base))
305 return new DocumentProxyChildVariable(parent, parent, other, name);
307 return new DocumentProxyChildVariable(base, parent, other, name);
312 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
313 public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
314 Variable session = graph.syncRequest(new ProxySessionRequest(context));
315 DocumentationResource DOC = DocumentationResource.getInstance(graph);
316 String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
318 // TODO HAXX - Please fix this
319 // we have no URI so this probably means that someone has inserted a non-session
320 // into the proxy variable => return that instead
323 return Variables.getVariable(graph, uri);
326 public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
327 Variable session = graph.syncRequest(new ProxySessionRequest(self));
329 throw new DatabaseException("No state for " + self.getURI(graph));
330 return session.getPossibleChild(graph, "__scl__");
333 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
334 public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
335 Variable session = graph.syncRequest(new ProxySessionRequest(context));
337 throw new DatabaseException("No state for " + context.getURI(graph));
338 return session.getPossibleChild(graph, "__scl__");
341 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
342 public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
343 Variable session = graph.syncRequest(new ProxySessionRequest(context));
344 return session.getPossibleChild(graph, "__icstate__");
347 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
348 public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
349 return graph.syncRequest(new ProxySessionRequest(context));
352 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
353 public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
354 // Try if experiment (run) has been used as the input
355 Variable var = input(graph, converter, context);
356 SimulationResource SR = SimulationResource.getInstance(graph);
357 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
358 var = var.getParent(graph);
362 IExperiment exp = getExperiment(graph, var);
370 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
371 public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
372 Variable var = input(graph, converter, context);
373 ModelingResources MOD = ModelingResources.getInstance(graph);
374 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
375 var = var.getParent(graph);
381 private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
383 ArrayList<Variable> result = new ArrayList<Variable>();
385 DocumentationResource DOC = DocumentationResource.getInstance(graph);
387 Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
388 if(broadcasted != null) result.add(broadcasted);
390 for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
391 result.addAll(getBroadcasted(graph, child));
398 private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
400 if(commandVariables.isEmpty()) return Collections.emptyList();
403 TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
405 DocumentationResource DOC = DocumentationResource.getInstance(graph);
408 for (Variable c : commandVariables) {
411 t = c.getName(graph);
413 Connection conn = c.getValue(graph);
414 Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
415 if (targetConnectionPoint != null) {
416 Variable target = targetConnectionPoint.getParent(graph);
417 if (target != null) {
419 Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
420 if(enabled != null && !enabled) continue;
428 String o = c.getPossiblePropertyValue(graph, "ordinal");
430 ordinal = Integer.parseInt(o);
431 } catch (NumberFormatException e) {}
434 String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
435 String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
437 CommandContextMutable newConstants = (CommandContextMutable)constants;
438 if(constantKey != null && constantValue != null) {
439 if(!constantKey.isEmpty()) {
440 newConstants = new CommandContextImpl().merge(constants);
441 newConstants.putString(constantKey, constantValue);
445 String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
446 if(requiredKey != null && !requiredKey.isEmpty()) {
447 if (newConstants == constants) {
448 newConstants = new CommandContextImpl().merge(constants);
450 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
453 String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
454 if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
455 if (newConstants == constants) {
456 newConstants = new CommandContextImpl().merge(constants);
458 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
461 if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
463 // This is a broadcast terminal of a container
464 List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
465 sequences.put(ordinal, broadcastCommands);
469 Command command = new Command(DocumentServerUtils.getId(graph, target), t,
470 targetConnectionPoint.getName(graph), newConstants);
471 sequences.put(ordinal, Collections.singletonList(command));
479 List<Command> commands = new ArrayList<Command>();
480 for (List<Command> commandList : sequences.values()) {
481 for (Command command : commandList) {
482 commands.add(command);
495 * @throws DatabaseException
497 public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
498 return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
507 * @throws DatabaseException
509 public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
510 DocumentationResource DOC = DocumentationResource.getInstance(graph);
511 ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
512 // Find data definition connections
513 for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
514 Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
515 // Find data the other end of definition connection
516 Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
517 dataDefinitionRelation, dataDefinitionConnection);
518 if (dataDefinitionProviders != null) {
520 for(Variable dataDefinitionProvider : dataDefinitionProviders) {
522 Variable dataDefinition = dataDefinitionProvider.getParent(graph);
523 if (dataDefinition != null) {
524 // Found other end. Is should contain ONE data
525 // definition connection to the actual data
526 Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
527 if (dataCollection.size() == 1) {
528 Variable dataRelation = dataCollection.iterator().next();
529 Connection dataConnection = dataRelation.getValue(graph);
530 // Find data the other end of definition connection
531 Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
532 dataRelation, dataConnection);
533 if (dataConnectionPoint != null) {
534 Variable data = dataConnectionPoint.getParent(graph);
535 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
537 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
539 String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
541 String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
544 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
545 sourceProperty, targetProperty));
547 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
549 List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
550 List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
552 for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
553 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
554 sourcesProperty.get(i), targetsProperty.get(i)));
563 return dataDefinitions;
566 @SuppressWarnings("unchecked")
567 private static <T> List<T> toList(Object o, Class<T> c) {
568 List<T> result = null;
569 if (o instanceof List) {
571 } else if (o instanceof Object[]) {
572 result = new ArrayList<T>(((Object[])o).length);
573 for (T item : (T[])o) {
578 return Collections.<T>emptyList();
583 public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
584 return new EventHandler() {
586 public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
593 public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
595 final Session session = graph.getSession();
597 return new AbstractEventHandler() {
600 public CommandResult handle(final CommandContext parameters) {
602 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
606 String result = session.sync(new WriteResultRequest<String>() {
609 public String perform(WriteGraph graph) throws DatabaseException {
610 SCLContext sclContext = SCLContext.getCurrent();
611 Object oldGraph = sclContext.put("graph", graph);
612 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
614 Function1<String,String> pf = new FunctionImpl1<String,String>() {
616 public String apply(String key) {
617 return parameters.getString(key);
620 Object response = (String)fn.apply(variable, pf);
621 if(response instanceof String) {
622 return (String)response;
626 sclContext.put("graph", oldGraph);
627 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
634 return new SuccessResponse(result);
636 } catch (Throwable e) {
637 Logger.defaultLogError(e);
638 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
647 public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
649 final Session session = graph.getSession();
651 return new AbstractEventHandler() {
654 public CommandResult handle(final CommandContext parameters) {
656 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
660 String result = session.sync(new UniqueRead<String>() {
663 public String perform(ReadGraph graph) throws DatabaseException {
664 SCLContext sclContext = SCLContext.getCurrent();
665 Object oldGraph = sclContext.put("graph", graph);
666 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
668 Function1<String,String> pf = new FunctionImpl1<String,String>() {
670 public String apply(String key) {
671 return parameters.getString(key);
674 Object response = (String)fn.apply(variable, pf);
675 if(response instanceof String) {
676 return (String)response;
680 sclContext.put("graph", oldGraph);
681 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
688 return new SuccessResponse(result);
690 } catch (Throwable e) {
691 Logger.defaultLogError(e);
692 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
701 public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
703 final Session session = graph.getSession();
705 return new AbstractEventHandler() {
708 public CommandResult handle(final CommandContext parameters) {
710 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
714 CommandResult result = session.sync(new UniqueRead<CommandResult>() {
717 public CommandResult perform(ReadGraph graph) throws DatabaseException {
718 SCLContext sclContext = SCLContext.getCurrent();
719 Object oldGraph = sclContext.put("graph", graph);
720 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
722 Object response = fn.apply(parameters);
723 if(response instanceof CommandResult) {
724 return (CommandResult)response;
728 sclContext.put("graph", oldGraph);
729 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
738 } catch (Throwable e) {
739 Logger.defaultLogError(e);
740 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
748 public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
750 Variable anyFunction = self.browse(graph, ".#" + function);
751 if(anyFunction == null) return null;
753 final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
755 Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
756 //String expression = anyFunction.getPropertyValue(graph, "expression");
758 final Session session = graph.getSession();
760 return new AbstractResponseHandler(fn) {
762 private String formatError(RequestProcessor proc, Throwable t) {
766 return proc.syncRequest(new UniqueRead<String>() {
769 public String perform(ReadGraph graph) throws DatabaseException {
770 Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
771 String uri2 = proxy.getURI(graph);
772 String uri = self.getParent(graph).getURI(graph);
774 String path = uri.substring(uri2.length());
776 String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
777 StringBuilder message = new StringBuilder();
778 message.append("Handler execution failed\n");
779 message.append(" handler=" + path + "\n");
780 message.append(" expression=" + expr + "\n");
781 message.append(" message=" + t.getMessage() + "\n");
783 StringWriter sw = new StringWriter();
784 t.printStackTrace(new PrintWriter(sw));
785 message.append(" stack trace=" + sw);
787 return message.toString();
792 } catch (DatabaseException e) {
794 return e.getMessage();
801 public CommandResult handle(final CommandContext parameters) {
803 IConsole console = parameters.getValue("__console__");
804 SCLReportingHandler printer = (console != null) ? new ConsoleSCLReportingHandler(console)
805 : (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
809 Object result = null;
810 if(effects.contains(Types.WRITE_GRAPH)) {
812 result = session.syncRequest(new WriteResultRequest<Object>() {
815 public Object perform(WriteGraph graph)
816 throws DatabaseException {
817 SCLContext sclContext = SCLContext.getCurrent();
818 Object oldGraph = sclContext.put("graph", graph);
819 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
821 return fn.apply(parameters);
823 sclContext.put("graph", oldGraph);
824 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
830 } else if(effects.contains(Types.READ_GRAPH)) {
832 result = session.sync(new UniqueRead<Object>() {
835 public Object perform(ReadGraph graph) throws DatabaseException {
837 SCLContext sclContext = SCLContext.getCurrent();
838 Object oldGraph = sclContext.put("graph", graph);
839 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
842 return fn.apply(parameters);
844 sclContext.put("graph", oldGraph);
845 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
853 SCLContext sclContext = SCLContext.getCurrent();
854 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
856 result = fn.apply(parameters);
858 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
863 if (result instanceof org.simantics.document.server.serverResponse.Error) {
864 return (CommandResult)result;
867 if (result instanceof CommandResult) {
868 return (CommandResult)result;
870 CommandContextMutable assignments = new CommandContextImpl();
871 assignments.putValue("result", result);
872 return new ServerResponse(200, "", assignments);
875 } catch (Throwable e) {
876 return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
885 public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
887 final Session session = graph.getSession();
889 return new AbstractEventHandler() {
892 public CommandResult handle(final CommandContext parameters) {
894 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
898 CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
901 public CommandResult perform(WriteGraph graph) throws DatabaseException {
902 SCLContext sclContext = SCLContext.getCurrent();
903 Object oldGraph = sclContext.put("graph", graph);
904 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
906 Object response = fn.apply(parameters);
907 if(response instanceof CommandResult) {
908 return (CommandResult)response;
912 sclContext.put("graph", oldGraph);
913 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
922 } catch (Throwable e) {
923 Logger.defaultLogError(e);
924 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
934 public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
936 return new AbstractEventHandler() {
939 public CommandResult handle(final CommandContext parameters) {
941 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
945 SCLContext sclContext = SCLContext.getCurrent();
946 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
948 Object response = fn.apply(parameters);
949 if(response instanceof CommandResult) {
950 return (CommandResult)response;
954 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
957 } catch (Throwable e) {
958 Logger.defaultLogError(e);
959 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
968 public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
970 return new AbstractEventHandler() {
973 public CommandResult handle(final CommandContext parameters) {
975 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
981 SCLContext sclContext = SCLContext.getCurrent();
982 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
984 Function1<String,String> pf = new FunctionImpl1<String,String>() {
986 public String apply(String key) {
987 return parameters.getString(key);
990 Object response = (String)fn.apply(pf);
991 if(response instanceof String) {
992 result = (String)response;
995 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
998 return new SuccessResponse(result);
1000 } catch (Throwable e) {
1001 Logger.defaultLogError(e);
1002 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
1010 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1011 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1012 return ServerSCLValueRequest.compileAndEvaluate(graph, context);
1015 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
1016 public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1017 return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
1020 @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
1021 public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
1022 return createComponentNamingStrategy(graph);
1025 public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
1026 Layer0X L0X = Layer0X.getInstance(graph);
1027 @SuppressWarnings({ "unchecked", "rawtypes" })
1028 final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
1029 @SuppressWarnings("rawtypes")
1030 Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
1032 public Object apply(ReadGraph p0, Resource p1, String p2) {
1033 return apply(p0, p1, p2);
1035 @SuppressWarnings("unchecked")
1037 public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
1038 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
1041 return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
1044 public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
1045 if (variable == null)
1048 SimulationResource SIMU = SimulationResource.getInstance(graph);
1050 Variable var = variable;
1051 Resource represents = var.getRepresents(graph);
1052 Resource activeRun = null;
1053 if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
1054 activeRun = represents;
1057 IProject project = Simantics.peekProject();
1058 if (activeRun != null && project != null) {
1059 IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
1061 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
1067 public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
1068 List<Object> list = new ArrayList<Object>();
1069 if (tuple instanceof Tuple) {
1070 Collections.addAll(list, ((Tuple)tuple).toArray());
1074 context.putRow(key, list);
1078 public static List<Object> getTuples(CommandContext context, String key) {
1079 List<List<Object>> rows = context.getRows(key);
1080 List<Object> tuples = new ArrayList<Object>();
1082 for (List<Object> row : rows) {
1083 switch (row.size()) {
1084 case 0: tuples.add(Tuple0.INSTANCE); break;
1085 case 1: tuples.add(row.get(1)); break;
1086 case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
1087 case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
1088 case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
1089 case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
1096 public static String printContext(CommandContext context) {
1097 return context.toString();
1100 @SCLValue(type = "AbstractEventHandler")
1101 public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
1104 public CommandResult handle(CommandContext context) {
1110 public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1112 String baseURI = base.getURI(graph);
1114 String selfURI = self.getURI(graph);
1116 String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
1117 String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
1118 String stripped = prefix + suffix;
1120 String relative = Variables.getRelativeRVI(baseURI, stripped);
1122 return Variables.getRVI(relative, ref);
1126 public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
1128 String id = sclStateKey(graph, base, self, ref);
1130 Variable sclVar = base.getPossibleChild(graph, "__scl__");
1131 if(sclVar == null) return null;
1133 return sclVar.getPossibleProperty(graph, id);
1137 public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
1139 Variable stateVariable = sclStateVariable(graph, base, self, ref);
1140 if (stateVariable != null) {
1142 return stateVariable.getValue(graph);
1146 return defaultValue;
1151 public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
1153 String id = sclStateKey(graph, base, self, ref);
1155 StateRealm realm = (StateRealm) StateSessionManager.getInstance().getOrCreateRealm(graph, base.getURI(graph)+"/__scl__");
1156 StateNodeManager nodeManager = (StateNodeManager) realm.getNodeManager();
1157 nodeManager.setState(id, value);
1161 public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
1162 Resource project = Simantics.getProjectResource();
1163 Variable component = self.getParent(graph);
1164 Variable projectVariable = Variables.getVariable(graph, project);
1165 return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
1168 public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
1169 Resource project = Simantics.getProjectResource();
1170 Variable component = self.getParent(graph);
1171 Variable projectVariable = Variables.getVariable(graph, project);
1172 setSclStateValue(graph, projectVariable, component, ref, value);
1175 private static Type getSCLType(Object value) throws DatabaseException {
1176 Binding b = Bindings.getBindingUnchecked(value.getClass());
1177 Datatype t = b.type();
1178 if(Datatypes.STRING.equals(t)) return Types.STRING;
1179 if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
1180 throw new DatabaseException("Type not supported");
1183 public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
1184 Resource project = Simantics.getProjectResource();
1185 ArrayList<Variable> result = new ArrayList<Variable>();
1186 for(Resource model : graph.syncRequest(new ProjectModels(project))) {
1187 result.add(Variables.getVariable(graph, model));
1192 public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
1193 return var.getName(graph);
1196 public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
1197 Variable property = graph.syncRequest(new VariableProperty(variable, name));
1198 return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
1201 public static class ParentExistsRequest extends VariableRead<Boolean> {
1203 public ParentExistsRequest(Variable parent) {
1208 public Boolean perform(ReadGraph graph) throws DatabaseException {
1210 Variable existsProperty = variable.getPossibleProperty(graph, "exists");
1211 if(existsProperty == null) return true;
1213 Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
1214 if (exists == null || !exists) return false;
1216 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
1222 public static class PathExistsRequest extends VariableRead<Boolean> {
1224 public PathExistsRequest(Variable variable) {
1229 public Boolean perform(ReadGraph graph) throws DatabaseException {
1231 Variable widget = variable.getParent(graph);
1233 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
1234 if (exists == null || !exists) return false;
1236 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
1238 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1239 Collection <Variable> cps = widget.getProperties(graph, DocumentationResource.URIs.Relations_parentRelation);
1240 for (Variable cp : cps) {
1242 Connection conn = cp.getValue(graph);
1243 Variable otherCp = DocumentServerUtils.getPossibleChildConnectionPoint(graph, cp, conn);
1244 if (otherCp != null) {
1245 Variable parentWidget = otherCp.getParent(graph);
1246 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1250 Variable parentCp = graph.sync(new BinaryRead<Variable, Connection, Variable>(widget, conn) {
1252 public Variable perform(ReadGraph graph) throws DatabaseException {
1253 DocumentationResource DOC = DocumentationResource.getInstance(graph);
1254 Collection<VariableConnectionPointDescriptor> descs = parameter2.getConnection2().getConnectionPointDescriptors(graph, parameter, null);
1256 for(VariableConnectionPointDescriptor desc : descs) {
1257 if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
1258 return desc.getVariable(graph);
1264 if (parentCp != null) {
1265 Variable parentWidget = parentCp.getParent(graph);
1266 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
1273 Resource type = widget.getType(graph);
1274 return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
1275 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
1279 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
1280 public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
1281 return graph.syncRequest(new PathExistsRequest(context));
1284 public static String compileDocumentSCLValueExpression(ReadGraph graph, Variable context) {
1286 ServerSCLValueRequest.validate(graph, context);
1288 } catch (Exception e) {
1289 return resolveIssueMessage(e);
1293 private static String resolveIssueMessage(Exception e) {
1294 if (e instanceof ImportFailureException)
1296 if (e.getCause() != null && e.getCause() instanceof ImportFailureException)
1298 if (e instanceof SCLDatabaseException) {
1299 SCLDatabaseException ee = (SCLDatabaseException) e;
1300 return ee.getMessage();
1302 if (LOGGER.isDebugEnabled())
1303 LOGGER.debug("", e);
1304 return e.getMessage();