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 extends Concept> conceptClass() { ret cc; }
public int countConcepts() { ret l(objectToValue); }
public Cl allConcepts() { ret (Cl) keys(objectToValue); }
O mutex() { this; }
}