1 package org.simantics.scl.commands.internal;
3 import org.simantics.db.ReadGraph;
4 import org.simantics.db.RequestProcessor;
5 import org.simantics.db.Resource;
6 import org.simantics.db.WriteGraph;
7 import org.simantics.db.common.request.WriteResultRequest;
8 import org.simantics.db.exception.DatabaseException;
9 import org.simantics.db.procedure.Procedure;
10 import org.simantics.db.request.Read;
11 import org.simantics.scl.commands.Command;
12 import org.simantics.scl.commands.internal.checker.Checker;
13 import org.simantics.scl.commands.internal.serialization.CommandSerializer;
14 import org.simantics.scl.commands.internal.serialization.CommandSerializerFactory;
15 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
16 import org.simantics.scl.compiler.top.ValueNotFound;
17 import org.simantics.scl.compiler.types.Type;
18 import org.simantics.scl.compiler.types.Types;
19 import org.simantics.scl.compiler.types.util.MultiFunction;
20 import org.simantics.scl.osgi.SCLOsgi;
21 import org.simantics.scl.runtime.SCLContext;
22 import org.simantics.scl.runtime.function.Function;
23 import org.simantics.utils.logging.TimeLogger;
26 * Default command implementation
28 * @author Hannu Niemistö
30 @SuppressWarnings({"rawtypes", "restriction"})
31 public class CommandImpl implements Command {
35 Type[] parameterTypes;
36 CommandSerializer serializer;
39 public CommandImpl(String name, Function command, Type[] parameterTypes,
40 CommandSerializer serializer, Checker checker) {
42 this.command = command;
43 this.parameterTypes = parameterTypes;
44 this.serializer = serializer;
45 this.checker = checker;
48 private class CheckRequest implements Read<Boolean> {
51 public CheckRequest(Object[] parameters) {
52 this.parameters = parameters;
56 public Boolean perform(ReadGraph graph) throws DatabaseException {
57 SCLContext sclContext = SCLContext.getCurrent();
58 Object oldGraph = sclContext.put("graph", graph);
59 boolean result = checker.check(parameters);
60 sclContext.put("graph", oldGraph);
66 public boolean check(RequestProcessor processor, Resource model,
67 Object... parameters) throws DatabaseException {
68 CheckRequest request = new CheckRequest(parameters);
69 if(processor instanceof ReadGraph)
70 return request.perform((ReadGraph)processor);
72 return processor.syncRequest(request);
75 private static boolean serializationErrorAlreadySeen = false;
77 private class CommitRequest extends WriteResultRequest<Object> {
81 public CommitRequest(Resource model, Object[] parameters) {
83 this.parameters = parameters;
87 public Object perform(WriteGraph graph) throws DatabaseException {
88 SCLContext sclContext = SCLContext.getCurrent();
89 Object oldGraph = sclContext.put("graph", graph);
90 // Serialize command first
92 serializer.serialize(graph, model, parameters);
93 } catch(Exception e) {
94 if(!serializationErrorAlreadySeen) {
96 serializationErrorAlreadySeen = true;
100 // Then execute (otherwise target of the command might not exist anymore)
102 return command.applyArray(parameters);
104 sclContext.put("graph", oldGraph);
111 public Object execute(RequestProcessor processor, Resource model, Object ... parameters) throws DatabaseException {
112 if(parameters.length != parameterTypes.length)
113 throw new IllegalArgumentException("Wrong number of parameters given (" + parameters.length + ") expected " +
114 parameterTypes.length + " parameters.");
115 CommitRequest request = new CommitRequest(model, parameters);
117 if(processor instanceof WriteGraph)
118 return request.perform((WriteGraph)processor);
120 return processor.syncRequest(request);
122 TimeLogger.log("Executed command " + name);
127 public void asyncExecute(RequestProcessor processor, Resource model,
128 Object[] parameters, Procedure<Object> procedure) {
129 processor.asyncRequest(new CommitRequest(model, parameters), procedure);
132 public static Command create(ReadGraph graph, String name) {
133 Object oldGraph = SCLContext.getCurrent().put("graph", graph);
135 SCLValue commandRef = SCLOsgi.MODULE_REPOSITORY.getValueRef(name);
136 MultiFunction mfun = Types.matchFunction(commandRef.getType());
137 Type[] parameterTypes = mfun.parameterTypes;
138 Function command = (Function)SCLOsgi.MODULE_REPOSITORY.getValue(name);
139 CommandSerializer serializer = CommandSerializerFactory.create(name, parameterTypes);
140 Checker checker = Checker.create(name + "_check");
141 return new CommandImpl(name, command, parameterTypes, serializer, checker);
142 } catch(ValueNotFound e) {
144 return new ErrorCommand(name);
146 SCLContext.getCurrent().put("graph", oldGraph);