]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scl.commands/src/org/simantics/scl/commands/internal/CommandImpl.java b/bundles/org.simantics.scl.commands/src/org/simantics/scl/commands/internal/CommandImpl.java
new file mode 100644 (file)
index 0000000..046a022
--- /dev/null
@@ -0,0 +1,149 @@
+package org.simantics.scl.commands.internal;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteResultRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Procedure;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.scl.commands.Command;\r
+import org.simantics.scl.commands.internal.checker.Checker;\r
+import org.simantics.scl.commands.internal.serialization.CommandSerializer;\r
+import org.simantics.scl.commands.internal.serialization.CommandSerializerFactory;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.top.ValueNotFound;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.util.MultiFunction;\r
+import org.simantics.scl.osgi.SCLOsgi;\r
+import org.simantics.scl.runtime.SCLContext;\r
+import org.simantics.scl.runtime.function.Function;\r
+import org.simantics.utils.logging.TimeLogger;\r
+\r
+/**\r
+ * Default command implementation\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+@SuppressWarnings({"rawtypes", "restriction"})\r
+public class CommandImpl implements Command {\r
+\r
+    String name;\r
+    Function command;\r
+    Type[] parameterTypes;\r
+    CommandSerializer serializer; \r
+    Checker checker;\r
+    \r
+    public CommandImpl(String name, Function command, Type[] parameterTypes,\r
+            CommandSerializer serializer, Checker checker) {\r
+        this.name = name;\r
+        this.command = command;\r
+        this.parameterTypes = parameterTypes;\r
+        this.serializer = serializer;\r
+        this.checker = checker;\r
+    }\r
+    \r
+    private class CheckRequest implements Read<Boolean> {\r
+        Object[] parameters;\r
+        \r
+        public CheckRequest(Object[] parameters) {\r
+            this.parameters = parameters;\r
+        }\r
+\r
+        @Override\r
+        public Boolean perform(ReadGraph graph) throws DatabaseException {\r
+            SCLContext sclContext = SCLContext.getCurrent();\r
+            Object oldGraph = sclContext.put("graph", graph);\r
+            boolean result = checker.check(parameters);\r
+            sclContext.put("graph", oldGraph);\r
+            return result;\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public boolean check(RequestProcessor processor, Resource model,\r
+            Object... parameters) throws DatabaseException {\r
+        CheckRequest request = new CheckRequest(parameters);\r
+        if(processor instanceof ReadGraph)\r
+            return request.perform((ReadGraph)processor);\r
+        else\r
+            return processor.syncRequest(request);\r
+    }\r
+\r
+    private static boolean serializationErrorAlreadySeen = false;\r
+    \r
+    private class CommitRequest extends WriteResultRequest<Object> {\r
+        Resource model;\r
+        Object[] parameters;\r
+        \r
+        public CommitRequest(Resource model, Object[] parameters) {\r
+            this.model = model;\r
+            this.parameters = parameters;\r
+        }\r
+\r
+        @Override\r
+        public Object perform(WriteGraph graph) throws DatabaseException {\r
+            SCLContext sclContext = SCLContext.getCurrent();\r
+            Object oldGraph = sclContext.put("graph", graph);\r
+            // Serialize command first\r
+            try {\r
+                serializer.serialize(graph, model, parameters);\r
+            } catch(Exception e) {\r
+                if(!serializationErrorAlreadySeen) {\r
+                    e.printStackTrace();\r
+                    serializationErrorAlreadySeen = true;\r
+                }\r
+            } \r
+            \r
+            // Then execute (otherwise target of the command might not exist anymore)\r
+            try {\r
+                return command.applyArray(parameters);\r
+            } finally {\r
+                sclContext.put("graph", oldGraph);\r
+            }\r
+        }\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public Object execute(RequestProcessor processor, Resource model, Object ... parameters) throws DatabaseException {\r
+        if(parameters.length != parameterTypes.length)\r
+            throw new IllegalArgumentException("Wrong number of parameters given (" + parameters.length + ") expected " +\r
+                    parameterTypes.length + " parameters.");\r
+        CommitRequest request = new CommitRequest(model, parameters);\r
+        try {\r
+            if(processor instanceof WriteGraph)\r
+                return request.perform((WriteGraph)processor);\r
+            else\r
+                return processor.syncRequest(request);\r
+        } finally {\r
+            TimeLogger.log("Executed command " + name);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void asyncExecute(RequestProcessor processor, Resource model,\r
+            Object[] parameters, Procedure<Object> procedure) {\r
+        processor.asyncRequest(new CommitRequest(model, parameters), procedure);\r
+    }\r
+\r
+    public static Command create(ReadGraph graph, String name) {\r
+        Object oldGraph = SCLContext.getCurrent().put("graph", graph);\r
+        try {\r
+            SCLValue commandRef = SCLOsgi.MODULE_REPOSITORY.getValueRef(name);\r
+            MultiFunction mfun = Types.matchFunction(commandRef.getType());\r
+            Type[] parameterTypes = mfun.parameterTypes;\r
+            Function command = (Function)SCLOsgi.MODULE_REPOSITORY.getValue(name);\r
+            CommandSerializer serializer = CommandSerializerFactory.create(name, parameterTypes);\r
+            Checker checker = Checker.create(name + "_check");\r
+            return new CommandImpl(name, command, parameterTypes, serializer, checker);\r
+        } catch(ValueNotFound e) {\r
+            e.printStackTrace();\r
+            return new ErrorCommand(name);\r
+        } finally {\r
+            SCLContext.getCurrent().put("graph", oldGraph);\r
+        }\r
+    }\r
+}\r