]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.simulator.toolkit.db;
2
3 import java.util.Collection;
4 import java.util.concurrent.ConcurrentHashMap;
5
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.StandardNodeManagerSupport;
13 import org.simantics.simulator.toolkit.StandardRealm;
14 import org.simantics.simulator.variable.NodeManager;
15
16 public abstract class StandardVariableSessionManager<Node, Engine extends StandardNodeManagerSupport<Node>> {
17
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<>();
21
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
25     // registered
26     private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {
27
28         public RealmRequest(String parameter) {
29             super(parameter);
30         }
31
32         @Override
33         public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
34             StandardRealm<Node, Engine> realm = REALMS.get(parameter);
35             if (realm == null) {
36                 try {
37                     realm = createRealmInner(graph, parameter);
38                 } catch (DatabaseException e) {
39                     e.printStackTrace();
40                 }
41             }
42
43             if(procedure.isDisposed()) {
44                 procedure.execute(realm);
45                 return;
46             }
47
48             Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
49             assert(existing == null);
50             realmListeners.put(parameter, procedure);
51             procedure.execute(realm);
52         }
53
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);
58             return realm;
59         }
60     }
61
62     protected StandardVariableSessionManager() {
63     }
64
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);
70             } else {
71                 return listener;
72             }
73         }
74         return null;
75     }
76
77     private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
78         if(realm != null) {
79             REALMS.put(key, realm);
80         } else {
81             StandardRealm<Node, Engine> removedRealm = REALMS.remove(key);
82             if (removedRealm != null)
83                 removedRealm.close();
84         }
85         Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
86         if(listener != null) {
87             listener.execute(realm);
88         }
89     }
90
91     public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {
92         synchronized(SUPPORTS) {
93             NodeSupport<Node> result = SUPPORTS.get(id);
94             if(result == null) {
95                 StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
96                 NodeManager nodeManager = realm.getNodeManager();
97                 if(!(nodeManager instanceof StandardVariableNodeManager))
98                     throw new DatabaseException("StandardVariableSessionManager requires an instance of  StandardVariableNodeManager, got " + nodeManager.getClass());
99                 StandardVariableNodeManager svnm = (StandardVariableNodeManager)nodeManager;
100                 result = svnm.support;
101                 SUPPORTS.put(id, result);
102             }
103             return result;
104         }
105     }
106
107     public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {
108         synchronized(REALMS) {
109             return graph.syncRequest(new RealmRequest(id));
110         }
111     }
112
113     protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
114     protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
115
116     public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
117         modifyRealms(id, null);
118         // remove listeners from this realm
119         realmListeners.remove(id);
120         // if node support has been created remove it as well
121         NodeSupport<Node> support = SUPPORTS.remove(id);
122         if (support != null)
123             support.dispose();
124     }
125
126     public Collection<String> getRealms() {
127         return REALMS.keySet();
128     }
129 }