X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2FFunctions.java;h=a6e9d6ab6818eba35ff09cd6ea5d0549bde1f0aa;hp=2fd422f5eb5447df01bbe491fd5349e5b861f0c8;hb=8959bb33806d2252cdf09e42386afd242919630a;hpb=75785e1454fbc60973848c72e2ed698d2cda5ce7 diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java index 2fd422f5e..a6e9d6ab6 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java @@ -1,1153 +1,1336 @@ -package org.simantics.document.server; - -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.VariableValue; -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.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 getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - - map = All.standardChildDomainChildren.getVariables(graph, context, map); - if(map == null) map = new THashMap(); - 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 getChildren(ReadGraph graph) throws DatabaseException { - - Collection 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); - } - - @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 getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException { - - ArrayList result = new ArrayList(); - - 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 getCommands(ReadGraph graph, Collection commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException { - - if(commandVariables.isEmpty()) return Collections.emptyList(); - - String t = trigger; - TreeMap> sequences = new TreeMap>(); - - 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.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.singletonList(forbiddenKey)); - } - - if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) { - - // This is a broadcast terminal of a container - List 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 commands = new ArrayList(); - for (List commandList : sequences.values()) { - for (Command command : commandList) { - commands.add(command); - } - } - - return commands; - } - - /** - * Commands - * - * @param graph - * @param variable - * @return - * @throws DatabaseException - */ - public static List 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 dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException { - DocumentationResource DOC = DocumentationResource.getInstance(graph); - ArrayList dataDefinitions = new ArrayList(); - // 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 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 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 sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class); - List 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 List toList(Object o, Class c) { - List result = null; - if (o instanceof List) { - return (List)o; - } else if (o instanceof Object[]) { - result = new ArrayList(((Object[])o).length); - for (T item : (T[])o) { - result.add(item); - } - return result; - } else { - return Collections.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() { - - @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 pf = new FunctionImpl1() { - @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() { - - @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 pf = new FunctionImpl1() { - @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() { - - @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 effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction); - - final Function1 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() { - - @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"); - return message.toString(); - } - - }); - - } catch (DatabaseException e) { - - return e.getMessage(); - - } - - } - - @Override - public CommandResult handle(final CommandContext parameters) { - - final SCLReportingHandler printer = (SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER); - - try { - - Object result = null; - if(effects.contains(Types.WRITE_GRAPH)) { - - result = session.syncRequest(new WriteResultRequest() { - - @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() { - - @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 { - result = fn.apply(parameters); - } - - 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() { - - @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 pf = new FunctionImpl1() { - @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.instance()); - @SuppressWarnings("rawtypes") - Function moduleNameFunction = new FunctionImpl4>>() { - @Override - public Object apply(ReadGraph p0, Resource p1, String p2) { - return apply(p0, p1, p2); - } - @SuppressWarnings("unchecked") - @Override - public List> apply(ReadGraph graph, Resource model, String search, Integer maxResults) { - return (List>)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 list = new ArrayList(); - if (tuple instanceof Tuple) { - Collections.addAll(list, ((Tuple)tuple).toArray()); - } else { - list.add(tuple); - } - context.putRow(key, list); - return context; - } - - public static List getTuples(CommandContext context, String key) { - List> rows = context.getRows(key); - List tuples = new ArrayList(); - if (rows != null) { - for (List 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) { - String str = context.toString(); - System.err.println(str); - return str; - } - - @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 documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException { - Resource project = Simantics.getProjectResource(); - ArrayList result = new ArrayList(); - 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 VariableValue(property)); - } - - public static class ParentExistsRequest extends VariableRead { - - 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 { - - 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 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.getPropertyValue(graph, "pathExists")) { - return true; - } - } else { - Variable parentCp = graph.sync(new UnaryRead(conn) { - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - DocumentationResource DOC = DocumentationResource.getInstance(graph); - Collection 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.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)); - } - +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.HashMap; +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.AsyncReadGraph; +import org.simantics.db.DirectStatements; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.Statement; +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.PropertyInfo; +import org.simantics.db.layer0.request.PropertyInfoRequest; +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.scl.SCLDatabaseException; +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.StandardAssertedGraphPropertyVariable; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; +import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; +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.db.procedure.AsyncProcedure; +import org.simantics.db.service.DirectQuerySupport; +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.NodeRequest; +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.module.repository.ImportFailureException; +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.StandardProceduralChildVariable; +import org.simantics.structural2.variables.VariableConnectionPointDescriptor; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.THashMap; + +public class Functions { + + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Functions.class); + + private static class PrimitivePropertyStatementsProcedure implements AsyncProcedure { + + public DirectStatements result; + + @Override + public void execute(AsyncReadGraph graph, DirectStatements result) { + this.result = result; + } + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + } + + } + + @SCLValue(type = "VariableMap") + public static VariableMap primitiveProperties = new VariableMapImpl() { + private void storePropertyValueAndExceptions(ReadGraph graph, Variable parent, String name, Variable property, Map map) { + try { + Object value = property.getValue(graph); + map.put(name, new ConstantPropertyVariable(parent, name, value, null)); + } catch (DatabaseException e) { + Variable propertyExceptions = map.get(NodeRequest.PROPERTY_VALUE_EXCEPTIONS); + Map exceptionMap; + if (propertyExceptions == null) { + exceptionMap = new TreeMap(); + propertyExceptions = new ConstantPropertyVariable(parent, NodeRequest.PROPERTY_VALUE_EXCEPTIONS, exceptionMap, null); + map.put(NodeRequest.PROPERTY_VALUE_EXCEPTIONS, propertyExceptions); + } else { + try { + exceptionMap = propertyExceptions.getValue(graph); + } catch (DatabaseException e1) { + Logger.defaultLogError(e1); + return; + } + } + String label = name; + try { + label = property.getLabel(graph); + } catch (DatabaseException e2) { + + } + exceptionMap.put(label, e); + } + } + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + return All.getStandardPropertyDomainPropertyVariableFromValue(graph, context, name); + } + + @Override + public Map getVariables(final ReadGraph graph, Variable context, Map map) throws DatabaseException { + + if(map == null) map = new HashMap(); + + Variable parent = context.getParent(graph); + + DocumentationResource DOC = DocumentationResource.getInstance(graph); + + if(parent instanceof StandardProceduralChildVariable) { + + StandardProceduralChildVariable procedural = (StandardProceduralChildVariable)parent; + for(Variable property : procedural.getProperties(graph/*, DocumentationResource.URIs.Document_AttributeRelation*/)) { + if(property instanceof StandardAssertedGraphPropertyVariable) { + StandardAssertedGraphPropertyVariable ass = (StandardAssertedGraphPropertyVariable)property; + if("dataDefinitions".equals(ass.property.name) || "commands".equals(ass.property.name) || "pollingFunction".equals(ass.property.name)) { + storePropertyValueAndExceptions(graph, parent, ass.property.name, property, map); + } + continue; + } + Resource predicate = property.getPossiblePredicateResource(graph); + if(predicate != null) { + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate)); + if(info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) { + Variable prop = parent.getProperty(graph, predicate); + storePropertyValueAndExceptions(graph, parent, info.name, prop, map); + } + } + } + + } else { + + Resource parentRes = parent.getRepresents(graph); + { + Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_commands); + storePropertyValueAndExceptions(graph, parent, "commands", prop, map); + } + + if (graph.getPossibleObject(parentRes, DOC.Properties_dataDefinitions) != null) { + Variable prop = new StandardGraphPropertyVariable(graph, parent, DOC.Properties_dataDefinitions); + storePropertyValueAndExceptions(graph, parent, "dataDefinitions", prop, map); + } + + DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class); + PrimitivePropertyStatementsProcedure foo = new PrimitivePropertyStatementsProcedure(); + + dqs.forEachDirectPersistentStatement(graph, parentRes, foo); + + for(Statement stm : foo.result) { + Resource predicate = stm.getPredicate(); + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate)); + + if(info.isHasProperty && info.hasClassification(DocumentationResource.URIs.Document_AttributeRelation)) { + Variable prop = new StandardGraphPropertyVariable(graph, parent, predicate); + storePropertyValueAndExceptions(graph, parent, info.name, prop, map); + } else { + Resource definition = graph.getPossibleObject(predicate, DOC.Document_definesAttributeRelation); + if(definition != null) { + PropertyInfo info2 = graph.syncRequest(new PropertyInfoRequest(definition)); + Variable prop = new StandardGraphPropertyVariable(graph, parent, definition); + map.put(info2.name, new PrimitiveValueVariable(parent, info2.name, prop)); + } + } + } + } + return map; + + } + + }; + + @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 getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + + map = All.standardChildDomainChildren.getVariables(graph, context, map); + if(map == null) map = new THashMap(); + 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 getChildren(ReadGraph graph) throws DatabaseException { + + Collection 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 getBroadcasted(ReadGraph graph, Variable target) throws DatabaseException { + + ArrayList result = new ArrayList(); + + 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 getCommands(ReadGraph graph, Collection commandVariables, String trigger, CommandContext constants, boolean broadcast) throws DatabaseException { + + if(commandVariables.isEmpty()) return Collections.emptyList(); + + String t = trigger; + TreeMap> sequences = new TreeMap>(); + + 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.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.singletonList(forbiddenKey)); + } + + if(DOC.Relations_broadcast.equals(targetConnectionPoint.getPredicateResource(graph))) { + + // This is a broadcast terminal of a container + List 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 commands = new ArrayList(); + for (List commandList : sequences.values()) { + for (Command command : commandList) { + commands.add(command); + } + } + + return commands; + } + + /** + * Commands + * + * @param graph + * @param variable + * @return + * @throws DatabaseException + */ + public static List 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 dataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException { + DocumentationResource DOC = DocumentationResource.getInstance(graph); + ArrayList dataDefinitions = new ArrayList(); + // 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 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 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 sourcesProperty = toList(dataDefinition.getPropertyValue(graph, DOC.Properties_sources), String.class); + List 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 List toList(Object o, Class c) { + List result = null; + if (o instanceof List) { + return (List)o; + } else if (o instanceof Object[]) { + result = new ArrayList(((Object[])o).length); + for (T item : (T[])o) { + result.add(item); + } + return result; + } else { + return Collections.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() { + + @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 pf = new FunctionImpl1() { + @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() { + + @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 pf = new FunctionImpl1() { + @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() { + + @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 effects = ServerSCLHandlerValueRequest.getEffects(graph, anyFunction); + + final Function1 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() { + + @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() { + + @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() { + + @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() { + + @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 pf = new FunctionImpl1() { + @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.instance()); + @SuppressWarnings("rawtypes") + Function moduleNameFunction = new FunctionImpl4>>() { + @Override + public Object apply(ReadGraph p0, Resource p1, String p2) { + return apply(p0, p1, p2); + } + @SuppressWarnings("unchecked") + @Override + public List> apply(ReadGraph graph, Resource model, String search, Integer maxResults) { + return (List>)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 list = new ArrayList(); + if (tuple instanceof Tuple) { + Collections.addAll(list, ((Tuple)tuple).toArray()); + } else { + list.add(tuple); + } + context.putRow(key, list); + return context; + } + + public static List getTuples(CommandContext context, String key) { + List> rows = context.getRows(key); + List tuples = new ArrayList(); + if (rows != null) { + for (List 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 documentModelContribution(ReadGraph graph, Resource doc) throws DatabaseException { + Resource project = Simantics.getProjectResource(); + ArrayList result = new ArrayList(); + 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(property, binding)); + } + + public static class ParentExistsRequest extends VariableRead { + + 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 { + + 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 cps = widget.getProperties(graph, DocumentationResource.URIs.Relations_parentRelation); + for (Variable cp : cps) { + + Connection conn = cp.getValue(graph); + Variable otherCp = DocumentServerUtils.getPossibleChildConnectionPoint(graph, cp, conn); + if (otherCp != null) { + Variable parentWidget = otherCp.getParent(graph); + if (parentWidget.getPropertyValue(graph, "pathExists")) { + return true; + } + } else { + Variable parentCp = graph.sync(new UnaryRead(conn) { + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + DocumentationResource DOC = DocumentationResource.getInstance(graph); + Collection 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.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)); + } + + public static String compileDocumentSCLValueExpression(ReadGraph graph, Variable context) { + try { + ServerSCLValueRequest.compile(graph, context); + return ""; + } catch (Exception e) { + return resolveIssueMessage(e); + } + } + + private static String resolveIssueMessage(Exception e) { + if (e instanceof ImportFailureException) + return ""; + if (e.getCause() != null && e.getCause() instanceof ImportFailureException) + return ""; + if (e instanceof SCLDatabaseException) { + SCLDatabaseException ee = (SCLDatabaseException) e; + return ee.getMessage(); + } + if (LOGGER.isDebugEnabled()) + LOGGER.debug("", e); + return e.getMessage(); + } + } \ No newline at end of file