1 package org.simantics.document.server;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
5 import java.util.Collections;
\r
6 import java.util.List;
\r
7 import java.util.Map;
\r
8 import java.util.TreeMap;
\r
10 import org.simantics.Simantics;
\r
11 import org.simantics.databoard.Bindings;
\r
12 import org.simantics.databoard.Datatypes;
\r
13 import org.simantics.databoard.binding.Binding;
\r
14 import org.simantics.databoard.type.Datatype;
\r
15 import org.simantics.db.ReadGraph;
\r
16 import org.simantics.db.RequestProcessor;
\r
17 import org.simantics.db.Resource;
\r
18 import org.simantics.db.Session;
\r
19 import org.simantics.db.WriteGraph;
\r
20 import org.simantics.db.common.primitiverequest.Adapter;
\r
21 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
\r
22 import org.simantics.db.common.request.UnaryRead;
\r
23 import org.simantics.db.common.request.UniqueRead;
\r
24 import org.simantics.db.common.request.WriteResultRequest;
\r
25 import org.simantics.db.common.utils.Logger;
\r
26 import org.simantics.db.common.utils.NameUtils;
\r
27 import org.simantics.db.exception.DatabaseException;
\r
28 import org.simantics.db.layer0.function.All;
\r
29 import org.simantics.db.layer0.request.ProjectModels;
\r
30 import org.simantics.db.layer0.request.VariableProperty;
\r
31 import org.simantics.db.layer0.request.VariableRead;
\r
32 import org.simantics.db.layer0.request.VariableValue;
\r
33 import org.simantics.db.layer0.variable.ConstantPropertyVariable;
\r
34 import org.simantics.db.layer0.variable.ProxyChildVariable;
\r
35 import org.simantics.db.layer0.variable.ProxySessionRequest;
\r
36 import org.simantics.db.layer0.variable.ProxyVariables;
\r
37 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
\r
38 import org.simantics.db.layer0.variable.Variable;
\r
39 import org.simantics.db.layer0.variable.VariableMap;
\r
40 import org.simantics.db.layer0.variable.VariableMapImpl;
\r
41 import org.simantics.db.layer0.variable.Variables;
\r
42 import org.simantics.document.base.ontology.DocumentationResource;
\r
43 import org.simantics.document.server.bean.Command;
\r
44 import org.simantics.document.server.bean.DataDefinition;
\r
45 import org.simantics.document.server.handler.AbstractEventHandler;
\r
46 import org.simantics.document.server.handler.AbstractResponseHandler;
\r
47 import org.simantics.document.server.handler.EventHandler;
\r
48 import org.simantics.document.server.io.CommandContext;
\r
49 import org.simantics.document.server.io.CommandContextImpl;
\r
50 import org.simantics.document.server.io.CommandContextMutable;
\r
51 import org.simantics.document.server.io.CommandResult;
\r
52 import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
\r
53 import org.simantics.document.server.request.ServerSCLValueRequest;
\r
54 import org.simantics.document.server.serverResponse.ServerResponse;
\r
55 import org.simantics.document.server.serverResponse.SuccessResponse;
\r
56 import org.simantics.modeling.ModelingResources;
\r
57 import org.simantics.modeling.scl.SCLRealm;
\r
58 import org.simantics.modeling.scl.SCLSessionManager;
\r
59 import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
\r
60 import org.simantics.modeling.services.ComponentNamingStrategy;
\r
61 import org.simantics.operation.Layer0X;
\r
62 import org.simantics.project.IProject;
\r
63 import org.simantics.scl.compiler.types.TCon;
\r
64 import org.simantics.scl.compiler.types.Type;
\r
65 import org.simantics.scl.compiler.types.Types;
\r
66 import org.simantics.scl.reflection.annotations.SCLValue;
\r
67 import org.simantics.scl.runtime.SCLContext;
\r
68 import org.simantics.scl.runtime.function.Function;
\r
69 import org.simantics.scl.runtime.function.Function1;
\r
70 import org.simantics.scl.runtime.function.FunctionImpl1;
\r
71 import org.simantics.scl.runtime.function.FunctionImpl4;
\r
72 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
\r
73 import org.simantics.scl.runtime.tuple.Tuple;
\r
74 import org.simantics.scl.runtime.tuple.Tuple0;
\r
75 import org.simantics.scl.runtime.tuple.Tuple2;
\r
76 import org.simantics.scl.runtime.tuple.Tuple3;
\r
77 import org.simantics.scl.runtime.tuple.Tuple4;
\r
78 import org.simantics.scl.runtime.tuple.Tuple5;
\r
79 import org.simantics.simulation.experiment.IExperiment;
\r
80 import org.simantics.simulation.ontology.SimulationResource;
\r
81 import org.simantics.simulation.project.IExperimentManager;
\r
82 import org.simantics.structural2.variables.Connection;
\r
83 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
\r
85 import gnu.trove.map.hash.THashMap;
\r
87 public class Functions {
\r
89 @SCLValue(type = "VariableMap")
\r
90 public static VariableMap inputSpaceChildren = new VariableMapImpl() {
\r
92 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
\r
93 Variable root = Variables.getRootVariable(graph);
\r
94 return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
\r
98 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
\r
100 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
\r
101 return All.standardChildDomainChildren.getVariable(graph, context, name);
\r
106 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
\r
108 map = All.standardChildDomainChildren.getVariables(graph, context, map);
\r
109 if(map == null) map = new THashMap<String,Variable>();
\r
110 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
\r
117 static class DocumentProxyChildVariable extends ProxyChildVariable {
\r
119 public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
\r
120 super(base, parent, other, name);
\r
124 public Variable create(Variable base, Variable parent, Variable other, String name) {
\r
125 return new DocumentProxyChildVariable(base, parent, other, name);
\r
128 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
\r
130 if(CONTEXT_END.equals(name)) {
\r
131 if(other instanceof ProxyChildVariable) {
\r
132 // The context is also a proxy - let it do the job
\r
133 return super.getPossibleChild(graph, name);
\r
135 return new RootVariable(this, base.getRepresents(graph));
\r
139 return super.getPossibleChild(graph, name);
\r
143 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
\r
145 Collection<Variable> result = super.getChildren(graph);
\r
146 if(!(base instanceof ProxyChildVariable)) {
\r
147 result.add(new RootVariable(this, base.getRepresents(graph)));
\r
155 static class RootVariable extends StandardGraphChildVariable {
\r
157 public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
\r
158 super(parent, null, resource);
\r
162 public String getName(ReadGraph graph) throws DatabaseException {
\r
163 return ProxyChildVariable.CONTEXT_END;
\r
166 @SuppressWarnings("deprecation")
\r
168 public Variable getNameVariable(ReadGraph graph) throws DatabaseException {
\r
169 return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);
\r
174 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
175 public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
176 Variable session = graph.syncRequest(new ProxySessionRequest(context));
\r
177 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
178 String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
\r
180 // TODO HAXX - Please fix this
\r
181 // we have no URI so this probably means that someone has inserted a non-session
\r
182 // into the proxy variable => return that instead
\r
185 return Variables.getVariable(graph, uri);
\r
188 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
189 public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
190 Variable session = graph.syncRequest(new ProxySessionRequest(context));
\r
191 if (session == null)
\r
192 throw new DatabaseException("No state for " + context.getURI(graph));
\r
193 return session.getPossibleChild(graph, "__scl__");
\r
196 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
197 public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
198 Variable session = graph.syncRequest(new ProxySessionRequest(context));
\r
199 return session.getPossibleChild(graph, "__icstate__");
\r
202 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
203 public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
204 return graph.syncRequest(new ProxySessionRequest(context));
\r
207 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
208 public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
209 // Try if experiment (run) has been used as the input
\r
210 Variable var = input(graph, converter, context);
\r
211 SimulationResource SR = SimulationResource.getInstance(graph);
\r
212 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
\r
213 var = var.getParent(graph);
\r
217 IExperiment exp = getExperiment(graph, var);
\r
225 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
\r
226 public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
227 Variable var = input(graph, converter, context);
\r
228 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
229 while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
\r
230 var = var.getParent(graph);
\r
236 private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
\r
238 ArrayList<Variable> result = new ArrayList<Variable>();
\r
240 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
242 Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
\r
243 if(broadcasted != null) result.add(broadcasted);
\r
245 for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
\r
246 result.addAll(getBroadcasted(graph, child));
\r
253 private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
\r
255 if(commandVariables.isEmpty()) return Collections.emptyList();
\r
257 String t = trigger;
\r
258 TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
\r
260 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
263 for (Variable c : commandVariables) {
\r
265 if(trigger == null)
\r
266 t = c.getName(graph);
\r
268 Connection conn = c.getValue(graph);
\r
269 Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
\r
270 if (targetConnectionPoint != null) {
\r
271 Variable target = targetConnectionPoint.getParent(graph);
\r
272 if (target != null) {
\r
274 Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
\r
275 if(enabled != null && !enabled) continue;
\r
283 String o = c.getPossiblePropertyValue(graph, "ordinal");
\r
285 ordinal = Integer.parseInt(o);
\r
286 } catch (NumberFormatException e) {}
\r
289 String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
\r
290 String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
\r
292 CommandContextMutable newConstants = (CommandContextMutable)constants;
\r
293 if(constantKey != null && constantValue != null) {
\r
294 if(!constantKey.isEmpty()) {
\r
295 newConstants = new CommandContextImpl().merge(constants);
\r
296 newConstants.putString(constantKey, constantValue);
\r
300 String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
\r
301 if(requiredKey != null && !requiredKey.isEmpty()) {
\r
302 if (newConstants == constants) {
\r
303 newConstants = new CommandContextImpl().merge(constants);
\r
305 newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
\r
308 String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
\r
309 if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
\r
310 if (newConstants == constants) {
\r
311 newConstants = new CommandContextImpl().merge(constants);
\r
313 newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
\r
316 if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
\r
318 // This is a broadcast terminal of a container
\r
319 List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
\r
320 sequences.put(ordinal, broadcastCommands);
\r
324 Command command = new Command(DocumentServerUtils.getId(graph, target), t,
\r
325 targetConnectionPoint.getName(graph), newConstants);
\r
326 sequences.put(ordinal, Collections.singletonList(command));
\r
334 List<Command> commands = new ArrayList<Command>();
\r
335 for (List<Command> commandList : sequences.values()) {
\r
336 for (Command command : commandList) {
\r
337 commands.add(command);
\r
350 * @throws DatabaseException
\r
352 public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
\r
353 return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
\r
362 * @throws DatabaseException
\r
364 public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
\r
365 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
366 ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
\r
367 // Find data definition connections
\r
368 for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
\r
369 Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
\r
370 // Find data the other end of definition connection
\r
371 Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
\r
372 dataDefinitionRelation, dataDefinitionConnection);
\r
373 if (dataDefinitionProviders != null) {
\r
375 for(Variable dataDefinitionProvider : dataDefinitionProviders) {
\r
377 Variable dataDefinition = dataDefinitionProvider.getParent(graph);
\r
378 if (dataDefinition != null) {
\r
379 // Found other end. Is should contain ONE data
\r
380 // definition connection to the actual data
\r
381 Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
\r
382 if (dataCollection.size() == 1) {
\r
383 Variable dataRelation = dataCollection.iterator().next();
\r
384 Connection dataConnection = dataRelation.getValue(graph);
\r
385 // Find data the other end of definition connection
\r
386 Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
\r
387 dataRelation, dataConnection);
\r
388 if (dataConnectionPoint != null) {
\r
389 Variable data = dataConnectionPoint.getParent(graph);
\r
390 Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
\r
392 if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
\r
394 String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
\r
396 String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
\r
399 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
\r
400 sourceProperty, targetProperty));
\r
402 } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
\r
404 List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
\r
405 List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
\r
407 for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
\r
408 dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
\r
409 sourcesProperty.get(i), targetsProperty.get(i)));
\r
418 return dataDefinitions;
\r
421 @SuppressWarnings("unchecked")
\r
422 private static <T> List<T> toList(Object o, Class<T> c) {
\r
423 List<T> result = null;
\r
424 if (o instanceof List) {
\r
426 } else if (o instanceof Object[]) {
\r
427 result = new ArrayList<T>(((Object[])o).length);
\r
428 for (T item : (T[])o) {
\r
433 return Collections.<T>emptyList();
\r
437 public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
\r
438 return new EventHandler() {
\r
441 public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
\r
448 public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
\r
450 final Session session = graph.getSession();
\r
452 return new AbstractEventHandler() {
\r
455 public CommandResult handle(final CommandContext parameters) {
\r
457 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
461 String result = session.sync(new WriteResultRequest<String>() {
\r
464 public String perform(WriteGraph graph) throws DatabaseException {
\r
465 SCLContext sclContext = SCLContext.getCurrent();
\r
466 Object oldGraph = sclContext.put("graph", graph);
\r
467 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
469 Function1<String,String> pf = new FunctionImpl1<String,String>() {
\r
471 public String apply(String key) {
\r
472 return parameters.getString(key);
\r
475 Object response = (String)fn.apply(variable, pf);
\r
476 if(response instanceof String) {
\r
477 return (String)response;
\r
480 } catch (Throwable t) {
\r
481 t.printStackTrace();
\r
483 sclContext.put("graph", oldGraph);
\r
484 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
493 return new SuccessResponse(result);
\r
495 } catch (Throwable e) {
\r
496 Logger.defaultLogError(e);
\r
497 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
505 public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
\r
507 final Session session = graph.getSession();
\r
509 return new AbstractEventHandler() {
\r
512 public CommandResult handle(final CommandContext parameters) {
\r
514 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
518 String result = session.sync(new UniqueRead<String>() {
\r
521 public String perform(ReadGraph graph) throws DatabaseException {
\r
522 SCLContext sclContext = SCLContext.getCurrent();
\r
523 Object oldGraph = sclContext.put("graph", graph);
\r
524 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
526 Function1<String,String> pf = new FunctionImpl1<String,String>() {
\r
528 public String apply(String key) {
\r
529 return parameters.getString(key);
\r
532 Object response = (String)fn.apply(variable, pf);
\r
533 if(response instanceof String) {
\r
534 return (String)response;
\r
537 } catch (Throwable t) {
\r
538 t.printStackTrace();
\r
540 sclContext.put("graph", oldGraph);
\r
541 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
550 return new SuccessResponse(result);
\r
552 } catch (Throwable e) {
\r
553 Logger.defaultLogError(e);
\r
554 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
562 public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
\r
564 final Session session = graph.getSession();
\r
566 return new AbstractEventHandler() {
\r
569 public CommandResult handle(final CommandContext parameters) {
\r
571 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
575 CommandResult result = session.sync(new UniqueRead<CommandResult>() {
\r
578 public CommandResult perform(ReadGraph graph) throws DatabaseException {
\r
579 SCLContext sclContext = SCLContext.getCurrent();
\r
580 Object oldGraph = sclContext.put("graph", graph);
\r
581 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
583 Object response = fn.apply(parameters);
\r
584 if(response instanceof CommandResult) {
\r
585 return (CommandResult)response;
\r
588 } catch (Throwable t) {
\r
589 t.printStackTrace();
\r
591 sclContext.put("graph", oldGraph);
\r
592 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
603 } catch (Throwable e) {
\r
604 Logger.defaultLogError(e);
\r
605 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
613 public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
\r
615 Variable anyFunction = self.browse(graph, ".#" + function);
\r
616 if(anyFunction == null) return null;
\r
618 final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
\r
620 final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
\r
621 String expression = anyFunction.getPropertyValue(graph, "expression");
\r
623 final Session session = graph.getSession();
\r
625 return new AbstractResponseHandler(expression) {
\r
627 private String formatError(RequestProcessor proc, Throwable t) {
\r
631 return proc.syncRequest(new UniqueRead<String>() {
\r
634 public String perform(ReadGraph graph) throws DatabaseException {
\r
635 Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
\r
636 String uri2 = proxy.getURI(graph);
\r
637 String uri = self.getParent(graph).getURI(graph);
\r
639 String path = uri.substring(uri2.length());
\r
641 String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
\r
642 StringBuilder message = new StringBuilder();
\r
643 message.append("Handler execution failed\n");
\r
644 message.append(" handler=" + path + "\n");
\r
645 message.append(" expression=" + expr + "\n");
\r
646 message.append(" message=" + t.getMessage() + "\n");
\r
647 return message.toString();
\r
652 } catch (DatabaseException e) {
\r
654 return e.getMessage();
\r
661 public CommandResult handle(final CommandContext parameters) {
\r
663 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
667 Object result = null;
\r
668 if(effects.contains(Types.WRITE_GRAPH)) {
\r
670 result = session.syncRequest(new WriteResultRequest<Object>() {
\r
673 public Object perform(WriteGraph graph)
\r
674 throws DatabaseException {
\r
675 SCLContext sclContext = SCLContext.getCurrent();
\r
676 Object oldGraph = sclContext.put("graph", graph);
\r
677 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
679 Object response = fn.apply(parameters);
\r
681 } catch (Throwable t) {
\r
682 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
\r
684 sclContext.put("graph", oldGraph);
\r
685 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
691 } else if(effects.contains(Types.READ_GRAPH)) {
\r
693 result = session.sync(new UniqueRead<Object>() {
\r
696 public Object perform(ReadGraph graph) throws DatabaseException {
\r
698 SCLContext sclContext = SCLContext.getCurrent();
\r
699 Object oldGraph = sclContext.put("graph", graph);
\r
700 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
703 Object response = fn.apply(parameters);
\r
705 } catch (Throwable t) {
\r
706 return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
\r
708 sclContext.put("graph", oldGraph);
\r
709 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
716 result = fn.apply(parameters);
\r
719 if (result instanceof org.simantics.document.server.serverResponse.Error) {
\r
720 return (CommandResult)result;
\r
723 if (result instanceof CommandResult) {
\r
724 return (CommandResult)result;
\r
726 CommandContextMutable assignments = new CommandContextImpl();
\r
727 assignments.putValue("result", result);
\r
728 return new ServerResponse(200, "", assignments);
\r
731 } catch (Throwable e) {
\r
732 return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
\r
740 public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
\r
742 final Session session = graph.getSession();
\r
744 return new AbstractEventHandler() {
\r
747 public CommandResult handle(final CommandContext parameters) {
\r
749 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
753 CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
\r
756 public CommandResult perform(WriteGraph graph) throws DatabaseException {
\r
757 SCLContext sclContext = SCLContext.getCurrent();
\r
758 Object oldGraph = sclContext.put("graph", graph);
\r
759 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
761 Object response = fn.apply(parameters);
\r
762 if(response instanceof CommandResult) {
\r
763 return (CommandResult)response;
\r
766 } catch (Throwable t) {
\r
767 t.printStackTrace();
\r
769 sclContext.put("graph", oldGraph);
\r
770 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
781 } catch (Throwable e) {
\r
782 Logger.defaultLogError(e);
\r
783 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
791 public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
\r
793 return new AbstractEventHandler() {
\r
796 public CommandResult handle(final CommandContext parameters) {
\r
798 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
802 SCLContext sclContext = SCLContext.getCurrent();
\r
803 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
805 Object response = fn.apply(parameters);
\r
806 if(response instanceof CommandResult) {
\r
807 return (CommandResult)response;
\r
810 } catch (Throwable t) {
\r
811 t.printStackTrace();
\r
813 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
818 } catch (Throwable e) {
\r
819 Logger.defaultLogError(e);
\r
820 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
828 public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
\r
830 return new AbstractEventHandler() {
\r
833 public CommandResult handle(final CommandContext parameters) {
\r
835 final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
\r
839 String result = "";
\r
841 SCLContext sclContext = SCLContext.getCurrent();
\r
842 Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
\r
844 Function1<String,String> pf = new FunctionImpl1<String,String>() {
\r
846 public String apply(String key) {
\r
847 return parameters.getString(key);
\r
850 Object response = (String)fn.apply(pf);
\r
851 if(response instanceof String) {
\r
852 result = (String)response;
\r
854 } catch (Throwable t) {
\r
855 t.printStackTrace();
\r
857 sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
\r
860 return new SuccessResponse(result);
\r
862 } catch (Throwable e) {
\r
863 Logger.defaultLogError(e);
\r
864 return new org.simantics.document.server.serverResponse.Error(e.getMessage());
\r
872 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
\r
873 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
874 return ServerSCLValueRequest.compileAndEvaluate(graph, context);
\r
877 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
\r
878 public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
879 return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
\r
882 @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
\r
883 public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
\r
884 return createComponentNamingStrategy(graph);
\r
887 public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
\r
888 Layer0X L0X = Layer0X.getInstance(graph);
\r
889 @SuppressWarnings({ "unchecked", "rawtypes" })
\r
890 final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
\r
891 @SuppressWarnings("rawtypes")
\r
892 Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
\r
894 public Object apply(ReadGraph p0, Resource p1, String p2) {
\r
895 return apply(p0, p1, p2);
\r
897 @SuppressWarnings("unchecked")
\r
899 public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
\r
900 return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
\r
903 return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
\r
906 public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
\r
907 if (variable == null)
\r
910 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
912 Variable var = variable;
\r
913 Resource represents = var.getRepresents(graph);
\r
914 Resource activeRun = null;
\r
915 if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
\r
916 activeRun = represents;
\r
919 IProject project = Simantics.peekProject();
\r
920 if (activeRun != null && project != null) {
\r
921 IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
\r
922 if (expMan != null)
\r
923 return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
\r
929 public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
\r
930 List<Object> list = new ArrayList<Object>();
\r
931 if (tuple instanceof Tuple) {
\r
932 Collections.addAll(list, ((Tuple)tuple).toArray());
\r
936 context.putRow(key, list);
\r
940 public static List<Object> getTuples(CommandContext context, String key) {
\r
941 List<List<Object>> rows = context.getRows(key);
\r
942 List<Object> tuples = new ArrayList<Object>();
\r
943 if (rows != null) {
\r
944 for (List<Object> row : rows) {
\r
945 switch (row.size()) {
\r
946 case 0: tuples.add(Tuple0.INSTANCE); break;
\r
947 case 1: tuples.add(row.get(1)); break;
\r
948 case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
\r
949 case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
\r
950 case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
\r
951 case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
\r
958 public static String printContext(CommandContext context) {
\r
959 String str = context.toString();
\r
960 System.err.println(str);
\r
964 @SCLValue(type = "AbstractEventHandler")
\r
965 public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
\r
968 public CommandResult handle(CommandContext context) {
\r
974 public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
\r
976 String baseURI = base.getURI(graph);
\r
978 String selfURI = self.getURI(graph);
\r
980 String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
\r
981 String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
\r
982 String stripped = prefix + suffix;
\r
984 String relative = Variables.getRelativeRVI(baseURI, stripped);
\r
986 return Variables.getRVI(relative, ref);
\r
990 public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
\r
992 String id = sclStateKey(graph, base, self, ref);
\r
994 Variable sclVar = base.getPossibleChild(graph, "__scl__");
\r
995 if(sclVar == null) return null;
\r
997 return sclVar.getPossibleProperty(graph, id);
\r
1001 public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
\r
1003 Variable stateVariable = sclStateVariable(graph, base, self, ref);
\r
1004 if (stateVariable != null) {
\r
1006 return stateVariable.getValue(graph);
\r
1010 String id = sclStateKey(graph, base, self, ref);
\r
1012 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");
\r
1013 realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);
\r
1015 return defaultValue;
\r
1020 public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
\r
1022 String id = sclStateKey(graph, base, self, ref);
\r
1024 SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");
\r
1025 realm.getConnection().setVariable(id, getSCLType(value), value);
\r
1026 realm.refreshVariablesSync();
\r
1030 public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
\r
1031 Resource project = Simantics.getProjectResource();
\r
1032 Variable component = self.getParent(graph);
\r
1033 Variable projectVariable = Variables.getVariable(graph, project);
\r
1034 return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
\r
1037 public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
\r
1038 Resource project = Simantics.getProjectResource();
\r
1039 Variable component = self.getParent(graph);
\r
1040 Variable projectVariable = Variables.getVariable(graph, project);
\r
1041 setSclStateValue(graph, projectVariable, component, ref, value);
\r
1044 private static Type getSCLType(Object value) throws DatabaseException {
\r
1045 Binding b = Bindings.getBindingUnchecked(value.getClass());
\r
1046 Datatype t = b.type();
\r
1047 if(Datatypes.STRING.equals(t)) return Types.STRING;
\r
1048 if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
\r
1049 throw new DatabaseException("Type not supported");
\r
1052 public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
\r
1053 Resource project = Simantics.getProjectResource();
\r
1054 ArrayList<Variable> result = new ArrayList<Variable>();
\r
1055 for(Resource model : graph.syncRequest(new ProjectModels(project))) {
\r
1056 result.add(Variables.getVariable(graph, model));
\r
1061 public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
\r
1062 return var.getName(graph);
\r
1065 public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
\r
1066 Variable property = graph.syncRequest(new VariableProperty(variable, name));
\r
1067 return graph.syncRequest(new VariableValue<Object>(property));
\r
1070 public static class ParentExistsRequest extends VariableRead<Boolean> {
\r
1072 public ParentExistsRequest(Variable parent) {
\r
1077 public Boolean perform(ReadGraph graph) throws DatabaseException {
\r
1079 Variable existsProperty = variable.getPossibleProperty(graph, "exists");
\r
1080 if(existsProperty == null) return true;
\r
1082 Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
\r
1083 if (exists == null || !exists) return false;
\r
1085 return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
\r
1091 public static class PathExistsRequest extends VariableRead<Boolean> {
\r
1093 public PathExistsRequest(Variable variable) {
\r
1098 public Boolean perform(ReadGraph graph) throws DatabaseException {
\r
1100 Variable widget = variable.getParent(graph);
\r
1102 Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
\r
1103 if (exists == null || !exists) return false;
\r
1105 if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
\r
1107 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
1108 Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);
\r
1109 for (Variable cp : cps) {
\r
1111 Connection conn = cp.getValue(graph);
\r
1112 Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);
\r
1113 if (otherCp != null) {
\r
1114 Variable parentWidget = otherCp.getParent(graph);
\r
1115 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
\r
1119 Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
\r
1121 public Variable perform(ReadGraph graph) throws DatabaseException {
\r
1122 DocumentationResource DOC = DocumentationResource.getInstance(graph);
\r
1123 Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
\r
1125 for(VariableConnectionPointDescriptor desc : descs) {
\r
1126 if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
\r
1127 return desc.getVariable(graph);
\r
1133 if (parentCp != null) {
\r
1134 Variable parentWidget = parentCp.getParent(graph);
\r
1135 if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
\r
1142 Resource type = widget.getType(graph);
\r
1143 return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
\r
1144 (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
\r
1148 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
\r
1149 public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
\r
1150 return graph.syncRequest(new PathExistsRequest(context));
\r