+++ /dev/null
-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);
-
-}
+++ /dev/null
-package org.simantics.db.layer0;
-
-public interface StandardNode {
-
-}
*/
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() {
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;
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);
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;
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() {
*/
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.
*/
package org.simantics.simulation.experiment;
public enum ExperimentState {
- INITIALIZING, RUNNING, STOPPED, DISPOSED
+ INITIALIZING, RUNNING, STOPPED, TO_BE_DISPOSED, DISPOSED
}
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+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
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+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
-package org.simantics.db.layer0;
+package org.simantics.simulator.toolkit.db;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
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
@Override
public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
-
StandardRealm<Node, Engine> realm = REALMS.get(parameter);
if (realm == null) {
try {
e.printStackTrace();
}
}
-
+
if(procedure.isDisposed()) {
procedure.execute(realm);
return;
}
-
+
Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
assert(existing == null);
realmListeners.put(parameter, procedure);
return realm;
}
}
-
+
protected StandardSessionManager() {
}
-
+
private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
if(listener != null) {
}
return null;
}
-
+
private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
if(realm != null) {
REALMS.put(key, realm);
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
if (support != null)
support.dispose();
}
-
+
public Collection<String> getRealms() {
return REALMS.keySet();
}
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+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
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+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);
+ }
+
+}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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
--- /dev/null
+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 {
+}
* 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;
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;
*
* @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 {
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
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);
}
}
}
-
+
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() {
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
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
}
valueCache.clear();
listeners.clear();
}
-}
+
+}
\ No newline at end of file
--- /dev/null
+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);
+
+}
-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;
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() {
}
}
};
-
+
protected StandardRealm(Engine engine, String id) {
this.engine = engine;
this.id = id;
}
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;
}
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;
context.put(getSCLContextKey(), oldConnection);
}
}
-
+
@SuppressWarnings("rawtypes")
public void asyncExec(final Function fun) {
executor.execute(new Runnable() {
@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();
@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 {
} catch (InterruptedException e) {
getLogger().info("Could not shutdown executor " + executor + " for realm " + this, e);
}
-
+
factory.clear();
factory = null;
// Should never be true
executorThread.interrupt();
executorThread = null;
executor = null;
-
+
// Clear nodeManager
nodeManager.clear();
nodeManager = null;
}
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
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+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
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+/*******************************************************************************
+ * 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
--- /dev/null
+/*******************************************************************************
+ * 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();
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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);
+
+}
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,
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;
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;
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;
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;
}
@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;
}
@Override
- public void setValue(SheetNode node, Object value) {
+ public void setEngineValue(SheetNode node, Object value) {
}
@Override
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;
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;
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();
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;
+ }
}
-
+
}
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);
}
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;
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;
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;
<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>
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"
--- /dev/null
+<?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
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?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>
--- /dev/null
+<?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
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?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>
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"
<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>