]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardVariableSessionManager.java
Refactoring of simulator toolkit
[simantics/platform.git] / bundles / org.simantics.simulator.toolkit.db / src / org / simantics / simulator / toolkit / db / StandardVariableSessionManager.java
diff --git a/bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardVariableSessionManager.java b/bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardVariableSessionManager.java
new file mode 100644 (file)
index 0000000..5e824f4
--- /dev/null
@@ -0,0 +1,129 @@
+package org.simantics.simulator.toolkit.db;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.WriteGraph;
+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;
+import org.simantics.simulator.variable.NodeManager;
+
+public abstract class StandardVariableSessionManager<Node, Engine extends StandardNodeManagerSupport<Node>> {
+
+    private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();
+    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
+    // the previously deleted one for the listeners to get discarded and new
+    // registered
+    private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {
+
+        public RealmRequest(String parameter) {
+            super(parameter);
+        }
+
+        @Override
+        public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
+            StandardRealm<Node, Engine> realm = REALMS.get(parameter);
+            if (realm == null) {
+                try {
+                    realm = createRealmInner(graph, parameter);
+                } catch (DatabaseException e) {
+                    e.printStackTrace();
+                }
+            }
+
+            if(procedure.isDisposed()) {
+                procedure.execute(realm);
+                return;
+            }
+
+            Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
+            assert(existing == null);
+            realmListeners.put(parameter, procedure);
+            procedure.execute(realm);
+        }
+
+        private StandardRealm<Node,Engine> createRealmInner(ReadGraph graph, String id) throws DatabaseException {
+            Engine engine = createEngine(graph, id);
+            StandardRealm<Node,Engine> realm = createRealm(engine, id);
+            modifyRealms(id, realm);
+            return realm;
+        }
+    }
+
+    protected StandardVariableSessionManager() {
+    }
+
+    private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
+        Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
+        if(listener != null) {
+            if(listener.isDisposed()) {
+                realmListeners.remove(key);
+            } else {
+                return listener;
+            }
+        }
+        return null;
+    }
+
+    private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
+        if(realm != null) {
+            REALMS.put(key, realm);
+        } else {
+            StandardRealm<Node, Engine> removedRealm = REALMS.remove(key);
+            if (removedRealm != null)
+                removedRealm.close();
+        }
+        Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
+        if(listener != null) {
+            listener.execute(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);
+                NodeManager nodeManager = realm.getNodeManager();
+                if(!(nodeManager instanceof StandardVariableNodeManager))
+                    throw new DatabaseException("StandardVariableSessionManager requires an instance of  StandardVariableNodeManager, got " + nodeManager.getClass());
+                StandardVariableNodeManager svnm = (StandardVariableNodeManager)nodeManager;
+                result = svnm.support;
+                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
+        realmListeners.remove(id);
+        // if node support has been created remove it as well
+        NodeSupport<Node> support = SUPPORTS.remove(id);
+        if (support != null)
+            support.dispose();
+    }
+
+    public Collection<String> getRealms() {
+        return REALMS.keySet();
+    }
+}