// TODO: run dbBot() sclass ConceptsLoadedOnDemand { new Map loaded; // key = just the case ID. value can be null in case of error L onCaseLoaded; // L L onUnloadingCase; // L Lock lock = lock(); Concepts get(S caseID, O extraInfo) { ret conceptsForCase(caseID, extraInfo); } Concepts getIfLoaded(S caseID) { lock lock; ret loaded.get(unnull(caseID)); } // caseID may be empty, then you get the program's main DB Concepts conceptsForCase(S caseID, O extraInfo) { lock lock; //assertNempty(+caseID); caseID = unnull(caseID); if (loaded.containsKey(caseID)) ret assertNotNull("Concepts load error", loaded.get(caseID)); S id = dbID(caseID); print("Loading concepts for case " + id); Concepts cc = new Concepts(id); cc.persist(); loaded.put(caseID, cc); pcallFAll(onCaseLoaded, caseID, extraInfo, cc); ret cc; } S dbID(S caseID) { ret combineWithSlash(getDBProgramID(), caseID); } void cleanMeUp { cleanUpAndClear(loaded); } void onCaseLoaded(VF3 f) { onCaseLoaded = listCreateAndAdd(onCaseLoaded, f); } void onUnloadingCase(VF2 f) { onUnloadingCase = listCreateAndAdd(onUnloadingCase, f); } void unloadCase(S caseID) { lock lock; caseID = unnull(caseID); Concepts cc = loaded.get(caseID); if (cc != null) { pcallFAll(onUnloadingCase, caseID, cc); cleanUp(cc); loaded.remove(caseID); } } }