]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.commands/src/org/simantics/scl/commands/internal/CommandImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.commands / src / org / simantics / scl / commands / internal / CommandImpl.java
1 package org.simantics.scl.commands.internal;\r
2 \r
3 import org.simantics.db.ReadGraph;\r
4 import org.simantics.db.RequestProcessor;\r
5 import org.simantics.db.Resource;\r
6 import org.simantics.db.WriteGraph;\r
7 import org.simantics.db.common.request.WriteResultRequest;\r
8 import org.simantics.db.exception.DatabaseException;\r
9 import org.simantics.db.procedure.Procedure;\r
10 import org.simantics.db.request.Read;\r
11 import org.simantics.scl.commands.Command;\r
12 import org.simantics.scl.commands.internal.checker.Checker;\r
13 import org.simantics.scl.commands.internal.serialization.CommandSerializer;\r
14 import org.simantics.scl.commands.internal.serialization.CommandSerializerFactory;\r
15 import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
16 import org.simantics.scl.compiler.top.ValueNotFound;\r
17 import org.simantics.scl.compiler.types.Type;\r
18 import org.simantics.scl.compiler.types.Types;\r
19 import org.simantics.scl.compiler.types.util.MultiFunction;\r
20 import org.simantics.scl.osgi.SCLOsgi;\r
21 import org.simantics.scl.runtime.SCLContext;\r
22 import org.simantics.scl.runtime.function.Function;\r
23 import org.simantics.utils.logging.TimeLogger;\r
24 \r
25 /**\r
26  * Default command implementation\r
27  * \r
28  * @author Hannu Niemistö\r
29  */\r
30 @SuppressWarnings({"rawtypes", "restriction"})\r
31 public class CommandImpl implements Command {\r
32 \r
33     String name;\r
34     Function command;\r
35     Type[] parameterTypes;\r
36     CommandSerializer serializer; \r
37     Checker checker;\r
38     \r
39     public CommandImpl(String name, Function command, Type[] parameterTypes,\r
40             CommandSerializer serializer, Checker checker) {\r
41         this.name = name;\r
42         this.command = command;\r
43         this.parameterTypes = parameterTypes;\r
44         this.serializer = serializer;\r
45         this.checker = checker;\r
46     }\r
47     \r
48     private class CheckRequest implements Read<Boolean> {\r
49         Object[] parameters;\r
50         \r
51         public CheckRequest(Object[] parameters) {\r
52             this.parameters = parameters;\r
53         }\r
54 \r
55         @Override\r
56         public Boolean perform(ReadGraph graph) throws DatabaseException {\r
57             SCLContext sclContext = SCLContext.getCurrent();\r
58             Object oldGraph = sclContext.put("graph", graph);\r
59             boolean result = checker.check(parameters);\r
60             sclContext.put("graph", oldGraph);\r
61             return result;\r
62         }\r
63     }\r
64     \r
65     @Override\r
66     public boolean check(RequestProcessor processor, Resource model,\r
67             Object... parameters) throws DatabaseException {\r
68         CheckRequest request = new CheckRequest(parameters);\r
69         if(processor instanceof ReadGraph)\r
70             return request.perform((ReadGraph)processor);\r
71         else\r
72             return processor.syncRequest(request);\r
73     }\r
74 \r
75     private static boolean serializationErrorAlreadySeen = false;\r
76     \r
77     private class CommitRequest extends WriteResultRequest<Object> {\r
78         Resource model;\r
79         Object[] parameters;\r
80         \r
81         public CommitRequest(Resource model, Object[] parameters) {\r
82             this.model = model;\r
83             this.parameters = parameters;\r
84         }\r
85 \r
86         @Override\r
87         public Object perform(WriteGraph graph) throws DatabaseException {\r
88             SCLContext sclContext = SCLContext.getCurrent();\r
89             Object oldGraph = sclContext.put("graph", graph);\r
90             // Serialize command first\r
91             try {\r
92                 serializer.serialize(graph, model, parameters);\r
93             } catch(Exception e) {\r
94                 if(!serializationErrorAlreadySeen) {\r
95                     e.printStackTrace();\r
96                     serializationErrorAlreadySeen = true;\r
97                 }\r
98             } \r
99             \r
100             // Then execute (otherwise target of the command might not exist anymore)\r
101             try {\r
102                 return command.applyArray(parameters);\r
103             } finally {\r
104                 sclContext.put("graph", oldGraph);\r
105             }\r
106         }\r
107         \r
108     }\r
109     \r
110     @Override\r
111     public Object execute(RequestProcessor processor, Resource model, Object ... parameters) throws DatabaseException {\r
112         if(parameters.length != parameterTypes.length)\r
113             throw new IllegalArgumentException("Wrong number of parameters given (" + parameters.length + ") expected " +\r
114                     parameterTypes.length + " parameters.");\r
115         CommitRequest request = new CommitRequest(model, parameters);\r
116         try {\r
117             if(processor instanceof WriteGraph)\r
118                 return request.perform((WriteGraph)processor);\r
119             else\r
120                 return processor.syncRequest(request);\r
121         } finally {\r
122             TimeLogger.log("Executed command " + name);\r
123         }\r
124     }\r
125 \r
126     @Override\r
127     public void asyncExecute(RequestProcessor processor, Resource model,\r
128             Object[] parameters, Procedure<Object> procedure) {\r
129         processor.asyncRequest(new CommitRequest(model, parameters), procedure);\r
130     }\r
131 \r
132     public static Command create(ReadGraph graph, String name) {\r
133         Object oldGraph = SCLContext.getCurrent().put("graph", graph);\r
134         try {\r
135             SCLValue commandRef = SCLOsgi.MODULE_REPOSITORY.getValueRef(name);\r
136             MultiFunction mfun = Types.matchFunction(commandRef.getType());\r
137             Type[] parameterTypes = mfun.parameterTypes;\r
138             Function command = (Function)SCLOsgi.MODULE_REPOSITORY.getValue(name);\r
139             CommandSerializer serializer = CommandSerializerFactory.create(name, parameterTypes);\r
140             Checker checker = Checker.create(name + "_check");\r
141             return new CommandImpl(name, command, parameterTypes, serializer, checker);\r
142         } catch(ValueNotFound e) {\r
143             e.printStackTrace();\r
144             return new ErrorCommand(name);\r
145         } finally {\r
146             SCLContext.getCurrent().put("graph", oldGraph);\r
147         }\r
148     }\r
149 }\r