Simulator toolkit enhancements 98/1498/8
authorAntti Villberg <antti.villberg@semantum.fi>
Tue, 27 Feb 2018 09:00:13 +0000 (11:00 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Thu, 1 Mar 2018 15:38:08 +0000 (17:38 +0200)
The basic simulator node manager and its supporting structures have been
moved to org.simantics.simulator[.toolkit] and stripped of any
dependency the Simantics database interfaces.

org.simantics.simulator.toolkit.db now contains the parts that bind the
simulator toolkit interfaces to the Simantics DB.

refs #7782

Change-Id: I266faaec323c772767d7a32331ed27e9f893f473

52 files changed:
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardEngine.java [deleted file]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNode.java [deleted file]
bundles/org.simantics.simulation/src/org/simantics/simulation/data/AbstractDatasource.java
bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java
bundles/org.simantics.simulation/src/org/simantics/simulation/data/PseudoSolver.java
bundles/org.simantics.simulation/src/org/simantics/simulation/data/VariableHandle.java
bundles/org.simantics.simulation/src/org/simantics/simulation/experiment/ExperimentState.java
bundles/org.simantics.simulator.toolkit.db/.classpath [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit.db/.project [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit.db/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit.db/build.properties [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/ExperimentStateExternalRead.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardSessionManager.java [moved from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardSessionManager.java with 85% similarity]
bundles/org.simantics.simulator.toolkit/.classpath [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/.project [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/build.properties [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentActionContext.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThread.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadListener.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadSequenceRunner.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardExperimentStates.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNode.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java [moved from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNodeManager.java with 52% similarity]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManagerSupport.java [new file with mode: 0644]
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardRealm.java [moved from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardRealm.java with 87% similarity]
bundles/org.simantics.simulator/.classpath [new file with mode: 0644]
bundles/org.simantics.simulator/.project [new file with mode: 0644]
bundles/org.simantics.simulator/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.simulator/build.properties [new file with mode: 0644]
bundles/org.simantics.simulator/src/org/simantics/simulator/ExperimentState.java [new file with mode: 0644]
bundles/org.simantics.simulator/src/org/simantics/simulator/IDynamicExperimentLocal.java [new file with mode: 0644]
bundles/org.simantics.simulator/src/org/simantics/simulator/IExperimentLocal.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet.graph/META-INF/MANIFEST.MF
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetNodeManager.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetRealm.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSessionManager.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java
bundles/pom.xml
features/org.simantics.sdk.feature/feature.xml
features/org.simantics.simulator.toolkit.db.feature/.project [new file with mode: 0644]
features/org.simantics.simulator.toolkit.db.feature/build.properties [new file with mode: 0644]
features/org.simantics.simulator.toolkit.db.feature/feature.xml [new file with mode: 0644]
features/org.simantics.simulator.toolkit.feature/.project [new file with mode: 0644]
features/org.simantics.simulator.toolkit.feature/build.properties [new file with mode: 0644]
features/org.simantics.simulator.toolkit.feature/feature.xml [new file with mode: 0644]
features/org.simantics.spreadsheet.ui.feature/feature.xml
features/pom.xml

diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardEngine.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardEngine.java
deleted file mode 100644 (file)
index 31e7387..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.simantics.db.layer0;
-
-import java.util.Map;
-
-import org.simantics.simulator.variable.exceptions.NodeManagerException;
-
-public interface StandardEngine<Node> {
-
-       Object getValue(Node node) throws NodeManagerException;
-       void setValue(Node node, Object value) throws NodeManagerException;
-       String getName(Node node);
-       Map<String,Node> getChildren(Node node);
-       Map<String,Node> getProperties(Node node);
-       
-}
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNode.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNode.java
deleted file mode 100644 (file)
index c29dc8f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.simantics.db.layer0;
-
-public interface StandardNode {
-
-}
index 4a15cba5214eb4eed4bdeb540a2f925a9b3fa97e..7b6e791daafbc8489e4c3c75f699b46d472bf0bb 100644 (file)
@@ -20,7 +20,7 @@ import org.simantics.utils.datastructures.ListenerList;
  */
 public abstract class AbstractDatasource implements Datasource {
 
-    protected ListenerList<DatasourceListener> listeners = new ListenerList<DatasourceListener>(DatasourceListener.class);
+    protected ListenerList<DatasourceListener> listeners = new ListenerList<>(DatasourceListener.class);
     protected Lock readLock, writeLock;
 
     public AbstractDatasource() {
@@ -40,20 +40,20 @@ public abstract class AbstractDatasource implements Datasource {
         listeners.remove(listener);
     }
 
-    protected void notifyStep() {
-        for (final DatasourceListener l : listeners.getListeners()) {
+    protected void notifyStep(Datasource source) {
+        for (DatasourceListener l : listeners.getListeners()) {
             if (l.getExecutor() == null) {
-                l.onStep( AbstractDatasource.this );
+                l.onStep( source );
             } else {
-                l.getExecutor().execute(new Runnable() {
-                    public void run() {
-                        l.onStep(AbstractDatasource.this);
-                    }
-                });
+                l.getExecutor().execute(() -> l.onStep(source));
             }
         }
     }
 
+    protected void notifyStep() {
+        notifyStep(AbstractDatasource.this);
+    }
+
     @Override
     public Lock readLock() {
         return readLock;
index 1b6f9b6f8ea9e4fa58c1764e59d2b12719630e84..1ee543f4c91c6ce7d45959f3d46ead583da32b57 100644 (file)
@@ -169,7 +169,7 @@ public class DatasourceAdapter implements DatasourceListener {
                     Object value = null;
                     if (handle != null) {
                         try {
-                            value = handle.getValue();
+                            value = handle.getValue(source);
                         } catch (AccessorException e) {
                             if (failedIds.add(key))
                                 logger.log(Level.SEVERE, e.toString(), e);
index 9a5be411b09df0b4cd90981cb80c6b6fc57953f3..fd3e08a2b1d7cd8442ec8c2298f9bf4cc6bab04a 100644 (file)
@@ -17,6 +17,7 @@ import java.util.List;
 import java.util.Random;
 
 import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.accessor.error.AccessorException;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.NumberBinding;
 import org.simantics.databoard.binding.error.BindingException;
@@ -160,6 +161,11 @@ public class PseudoSolver extends AbstractDatasource {
                public Object getValue() {
                        return PseudoSolver.this.getValue(key, b);
                }
+               
+               @Override
+               public Object getValue(Datasource datasource) throws AccessorException {
+                       return PseudoSolver.this.getValue(key, b);
+               }
 
                @Override
                public void dispose() {
index d501dbecd5317cafceaf90a76edc67c6f2c98cb3..360ea96fc2db48b3e3a031d67212d54888cafeef 100644 (file)
@@ -36,6 +36,12 @@ public interface VariableHandle {
         */
        Object getValue() throws AccessorException;
 
+       /**
+        * @return current value associated with this handle within the given Datasource
+        * @throws AccessorException if value cannot be retrieved
+        */
+       Object getValue(Datasource datasource) throws AccessorException;
+       
        /**
         * Frees any resource related to this handle.
         */
index 66ec2d3cb7b316a1a9a83d8680e5e84510bdae06..d724e880459cfa79e9a77df86be7454a7bdd5082 100644 (file)
@@ -12,5 +12,5 @@
 package org.simantics.simulation.experiment;
 
 public enum ExperimentState {
-    INITIALIZING, RUNNING, STOPPED, DISPOSED
+    INITIALIZING, RUNNING, STOPPED, TO_BE_DISPOSED, DISPOSED
 }
diff --git a/bundles/org.simantics.simulator.toolkit.db/.classpath b/bundles/org.simantics.simulator.toolkit.db/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.simulator.toolkit.db/.project b/bundles/org.simantics.simulator.toolkit.db/.project
new file mode 100644 (file)
index 0000000..6684705
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.simulator.toolkit.db</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.simulator.toolkit.db/META-INF/MANIFEST.MF b/bundles/org.simantics.simulator.toolkit.db/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..ea7f97e
--- /dev/null
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simulator Toolkit for DB
+Bundle-SymbolicName: org.simantics.simulator.toolkit.db
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.simulator.toolkit;bundle-version="1.0.0";visibility:=reexport,
+ org.simantics.db.layer0;bundle-version="1.1.0"
+Export-Package: org.simantics.simulator.toolkit.db
+Bundle-Vendor: Semantum Oy
diff --git a/bundles/org.simantics.simulator.toolkit.db/build.properties b/bundles/org.simantics.simulator.toolkit.db/build.properties
new file mode 100644 (file)
index 0000000..41eb6ad
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .\r
diff --git a/bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/ExperimentStateExternalRead.java b/bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/ExperimentStateExternalRead.java
new file mode 100644 (file)
index 0000000..ad2b2c4
--- /dev/null
@@ -0,0 +1,42 @@
+package org.simantics.simulator.toolkit.db;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.common.request.ParametrizedPrimitiveRead;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.procedure.Listener;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public class ExperimentStateExternalRead extends ParametrizedPrimitiveRead<Object, Integer> {
+
+       private int value = 0;
+       private Listener<Integer> listener = null;
+
+       public ExperimentStateExternalRead(Object experiment) {
+               super(experiment);
+       }
+
+       @Override
+       public void register(ReadGraph graph, Listener<Integer> procedure) {
+               procedure.execute(value);
+               if (procedure.isDisposed())
+                       return;
+               if (listener != null)
+                       throw new RuntimeDatabaseException("Internal error");
+               listener = procedure;
+       }
+
+       @Override
+       public void unregistered() {
+               listener = null;
+       }
+
+       public void fire() {
+               value++;
+               if (listener != null)
+                       listener.execute(value);
+       }
+
+}
\ No newline at end of file
similarity index 85%
rename from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardSessionManager.java
rename to bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardSessionManager.java
index cdd8e074c404ee4d698878b37eaf7d7478c36eca..62389597a9916ea0509608592ee0bf72f83d740d 100644 (file)
@@ -1,4 +1,4 @@
-package org.simantics.db.layer0;
+package org.simantics.simulator.toolkit.db;
 
 import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
@@ -9,12 +9,14 @@ import org.simantics.db.common.request.ParametrizedPrimitiveRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.variable.NodeSupport;
 import org.simantics.db.procedure.Listener;
+import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
+import org.simantics.simulator.toolkit.StandardRealm;
 
-abstract public class StandardSessionManager<Node, Engine extends StandardEngine<Node>> {
+public abstract class StandardSessionManager<Node, Engine extends StandardNodeManagerSupport<Node>> {
 
     private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();
-    private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<String, StandardRealm<Node,Engine>>(); 
-    private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<String, NodeSupport<Node>>(); 
+    private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<>(); 
+    private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<>(); 
 
     // Accessing Realms should be done over ParametrizedPrimitveRead for the
     // case if a realm is destroyed and new one is created with the same id than
@@ -28,7 +30,6 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
 
         @Override
         public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
-
             StandardRealm<Node, Engine> realm = REALMS.get(parameter);
             if (realm == null) {
                 try {
@@ -37,12 +38,12 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
                     e.printStackTrace();
                 }
             }
-            
+
             if(procedure.isDisposed()) {
                 procedure.execute(realm);
                 return;
             }
-            
+
             Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
             assert(existing == null);
             realmListeners.put(parameter, procedure);
@@ -56,10 +57,10 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
             return realm;
         }
     }
-    
+
     protected StandardSessionManager() {
     }
-    
+
     private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
         Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
         if(listener != null) {
@@ -71,7 +72,7 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
         }
         return null;
     }
-    
+
     private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
         if(realm != null) {
             REALMS.put(key, realm);
@@ -88,25 +89,25 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
 
     public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {
         synchronized(SUPPORTS) {
-               NodeSupport<Node> result = SUPPORTS.get(id);
-               if(result == null) {
-                       StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
-                       result = new NodeSupport<Node>(realm.getNodeManager());
-                       SUPPORTS.put(id, result);
-               }
-               return result;
+            NodeSupport<Node> result = SUPPORTS.get(id);
+            if(result == null) {
+                StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
+                result = new NodeSupport<Node>(realm.getNodeManager());
+                SUPPORTS.put(id, result);
+            }
+            return result;
         }
     }
-    
+
     public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {
         synchronized(REALMS) {
             return graph.syncRequest(new RealmRequest(id));
         }
     }
-    
+
     protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
     protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
-    
+
     public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
         modifyRealms(id, null);
         // remove listeners from this realm
@@ -116,7 +117,7 @@ abstract public class StandardSessionManager<Node, Engine extends StandardEngine
         if (support != null)
             support.dispose();
     }
-    
+
     public Collection<String> getRealms() {
         return REALMS.keySet();
     }
diff --git a/bundles/org.simantics.simulator.toolkit/.classpath b/bundles/org.simantics.simulator.toolkit/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.simulator.toolkit/.project b/bundles/org.simantics.simulator.toolkit/.project
new file mode 100644 (file)
index 0000000..f041175
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.simulator.toolkit</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.simulator.toolkit/META-INF/MANIFEST.MF b/bundles/org.simantics.simulator.toolkit/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..99f251c
--- /dev/null
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Local Simulator Toolkit
+Bundle-SymbolicName: org.simantics.simulator.toolkit
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.simulator.variable;bundle-version="1.0.0";visibility:=reexport,
+ org.simantics.simulator;bundle-version="1.0.0";visibility:=reexport,
+ gnu.trove3;bundle-version="3.0.3",
+ org.slf4j.api;bundle-version="1.7.25",
+ org.simantics.simulation.sequences;bundle-version="1.0.0",
+ org.eclipse.core.runtime,
+ org.simantics.databoard;bundle-version="0.6.6",
+ org.simantics.scl.osgi;bundle-version="1.0.4"
+Export-Package: org.simantics.simulator.toolkit
diff --git a/bundles/org.simantics.simulator.toolkit/build.properties b/bundles/org.simantics.simulator.toolkit/build.properties
new file mode 100644 (file)
index 0000000..41eb6ad
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .\r
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentActionContext.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentActionContext.java
new file mode 100644 (file)
index 0000000..cdf478f
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.simulator.toolkit;
+
+import org.simantics.databoard.binding.Binding;
+import org.simantics.simulation.sequences.action.AbstractActionContext;
+import org.simantics.simulator.IDynamicExperimentLocal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DynamicExperimentActionContext extends AbstractActionContext {
+
+       private static final Logger LOGGER = LoggerFactory.getLogger(DynamicExperimentActionContext.class);
+
+       final private IDynamicExperimentLocal experiment;
+       
+       public DynamicExperimentActionContext(IDynamicExperimentLocal experiment) {
+               this.experiment = experiment;
+       }
+       
+       @Override
+       public Object get(String variableName, Binding binding) {
+               return experiment.getVariableValueById(variableName);
+       }
+
+       @Override
+       public void set(String variableName, Object value, Binding binding) {
+               experiment.setVariableValueById(variableName, value, binding);
+       }
+
+}
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThread.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThread.java
new file mode 100644 (file)
index 0000000..66cec38
--- /dev/null
@@ -0,0 +1,298 @@
+package org.simantics.simulator.toolkit;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+import org.simantics.simulator.ExperimentState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+abstract public class DynamicExperimentThread extends Thread {
+
+       private static final Logger LOGGER = LoggerFactory.getLogger(DynamicExperimentThread.class);
+
+       private CopyOnWriteArrayList<DynamicExperimentThreadListener> listeners = new CopyOnWriteArrayList<>();
+
+       private ExperimentState state = StandardExperimentStates.CREATED;
+
+       private long runStart = 0;
+
+       private double desiredRealtimeRatio = 1000.0;
+       private double obtainedRealtimeRatio = 1.0;
+
+       private long runTimeNs = 0;
+       private long endTimeNs = 0;
+       protected long simulationStepNs = 0;
+       protected double stepInSeconds = 1.0;
+
+       public DynamicExperimentThread() {
+       }
+
+       private void updateTimes() {
+               long time = System.nanoTime();
+               long elapsed = time-runStart; 
+
+               obtainedRealtimeRatio = longToDoubleDivision(runTimeNs, elapsed);
+       }
+
+       private long rt;
+       private long rt_l;
+
+       protected double longToDoubleDivision(long l1, long l2) {
+               rt = l1 / l2;
+               rt_l = l1 % l2;
+               double d = ((double)rt_l)/((double)l2);
+               d += (double)rt;
+               return d;
+       }
+
+       protected ArrayList<Runnable> tasks = new ArrayList<>();
+
+       abstract public void step(double stepLengthNanoSeconds);
+
+       public boolean inState(Class<? extends ExperimentState> state) {
+               return state.isInstance(this.state);
+       }
+
+       public void initialize() throws Exception {
+       }
+
+       public void deinitialize() throws Exception {
+       }
+
+       long stepTime = 0;
+       long taskTime = 0;
+
+       @Override
+       public void run() {
+
+               try {
+
+                       try {
+
+                               initialize();
+
+                               try {
+                                       runReally();
+                               } catch (Exception e) {
+                                       LOGGER.error("Unhandled exception while running simulation thread", e);
+                               } 
+
+                       } catch (Exception e) {
+                               LOGGER.error("Unhandled exception while initializing simulation thread", e);
+                       } 
+
+               } finally {
+
+                       try {
+                               deinitialize();
+                       } catch (Exception e) {
+                               LOGGER.error("Error while deinitializing simulation thread", e);
+                       }
+
+               }
+
+       }
+
+       protected boolean inActiveState() {
+               return !(
+                               inState(StandardExperimentStates.Disposed.class)
+                               || inState(StandardExperimentStates.Disposing.class)
+                               //|| inState(StandardExperimentStates.Failure.class)
+                               || inState(StandardExperimentStates.ToBeDisposed.class)
+                               );
+       }
+
+       private void runReally() {
+
+               while(inActiveState()) {
+
+                       if(inState(StandardExperimentStates.Running.class)) {
+
+                               long asd = System.nanoTime();
+                               step(simulationStepNs);
+                               stepTime += System.nanoTime() - asd;
+                               runTimeNs += simulationStepNs;
+                               updateTimes();
+                               long asd2 = System.nanoTime();
+                               runTasks();
+                               taskTime += System.nanoTime() - asd2;
+
+                               System.err.println(" st = " + 1e-9*stepTime + " tt = " + 1e-9*taskTime);
+
+                               while(obtainedRealtimeRatio > desiredRealtimeRatio) {
+                                       int ran = runTasks();
+                                       if(ran == 0) {
+                                               long elapsed = System.nanoTime()-runStart; 
+                                               long deltaNs = BigDecimal.valueOf(runTimeNs).divide(BigDecimal.valueOf(desiredRealtimeRatio)).longValue() - elapsed;
+
+                                               long deltaMs = deltaNs / 1000000;
+                                               int deltaNsRem = (int)(deltaNs % 1000000);
+
+                                               if(deltaNs > 0) {
+                                                       synchronized(tasks) {
+                                                               try {
+                                                                       tasks.wait(deltaMs, deltaNsRem);
+                                                               } catch (InterruptedException e) {
+                                                                       e.printStackTrace();
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       updateTimes();
+                               }
+
+                       } else {
+
+                               while(!inState(StandardExperimentStates.Running.class) && inActiveState()) {
+
+                                       synchronized(tasks) {
+                                               int ran = runTasks();
+                                               if(ran == 0) {
+                                                       try {
+                                                               tasks.wait(Integer.MAX_VALUE);
+                                                       } catch (InterruptedException e) {
+                                                               e.printStackTrace();
+                                                       }
+                                               }
+                                       }
+
+                               }
+
+                       }
+
+                       if(runTimeNs >= endTimeNs && inActiveState())
+                               changeState(StandardExperimentStates.STOPPED);
+
+               }
+
+       }
+
+       Thread executorThread = this;
+
+       Semaphore beginSyncExec = new Semaphore(0);
+       Semaphore endSyncExec = new Semaphore(0);
+
+       Runnable scheduleSyncExec = () -> {
+               beginSyncExec.release();
+               try {
+                       endSyncExec.acquire();
+               } catch (InterruptedException e) {
+               }
+       };
+
+       public int runTasks() {
+               ArrayList<Runnable> todo = new ArrayList<>();
+               synchronized(tasks) {
+                       todo.addAll(tasks);
+                       tasks.clear();
+               }
+               todo.forEach(Runnable::run);
+               return todo.size();
+       }
+
+       public void queue(Runnable runnable) {
+               synchronized(tasks) {
+                       tasks.add(runnable);
+                       tasks.notify();
+               }
+       }
+
+       public <T> T syncExec(Callable<T> callable) throws InterruptedException {
+
+               if(executorThread == Thread.currentThread()) {
+                       try {
+                               return callable.call();
+                       } catch (Throwable t) {
+                               LOGGER.error("syncExec in current thread failed", t);
+                               return null;
+                       } finally {
+                       }
+               }
+
+               queue(scheduleSyncExec);
+
+               beginSyncExec.acquire();
+               Thread oldThread = executorThread;
+               executorThread = Thread.currentThread();
+               try {
+                       return callable.call();
+               } catch (Throwable t) {
+                       LOGGER.error("syncExec failed", t);
+                       return null;
+               } finally {
+                       executorThread = oldThread;
+                       endSyncExec.release();
+               }
+
+       }
+
+       public void asyncExec(Runnable runnable) {
+
+               if(executorThread == Thread.currentThread()) {
+                       try {
+                               runnable.run();
+                       } catch (Throwable t) {
+                               LOGGER.error("asyncExec failed", t);
+                       } finally {
+                       }
+                       return;
+               }
+
+               queue(runnable);
+
+       }
+
+       public void setSimulationStepNs(long ns) {
+               simulationStepNs = ns;
+               stepInSeconds = BigDecimal.valueOf(simulationStepNs).multiply(BigDecimal.valueOf(1e-9)).doubleValue();
+       }
+
+       public void runDuration(long ns) {
+               runStart = System.nanoTime();
+               runTimeNs = 0;
+               endTimeNs = ns;
+               synchronized(tasks) {
+                       changeState(StandardExperimentStates.RUNNING);
+                       tasks.notify();
+               }
+       }
+
+       public ExperimentState getExperimentState() {
+               return state;
+       }
+
+       public void changeState(ExperimentState state) {
+               this.state = state;
+               fireStateChanged(state);
+       }
+
+       public void addListener(DynamicExperimentThreadListener listener) {
+               if(!listeners.contains(listener))
+                       listeners.add(listener);
+       }
+
+       public void removeListener(DynamicExperimentThreadListener listener) {
+               listeners.remove(listener);
+       }
+
+       protected void fireAfterStep() {
+               listeners.forEach(DynamicExperimentThreadListener::afterStep);
+       }
+
+       protected void fireBeforeStep() {
+               listeners.forEach(DynamicExperimentThreadListener::beforeStep);
+       }
+
+       protected void fireStateChanged(ExperimentState newState) {
+               listeners.forEach(l -> l.stateChanged(newState));
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadListener.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadListener.java
new file mode 100644 (file)
index 0000000..1808079
--- /dev/null
@@ -0,0 +1,13 @@
+package org.simantics.simulator.toolkit;
+
+import org.simantics.simulator.ExperimentState;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public interface DynamicExperimentThreadListener {
+       default void beforeStep() {}
+       default void afterStep() {}
+       default void stateChanged(ExperimentState newState) {}
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadSequenceRunner.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/DynamicExperimentThreadSequenceRunner.java
new file mode 100644 (file)
index 0000000..2143e5a
--- /dev/null
@@ -0,0 +1,72 @@
+package org.simantics.simulator.toolkit;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.simulator.IDynamicExperimentLocal;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public class DynamicExperimentThreadSequenceRunner {
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static DynamicExperimentActionContext runAction(IDynamicExperimentLocal experiment, DynamicExperimentThread thread, Function action, final boolean simulateAndWaitCompletion) {
+        final DynamicExperimentActionContext context = new DynamicExperimentActionContext(experiment);
+        context.scheduleNextStep(action);
+        final Object sync = new Object();
+        final SCLContext sclContext = SCLContext.getCurrent();
+
+        thread.addListener(new DynamicExperimentThreadListener() {
+
+            @Override
+            public void beforeStep() {
+                if(!context.isStopped()) {
+                    SCLContext.push(sclContext);
+                    context.handleStep(experiment.getSimulationTime());
+                    SCLContext.pop();
+                }
+                removeIfStopped();
+            }
+
+            public void removeIfStopped() {
+                if(context.isStopped()) {
+                    thread.removeListener(this);
+                    if(simulateAndWaitCompletion) {
+                        experiment.simulate(false);
+                        synchronized(sync) {
+                            sync.notify();
+                        }
+                    }
+                    experiment.shutdown(new NullProgressMonitor());
+                }
+            }
+
+        });
+
+        if(simulateAndWaitCompletion) {
+            experiment.simulate(true);
+
+            try {
+                synchronized(sync) {
+                    while(!context.isStopped())
+                        sync.wait(1000L);
+                }
+            } catch(InterruptedException e) {
+                context.stop();
+            }
+
+            if (context.exceptions != null && !context.exceptions.isEmpty()) {
+                StringBuilder builder = new StringBuilder();
+                builder.append("Action failures:");
+                for (Exception e : context.exceptions) {
+                    builder.append("\n");
+                    builder.append(e.getMessage());
+                }
+
+                throw new RuntimeException(builder.toString());
+            }
+        }
+        return context;
+    }
+}
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardExperimentStates.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardExperimentStates.java
new file mode 100644 (file)
index 0000000..c314643
--- /dev/null
@@ -0,0 +1,124 @@
+package org.simantics.simulator.toolkit;
+
+import org.simantics.simulator.ExperimentState;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public class StandardExperimentStates implements ExperimentState {
+
+    /**
+     * The experiment context has been created.
+     *
+     * <p>
+     * Allowed successor states: {@link Instantiated}, {@link ToBeDisposed}
+     */
+    public interface Created extends ExperimentState {}
+
+    /**
+     * The experiment context has been instantiated, i.e. underlying experimentation
+     * resources have been acquired. Some experiment setup (e.g. setting certain
+     * values) can be done in this state that cannot be touched once the experiment
+     * is initialized.
+     *
+     * <p>
+     * Allowed successor states: {@link Initializing}, {@link ToBeDisposed}
+     */
+    public interface Instantiated extends ExperimentState {}
+
+    /**
+     * The experiment context is in the process of being initialized. This means
+     * that any initial conditions or related data is being loaded into the
+     * simulator/solver/what ever system that runs the experiment.
+     * 
+     * If the initialization fails due to an irrecoverable system error, the
+     * experiment shall move to {@link Failure} state. If the initialization fails
+     * due to a recoverable error in user input, the experiment shall move to
+     * {@link Instantiated} state.
+     *
+     * <p>
+     * Allowed successor states: {@link Initialized}, {@link Instantiated},
+     * {@link Failure}
+     */
+    public interface Initializing extends ExperimentState {}
+
+    /**
+     * The experiment context has been initialized, i.e. the underlying
+     * experimentation resources have been both acquired and initialized with a
+     * specific state.
+     * 
+     * <p>
+     * Allowed successor states: {@link Stopped}, {@link Running},
+     * {@link ToBeDisposed}
+     */
+    public interface Initialized extends ExperimentState {}
+
+    /**
+     * The experiment shall be ran until it reaches an objective such as
+     * steady-state or running for a duration or until the state changes to
+     * {@link Stopped}.
+     *
+     * <p>
+     * Allowed successor states: {@link Stopped}, {@link ToBeDisposed}
+     */
+    public interface Running extends ExperimentState {}
+
+    /**
+     * The experiment shall remain stopped. Everything in the experiment context
+     * should remain constant while in this state.
+     *
+     * <p>
+     * Allowed successor states: {@link Running}, {@link ToBeDisposed}
+     */
+    public interface Stopped extends ExperimentState {}
+
+    /**
+     * Moving into this state marks the beginning of the disposal of this
+     * experiment. The imminent disposal is irreversible and cannot be vetoed
+     * or interrupted.
+     *
+     * <p>
+     * Allowed successor states: {@link Disposing}
+     */
+    public interface ToBeDisposed extends ExperimentState {}
+
+    /**
+     * The experiment context is being disposed, i.e. underlying experimentation
+     * resources are being freed and disposed of accordingly.
+     *
+     * <p>
+     * Allowed successor states: {@link Disposing}
+     */
+    public interface Disposing extends ExperimentState {}
+
+    /**
+     * The experiment has been completely disposed and cannot any longer be used for
+     * anything.
+     *
+     * <p>
+     * Allowed successor states: none, this is a final state
+     */
+    public interface Disposed extends ExperimentState {}
+
+    /**
+     * The experiment implementation has ran into a fatal failure. The experiment
+     * context can still be accessed at this point but the experiment can only move
+     * into {@link Disposed} state.
+     *
+     * <p>
+     * Allowed successor states: {@link Disposed}
+     */
+    public interface Failure extends ExperimentState {}
+
+    public static final ExperimentState CREATED = new Created() {};
+    public static final ExperimentState INSTANTIATED = new Instantiated() {};
+    public static final ExperimentState INITIALIZING = new Initializing() {};
+    public static final ExperimentState INITIALIZED = new Initialized() {};
+    public static final ExperimentState RUNNING = new Running() {};
+    public static final ExperimentState STOPPED = new Stopped() {};
+    public static final ExperimentState TO_BE_DISPOSED = new ToBeDisposed() {};
+    public static final ExperimentState DISPOSING = new Disposing() {};
+    public static final ExperimentState DISPOSED = new Disposed() {};
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNode.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNode.java
new file mode 100644 (file)
index 0000000..6d6878a
--- /dev/null
@@ -0,0 +1,14 @@
+package org.simantics.simulator.toolkit;
+
+/**
+ * Standard simulator variable node interface used with {@link StandardNodeManagerSupport}
+ * and {@link StandardNodeManager}.
+ * 
+ * This used to exist in org.simantics.db.layer0 in earlier versions but was
+ * moved here to make it DB-independent.
+ * 
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public interface StandardNode {
+}
similarity index 52%
rename from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNodeManager.java
rename to bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java
index c48c3f9d11983f333c78acdfb5e29d12b21011f5..87ae4f32f3b7394d1e8168c705c2584ba0ae3f8c 100644 (file)
@@ -10,7 +10,7 @@
  *     VTT Technical Research Centre of Finland - initial API and implementation
  *     Semantum Oy - initial API and implementation
  *******************************************************************************/
-package org.simantics.db.layer0;
+package org.simantics.simulator.toolkit;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -19,19 +19,22 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.simantics.databoard.Bindings;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.adapter.Adapter;
+import org.simantics.databoard.adapter.AdapterConstructionException;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.VariantBinding;
-import org.simantics.databoard.binding.error.BindingConstructionException;
 import org.simantics.databoard.binding.error.BindingException;
 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.type.Datatype;
-import org.simantics.db.exception.DatabaseException;
 import org.simantics.simulator.variable.NodeManager;
 import org.simantics.simulator.variable.Realm;
 import org.simantics.simulator.variable.exceptions.NoSuchNodeException;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.simulator.variable.exceptions.NotInRealmException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.THashMap;
 import gnu.trove.procedure.TObjectProcedure;
@@ -43,12 +46,14 @@ import gnu.trove.set.hash.THashSet;
  * 
  * @author Antti Villberg
  */
-public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Node>> implements NodeManager<Node> {
-       
-       final private Node root;
-       final private StandardRealm<Node,Engine> realm;
+public abstract class StandardNodeManager<Node, Engine extends StandardNodeManagerSupport<Node>> implements NodeManager<Node> {
 
-    final static Binding NO_BINDING = new VariantBinding() {
+    private static final Logger LOGGER = LoggerFactory.getLogger(StandardNodeManager.class);
+
+    private final Node root;
+    private final StandardRealm<Node,Engine> realm;
+
+    static final Binding NO_BINDING = new VariantBinding() {
 
         @Override
         public Object getContent(Object variant, Binding contentBinding) throws BindingException {
@@ -89,149 +94,135 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         public void assertInstaceIsValid(Object obj, Set<Object> validInstances) throws BindingException {
             throw new Error();
         }
-        
+
         @Override
         public int compare(Object o1, Object o2) throws org.simantics.databoard.binding.error.RuntimeBindingException {
-               if(o1 == null) {
-                       if(o2 == null) {
-                               return 0;
-                       } else {
-                               return  - System.identityHashCode(o2);
-                       }
-               } else {
-                       if(o2 == null) {
-                               return  System.identityHashCode(o1);
-                       } else {
-                               if(o1.equals(o2)) return 0;
-                               return System.identityHashCode(o1) - System.identityHashCode(o2);       
-                       }
-               }
+            if(o1 == null) {
+                if(o2 == null) {
+                    return 0;
+                } else {
+                    return  - System.identityHashCode(o2);
+                }
+            } else {
+                if(o2 == null) {
+                    return  System.identityHashCode(o1);
+                } else {
+                    if(o1.equals(o2)) return 0;
+                    return System.identityHashCode(o1) - System.identityHashCode(o2);  
+                }
+            }
         }
 
     };
-    
-    THashMap<Node, Object> valueCache = new THashMap<Node, Object>(); 
-    protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<Node, THashSet<Runnable>>(); 
-    
+
+    THashMap<Node, Variant> valueCache = new THashMap<>(); 
+    protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<>(); 
+
     AtomicBoolean fireNodeListenersScheduled = new AtomicBoolean(false);
     Runnable fireNodeListeners = new Runnable() {
         @Override
         public void run() {
             fireNodeListenersScheduled.set(false);
-            final TObjectProcedure<Runnable> procedure = new TObjectProcedure<Runnable>() {
-                @Override
-                public boolean execute(Runnable object) {
-                    object.run();
-                    return true;
-                }
+            TObjectProcedure<Runnable> procedure = r -> {
+                r.run();
+                return true;
             };
             synchronized(listeners) {
-                listeners.forEachValue(new TObjectProcedure<THashSet<Runnable>>() {
-                    @Override
-                    public boolean execute(THashSet<Runnable> object) {
-                        object.forEach(procedure);
-                        return true;
-                    }
+                listeners.forEachValue(set -> {
+                    set.forEach(procedure);
+                    return true;
                 });
             }
         }
     };
-    
-    Runnable clearValueCache = new Runnable() {
-        @Override
-        public void run() {
-            valueCache.clear(); 
-        }
-    };
-    
+
+    Runnable clearValueCache = () -> valueCache.clear(); 
+
     public StandardNodeManager(StandardRealm<Node,Engine> realm, Node root) {
-       this.realm = realm;
-       this.root = root;
-       }
-    
-       @Override
-       public List<String> getChildNames(Node node) throws NodeManagerException {
-               List<Node> children = getChildren(node);
-               ArrayList<String> names = new ArrayList<String>(children.size());
-               for(Node child : children)
-                       names.add(getName(child));
-               return names;
-       }
-       
-       @Override
-       public List<String> getPropertyNames(Node node) throws NodeManagerException {
-               List<Node> properties = getProperties(node);
-               ArrayList<String> names = new ArrayList<String>(properties.size());
-               for(Node property : properties)
-                       names.add(getName(property));
-               return names;
-       }
-       
-       @Override
-       public Object getValue(Node node, String propertyName, Binding binding)
-                       throws NodeManagerException, BindingException {
-               Node property = getProperty(node, propertyName);
-               if(property == null)
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);
-               return getValue(property, binding);
-       }
-       
-       @Override
-       public void setValue(Node node, String propertyName, Object value,
-                       Binding binding) throws NodeManagerException, BindingException {
-               Node property = getProperty(node, propertyName);
-               if(property == null)
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);
-               setValue(property, value, binding);
-       }
-       
-       @Override
-       public Variant getValue(Node node) throws NodeManagerException {
-               Object value = getEngineValueOrCached(node);
-               if (value instanceof Variant)
-                   return (Variant) value;
+        assert(realm != null);
+        assert(root != null);
+        this.realm = realm;
+        this.root = root;
+    }
+
+    @Override
+    public List<String> getChildNames(Node node) throws NodeManagerException {
+        List<Node> children = getChildren(node);
+        ArrayList<String> names = new ArrayList<>(children.size());
+        for(Node child : children)
+            names.add(getName(child));
+        return names;
+    }
+
+    @Override
+    public List<String> getPropertyNames(Node node) throws NodeManagerException {
+        List<Node> properties = getProperties(node);
+        ArrayList<String> names = new ArrayList<>(properties.size());
+        for(Node property : properties)
+            names.add(getName(property));
+        return names;
+    }
+
+    @Override
+    public Object getValue(Node node, String propertyName, Binding binding)
+            throws NodeManagerException, BindingException {
+        Node property = getProperty(node, propertyName);
+        if(property == null)
+            throw new NoSuchNodeException("Didn't find a property " + propertyName);
+        return getValue(property, binding);
+    }
+
+    @Override
+    public void setValue(Node node, String propertyName, Object value,
+            Binding binding) throws NodeManagerException, BindingException {
+        Node property = getProperty(node, propertyName);
+        if(property == null)
+            throw new NoSuchNodeException("Didn't find a property " + propertyName);
+        setValue(property, value, binding);
+    }
+
+    @Override
+    public Variant getValue(Node node, String propertyName)
+            throws NodeManagerException {
+        Node property = getProperty(node, propertyName);
+        if(property == null)
+            throw new NoSuchNodeException("Didn't find a property " + propertyName);
+        return getValue(property);
+    }
+
+    @Override
+    public Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException {
         try {
-            Binding binding = Bindings.getBinding(value.getClass());
-            return new Variant(binding, value);
-        } catch (BindingConstructionException e) {
-            e.printStackTrace();
-            return null;
+            return getValue(node).getValue(binding);
+        } catch (AdaptException e) {
+            throw new BindingException(e);
         }
-       }
-       
-       @Override
-       public Variant getValue(Node node, String propertyName)
-                       throws NodeManagerException {
-               Node property = getProperty(node, propertyName);
-               if(property == null)
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);
-               return getValue(property);
-       }
-       
+    }
+
     @Override
     public String getPropertyURI(Node parent, Node property) {
         return null;
     }
-    
+
     @Override
     public Realm getRealm() {
-       return realm;
+        return realm;
     }
-    
+
     public StandardRealm<Node, Engine> getStandardRealm() {
-       return realm;
+        return realm;
     }
-    
+
     protected String getRealmId() {
-       return realm.getId();
+        return realm.getId();
     }
-    
+
     public Node getRoot() {
-       return root;
+        return root;
     }
-    
+
     protected boolean isRoot(Node node) {
-       return root.equals(node);
+        return root.equals(node);
     }
 
     @Override
@@ -239,7 +230,7 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         synchronized(listeners) {
             THashSet<Runnable> l = listeners.get(node);
             if(l == null) {
-                l = new THashSet<Runnable>();
+                l = new THashSet<>();
                 listeners.put(node, l);
             }
             l.add(listener);
@@ -258,18 +249,18 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
             }
         }
     }
-    
+
     public void fireNodeListeners() {
         if(!fireNodeListenersScheduled.getAndSet(true))
             realm.asyncExec(fireNodeListeners);
     }
-    
+
     public void fireNodeListenersSync() {
-       try {
-                       realm.syncExec(fireNodeListeners);
-               } catch (InterruptedException e) {
-                       e.printStackTrace();
-               }
+        try {
+            realm.syncExec(fireNodeListeners);
+        } catch (InterruptedException e) {
+            LOGGER.error("Synchronous node listener firing was interrupted.", e);
+        }
     }
 
     public void refreshVariables() {
@@ -279,82 +270,97 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
 
     public void refreshVariablesSync() {
         try {
-                       realm.syncExec(clearValueCache);
-               } catch (InterruptedException e) {
-                       e.printStackTrace();
-               }
+            realm.syncExec(clearValueCache);
+        } catch (InterruptedException e) {
+            LOGGER.error("Synchronous value cache refresh was interrupted.", e);
+        }
         fireNodeListenersSync();
     }
-    
-    protected Object getEngineValueOrCached(Node node) throws NodeManagerException {
-        Object value = valueCache.get(node);
-        if(value == null) {
-               value = realm.getEngine().getValue(node);
-            valueCache.put(node, value);
+
+    protected Variant getEngineVariantOrCached(Node node) throws NodeManagerException {
+        Variant variant = valueCache.get(node);
+        if(variant == null) {
+            Object value = realm.getEngine().getEngineValue(node);
+            Binding binding = realm.getEngine().getEngineBinding(node);
+            variant = new Variant(binding, value);
+            valueCache.put(node, variant);
         }
-        return value;
+        return variant;
     }
-    
 
     @Override
-    public Object getValue(Node node, Binding binding) throws NodeManagerException {
+    public Variant getValue(Node node) throws NodeManagerException {
         checkThreadAccess();
-        return getEngineValueOrCached(node);
+        return getEngineVariantOrCached(node);
     }
 
     protected void checkThreadAccess() throws NodeManagerException {
         if(Thread.currentThread() != realm.getThread())
             throw new NotInRealmException();
     }
-    
-    protected Datatype getDatatypeForValue(Object value) throws DatabaseException {
-       Binding binding = Bindings.getBindingUnchecked(value.getClass());
-       if(binding == null) return null;
-       else return binding.type();
+
+    protected Datatype getDatatypeForValue(Object value) {
+        Binding binding = Bindings.getBindingUnchecked(value.getClass());
+        if(binding == null) return null;
+        else return binding.type();
     }
-    
+
     @Override
     public void setValue(Node node, Object value, Binding binding)
             throws NodeManagerException {
-       checkThreadAccess();
-       valueCache.put(node, value);
-       realm.getEngine().setValue(node, value);
-       realm.getNodeManager().valueCache.put(node, value);
-       refreshVariables();
+        checkThreadAccess();
+        Binding targetBinding = realm.getEngine().getEngineBinding(node);
+        if(binding.equals(targetBinding)) {
+            Variant variant = new Variant(binding, value);
+            valueCache.put(node, variant);
+            realm.getEngine().setEngineValue(node, value);
+        } else {
+            try {
+                Adapter adapter = Bindings.getAdapter(binding, targetBinding);
+                Object targetValue = adapter.adapt(value);
+                Variant variant = new Variant(targetBinding, targetValue);
+                valueCache.put(node, variant);
+                realm.getEngine().setEngineValue(node, targetValue);
+            } catch (AdapterConstructionException e) {
+                throw new NodeManagerException(e);
+            } catch (AdaptException e) {
+                throw new NodeManagerException(e);
+            }
+        }
+        refreshVariables();
     }
-    
+
     @Override
     public String getName(Node node) {
         if(isRoot(node)) {
-               String id = getRealmId();
-               int lastSlash = id.lastIndexOf("/");
-               if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
-               String name = id.substring(lastSlash+1); 
-               return name;
+            String id = getRealmId();
+            int lastSlash = id.lastIndexOf("/");
+            if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
+            String name = id.substring(lastSlash+1); 
+            return name;
         } else {
-               return realm.getEngine().getName(node);
+            return realm.getEngine().getName(node);
         }
     }
-    
 
     @Override
     public Node getNode(String path) throws NodeManagerException {
         checkThreadAccess();
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public Node getChild(Node node, String name) throws NodeManagerException {
         checkThreadAccess();
-       Map<String,Node> map = realm.getEngine().getChildren(node);
-       return map.get(name);
+        Map<String,Node> map = realm.getEngine().getChildren(node);
+        return map.get(name);
     }
 
     @Override
     public Node getProperty(Node node, String name) throws NodeManagerException {
-       checkThreadAccess();
-       Map<String,Node> map = realm.getEngine().getProperties(node);
-       return map.get(name);
+        checkThreadAccess();
+        Map<String,Node> map = realm.getEngine().getProperties(node);
+        return map.get(name);
     }
 
     @Override
@@ -373,10 +379,10 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
     public Datatype getDatatype(Node node) throws NodeManagerException {
         checkThreadAccess();
         try {
-            Datatype type = getDatatypeForValue(getEngineValueOrCached(node));
-            return type;
-        } catch (DatabaseException e) {
-            e.printStackTrace();
+            Variant v = getEngineVariantOrCached(node);
+            Binding b = v.getBinding();
+            if(b == null) return null;
+            return b.type();
         } catch (RuntimeBindingConstructionException e) {
             // There is no datatype for all values
         }
@@ -387,4 +393,5 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         valueCache.clear();
         listeners.clear();
     }
-}
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManagerSupport.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManagerSupport.java
new file mode 100644 (file)
index 0000000..cdf20c3
--- /dev/null
@@ -0,0 +1,30 @@
+package org.simantics.simulator.toolkit;
+
+import java.util.Map;
+
+import org.simantics.databoard.binding.Binding;
+import org.simantics.simulator.variable.NodeManager;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+
+/**
+ * This interface is a simplified version of {@link NodeManager} that only
+ * provides node structure retrieval and property value getting and setting
+ * without regard to realms or listeners.
+ * 
+ * This used to exist in org.simantics.db.layer0 in earlier versions but was
+ * moved here to make it DB-independent.
+ * 
+ * @author Antti Villberg
+ * @since 1.34.0
+ * @param <Node>
+ */
+public interface StandardNodeManagerSupport<Node> {
+
+       Object getEngineValue(Node node) throws NodeManagerException;
+       Binding getEngineBinding(Node node) throws NodeManagerException;
+       void setEngineValue(Node node, Object value) throws NodeManagerException;
+       String getName(Node node);
+       Map<String,Node> getChildren(Node node);
+       Map<String,Node> getProperties(Node node);
+
+}
similarity index 87%
rename from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardRealm.java
rename to bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardRealm.java
index 68d002458b3af80e448f19f2f4314dc6b4794af2..e228b603d803d86a2fa6146bccbdd51a294b57ad 100644 (file)
@@ -1,7 +1,6 @@
-package org.simantics.db.layer0;
+package org.simantics.simulator.toolkit;
 
 import java.util.List;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.ThreadFactory;
@@ -9,24 +8,27 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
-import org.simantics.db.common.utils.Logger;
 import org.simantics.scl.runtime.SCLContext;
 import org.simantics.scl.runtime.tuple.Tuple0;
 import org.simantics.simulator.variable.Realm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> implements Realm {
+abstract public class StandardRealm<Node, Engine extends StandardNodeManagerSupport<Node>> implements Realm {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(StandardRealm.class);
 
     private String id;
-    private Thread executorThread;
+    protected Thread executorThread;
     private StandardRealmThreadFactory factory = new StandardRealmThreadFactory(this);
     private ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
-            new LinkedBlockingQueue<Runnable>(), factory);
+            new LinkedBlockingQueue<>(), factory);
     private Semaphore beginSyncExec = new Semaphore(0);
     private Semaphore endSyncExec = new Semaphore(0);
-    
+
     private Engine engine;
-    private StandardNodeManager<Node, Engine> nodeManager;
-    
+    protected StandardNodeManager<Node, Engine> nodeManager;
+
     private Runnable scheduleSyncExec = new Runnable() {
         @Override
         public void run() {
@@ -37,7 +39,7 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
             }
         }
     };
-    
+
     protected StandardRealm(Engine engine, String id) {
         this.engine = engine;
         this.id = id;
@@ -45,15 +47,15 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
     }
 
     abstract protected StandardNodeManager<Node, Engine> createManager();
-    
+
     protected String getSCLContextKey() {
-       return getClass().getSimpleName();
+        return getClass().getSimpleName();
     }
 
     public String getId() {
         return id;
     }
-    
+
     public Engine getEngine() {
         return engine;
     }
@@ -61,14 +63,13 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
     public Thread getThread() {
         return executorThread;
     }
-    
+
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public Object syncExec(Function fun) throws InterruptedException {
-       
         executor.execute(scheduleSyncExec);
         SCLContext context = SCLContext.getCurrent();
         Engine oldConnection = (Engine)context.put(getSCLContextKey(), engine);
-        
+
         try {
             beginSyncExec.acquire();
             Thread oldThread = executorThread;
@@ -83,7 +84,7 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
             context.put(getSCLContextKey(), oldConnection);
         }
     }
-    
+
     @SuppressWarnings("rawtypes")
     public void asyncExec(final Function fun) {
         executor.execute(new Runnable() {
@@ -99,26 +100,25 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
 
     @Override
     public void syncExec(Runnable runnable) throws InterruptedException {
-       
         if(executorThread == Thread.currentThread()) {
             try {
                 runnable.run();
             } catch (Throwable t) {
-               Logger.defaultLogError(t);
+               LOGGER.error("Error executing runnable in realm", t);
             } finally {
             }
             return;
         }
 
-       executor.execute(scheduleSyncExec);
-        
+        executor.execute(scheduleSyncExec);
+
         beginSyncExec.acquire();
         Thread oldThread = executorThread;
         executorThread = Thread.currentThread();
         try {
             runnable.run();
         } catch (Throwable t) {
-               Logger.defaultLogError(t);
+            LOGGER.error("Error executing runnable in realm", t);
         } finally {
             executorThread = oldThread;
             endSyncExec.release();
@@ -127,20 +127,19 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
 
     @Override
     public void asyncExec(Runnable runnable) {
-
-       if(executorThread == Thread.currentThread()) {
+        if(executorThread == Thread.currentThread()) {
             try {
                 runnable.run();
             } catch (Throwable t) {
-               Logger.defaultLogError(t);
+                LOGGER.error("Error executing runnable in realm", t);
             } finally {
             }
             return;
         }
-       
+
         executor.execute(runnable);
     }
-    
+
     public void close() {
         executor.shutdown();
         try {
@@ -153,7 +152,7 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
         } catch (InterruptedException e) {
             getLogger().info("Could not shutdown executor " + executor + " for realm " + this, e);
         }
-        
+
         factory.clear();
         factory = null;
         // Should never be true
@@ -161,7 +160,7 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
             executorThread.interrupt();
         executorThread = null;
         executor = null;
-        
+
         // Clear nodeManager
         nodeManager.clear();
         nodeManager = null;
@@ -178,22 +177,23 @@ abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> i
     }
 
     private static class StandardRealmThreadFactory implements ThreadFactory {
-        
+
         private StandardRealm<?, ?> realm;
 
         public StandardRealmThreadFactory(StandardRealm<?, ?> realm) {
             this.realm = realm;
         }
-        
+
         @Override
         public Thread newThread(Runnable r) {
             Thread t = new Thread(r);
             realm.setExecutorThread(t);
             return t;
         }
-        
+
         void clear() {
             realm = null;
         }
     }
-}
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator/.classpath b/bundles/org.simantics.simulator/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.simulator/.project b/bundles/org.simantics.simulator/.project
new file mode 100644 (file)
index 0000000..2487735
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.simulator</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.simulator/META-INF/MANIFEST.MF b/bundles/org.simantics.simulator/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..fb56010
--- /dev/null
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simulator
+Bundle-SymbolicName: org.simantics.simulator
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.slf4j.api;bundle-version="1.7.25",
+ org.eclipse.core.runtime,
+ org.simantics.databoard;bundle-version="0.6.6"
+Export-Package: org.simantics.simulator
diff --git a/bundles/org.simantics.simulator/build.properties b/bundles/org.simantics.simulator/build.properties
new file mode 100644 (file)
index 0000000..41eb6ad
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .\r
diff --git a/bundles/org.simantics.simulator/src/org/simantics/simulator/ExperimentState.java b/bundles/org.simantics.simulator/src/org/simantics/simulator/ExperimentState.java
new file mode 100644 (file)
index 0000000..6f04153
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.simulator;
+
+/**
+ * An abstract representation of the state of an experiment.
+ * 
+ * <p>
+ * A standard set of states can be found in
+ * <code>org.simantics.simulator.toolkit.StandardExperimentStates</code>.
+ * 
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public interface ExperimentState {
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.simulator/src/org/simantics/simulator/IDynamicExperimentLocal.java b/bundles/org.simantics.simulator/src/org/simantics/simulator/IDynamicExperimentLocal.java
new file mode 100644 (file)
index 0000000..2d3002d
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.simulator;
+
+import org.simantics.databoard.binding.Binding;
+
+public interface IDynamicExperimentLocal extends IExperimentLocal {
+
+    /**
+     * Starts or stops simulation depending on the
+     * parameter.
+     */
+    public void simulate(boolean enabled);
+
+    /**
+     * Simulates the experiment at lest the given period of time.
+     * Giving 0 as parameter simulates the experiment one 'step'.
+     * After the duration, the simulation is stopped.
+     */
+    public void simulateDuration(double duration);
+
+    void setVariableValueById(String id, Object value, Binding binding);
+    Object getVariableValueById(String id);
+
+    double getSimulationTime();
+
+}
diff --git a/bundles/org.simantics.simulator/src/org/simantics/simulator/IExperimentLocal.java b/bundles/org.simantics.simulator/src/org/simantics/simulator/IExperimentLocal.java
new file mode 100644 (file)
index 0000000..addfbcf
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.simulator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public interface IExperimentLocal {
+
+    <T> T getService(Class<T> clazz);
+
+    String getIdentifier();
+
+    /**
+     * @param monitor
+     *            the progress monitor to use for reporting progress to the user
+     *            during the operation. It is the caller's responsibility to
+     *            call done() on the given monitor. Accepts null, indicating
+     *            that no progress should be reported and that the operation
+     *            cannot be cancelled.
+     */
+    void shutdown(IProgressMonitor monitor);
+
+    ExperimentState getStateL();
+    void changeStateL(ExperimentState state);
+
+}
index 8ecef199d819ff57e72b3dabf1079e6acdbb7612..cb7afb74dfc76525df7f0ba62d67a6edb1845c58 100644 (file)
@@ -29,7 +29,9 @@ Require-Bundle: org.simantics.layer0.utils,
  org.eclipse.e4.core.contexts,
  org.eclipse.e4.ui.di,
  org.simantics.browsing.ui.swt,
- org.slf4j.api;bundle-version="1.7.20"
+ org.slf4j.api;bundle-version="1.7.20",
+ org.simantics.simulator.toolkit;bundle-version="1.0.0",
+ org.simantics.simulator.toolkit.db;bundle-version="1.0.0"
 Export-Package: org.apache.commons.math3.stat.regression,
  org.simantics.spreadsheet.graph,
  org.simantics.spreadsheet.graph.adapter,
index 5850eb84750d7303e64a33abac540fc850c7e4ab..607661163f5f138701da9e08acf46ea61d48cb46 100644 (file)
@@ -45,7 +45,6 @@ import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.common.request.WriteResultRequest;
 import org.simantics.db.common.session.SessionEventListenerAdapter;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.StandardRealm;
 import org.simantics.db.layer0.request.PossibleURIVariable;
 import org.simantics.db.layer0.request.VariableName;
 import org.simantics.db.layer0.request.VariableRead;
@@ -56,6 +55,7 @@ import org.simantics.db.procedure.SyncListener;
 import org.simantics.db.request.Write;
 import org.simantics.db.service.SessionEventSupport;
 import org.simantics.layer0.Layer0;
+import org.simantics.simulator.toolkit.StandardRealm;
 import org.simantics.spreadsheet.Adaptable;
 import org.simantics.spreadsheet.CellEditor;
 import org.simantics.spreadsheet.ClientModel;
index 277b10cb0635f6e8401f78069a175f56104bc037..f87ce4d0675e851fee84a432d093241f38245607 100644 (file)
@@ -10,9 +10,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.StandardEngine;
+import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
 import org.simantics.spreadsheet.graph.synchronization.LineNodeUpdater;
 import org.simantics.spreadsheet.graph.synchronization.LineUpdater;
@@ -33,7 +36,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.longs.LongArraySet;
 import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
 
-public class SpreadsheetBook implements SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, StandardEngine<SheetNode>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
+public class SpreadsheetBook implements StandardNodeManagerSupport<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
 
        private static final long serialVersionUID = 7417208688311691396L;
        
@@ -90,7 +93,17 @@ public class SpreadsheetBook implements SpreadsheetElement<SpreadsheetElement, S
        }
        
        @Override
-       public Object getValue(SheetNode node) {
+       public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
+               Object value = getEngineValue(node);
+               if(value instanceof Variant) return Bindings.VARIANT;
+               if(value instanceof String) return Bindings.STRING;
+               if(value instanceof Boolean) return Bindings.BOOLEAN;
+               else return Bindings.VOID;
+               
+       }
+       
+       @Override
+       public Object getEngineValue(SheetNode node) {
                if(node instanceof SpreadsheetCellContent) {
                        try {
                                SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
@@ -139,7 +152,7 @@ public class SpreadsheetBook implements SpreadsheetElement<SpreadsheetElement, S
        }
 
        @Override
-       public void setValue(SheetNode node, Object value) {
+       public void setEngineValue(SheetNode node, Object value) {
        }
 
        @Override
index 285f6ce5e26edde167f59329e48713ca5a4cb01f..364e9261b7574bc9c440c29533c63f56d11aeb5e 100644 (file)
@@ -9,6 +9,7 @@ import java.util.Optional;
 import org.simantics.spreadsheet.Range;
 import org.simantics.spreadsheet.graph.parser.ast.AstRange;
 
+@SuppressWarnings("rawtypes")
 public class SpreadsheetEngine implements SpreadsheetElement, SheetNode {
 
        private static final long serialVersionUID = -5246063647558595642L;
index cf288dd808a1ac77ea6a1d04e9efd15fc0c3caa4..297ac9dc9fffe17f2afd48fdd6d4dd9b0913e879 100644 (file)
@@ -27,13 +27,13 @@ import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.utils.LiteralFileUtil;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ServiceException;
-import org.simantics.db.layer0.StandardRealm;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.db.service.ClusteringSupport;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.runtime.tuple.Tuple2;
+import org.simantics.simulator.toolkit.StandardRealm;
 import org.simantics.spreadsheet.Range;
 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
index a6ebeb0980ad0eb811d75b9c31e28d7f318a33ab..56985d16c948c6754551484294381184e2eb1b62 100644 (file)
@@ -3,21 +3,21 @@ package org.simantics.spreadsheet.graph;
 import java.util.Collections;
 import java.util.Set;
 
-import org.simantics.db.layer0.StandardNodeManager;
 import org.simantics.layer0.Layer0;
+import org.simantics.simulator.toolkit.StandardNodeManager;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
 import org.simantics.structural.stubs.StructuralResource2;
 
 @SuppressWarnings("rawtypes")
 public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, SpreadsheetBook> {
-       
+
     public SpreadsheetNodeManager(SpreadsheetRealm realm) {
         super(realm, realm.getEngine());
     }
 
     static final Set<String> COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component);
-            
+
     @Override
     public Set<String> getClassifications(SheetNode node) throws NodeManagerException {
         checkThreadAccess();
@@ -26,22 +26,22 @@ public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, Sprea
         else
             return Collections.emptySet();
     }
-    
+
     @Override
     public String getPropertyURI(SheetNode parent, SheetNode property) {
-       if(property instanceof SpreadsheetCellContent) {
+        if(property instanceof SpreadsheetCellContent) {
             return SpreadsheetResource.URIs.Cell_content;
-       } else if(property instanceof SpreadsheetTypeNode) {
+        } else if(property instanceof SpreadsheetTypeNode) {
             return Layer0.URIs.typeURI;
-       } else if(property instanceof SpreadsheetCellContentExpression) {
+        } else if(property instanceof SpreadsheetCellContentExpression) {
             return Layer0.URIs.SCLValue_expression;
-       } else if (property instanceof SpreadsheetCellStyle) {
-           return SpreadsheetResource.URIs.Cell_style;
-       } else if (property instanceof SpreadsheetCellEditable){
-           return SpreadsheetResource.URIs.Cell_editable;
-       } else {
-               return null;
-       }
+        } else if (property instanceof SpreadsheetCellStyle) {
+            return SpreadsheetResource.URIs.Cell_style;
+        } else if (property instanceof SpreadsheetCellEditable){
+            return SpreadsheetResource.URIs.Cell_editable;
+        } else {
+            return null;
+        }
     }
-    
+
 }
index 90ef89fab61ad5ca4cd8b028b18af160e94f1e1a..5ec73b1e5729ddea5eaa870c59c052a9a929308e 100644 (file)
@@ -1,14 +1,15 @@
 package org.simantics.spreadsheet.graph;
 
-import org.simantics.db.layer0.StandardNodeManager;
-import org.simantics.db.layer0.StandardRealm;
+import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.StandardRealm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@SuppressWarnings("rawtypes")
 public class SpreadsheetRealm extends StandardRealm<SheetNode,SpreadsheetBook> {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetRealm.class);
-    
+
        SpreadsheetRealm(SpreadsheetBook book, String id) {
                super(book, id);
        }
index d90fe3106613fbad5907920a5711f00492c4bc51..19c9948060f60787d94d99f441d920fe2653d0f0 100644 (file)
@@ -15,11 +15,11 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.StandardRealm;
-import org.simantics.db.layer0.StandardSessionManager;
 import org.simantics.db.layer0.variable.ProxyVariables;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.simulator.toolkit.db.StandardSessionManager;
 import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
index 0affbc1c56cade37845ebee95ed19a33155b19ca..1439a941dcb53d5a023d894a4615cb8924d469d0 100644 (file)
@@ -29,7 +29,6 @@ import org.simantics.db.common.request.WriteRequest;
 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.StandardRealm;
 import org.simantics.db.layer0.exception.MissingVariableException;
 import org.simantics.db.layer0.function.StandardChildDomainChildren;
 import org.simantics.db.layer0.request.PossibleActiveRun;
@@ -50,6 +49,7 @@ import org.simantics.document.server.io.IFont;
 import org.simantics.document.server.io.ITableCell;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.simulator.toolkit.StandardRealm;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.spreadsheet.CellEditor;
 import org.simantics.spreadsheet.ClientModel;
index 43a6f72ab40084660b6584dcbe9c5486b286d7b5..59ac14535c39204f6960543fc451ce99328dd640 100644 (file)
                <module>org.simantics.simulation.ontology</module>
                <module>org.simantics.simulation.sequences</module>
                <module>org.simantics.simulation.ui</module>
+               <module>org.simantics.simulator</module>
+               <module>org.simantics.simulator.toolkit</module>
+               <module>org.simantics.simulator.toolkit.db</module>
                <module>org.simantics.simulator.variable</module>
                <module>org.simantics.softwareconfiguration.ontology</module>
                <module>org.simantics.spreadsheet</module>
index 5aeb671c855c366e4d55a4b1487c068ba283614b..b9e8cfcfcd3944b2936f3361d92be65ac77a6e07 100644 (file)
          id="org.simantics.scl.ui.feature"
          version="0.0.0"/>
 
+   <includes
+         id="org.simantics.simulator.toolkit.feature"
+         version="0.0.0"/>
+
+   <includes
+         id="org.simantics.simulator.toolkit.db.feature"
+         version="0.0.0"/>
+
    <plugin
          id="org.simantics.fileimport"
          download-size="0"
diff --git a/features/org.simantics.simulator.toolkit.db.feature/.project b/features/org.simantics.simulator.toolkit.db.feature/.project
new file mode 100644 (file)
index 0000000..5255a41
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.simulator.toolkit.db.feature</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.FeatureBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.FeatureNature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/features/org.simantics.simulator.toolkit.db.feature/build.properties b/features/org.simantics.simulator.toolkit.db.feature/build.properties
new file mode 100644 (file)
index 0000000..82ab19c
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = feature.xml\r
diff --git a/features/org.simantics.simulator.toolkit.db.feature/feature.xml b/features/org.simantics.simulator.toolkit.db.feature/feature.xml
new file mode 100644 (file)
index 0000000..8751163
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.simantics.simulator.toolkit.db.feature"
+      label="Simulator Toolkit for Simantics Database"
+      version="1.0.0.qualifier"
+      provider-name="Semantum Oy">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <includes
+         id="org.simantics.simulator.toolkit.feature"
+         version="0.0.0"/>
+
+   <plugin
+         id="org.simantics.simulator.toolkit.db"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.simantics.simulator.toolkit.feature/.project b/features/org.simantics.simulator.toolkit.feature/.project
new file mode 100644 (file)
index 0000000..241fafe
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.simulator.toolkit.feature</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.FeatureBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.FeatureNature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/features/org.simantics.simulator.toolkit.feature/build.properties b/features/org.simantics.simulator.toolkit.feature/build.properties
new file mode 100644 (file)
index 0000000..82ab19c
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = feature.xml\r
diff --git a/features/org.simantics.simulator.toolkit.feature/feature.xml b/features/org.simantics.simulator.toolkit.feature/feature.xml
new file mode 100644 (file)
index 0000000..79c4b2c
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.simantics.simulator.toolkit.feature"
+      label="Simantics Simulator Toolkit"
+      version="1.0.0.qualifier"
+      provider-name="Semantum Oy">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <plugin
+         id="org.simantics.simulator"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulator.toolkit"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulator.variable"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.databoard"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulation.sequences"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.scl.osgi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
index b81d38a3be9c6b6d18acb29d7dd6dbfa675a0160..33385bcaa995c14f79f5e057921f8b965b69c03b 100644 (file)
          id="org.simantics.scl"
          version="0.0.0"/>
 
+   <includes
+         id="org.simantics.simulator.toolkit.db.feature"
+         version="0.0.0"/>
+
    <plugin
          id="org.simantics.spreadsheet.common"
          download-size="0"
index 972a35a3baa7f564c861b9649f03062efc235965..7b7e3335bdd8ae6b701ac70d7a3311e66d6dbaff 100644 (file)
         <module>org.simantics.sdk.feature</module>
         <module>org.simantics.selectionview.feature</module>
         <module>org.simantics.simulation.feature</module>
+        <module>org.simantics.simulator.toolkit.feature</module>
+        <module>org.simantics.simulator.toolkit.db.feature</module>
         <module>org.simantics.spreadsheet.feature</module>
         <module>org.simantics.spreadsheet.ui.feature</module>
         <module>org.simantics.structural.feature</module>