asclass ConceptFieldIndexBase_certainValues implements IConceptIndex, IPartialFieldIndex { Concepts concepts; Class cc; S field; Map objectToValue = syncHashMap(); MultiSetMap valueToObject; // initialized in subclass *() { init(); } *(Class cc, S field) { this(db_mainConcepts(), cc, field); } *(Concepts *concepts, Class *cc, S *field) { this(); concepts.addConceptIndex(this); for (A c : list(concepts, cc)) updateImpl(c); register(); } abstract void init(); abstract void register(); public abstract bool isApplicableValue(Val value); public void update(Concept c) { if (!isInstance(cc, c)) ret; updateImpl((A) c); } synchronized void updateImpl(A c) { Val newValue = cast cget(c, field); Val oldValue = objectToValue.get(c); if (newValue == oldValue && (oldValue != null || objectToValue.containsKey(c))) ret; valueToObject.remove(oldValue, c); if (isApplicableValue(newValue)) { valueToObject.put(newValue, c); put(objectToValue, c, newValue); } else main remove(objectToValue, c); } public synchronized void remove(Concept c) { if (!isInstance(cc, c)) ret; if (!objectToValue.containsKey(c)) ret; Val value = objectToValue.get(c); objectToValue.remove(c); valueToObject.remove(value, (A) c); } synchronized A get(Val value) { ret valueToObject.getFirst(value); } // older version - may return empty list as null // should be phased out everywhere! public synchronized Cl getAll(Val value) { ret valueToObject.get(value); } // newer version - returns null iff it's not applicable public synchronized Cl getAllIfApplicable(Val value) { if (!isApplicableValue(value)) null; ret unnullForIteration(valueToObject.get(value)); } public synchronized L allValues() { ret cloneKeys_noSync(valueToObject.data); } IterableIterator objectIterator() { ret navigableMultiSetMapValuesIterator_concurrent(valueToObject, this); } public synchronized MultiSet allValues_multiSet() { ret multiSetMapToMultiSet(valueToObject); } public Class conceptClass() { ret cc; } public int countConcepts() { ret l(objectToValue); } public Cl allConcepts() { ret (Cl) keys(objectToValue); } O mutex() { this; } }