-package org.simantics.document.server;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.primitiverequest.Adapter;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.common.request.UniqueRead;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.function.All;\r
-import org.simantics.db.layer0.request.ProjectModels;\r
-import org.simantics.db.layer0.request.VariableProperty;\r
-import org.simantics.db.layer0.request.VariableRead;\r
-import org.simantics.db.layer0.request.VariableValue;\r
-import org.simantics.db.layer0.variable.ConstantPropertyVariable;\r
-import org.simantics.db.layer0.variable.ProxyChildVariable;\r
-import org.simantics.db.layer0.variable.ProxySessionRequest;\r
-import org.simantics.db.layer0.variable.ProxyVariables;\r
-import org.simantics.db.layer0.variable.StandardGraphChildVariable;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.VariableMap;\r
-import org.simantics.db.layer0.variable.VariableMapImpl;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.document.base.ontology.DocumentationResource;\r
-import org.simantics.document.server.bean.Command;\r
-import org.simantics.document.server.bean.DataDefinition;\r
-import org.simantics.document.server.handler.AbstractEventHandler;\r
-import org.simantics.document.server.handler.AbstractResponseHandler;\r
-import org.simantics.document.server.handler.EventHandler;\r
-import org.simantics.document.server.io.CommandContext;\r
-import org.simantics.document.server.io.CommandContextImpl;\r
-import org.simantics.document.server.io.CommandContextMutable;\r
-import org.simantics.document.server.io.CommandResult;\r
-import org.simantics.document.server.request.ServerSCLHandlerValueRequest;\r
-import org.simantics.document.server.request.ServerSCLValueRequest;\r
-import org.simantics.document.server.serverResponse.ServerResponse;\r
-import org.simantics.document.server.serverResponse.SuccessResponse;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.scl.SCLRealm;\r
-import org.simantics.modeling.scl.SCLSessionManager;\r
-import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;\r
-import org.simantics.modeling.services.ComponentNamingStrategy;\r
-import org.simantics.operation.Layer0X;\r
-import org.simantics.project.IProject;\r
-import org.simantics.scl.compiler.types.TCon;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.reflection.annotations.SCLValue;\r
-import org.simantics.scl.runtime.SCLContext;\r
-import org.simantics.scl.runtime.function.Function;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.scl.runtime.function.FunctionImpl1;\r
-import org.simantics.scl.runtime.function.FunctionImpl4;\r
-import org.simantics.scl.runtime.reporting.SCLReportingHandler;\r
-import org.simantics.scl.runtime.tuple.Tuple;\r
-import org.simantics.scl.runtime.tuple.Tuple0;\r
-import org.simantics.scl.runtime.tuple.Tuple2;\r
-import org.simantics.scl.runtime.tuple.Tuple3;\r
-import org.simantics.scl.runtime.tuple.Tuple4;\r
-import org.simantics.scl.runtime.tuple.Tuple5;\r
-import org.simantics.simulation.experiment.IExperiment;\r
-import org.simantics.simulation.ontology.SimulationResource;\r
-import org.simantics.simulation.project.IExperimentManager;\r
-import org.simantics.structural2.variables.Connection;\r
-import org.simantics.structural2.variables.VariableConnectionPointDescriptor;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-public class Functions {\r
- \r
- @SCLValue(type = "VariableMap")\r
- public static VariableMap inputSpaceChildren = new VariableMapImpl() {\r
-\r
- private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {\r
- Variable root = Variables.getRootVariable(graph);\r
- return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);\r
- }\r
- \r
- @Override\r
- public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-\r
- if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);\r
- return All.standardChildDomainChildren.getVariable(graph, context, name);\r
- \r
- }\r
-\r
- @Override\r
- public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-\r
- map = All.standardChildDomainChildren.getVariables(graph, context, map);\r
- if(map == null) map = new THashMap<String,Variable>();\r
- map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));\r
- return map;\r
- \r
- }\r
- \r
- };\r
- \r
- static class DocumentProxyChildVariable extends ProxyChildVariable {\r
-\r
- public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {\r
- super(base, parent, other, name);\r
- }\r
- \r
- @Override\r
- public Variable create(Variable base, Variable parent, Variable other, String name) {\r
- return new DocumentProxyChildVariable(base, parent, other, name);\r
- }\r
- \r
- public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
- \r
- if(CONTEXT_END.equals(name)) {\r
- if(other instanceof ProxyChildVariable) {\r
- // The context is also a proxy - let it do the job\r
- return super.getPossibleChild(graph, name);\r
- } else {\r
- return new RootVariable(this, base.getRepresents(graph));\r
- }\r
- }\r
- \r
- return super.getPossibleChild(graph, name);\r
- \r
- }\r
- \r
- public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
-\r
- Collection<Variable> result = super.getChildren(graph);\r
- if(!(base instanceof ProxyChildVariable)) {\r
- result.add(new RootVariable(this, base.getRepresents(graph)));\r
- }\r
- return result;\r
- \r
- } \r
- \r
- }\r
- \r
- static class RootVariable extends StandardGraphChildVariable {\r
-\r
- public RootVariable(DocumentProxyChildVariable parent, Resource resource) {\r
- super(parent, null, resource);\r
- }\r
- \r
- @Override\r
- public String getName(ReadGraph graph) throws DatabaseException {\r
- return ProxyChildVariable.CONTEXT_END;\r
- }\r
- \r
- @SuppressWarnings("deprecation")\r
- @Override\r
- public Variable getNameVariable(ReadGraph graph) throws DatabaseException {\r
- return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);\r
- }\r
- \r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
- DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
- String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);\r
- if(uri == null) {\r
- // TODO HAXX - Please fix this\r
- // we have no URI so this probably means that someone has inserted a non-session \r
- // into the proxy variable => return that instead\r
- return session;\r
- }\r
- return Variables.getVariable(graph, uri);\r
- }\r
- \r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
- if (session == null)\r
- throw new DatabaseException("No state for " + context.getURI(graph));\r
- return session.getPossibleChild(graph, "__scl__");\r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- Variable session = graph.syncRequest(new ProxySessionRequest(context));\r
- return session.getPossibleChild(graph, "__icstate__");\r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- return graph.syncRequest(new ProxySessionRequest(context));\r
- }\r
- \r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- // Try if experiment (run) has been used as the input\r
- Variable var = input(graph, converter, context);\r
- SimulationResource SR = SimulationResource.getInstance(graph);\r
- while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {\r
- var = var.getParent(graph);\r
- }\r
- \r
- if(var != null) {\r
- IExperiment exp = getExperiment(graph, var);\r
- if(exp == null)\r
- return null;\r
- }\r
- \r
- return var;\r
- }\r
- \r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
- public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- Variable var = input(graph, converter, context);\r
- ModelingResources MOD = ModelingResources.getInstance(graph);\r
- while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {\r
- var = var.getParent(graph);\r
- }\r
- \r
- return var;\r
- }\r
- \r
- private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {\r
- \r
- ArrayList<Variable> result = new ArrayList<Variable>();\r
- \r
- DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
-\r
- Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);\r
- if(broadcasted != null) result.add(broadcasted);\r
- \r
- for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {\r
- result.addAll(getBroadcasted(graph, child));\r
- }\r
- \r
- return result;\r
- \r
- }\r
-\r
- private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {\r
- \r
- if(commandVariables.isEmpty()) return Collections.emptyList();\r
- \r
- String t = trigger;\r
- TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();\r
- \r
- DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
- \r
- int count = 0;\r
- for (Variable c : commandVariables) {\r
- \r
- if(trigger == null)\r
- t = c.getName(graph);\r
- \r
- Connection conn = c.getValue(graph);\r
- Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);\r
- if (targetConnectionPoint != null) {\r
- Variable target = targetConnectionPoint.getParent(graph);\r
- if (target != null) {\r
- \r
- Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);\r
- if(enabled != null && !enabled) continue;\r
- \r
- Integer ordinal;\r
- if (broadcast) {\r
- ordinal = ++count;\r
- } else {\r
- ordinal = 1;\r
- try {\r
- String o = c.getPossiblePropertyValue(graph, "ordinal");\r
- if(o != null)\r
- ordinal = Integer.parseInt(o);\r
- } catch (NumberFormatException e) {}\r
- }\r
- \r
- String constantKey = target.getPossiblePropertyValue(graph, "constantKey");\r
- String constantValue = target.getPossiblePropertyValue(graph, "constantValue");\r
- \r
- CommandContextMutable newConstants = (CommandContextMutable)constants; \r
- if(constantKey != null && constantValue != null) {\r
- if(!constantKey.isEmpty()) {\r
- newConstants = new CommandContextImpl().merge(constants);\r
- newConstants.putString(constantKey, constantValue);\r
- }\r
- }\r
- \r
- String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");\r
- if(requiredKey != null && !requiredKey.isEmpty()) {\r
- if (newConstants == constants) {\r
- newConstants = new CommandContextImpl().merge(constants);\r
- }\r
- newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));\r
- }\r
- \r
- String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");\r
- if(forbiddenKey != null && !forbiddenKey.isEmpty()) {\r
- if (newConstants == constants) {\r
- newConstants = new CommandContextImpl().merge(constants);\r
- }\r
- newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));\r
- }\r
-\r
- if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {\r
-\r
- // This is a broadcast terminal of a container\r
- List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);\r
- sequences.put(ordinal, broadcastCommands);\r
-\r
- } else {\r
-\r
- Command command = new Command(DocumentServerUtils.getId(graph, target), t, \r
- targetConnectionPoint.getName(graph), newConstants);\r
- sequences.put(ordinal, Collections.singletonList(command));\r
- \r
- }\r
-\r
- }\r
- }\r
- }\r
-\r
- List<Command> commands = new ArrayList<Command>();\r
- for (List<Command> commandList : sequences.values()) {\r
- for (Command command : commandList) {\r
- commands.add(command);\r
- }\r
- }\r
- \r
- return commands;\r
- }\r
-\r
- /**\r
- * Commands\r
- * \r
- * @param graph\r
- * @param variable\r
- * @return\r
- * @throws DatabaseException\r
- */\r
- public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {\r
- return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);\r
- }\r
-\r
- /**\r
- * Data definitions\r
- * \r
- * @param graph\r
- * @param variable\r
- * @return\r
- * @throws DatabaseException\r
- */\r
- public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {\r
- DocumentationResource DOC = DocumentationResource.getInstance(graph); \r
- ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();\r
- // Find data definition connections\r
- for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {\r
- Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);\r
- // Find data the other end of definition connection\r
- Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,\r
- dataDefinitionRelation, dataDefinitionConnection);\r
- if (dataDefinitionProviders != null) {\r
-\r
- for(Variable dataDefinitionProvider : dataDefinitionProviders) {\r
-\r
- Variable dataDefinition = dataDefinitionProvider.getParent(graph);\r
- if (dataDefinition != null) {\r
- // Found other end. Is should contain ONE data\r
-// definition connection to the actual data\r
- Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);\r
- if (dataCollection.size() == 1) {\r
- Variable dataRelation = dataCollection.iterator().next();\r
- Connection dataConnection = dataRelation.getValue(graph);\r
- // Find data the other end of definition connection\r
- Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,\r
- dataRelation, dataConnection);\r
- if (dataConnectionPoint != null) {\r
- Variable data = dataConnectionPoint.getParent(graph);\r
- Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);\r
-\r
- if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {\r
-\r
- String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,\r
- Bindings.STRING);\r
- String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,\r
- Bindings.STRING);\r
-\r
- dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
- sourceProperty, targetProperty));\r
- \r
- } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {\r
-\r
- List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);\r
- List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);\r
-\r
- for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {\r
- dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),\r
- sourcesProperty.get(i), targetsProperty.get(i)));\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return dataDefinitions;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- private static <T> List<T> toList(Object o, Class<T> c) {\r
- List<T> result = null;\r
- if (o instanceof List) {\r
- return (List<T>)o;\r
- } else if (o instanceof Object[]) {\r
- result = new ArrayList<T>(((Object[])o).length);\r
- for (T item : (T[])o) {\r
- result.add(item);\r
- }\r
- return result;\r
- } else {\r
- return Collections.<T>emptyList();\r
- }\r
- }\r
- \r
- public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {\r
- return new EventHandler() {\r
-\r
- @Override\r
- public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {\r
- return null;\r
- }\r
-\r
- };\r
- }\r
- \r
- public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
- \r
- final Session session = graph.getSession();\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- String result = session.sync(new WriteResultRequest<String>() {\r
- \r
- @Override\r
- public String perform(WriteGraph graph) throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
- @Override\r
- public String apply(String key) {\r
- return parameters.getString(key);\r
- }\r
- }; \r
- Object response = (String)fn.apply(variable, pf);\r
- if(response instanceof String) {\r
- return (String)response;\r
- }\r
- return null;\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- return null;\r
- \r
- }\r
- \r
- });\r
- \r
- return new SuccessResponse(result);\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
- \r
- public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {\r
- \r
- final Session session = graph.getSession();\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- String result = session.sync(new UniqueRead<String>() {\r
- \r
- @Override\r
- public String perform(ReadGraph graph) throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
- @Override\r
- public String apply(String key) {\r
- return parameters.getString(key);\r
- }\r
- }; \r
- Object response = (String)fn.apply(variable, pf);\r
- if(response instanceof String) {\r
- return (String)response;\r
- }\r
- return null;\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- return null;\r
- \r
- }\r
- \r
- });\r
- \r
- return new SuccessResponse(result);\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
-\r
- public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {\r
- \r
- final Session session = graph.getSession();\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- CommandResult result = session.sync(new UniqueRead<CommandResult>() {\r
- \r
- @Override\r
- public CommandResult perform(ReadGraph graph) throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Object response = fn.apply(parameters);\r
- if(response instanceof CommandResult) {\r
- return (CommandResult)response;\r
- }\r
- return null;\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- return null;\r
- \r
- }\r
- \r
- });\r
- \r
- return result;\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
-\r
- public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {\r
-\r
- Variable anyFunction = self.browse(graph, ".#" + function);\r
- if(anyFunction == null) return null;\r
-\r
- final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);\r
- \r
- final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);\r
- String expression = anyFunction.getPropertyValue(graph, "expression");\r
- \r
- final Session session = graph.getSession();\r
- \r
- return new AbstractResponseHandler(expression) {\r
- \r
- private String formatError(RequestProcessor proc, Throwable t) {\r
- \r
- try {\r
- \r
- return proc.syncRequest(new UniqueRead<String>() {\r
-\r
- @Override\r
- public String perform(ReadGraph graph) throws DatabaseException {\r
- Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);\r
- String uri2 = proxy.getURI(graph);\r
- String uri = self.getParent(graph).getURI(graph);\r
-\r
- String path = uri.substring(uri2.length());\r
-\r
- String expr = anyFunction.getPossiblePropertyValue(graph, "expression");\r
- StringBuilder message = new StringBuilder();\r
- message.append("Handler execution failed\n");\r
- message.append(" handler=" + path + "\n");\r
- message.append(" expression=" + expr + "\n");\r
- message.append(" message=" + t.getMessage() + "\n");\r
- return message.toString();\r
- }\r
- \r
- });\r
- \r
- } catch (DatabaseException e) {\r
- \r
- return e.getMessage();\r
- \r
- }\r
- \r
- }\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- Object result = null;\r
- if(effects.contains(Types.WRITE_GRAPH)) {\r
-\r
- result = session.syncRequest(new WriteResultRequest<Object>() {\r
-\r
- @Override\r
- public Object perform(WriteGraph graph)\r
- throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Object response = fn.apply(parameters);\r
- return response;\r
- } catch (Throwable t) {\r
- return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
-\r
- }\r
- });\r
- \r
- } else if(effects.contains(Types.READ_GRAPH)) {\r
-\r
- result = session.sync(new UniqueRead<Object>() {\r
-\r
- @Override\r
- public Object perform(ReadGraph graph) throws DatabaseException {\r
- \r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- \r
- try {\r
- Object response = fn.apply(parameters);\r
- return response;\r
- } catch (Throwable t) {\r
- return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- }\r
- });\r
-\r
- } else {\r
- result = fn.apply(parameters);\r
- }\r
-\r
- if (result instanceof org.simantics.document.server.serverResponse.Error) {\r
- return (CommandResult)result;\r
- }\r
- \r
- if (result instanceof CommandResult) {\r
- return (CommandResult)result;\r
- } else {\r
- CommandContextMutable assignments = new CommandContextImpl();\r
- assignments.putValue("result", result);\r
- return new ServerResponse(200, "", assignments);\r
- } \r
- \r
- } catch (Throwable e) {\r
- return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));\r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
- \r
- public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {\r
- \r
- final Session session = graph.getSession();\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {\r
- \r
- @Override\r
- public CommandResult perform(WriteGraph graph) throws DatabaseException {\r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldGraph = sclContext.put("graph", graph);\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Object response = fn.apply(parameters);\r
- if(response instanceof CommandResult) {\r
- return (CommandResult)response;\r
- }\r
- return null;\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put("graph", oldGraph);\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- return null;\r
- \r
- }\r
- \r
- });\r
- \r
- return result;\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
-\r
- public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
- \r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Object response = fn.apply(parameters);\r
- if(response instanceof CommandResult) {\r
- return (CommandResult)response;\r
- }\r
- return null;\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
-\r
- return null;\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
-\r
- public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {\r
- \r
- return new AbstractEventHandler() {\r
- \r
- @Override\r
- public CommandResult handle(final CommandContext parameters) {\r
- \r
- final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);\r
- \r
- try {\r
-\r
- String result = "";\r
- \r
- SCLContext sclContext = SCLContext.getCurrent();\r
- Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);\r
- try {\r
- Function1<String,String> pf = new FunctionImpl1<String,String>() {\r
- @Override\r
- public String apply(String key) {\r
- return parameters.getString(key);\r
- }\r
- }; \r
- Object response = (String)fn.apply(pf);\r
- if(response instanceof String) {\r
- result = (String)response;\r
- }\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- } finally {\r
- sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);\r
- }\r
- \r
- return new SuccessResponse(result);\r
- \r
- } catch (Throwable e) {\r
- Logger.defaultLogError(e);\r
- return new org.simantics.document.server.serverResponse.Error(e.getMessage()); \r
- }\r
- \r
- }\r
- \r
- };\r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
- public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- return ServerSCLValueRequest.compileAndEvaluate(graph, context);\r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
- public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);\r
- }\r
-\r
- @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")\r
- public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {\r
- return createComponentNamingStrategy(graph);\r
- }\r
-\r
- public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {\r
- Layer0X L0X = Layer0X.getInstance(graph);\r
- @SuppressWarnings({ "unchecked", "rawtypes" })\r
- final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());\r
- @SuppressWarnings("rawtypes")\r
- Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {\r
- @Override\r
- public Object apply(ReadGraph p0, Resource p1, String p2) {\r
- return apply(p0, p1, p2);\r
- }\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {\r
- return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);\r
- }\r
- };\r
- return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);\r
- }\r
-\r
- public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {\r
- if (variable == null)\r
- return null;\r
-\r
- SimulationResource SIMU = SimulationResource.getInstance(graph);\r
-\r
- Variable var = variable;\r
- Resource represents = var.getRepresents(graph);\r
- Resource activeRun = null;\r
- if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {\r
- activeRun = represents;\r
- }\r
-\r
- IProject project = Simantics.peekProject();\r
- if (activeRun != null && project != null) {\r
- IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
- if (expMan != null)\r
- return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));\r
- }\r
-\r
- return null;\r
- }\r
- \r
- public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {\r
- List<Object> list = new ArrayList<Object>();\r
- if (tuple instanceof Tuple) {\r
- Collections.addAll(list, ((Tuple)tuple).toArray());\r
- } else {\r
- list.add(tuple); \r
- }\r
- context.putRow(key, list);\r
- return context;\r
- }\r
- \r
- public static List<Object> getTuples(CommandContext context, String key) {\r
- List<List<Object>> rows = context.getRows(key);\r
- List<Object> tuples = new ArrayList<Object>();\r
- if (rows != null) {\r
- for (List<Object> row : rows) {\r
- switch (row.size()) {\r
- case 0: tuples.add(Tuple0.INSTANCE); break;\r
- case 1: tuples.add(row.get(1)); break;\r
- case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;\r
- case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;\r
- case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;\r
- case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;\r
- }\r
- }\r
- }\r
- return tuples;\r
- }\r
- \r
- public static String printContext(CommandContext context) {\r
- String str = context.toString();\r
- System.err.println(str);\r
- return str;\r
- }\r
- \r
- @SCLValue(type = "AbstractEventHandler")\r
- public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {\r
-\r
- @Override\r
- public CommandResult handle(CommandContext context) {\r
- return null;\r
- }\r
-\r
- };\r
-\r
- public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
- \r
- String baseURI = base.getURI(graph);\r
- \r
- String selfURI = self.getURI(graph);\r
- \r
- String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));\r
- String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());\r
- String stripped = prefix + suffix;\r
- \r
- String relative = Variables.getRelativeRVI(baseURI, stripped); \r
- \r
- return Variables.getRVI(relative, ref);\r
- \r
- }\r
- \r
- public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {\r
- \r
- String id = sclStateKey(graph, base, self, ref);\r
-\r
- Variable sclVar = base.getPossibleChild(graph, "__scl__");\r
- if(sclVar == null) return null;\r
- \r
- return sclVar.getPossibleProperty(graph, id);\r
- \r
- }\r
- \r
- public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
- \r
- Variable stateVariable = sclStateVariable(graph, base, self, ref);\r
- if (stateVariable != null) {\r
- \r
- return stateVariable.getValue(graph);\r
- \r
- } else {\r
- \r
- String id = sclStateKey(graph, base, self, ref);\r
-\r
- SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");\r
- realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);\r
- \r
- return defaultValue;\r
- \r
- }\r
- }\r
- \r
- public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {\r
- \r
- String id = sclStateKey(graph, base, self, ref);\r
-\r
- SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");\r
- realm.getConnection().setVariable(id, getSCLType(value), value);\r
- realm.refreshVariablesSync();\r
- \r
- }\r
- \r
- public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {\r
- Resource project = Simantics.getProjectResource();\r
- Variable component = self.getParent(graph);\r
- Variable projectVariable = Variables.getVariable(graph, project);\r
- return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);\r
- }\r
- \r
- public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {\r
- Resource project = Simantics.getProjectResource();\r
- Variable component = self.getParent(graph);\r
- Variable projectVariable = Variables.getVariable(graph, project);\r
- setSclStateValue(graph, projectVariable, component, ref, value);\r
- }\r
- \r
- private static Type getSCLType(Object value) throws DatabaseException {\r
- Binding b = Bindings.getBindingUnchecked(value.getClass());\r
- Datatype t = b.type();\r
- if(Datatypes.STRING.equals(t)) return Types.STRING;\r
- if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;\r
- throw new DatabaseException("Type not supported");\r
- }\r
-\r
- public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {\r
- Resource project = Simantics.getProjectResource();\r
- ArrayList<Variable> result = new ArrayList<Variable>();\r
- for(Resource model : graph.syncRequest(new ProjectModels(project))) {\r
- result.add(Variables.getVariable(graph, model));\r
- }\r
- return result;\r
- }\r
-\r
- public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {\r
- return var.getName(graph);\r
- }\r
- \r
- public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {\r
- Variable property = graph.syncRequest(new VariableProperty(variable, name));\r
- return graph.syncRequest(new VariableValue<Object>(property));\r
- }\r
-\r
- public static class ParentExistsRequest extends VariableRead<Boolean> {\r
-\r
- public ParentExistsRequest(Variable parent) {\r
- super(parent);\r
- }\r
-\r
- @Override\r
- public Boolean perform(ReadGraph graph) throws DatabaseException {\r
- \r
- Variable existsProperty = variable.getPossibleProperty(graph, "exists");\r
- if(existsProperty == null) return true;\r
- \r
- Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);\r
- if (exists == null || !exists) return false;\r
-\r
- return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));\r
-\r
- }\r
- \r
- } \r
-\r
- public static class PathExistsRequest extends VariableRead<Boolean> {\r
-\r
- public PathExistsRequest(Variable variable) {\r
- super(variable);\r
- }\r
-\r
- @Override\r
- public Boolean perform(ReadGraph graph) throws DatabaseException {\r
- \r
- Variable widget = variable.getParent(graph);\r
- \r
- Boolean exists = widget.getPossiblePropertyValue(graph, "exists");\r
- if (exists == null || !exists) return false;\r
- \r
- if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;\r
- \r
- DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
- Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);\r
- for (Variable cp : cps) {\r
- \r
- Connection conn = cp.getValue(graph);\r
- Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);\r
- if (otherCp != null) {\r
- Variable parentWidget = otherCp.getParent(graph);\r
- if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
- return true;\r
- }\r
- } else {\r
- Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {\r
- @Override\r
- public Variable perform(ReadGraph graph) throws DatabaseException {\r
- DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
- Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);\r
-\r
- for(VariableConnectionPointDescriptor desc : descs) {\r
- if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {\r
- return desc.getVariable(graph);\r
- }\r
- }\r
- return null;\r
- }\r
- });\r
- if (parentCp != null) {\r
- Variable parentWidget = parentCp.getParent(graph);\r
- if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {\r
- return true;\r
- }\r
- }\r
- }\r
- }\r
- \r
- Resource type = widget.getType(graph);\r
- return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||\r
- (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());\r
- }\r
- } \r
- \r
- @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")\r
- public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
- return graph.syncRequest(new PathExistsRequest(context));\r
- }\r
- \r
+package org.simantics.document.server;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.primitiverequest.Adapter;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.function.All;
+import org.simantics.db.layer0.request.ProjectModels;
+import org.simantics.db.layer0.request.VariableProperty;
+import org.simantics.db.layer0.request.VariableRead;
+import org.simantics.db.layer0.request.VariableValueWithBinding;
+import org.simantics.db.layer0.variable.ConstantPropertyVariable;
+import org.simantics.db.layer0.variable.ProxyChildVariable;
+import org.simantics.db.layer0.variable.ProxySessionRequest;
+import org.simantics.db.layer0.variable.ProxyVariables;
+import org.simantics.db.layer0.variable.StandardGraphChildVariable;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.VariableMap;
+import org.simantics.db.layer0.variable.VariableMapImpl;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.document.base.ontology.DocumentationResource;
+import org.simantics.document.server.bean.Command;
+import org.simantics.document.server.bean.DataDefinition;
+import org.simantics.document.server.handler.AbstractEventHandler;
+import org.simantics.document.server.handler.AbstractResponseHandler;
+import org.simantics.document.server.handler.EventHandler;
+import org.simantics.document.server.io.CommandContext;
+import org.simantics.document.server.io.CommandContextImpl;
+import org.simantics.document.server.io.CommandContextMutable;
+import org.simantics.document.server.io.CommandResult;
+import org.simantics.document.server.io.IConsole;
+import org.simantics.document.server.request.ServerSCLHandlerValueRequest;
+import org.simantics.document.server.request.ServerSCLValueRequest;
+import org.simantics.document.server.serverResponse.ServerResponse;
+import org.simantics.document.server.serverResponse.SuccessResponse;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.scl.SCLRealm;
+import org.simantics.modeling.scl.SCLSessionManager;
+import org.simantics.modeling.services.CaseInsensitiveComponentFunctionNamingStrategy;
+import org.simantics.modeling.services.ComponentNamingStrategy;
+import org.simantics.operation.Layer0X;
+import org.simantics.project.IProject;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.FunctionImpl1;
+import org.simantics.scl.runtime.function.FunctionImpl4;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
+import org.simantics.scl.runtime.tuple.Tuple;
+import org.simantics.scl.runtime.tuple.Tuple0;
+import org.simantics.scl.runtime.tuple.Tuple2;
+import org.simantics.scl.runtime.tuple.Tuple3;
+import org.simantics.scl.runtime.tuple.Tuple4;
+import org.simantics.scl.runtime.tuple.Tuple5;
+import org.simantics.simulation.experiment.IExperiment;
+import org.simantics.simulation.ontology.SimulationResource;
+import org.simantics.simulation.project.IExperimentManager;
+import org.simantics.structural2.variables.Connection;
+import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
+
+import gnu.trove.map.hash.THashMap;
+
+public class Functions {
+
+ @SCLValue(type = "VariableMap")
+ public static VariableMap inputSpaceChildren = new VariableMapImpl() {
+
+ private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
+ Variable root = Variables.getRootVariable(graph);
+ return new DocumentProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
+ }
+
+ @Override
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+
+ if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
+ return All.standardChildDomainChildren.getVariable(graph, context, name);
+
+ }
+
+ @Override
+ public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+ map = All.standardChildDomainChildren.getVariables(graph, context, map);
+ if(map == null) map = new THashMap<String,Variable>();
+ map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
+ return map;
+
+ }
+
+ };
+
+ static class DocumentProxyChildVariable extends ProxyChildVariable {
+
+ public DocumentProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
+ super(base, parent, other, name);
+ }
+
+ @Override
+ public Variable create(Variable base, Variable parent, Variable other, String name) {
+ return new DocumentProxyChildVariable(base, parent, other, name);
+ }
+
+ public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
+
+ if(CONTEXT_END.equals(name)) {
+ if(other instanceof ProxyChildVariable) {
+ // The context is also a proxy - let it do the job
+ return super.getPossibleChild(graph, name);
+ } else {
+ return new RootVariable(this, base.getRepresents(graph));
+ }
+ }
+
+ return super.getPossibleChild(graph, name);
+
+ }
+
+ public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
+
+ Collection<Variable> result = super.getChildren(graph);
+ if(!(base instanceof ProxyChildVariable)) {
+ result.add(new RootVariable(this, base.getRepresents(graph)));
+ }
+ return result;
+
+ }
+
+ }
+
+ static class RootVariable extends StandardGraphChildVariable {
+
+ public RootVariable(DocumentProxyChildVariable parent, Resource resource) {
+ super(parent, null, resource);
+ }
+
+ @Override
+ public String getName(ReadGraph graph) throws DatabaseException {
+ return ProxyChildVariable.CONTEXT_END;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public Variable getNameVariable(ReadGraph graph) throws DatabaseException {
+ return new ConstantPropertyVariable(this, Variables.NAME, ProxyChildVariable.CONTEXT_END, Bindings.STRING);
+ }
+
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable input(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ Variable session = graph.syncRequest(new ProxySessionRequest(context));
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+ String uri = session.getPossiblePropertyValue(graph, DOC.Session_inputURI);
+ if(uri == null) {
+ // TODO HAXX - Please fix this
+ // we have no URI so this probably means that someone has inserted a non-session
+ // into the proxy variable => return that instead
+ return session;
+ }
+ return Variables.getVariable(graph, uri);
+ }
+
+ public static Variable stateVariable(ReadGraph graph, Variable self) throws DatabaseException {
+ Variable session = graph.syncRequest(new ProxySessionRequest(self));
+ if (session == null)
+ throw new DatabaseException("No state for " + self.getURI(graph));
+ return session.getPossibleChild(graph, "__scl__");
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable state(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ Variable session = graph.syncRequest(new ProxySessionRequest(context));
+ if (session == null)
+ throw new DatabaseException("No state for " + context.getURI(graph));
+ return session.getPossibleChild(graph, "__scl__");
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable icstate(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ Variable session = graph.syncRequest(new ProxySessionRequest(context));
+ return session.getPossibleChild(graph, "__icstate__");
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable session(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ return graph.syncRequest(new ProxySessionRequest(context));
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable experiment(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ // Try if experiment (run) has been used as the input
+ Variable var = input(graph, converter, context);
+ SimulationResource SR = SimulationResource.getInstance(graph);
+ while(var != null && !graph.isInstanceOf(var.getRepresents(graph), SR.Run)) {
+ var = var.getParent(graph);
+ }
+
+ if(var != null) {
+ IExperiment exp = getExperiment(graph, var);
+ if(exp == null)
+ return null;
+ }
+
+ return var;
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+ public static Variable model(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ Variable var = input(graph, converter, context);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ while(var != null && !graph.isInstanceOf(var.getRepresents(graph), MOD.StructuralModel)) {
+ var = var.getParent(graph);
+ }
+
+ return var;
+ }
+
+ private static Collection<Variable> getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException {
+
+ ArrayList<Variable> result = new ArrayList<Variable>();
+
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+ Variable broadcasted = target.getPossibleProperty(graph, DOC.Relations_broadcasted);
+ if(broadcasted != null) result.add(broadcasted);
+
+ for(Variable child : DocumentServerUtils.getChildrenInOrdinalOrder(graph, target)) {
+ result.addAll(getBroadcasted(graph, child));
+ }
+
+ return result;
+
+ }
+
+ private static List<Command> getCommands(ReadGraph graph, Collection<Variable> commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException {
+
+ if(commandVariables.isEmpty()) return Collections.emptyList();
+
+ String t = trigger;
+ TreeMap<Integer, List<Command>> sequences = new TreeMap<Integer, List<Command>>();
+
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+ int count = 0;
+ for (Variable c : commandVariables) {
+
+ if(trigger == null)
+ t = c.getName(graph);
+
+ Connection conn = c.getValue(graph);
+ Variable targetConnectionPoint = DocumentServerUtils.getPossibleCommandTriggerConnectionPoint(graph, c, conn);
+ if (targetConnectionPoint != null) {
+ Variable target = targetConnectionPoint.getParent(graph);
+ if (target != null) {
+
+ Boolean enabled = target.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
+ if(enabled != null && !enabled) continue;
+
+ Integer ordinal;
+ if (broadcast) {
+ ordinal = ++count;
+ } else {
+ ordinal = 1;
+ try {
+ String o = c.getPossiblePropertyValue(graph, "ordinal");
+ if(o != null)
+ ordinal = Integer.parseInt(o);
+ } catch (NumberFormatException e) {}
+ }
+
+ String constantKey = target.getPossiblePropertyValue(graph, "constantKey");
+ String constantValue = target.getPossiblePropertyValue(graph, "constantValue");
+
+ CommandContextMutable newConstants = (CommandContextMutable)constants;
+ if(constantKey != null && constantValue != null) {
+ if(!constantKey.isEmpty()) {
+ newConstants = new CommandContextImpl().merge(constants);
+ newConstants.putString(constantKey, constantValue);
+ }
+ }
+
+ String requiredKey = target.getPossiblePropertyValue(graph, "requiredKey");
+ if(requiredKey != null && !requiredKey.isEmpty()) {
+ if (newConstants == constants) {
+ newConstants = new CommandContextImpl().merge(constants);
+ }
+ newConstants.putRow(CommandContext.REQUIRED_KEYS, Collections.<Object>singletonList(requiredKey));
+ }
+
+ String forbiddenKey = target.getPossiblePropertyValue(graph, "forbiddenKey");
+ if(forbiddenKey != null && !forbiddenKey.isEmpty()) {
+ if (newConstants == constants) {
+ newConstants = new CommandContextImpl().merge(constants);
+ }
+ newConstants.putRow(CommandContext.FORBIDDEN_KEYS, Collections.<Object>singletonList(forbiddenKey));
+ }
+
+ if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) {
+
+ // This is a broadcast terminal of a container
+ List<Command> broadcastCommands = getCommands(graph, getBroadcasted(graph, target), t, newConstants, true);
+ sequences.put(ordinal, broadcastCommands);
+
+ } else {
+
+ Command command = new Command(DocumentServerUtils.getId(graph, target), t,
+ targetConnectionPoint.getName(graph), newConstants);
+ sequences.put(ordinal, Collections.singletonList(command));
+
+ }
+
+ }
+ }
+ }
+
+ List<Command> commands = new ArrayList<Command>();
+ for (List<Command> commandList : sequences.values()) {
+ for (Command command : commandList) {
+ commands.add(command);
+ }
+ }
+
+ return commands;
+ }
+
+ /**
+ * Commands
+ *
+ * @param graph
+ * @param variable
+ * @return
+ * @throws DatabaseException
+ */
+ public static List<Command> commandList(ReadGraph graph, Variable variable) throws DatabaseException {
+ return getCommands(graph, DocumentServerUtils.getTriggerCommands(graph, variable.getParent(graph)), null, new CommandContextImpl(), false);
+ }
+
+ /**
+ * Data definitions
+ *
+ * @param graph
+ * @param variable
+ * @return
+ * @throws DatabaseException
+ */
+ public static List<DataDefinition> dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+ ArrayList<DataDefinition> dataDefinitions = new ArrayList<DataDefinition>();
+ // Find data definition connections
+ for (Variable dataDefinitionRelation : DocumentServerUtils.getDataDefinitions(graph, variable.getParent(graph))) {
+ Connection dataDefinitionConnection = dataDefinitionRelation.getValue(graph);
+ // Find data the other end of definition connection
+ Collection<Variable> dataDefinitionProviders = DocumentServerUtils.getPossibleOtherConnectionPoints(graph,
+ dataDefinitionRelation, dataDefinitionConnection);
+ if (dataDefinitionProviders != null) {
+
+ for(Variable dataDefinitionProvider : dataDefinitionProviders) {
+
+ Variable dataDefinition = dataDefinitionProvider.getParent(graph);
+ if (dataDefinition != null) {
+ // Found other end. Is should contain ONE data
+// definition connection to the actual data
+ Collection<Variable> dataCollection = DocumentServerUtils.getDataRelations(graph, dataDefinition);
+ if (dataCollection.size() == 1) {
+ Variable dataRelation = dataCollection.iterator().next();
+ Connection dataConnection = dataRelation.getValue(graph);
+ // Find data the other end of definition connection
+ Variable dataConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph,
+ dataRelation, dataConnection);
+ if (dataConnectionPoint != null) {
+ Variable data = dataConnectionPoint.getParent(graph);
+ Resource type = dataDefinition.getPossibleType(graph, DOC.Components_Component);
+
+ if (graph.isInheritedFrom(type, DOC.Components_DefVar)) {
+
+ String sourceProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_source,
+ Bindings.STRING);
+ String targetProperty = dataDefinition.getPropertyValue(graph, DOC.Properties_target,
+ Bindings.STRING);
+
+ dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
+ sourceProperty, targetProperty));
+
+ } else if (graph.isInheritedFrom(type, DOC.Components_DefVars)) {
+
+ List<String> sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class);
+ List<String> targetsProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_targets), String.class);
+
+ for (int i = 0; i < Math.min(sourcesProperty.size(), targetsProperty.size()); i++) {
+ dataDefinitions.add(new DataDefinition(DocumentServerUtils.getId(graph, data),
+ sourcesProperty.get(i), targetsProperty.get(i)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return dataDefinitions;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> List<T> toList(Object o, Class<T> c) {
+ List<T> result = null;
+ if (o instanceof List) {
+ return (List<T>)o;
+ } else if (o instanceof Object[]) {
+ result = new ArrayList<T>(((Object[])o).length);
+ for (T item : (T[])o) {
+ result.add(item);
+ }
+ return result;
+ } else {
+ return Collections.<T>emptyList();
+ }
+ }
+
+ public static AbstractEventHandler emptyOnClick(ReadGraph graph) throws DatabaseException {
+ return new EventHandler() {
+
+ @Override
+ public ServerResponse handle(ReadGraph graph, CommandContext parameters) throws DatabaseException {
+ return null;
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler writeEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
+
+ final Session session = graph.getSession();
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ String result = session.sync(new WriteResultRequest<String>() {
+
+ @Override
+ public String perform(WriteGraph graph) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Function1<String,String> pf = new FunctionImpl1<String,String>() {
+ @Override
+ public String apply(String key) {
+ return parameters.getString(key);
+ }
+ };
+ Object response = (String)fn.apply(variable, pf);
+ if(response instanceof String) {
+ return (String)response;
+ }
+ return null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return null;
+
+ }
+
+ });
+
+ return new SuccessResponse(result);
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler readEventHandler(ReadGraph graph, final Variable variable, final Function fn) {
+
+ final Session session = graph.getSession();
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ String result = session.sync(new UniqueRead<String>() {
+
+ @Override
+ public String perform(ReadGraph graph) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Function1<String,String> pf = new FunctionImpl1<String,String>() {
+ @Override
+ public String apply(String key) {
+ return parameters.getString(key);
+ }
+ };
+ Object response = (String)fn.apply(variable, pf);
+ if(response instanceof String) {
+ return (String)response;
+ }
+ return null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return null;
+
+ }
+
+ });
+
+ return new SuccessResponse(result);
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler readEventHandler2(ReadGraph graph, final Function fn) {
+
+ final Session session = graph.getSession();
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ CommandResult result = session.sync(new UniqueRead<CommandResult>() {
+
+ @Override
+ public CommandResult perform(ReadGraph graph) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Object response = fn.apply(parameters);
+ if(response instanceof CommandResult) {
+ return (CommandResult)response;
+ }
+ return null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return null;
+
+ }
+
+ });
+
+ return result;
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler responseHandler(ReadGraph graph, Variable self, String function) throws DatabaseException {
+
+ Variable anyFunction = self.browse(graph, ".#" + function);
+ if(anyFunction == null) return null;
+
+ final List<TCon> effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction);
+
+ final Function1<CommandContext, CommandResult> fn = anyFunction.getValue(graph);
+ String expression = anyFunction.getPropertyValue(graph, "expression");
+
+ final Session session = graph.getSession();
+
+ return new AbstractResponseHandler(expression) {
+
+ private String formatError(RequestProcessor proc, Throwable t) {
+
+ try {
+
+ return proc.syncRequest(new UniqueRead<String>() {
+
+ @Override
+ public String perform(ReadGraph graph) throws DatabaseException {
+ Variable proxy = ProxyVariables.proxyVariableRoot(graph, anyFunction);
+ String uri2 = proxy.getURI(graph);
+ String uri = self.getParent(graph).getURI(graph);
+
+ String path = uri.substring(uri2.length());
+
+ String expr = anyFunction.getPossiblePropertyValue(graph, "expression");
+ StringBuilder message = new StringBuilder();
+ message.append("Handler execution failed\n");
+ message.append(" handler=" + path + "\n");
+ message.append(" expression=" + expr + "\n");
+ message.append(" message=" + t.getMessage() + "\n");
+
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ message.append(" stack trace=" + sw);
+
+ return message.toString();
+ }
+
+ });
+
+ } catch (DatabaseException e) {
+
+ return e.getMessage();
+
+ }
+
+ }
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ IConsole console = parameters.getValue("__console__");
+ SCLReportingHandler printer = (console != null) ? new ConsoleSCLReportingHandler(console)
+ : (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ Object result = null;
+ if(effects.contains(Types.WRITE_GRAPH)) {
+
+ result = session.syncRequest(new WriteResultRequest<Object>() {
+
+ @Override
+ public Object perform(WriteGraph graph)
+ throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Object response = fn.apply(parameters);
+ return response;
+ } catch (Throwable t) {
+ return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ }
+ });
+
+ } else if(effects.contains(Types.READ_GRAPH)) {
+
+ result = session.sync(new UniqueRead<Object>() {
+
+ @Override
+ public Object perform(ReadGraph graph) throws DatabaseException {
+
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+
+ try {
+ Object response = fn.apply(parameters);
+ return response;
+ } catch (Throwable t) {
+ return new org.simantics.document.server.serverResponse.Error(formatError(graph, t));
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ }
+ });
+
+ } else {
+
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ result = fn.apply(parameters);
+ } finally {
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ }
+
+ if (result instanceof org.simantics.document.server.serverResponse.Error) {
+ return (CommandResult)result;
+ }
+
+ if (result instanceof CommandResult) {
+ return (CommandResult)result;
+ } else {
+ CommandContextMutable assignments = new CommandContextImpl();
+ assignments.putValue("result", result);
+ return new ServerResponse(200, "", assignments);
+ }
+
+ } catch (Throwable e) {
+ return new org.simantics.document.server.serverResponse.Error(formatError(Simantics.getSession(), e));
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler writeEventHandler2(ReadGraph graph, final Function fn) {
+
+ final Session session = graph.getSession();
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ CommandResult result = session.syncRequest(new WriteResultRequest<CommandResult>() {
+
+ @Override
+ public CommandResult perform(WriteGraph graph) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Object response = fn.apply(parameters);
+ if(response instanceof CommandResult) {
+ return (CommandResult)response;
+ }
+ return null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put("graph", oldGraph);
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return null;
+
+ }
+
+ });
+
+ return result;
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler eventHandler2(ReadGraph graph, final Function fn) {
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Object response = fn.apply(parameters);
+ if(response instanceof CommandResult) {
+ return (CommandResult)response;
+ }
+ return null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return null;
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ public static AbstractEventHandler eventHandler(ReadGraph graph, final Function fn) {
+
+ return new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(final CommandContext parameters) {
+
+ final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+
+ try {
+
+ String result = "";
+
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldPrinter = sclContext.put(SCLReportingHandler.REPORTING_HANDLER, printer);
+ try {
+ Function1<String,String> pf = new FunctionImpl1<String,String>() {
+ @Override
+ public String apply(String key) {
+ return parameters.getString(key);
+ }
+ };
+ Object response = (String)fn.apply(pf);
+ if(response instanceof String) {
+ result = (String)response;
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ sclContext.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
+ }
+
+ return new SuccessResponse(result);
+
+ } catch (Throwable e) {
+ Logger.defaultLogError(e);
+ return new org.simantics.document.server.serverResponse.Error(e.getMessage());
+ }
+
+ }
+
+ };
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+ public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ return ServerSCLValueRequest.compileAndEvaluate(graph, context);
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+ public static Object sclHandlerValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ return ServerSCLHandlerValueRequest.compileAndEvaluate(graph, context);
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Resource -> ComponentNamingStrategy")
+ public static ComponentNamingStrategy componentNamingStrategy(ReadGraph graph, Resource converter, Resource context) throws DatabaseException {
+ return createComponentNamingStrategy(graph);
+ }
+
+ public static CaseInsensitiveComponentFunctionNamingStrategy createComponentNamingStrategy(ReadGraph graph) throws DatabaseException {
+ Layer0X L0X = Layer0X.getInstance(graph);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final Function dependencies = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
+ @SuppressWarnings("rawtypes")
+ Function moduleNameFunction = new FunctionImpl4<ReadGraph, Resource, String, Integer, List<Map<String, Object>>>() {
+ @Override
+ public Object apply(ReadGraph p0, Resource p1, String p2) {
+ return apply(p0, p1, p2);
+ }
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Map<String, Object>> apply(ReadGraph graph, Resource model, String search, Integer maxResults) {
+ return (List<Map<String, Object>>)dependencies.apply(graph, model, search, maxResults);
+ }
+ };
+ return new CaseInsensitiveComponentFunctionNamingStrategy("%s%02d", moduleNameFunction);
+ }
+
+ public static IExperiment getExperiment(ReadGraph graph, Variable variable) throws DatabaseException {
+ if (variable == null)
+ return null;
+
+ SimulationResource SIMU = SimulationResource.getInstance(graph);
+
+ Variable var = variable;
+ Resource represents = var.getRepresents(graph);
+ Resource activeRun = null;
+ if (represents != null && graph.isInstanceOf(represents, SIMU.Run)) {
+ activeRun = represents;
+ }
+
+ IProject project = Simantics.peekProject();
+ if (activeRun != null && project != null) {
+ IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
+ if (expMan != null)
+ return expMan.getExperiment(NameUtils.getSafeName(graph, activeRun));
+ }
+
+ return null;
+ }
+
+ public static CommandContextMutable putTuple(CommandContextMutable context, String key, Object tuple) {
+ List<Object> list = new ArrayList<Object>();
+ if (tuple instanceof Tuple) {
+ Collections.addAll(list, ((Tuple)tuple).toArray());
+ } else {
+ list.add(tuple);
+ }
+ context.putRow(key, list);
+ return context;
+ }
+
+ public static List<Object> getTuples(CommandContext context, String key) {
+ List<List<Object>> rows = context.getRows(key);
+ List<Object> tuples = new ArrayList<Object>();
+ if (rows != null) {
+ for (List<Object> row : rows) {
+ switch (row.size()) {
+ case 0: tuples.add(Tuple0.INSTANCE); break;
+ case 1: tuples.add(row.get(1)); break;
+ case 2: tuples.add(new Tuple2(row.get(0), row.get(1))); break;
+ case 3: tuples.add(new Tuple3(row.get(0), row.get(1), row.get(2))); break;
+ case 4: tuples.add(new Tuple4(row.get(0), row.get(1), row.get(2), row.get(3))); break;
+ case 5: tuples.add(new Tuple5(row.get(0), row.get(1), row.get(2), row.get(3), row.get(4))); break;
+ }
+ }
+ }
+ return tuples;
+ }
+
+ public static String printContext(CommandContext context) {
+ return context.toString();
+ }
+
+ @SCLValue(type = "AbstractEventHandler")
+ public static AbstractEventHandler emptyEvent = new AbstractEventHandler() {
+
+ @Override
+ public CommandResult handle(CommandContext context) {
+ return null;
+ }
+
+ };
+
+ public static String sclStateKey(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
+
+ String baseURI = base.getURI(graph);
+
+ String selfURI = self.getURI(graph);
+
+ String prefix = selfURI.substring(0, selfURI.indexOf(ProxyChildVariable.CONTEXT_BEGIN));
+ String suffix = selfURI.substring(selfURI.lastIndexOf(ProxyChildVariable.CONTEXT_END) + ProxyChildVariable.CONTEXT_END.length());
+ String stripped = prefix + suffix;
+
+ String relative = Variables.getRelativeRVI(baseURI, stripped);
+
+ return Variables.getRVI(relative, ref);
+
+ }
+
+ public static Variable sclStateVariable(ReadGraph graph, Variable base, Variable self, String ref) throws DatabaseException {
+
+ String id = sclStateKey(graph, base, self, ref);
+
+ Variable sclVar = base.getPossibleChild(graph, "__scl__");
+ if(sclVar == null) return null;
+
+ return sclVar.getPossibleProperty(graph, id);
+
+ }
+
+ public static Object sclStateValueOrDefault(ReadGraph graph, Variable base, Variable self, String ref, Object defaultValue) throws DatabaseException {
+
+ Variable stateVariable = sclStateVariable(graph, base, self, ref);
+ if (stateVariable != null) {
+
+ return stateVariable.getValue(graph);
+
+ } else {
+
+ String id = sclStateKey(graph, base, self, ref);
+
+ SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph) + "/__scl__");
+ realm.getConnection().setVariable(id, getSCLType(defaultValue), defaultValue);
+
+ return defaultValue;
+
+ }
+ }
+
+ public static void setSclStateValue(WriteGraph graph, Variable base, Variable self, String ref, Object value) throws DatabaseException {
+
+ String id = sclStateKey(graph, base, self, ref);
+
+ SCLRealm realm = SCLSessionManager.getOrCreateSCLRealm(base.getURI(graph)+"/__scl__");
+ realm.getConnection().setVariable(id, getSCLType(value), value);
+ realm.refreshVariablesSync();
+
+ }
+
+ public static Object projectComponentState(ReadGraph graph, Variable self, String ref, Object defaultValue) throws DatabaseException {
+ Resource project = Simantics.getProjectResource();
+ Variable component = self.getParent(graph);
+ Variable projectVariable = Variables.getVariable(graph, project);
+ return sclStateValueOrDefault(graph, projectVariable, component, ref, defaultValue);
+ }
+
+ public static void setProjectComponentState(WriteGraph graph, Variable self, String ref, Object value) throws DatabaseException {
+ Resource project = Simantics.getProjectResource();
+ Variable component = self.getParent(graph);
+ Variable projectVariable = Variables.getVariable(graph, project);
+ setSclStateValue(graph, projectVariable, component, ref, value);
+ }
+
+ private static Type getSCLType(Object value) throws DatabaseException {
+ Binding b = Bindings.getBindingUnchecked(value.getClass());
+ Datatype t = b.type();
+ if(Datatypes.STRING.equals(t)) return Types.STRING;
+ if(Datatypes.DOUBLE.equals(t)) return Types.DOUBLE;
+ throw new DatabaseException("Type not supported");
+ }
+
+ public static List<Variable> documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException {
+ Resource project = Simantics.getProjectResource();
+ ArrayList<Variable> result = new ArrayList<Variable>();
+ for(Resource model : graph.syncRequest(new ProjectModels(project))) {
+ result.add(Variables.getVariable(graph, model));
+ }
+ return result;
+ }
+
+ public static String documentModelContributionLabel(ReadGraph graph, Variable var) throws DatabaseException {
+ return var.getName(graph);
+ }
+
+ public static Object getPropertyValueCached(ReadGraph graph, Variable variable, String name, Binding binding) throws DatabaseException {
+ Variable property = graph.syncRequest(new VariableProperty(variable, name));
+ return graph.syncRequest(new VariableValueWithBinding<Object>(property, binding));
+ }
+
+ public static class ParentExistsRequest extends VariableRead<Boolean> {
+
+ public ParentExistsRequest(Variable parent) {
+ super(parent);
+ }
+
+ @Override
+ public Boolean perform(ReadGraph graph) throws DatabaseException {
+
+ Variable existsProperty = variable.getPossibleProperty(graph, "exists");
+ if(existsProperty == null) return true;
+
+ Boolean exists = existsProperty.getPossibleValue(graph, Bindings.BOOLEAN);
+ if (exists == null || !exists) return false;
+
+ return graph.syncRequest(new ParentExistsRequest(variable.getParent(graph)));
+
+ }
+
+ }
+
+ public static class PathExistsRequest extends VariableRead<Boolean> {
+
+ public PathExistsRequest(Variable variable) {
+ super(variable);
+ }
+
+ @Override
+ public Boolean perform(ReadGraph graph) throws DatabaseException {
+
+ Variable widget = variable.getParent(graph);
+
+ Boolean exists = widget.getPossiblePropertyValue(graph, "exists");
+ if (exists == null || !exists) return false;
+
+ if (!graph.syncRequest(new ParentExistsRequest(widget.getParent(graph)))) return false;
+
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+ Collection <Variable> cps = widget.getProperties(graph, DOC.Relations_parentRelation);
+ for (Variable cp : cps) {
+
+ Connection conn = cp.getValue(graph);
+ Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, cp, conn);
+ if (otherCp != null) {
+ Variable parentWidget = otherCp.getParent(graph);
+ if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
+ return true;
+ }
+ } else {
+ Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
+ @Override
+ public Variable perform(ReadGraph graph) throws DatabaseException {
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+ Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
+
+ for(VariableConnectionPointDescriptor desc : descs) {
+ if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
+ return desc.getVariable(graph);
+ }
+ }
+ return null;
+ }
+ });
+ if (parentCp != null) {
+ Variable parentWidget = parentCp.getParent(graph);
+ if (parentWidget.<Boolean>getPropertyValue(graph, "pathExists")) {
+ return true;
+ }
+ }
+ }
+ }
+
+ Resource type = widget.getType(graph);
+ return graph.isInheritedFrom(type, DOC.Components_ParentlessComponent) ||
+ (graph.isInheritedFrom(type, DOC.DocumentComponent) && cps.isEmpty());
+ }
+ }
+
+ @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
+ public static boolean pathExists(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+ return graph.syncRequest(new PathExistsRequest(context));
+ }
+
+ static class ConsoleSCLReportingHandler implements SCLReportingHandler {
+
+ private final IConsole console;
+
+ ConsoleSCLReportingHandler(IConsole console) {
+ this.console = console;
+ }
+
+ @Override
+ public void print(String text) {
+ console.addMessage(text);
+ }
+
+ @Override
+ public void printError(String error) {
+ console.addMessage(error);
+ }
+
+ @Override
+ public void printCommand(String command) {
+ console.addMessage(command);
+ }
+
+ @Override
+ public void didWork(double amount) {
+ console.addMessage("didWork " + amount);
+ }
+
+ }
+
+