/*
* AbstractIndexTable.java
*
* Created on July 2, 2001, 2:55 PM
*/
package context.arch.discoverer.component.dataModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import context.arch.discoverer.ComponentDescription;
import context.arch.discoverer.component.AbstractElement;
/**
*
* The IndexTable is sort of a reverse lookup key-value table, where the key is the component, and value is the index.
* So for each component, there can be multiple indices (dependent on the class type of V_INTERNAL).
*
* IndexTable is refactored from IndexTableIF, from an interface to an abstract class.
* It uses most of the code from AbstractIndexTableImpl and replaces it, since the latter was the only class implementing IndexTableIF.
*
* Notice the insidious "switcheroo" where the key for IndexTable has a different class than the internal Hashtable key.
* This is because we take in keys of type K, and convert it to String to store internally.
* TODO: why do we need to store internally as a string???
*
* @author Agathe
* @author Brian Y. Lim
*/
public abstract class IndexTable<E> extends ConcurrentHashMap<E, List<ComponentDescription>> {
private static final long serialVersionUID = 7407778683914827251L;
protected String name;
protected AbstractElement<E, ?,?> delegate;
public IndexTable(String indexName, AbstractElement<E, ?,?> delegate) {
super();
this.name = indexName;
this.delegate = delegate;
}
public void addComponent(ComponentDescription component) {
E elementAsKey = extractKey(component);
List<ComponentDescription> components = super.get(elementAsKey);
// create components entry if not done before
if (components == null) {
components = Collections.synchronizedList(new ArrayList<ComponentDescription>());
put(elementAsKey, components);
}
// add index to the vector; i.e. one of the indices for this component
components.add(component);
}
/**
* Remove from the table the entry
* @param component
*/
public void removeComponent(ComponentDescription component) {
E elementAsKey = extractKey(component);
List<ComponentDescription> components = super.get(elementAsKey);
if (components != null) {
components.remove(component);
if (components.isEmpty()) {
super.remove(elementAsKey);
}
}
}
public String getName() {
return name;
}
public String toString() {
return getName() + super.toString();
}
/**
* Returns the element of the object key that is used as the key of the
* indexTable.
* That is the final class that chooses what element of the complex object
* is stored as a key.
* This is unnaturally coupled with #AbstractDescriptionElement.extractElement
*
* @param object The object from which the class extracts what is relevant for it.
* @return index as class type E
* @see AbstractElement#extractElement(ComponentDescription)
*/
protected E extractKey(ComponentDescription component) {
return delegate.extractElement(component);
}
}