b82860de1010b79bcaa9f31e6737f4cc7e490348
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / StandardSessionManager.java
1 package org.simantics.db.layer0;
2
3 import java.util.Collection;
4 import java.util.concurrent.ConcurrentHashMap;
5
6 import org.simantics.db.ReadGraph;
7 import org.simantics.db.common.request.ParametrizedPrimitiveRead;
8 import org.simantics.db.exception.DatabaseException;
9 import org.simantics.db.layer0.variable.NodeSupport;
10 import org.simantics.db.procedure.Listener;
11
12 abstract public class StandardSessionManager<Node, Engine extends StandardEngine<Node>> {
13
14     private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();
15     private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<String, StandardRealm<Node,Engine>>(); 
16     private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<String, NodeSupport<Node>>(); 
17
18     // Accessing Realms should be done over ParametrizedPrimitveRead for the
19     // case if a realm is destroyed and new one is created with the same id than
20     // the previously deleted one for the listeners to get discarded and new
21     // registered
22     private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {
23
24         public RealmRequest(String parameter) {
25             super(parameter);
26         }
27
28         @Override
29         public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
30
31             StandardRealm<Node, Engine> realm = REALMS.get(parameter);
32             if (realm == null) {
33                 try {
34                     realm = createRealmInner(graph, parameter);
35                 } catch (DatabaseException e) {
36                     e.printStackTrace();
37                 }
38             }
39             
40             if(procedure.isDisposed()) {
41                 procedure.execute(realm);
42                 return;
43             }
44             
45             Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
46             assert(existing == null);
47             realmListeners.put(parameter, procedure);
48             procedure.execute(realm);
49         }
50
51         private StandardRealm<Node,Engine> createRealmInner(ReadGraph graph, String id) throws DatabaseException {
52             Engine engine = createEngine(graph, id);
53             StandardRealm<Node,Engine> realm = createRealm(engine, id);
54             modifyRealms(id, realm);
55             return realm;
56         }
57     }
58     
59     protected StandardSessionManager() {
60     }
61     
62     private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
63         Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
64         if(listener != null) {
65             if(listener.isDisposed()) {
66                 realmListeners.remove(key);
67             } else {
68                 return listener;
69             }
70         }
71         return null;
72     }
73     
74     private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
75         if(realm != null) {
76             REALMS.put(key, realm);
77         } else {
78             REALMS.remove(key);
79         }
80         Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
81         if(listener != null) {
82             listener.execute(realm);
83         }
84     }
85
86     public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {
87         synchronized(SUPPORTS) {
88                 NodeSupport<Node> result = SUPPORTS.get(id);
89                 if(result == null) {
90                         StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
91                         result = new NodeSupport<Node>(realm.getNodeManager());
92                         SUPPORTS.put(id, result);
93                 }
94                 return result;
95         }
96     }
97     
98     public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {
99         synchronized(REALMS) {
100             return graph.syncRequest(new RealmRequest(id));
101         }
102     }
103     
104     protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
105     protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
106     
107     public void removeRealm(String id) {
108         modifyRealms(id, null);
109         // if node support has been created remove it as well
110         SUPPORTS.remove(id);
111     }
112     
113     public Collection<String> getRealms() {
114         return REALMS.keySet();
115     }
116 }