]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.commands/src/org/simantics/scl/commands/internal/CommandImpl.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.scl.commands / src / org / simantics / scl / commands / internal / CommandImpl.java
1 package org.simantics.scl.commands.internal;
2
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;
24
25 /**
26  * Default command implementation
27  * 
28  * @author Hannu Niemistö
29  */
30 @SuppressWarnings({"rawtypes", "restriction"})
31 public class CommandImpl implements Command {
32
33     String name;
34     Function command;
35     Type[] parameterTypes;
36     CommandSerializer serializer; 
37     Checker checker;
38     
39     public CommandImpl(String name, Function command, Type[] parameterTypes,
40             CommandSerializer serializer, Checker checker) {
41         this.name = name;
42         this.command = command;
43         this.parameterTypes = parameterTypes;
44         this.serializer = serializer;
45         this.checker = checker;
46     }
47     
48     private class CheckRequest implements Read<Boolean> {
49         Object[] parameters;
50         
51         public CheckRequest(Object[] parameters) {
52             this.parameters = parameters;
53         }
54
55         @Override
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);
61             return result;
62         }
63     }
64     
65     @Override
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);
71         else
72             return processor.syncRequest(request);
73     }
74
75     private static boolean serializationErrorAlreadySeen = false;
76     
77     private class CommitRequest extends WriteResultRequest<Object> {
78         Resource model;
79         Object[] parameters;
80         
81         public CommitRequest(Resource model, Object[] parameters) {
82             this.model = model;
83             this.parameters = parameters;
84         }
85
86         @Override
87         public Object perform(WriteGraph graph) throws DatabaseException {
88             SCLContext sclContext = SCLContext.getCurrent();
89             Object oldGraph = sclContext.put("graph", graph);
90             // Serialize command first
91             try {
92                 serializer.serialize(graph, model, parameters);
93             } catch(Exception e) {
94                 if(!serializationErrorAlreadySeen) {
95                     e.printStackTrace();
96                     serializationErrorAlreadySeen = true;
97                 }
98             } 
99             
100             // Then execute (otherwise target of the command might not exist anymore)
101             try {
102                 return command.applyArray(parameters);
103             } finally {
104                 sclContext.put("graph", oldGraph);
105             }
106         }
107         
108     }
109     
110     @Override
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);
116         try {
117             if(processor instanceof WriteGraph)
118                 return request.perform((WriteGraph)processor);
119             else
120                 return processor.syncRequest(request);
121         } finally {
122             TimeLogger.log("Executed command " + name);
123         }
124     }
125
126     @Override
127     public void asyncExecute(RequestProcessor processor, Resource model,
128             Object[] parameters, Procedure<Object> procedure) {
129         processor.asyncRequest(new CommitRequest(model, parameters), procedure);
130     }
131
132     public static Command create(ReadGraph graph, String name) {
133         Object oldGraph = SCLContext.getCurrent().put("graph", graph);
134         try {
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) {
143             e.printStackTrace();
144             return new ErrorCommand(name);
145         } finally {
146             SCLContext.getCurrent().put("graph", oldGraph);
147         }
148     }
149 }