--- /dev/null
+package org.simantics.db.layer0;\r
+\r
+import java.util.Collection;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.common.request.ParametrizedPrimitiveRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.NodeSupport;\r
+import org.simantics.db.procedure.Listener;\r
+\r
+abstract public class StandardSessionManager<Node, Engine extends StandardEngine<Node>> {\r
+\r
+ private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();\r
+ private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<String, StandardRealm<Node,Engine>>(); \r
+ private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<String, NodeSupport<Node>>(); \r
+\r
+ // Accessing Realms should be done over ParametrizedPrimitveRead for the\r
+ // case if a realm is destroyed and new one is created with the same id than\r
+ // the previously deleted one for the listeners to get discarded and new\r
+ // registered\r
+ private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {\r
+\r
+ public RealmRequest(String parameter) {\r
+ super(parameter);\r
+ }\r
+\r
+ @Override\r
+ public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {\r
+\r
+ StandardRealm<Node, Engine> realm = REALMS.get(parameter);\r
+ if (realm == null) {\r
+ try {\r
+ realm = createRealmInner(graph, parameter);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ if(procedure.isDisposed()) {\r
+ procedure.execute(realm);\r
+ return;\r
+ }\r
+ \r
+ Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);\r
+ assert(existing == null);\r
+ realmListeners.put(parameter, procedure);\r
+ procedure.execute(realm);\r
+ }\r
+\r
+ private StandardRealm<Node,Engine> createRealmInner(ReadGraph graph, String id) throws DatabaseException {\r
+ Engine engine = createEngine(graph, id);\r
+ StandardRealm<Node,Engine> realm = createRealm(engine, id);\r
+ modifyRealms(id, realm);\r
+ return realm;\r
+ }\r
+ }\r
+ \r
+ protected StandardSessionManager() {\r
+ }\r
+ \r
+ private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {\r
+ Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);\r
+ if(listener != null) {\r
+ if(listener.isDisposed()) {\r
+ realmListeners.remove(key);\r
+ } else {\r
+ return listener;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {\r
+ if(realm != null) {\r
+ REALMS.put(key, realm);\r
+ } else {\r
+ REALMS.remove(key);\r
+ }\r
+ Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);\r
+ if(listener != null) {\r
+ listener.execute(realm);\r
+ }\r
+ }\r
+\r
+ public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {\r
+ synchronized(SUPPORTS) {\r
+ NodeSupport<Node> result = SUPPORTS.get(id);\r
+ if(result == null) {\r
+ StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);\r
+ result = new NodeSupport<Node>(realm.getNodeManager());\r
+ SUPPORTS.put(id, result);\r
+ }\r
+ return result;\r
+ }\r
+ }\r
+ \r
+ public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {\r
+ synchronized(REALMS) {\r
+ return graph.syncRequest(new RealmRequest(id));\r
+ }\r
+ }\r
+ \r
+ protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;\r
+ protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);\r
+ \r
+ public void removeRealm(String id) {\r
+ modifyRealms(id, null);\r
+ // if node support has been created remove it as well\r
+ SUPPORTS.remove(id);\r
+ }\r
+ \r
+ public Collection<String> getRealms() {\r
+ return REALMS.keySet();\r
+ }\r
+}\r