package org.simantics.db.layer0; 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; abstract public class StandardSessionManager> { private ConcurrentHashMap>> realmListeners = new ConcurrentHashMap<>(); private ConcurrentHashMap> REALMS = new ConcurrentHashMap>(); private ConcurrentHashMap> 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> { public RealmRequest(String parameter) { super(parameter); } @Override public void register(ReadGraph graph, Listener> procedure) { StandardRealm 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> existing = getOrDisposeListener(parameter); assert(existing == null); realmListeners.put(parameter, procedure); procedure.execute(realm); } private StandardRealm createRealmInner(ReadGraph graph, String id) throws DatabaseException { Engine engine = createEngine(graph, id); StandardRealm realm = createRealm(engine, id); modifyRealms(id, realm); return realm; } } protected StandardSessionManager() { } private Listener> getOrDisposeListener(String key) { Listener> listener = realmListeners.get(key); if(listener != null) { if(listener.isDisposed()) { realmListeners.remove(key); } else { return listener; } } return null; } private void modifyRealms(String key, StandardRealm realm) { if(realm != null) { REALMS.put(key, realm); } else { StandardRealm removedRealm = REALMS.remove(key); if (removedRealm != null) removedRealm.close(); } Listener> listener = getOrDisposeListener(key); if(listener != null) { listener.execute(realm); } } public NodeSupport getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException { synchronized(SUPPORTS) { NodeSupport result = SUPPORTS.get(id); if(result == null) { StandardRealm realm = getOrCreateRealm(graph, id); result = new NodeSupport(realm.getNodeManager()); SUPPORTS.put(id, result); } return result; } } public StandardRealm 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 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 support = SUPPORTS.remove(id); if (support != null) support.dispose(); } public Collection getRealms() { return REALMS.keySet(); } }