1 package org.simantics.simulator.toolkit.db;
3 import java.util.Collection;
4 import java.util.concurrent.ConcurrentHashMap;
6 import org.simantics.db.ReadGraph;
7 import org.simantics.db.WriteGraph;
8 import org.simantics.db.common.request.ParametrizedPrimitiveRead;
9 import org.simantics.db.exception.DatabaseException;
10 import org.simantics.db.layer0.variable.NodeSupport;
11 import org.simantics.db.procedure.Listener;
12 import org.simantics.simulator.toolkit.StandardNodeManager;
13 import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
14 import org.simantics.simulator.toolkit.StandardRealm;
16 public abstract class StandardSessionManager<Node, Engine extends StandardNodeManagerSupport<Node>> {
18 private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();
19 private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<>();
20 private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<>();
22 // Accessing Realms should be done over ParametrizedPrimitveRead for the
23 // case if a realm is destroyed and new one is created with the same id than
24 // the previously deleted one for the listeners to get discarded and new
26 private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {
28 public RealmRequest(String parameter) {
33 public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
34 StandardRealm<Node, Engine> realm = REALMS.get(parameter);
37 realm = createRealmInner(graph, parameter);
38 } catch (DatabaseException e) {
43 if(procedure.isDisposed()) {
44 procedure.execute(realm);
48 Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
49 assert(existing == null);
50 realmListeners.put(parameter, procedure);
51 procedure.execute(realm);
54 private StandardRealm<Node,Engine> createRealmInner(ReadGraph graph, String id) throws DatabaseException {
55 Engine engine = createEngine(graph, id);
56 StandardRealm<Node,Engine> realm = createRealm(engine, id);
57 modifyRealms(id, realm);
62 protected StandardSessionManager() {
65 private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
66 Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
67 if(listener != null) {
68 if(listener.isDisposed()) {
69 realmListeners.remove(key);
77 private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
79 REALMS.put(key, realm);
81 StandardRealm<Node, Engine> removedRealm = REALMS.remove(key);
82 if (removedRealm != null)
85 Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
86 if(listener != null) {
87 listener.execute(realm);
91 public void registerNodeSupport(StandardNodeManager<Node,Engine> realm, NodeSupport<Node> support) {
95 public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {
96 synchronized(SUPPORTS) {
97 NodeSupport<Node> result = SUPPORTS.get(id);
99 StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
100 result = new NodeSupport<Node>(realm.getNodeManager());
101 registerNodeSupport(realm.getNodeManager(), result);
102 SUPPORTS.put(id, result);
108 public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {
109 synchronized(REALMS) {
110 return graph.syncRequest(new RealmRequest(id));
114 protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
115 protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
117 public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
118 modifyRealms(id, null);
119 // remove listeners from this realm
120 realmListeners.remove(id);
121 // if node support has been created remove it as well
122 NodeSupport<Node> support = SUPPORTS.remove(id);
127 public Collection<String> getRealms() {
128 return REALMS.keySet();