package uk.ac.rhul.cs.utils;
import java.util.*;
import com.sosnoski.util.hashmap.ObjectIntHashMap;
import uk.ac.rhul.cs.graph.Graph;
/**
* Class that is used in graph readers to generate unique numeric IDs for string IDs
* (or any other hashable objects).
*
* This class implements a single public method named get() which returns the numeric
* ID for the given node name. Internally, the generator uses a map to keep track of
* the name-ID assignments. Whenever an ID is requested for a name that is not in the
* map yet, a new ID will be generated. The names used must be immutable objects.
*/
public class UniqueIDGenerator<K> {
/**
* Internal storage for name-ID assignments
*/
protected ObjectIntHashMap map = new ObjectIntHashMap();
/**
* The graph this generator is associated with
*/
protected Graph graph = null;
/**
* Constructs a generator associated to the given graph
*/
public UniqueIDGenerator(Graph graph) {
this.graph = graph;
}
/**
* Returns the ID for the given node name
*
* A new ID will be created for the given node name if it was not
* seen before.
*
* @param name the name we are looking for
* @return the corresponding ID
*/
public int get(K name) {
int result = map.get(name);
if (result == ObjectIntHashMap.DEFAULT_NOT_FOUND) {
result = graph.createNode(name.toString());
map.add(name, result);
}
return result;
}
/**
* Returns the ID for the given node name (strict variant)
*
* This one differs from {@link #get(K)} by requiring that the given
* name already has an associated ID.
*
* @throw IllegalStateException if the given key does not have
* an associated ID
*/
public int getStrict(K name) {
int result = map.get(name);
if (result == ObjectIntHashMap.DEFAULT_NOT_FOUND) {
throw new IllegalStateException("key not found: " + name.toString());
}
return result;
}
/**
* Returns a copy of the internal map
*
* @return a map mapping node names to integer node IDs according to the present
* state of the ID generator
*/
public Map<K, Integer> toMap() {
Map<K, Integer> result = new TreeMap<K, Integer>();
Iterator<?> it = map.iterator();
while (it.hasNext())
{
K key = (K)it.next();
result.put(key, map.get(key));
}
return result;
}
/**
* Returns a reverse mapping constructed from the internal map
*
* @return a map mapping integer node IDs to node names according to the present
* state of the ID generator
*/
public Map<Integer, K> getReversedMap() {
Map<Integer, K> result = new TreeMap<Integer, K>();
Iterator<?> it = map.iterator();
while (it.hasNext())
{
K key = (K)it.next();
result.put(map.get(key), key);
}
return result;
}
/**
* Returns a reverse mapping list constructed from the internal map
*
* @return a list mapping integer node IDs to node names according to the present
* state of the ID generator
*/
public List<K> getReversedList() {
List<K> result = new ArrayList<K>(map.size());
for (int i = 0; i < map.size(); i++) {
result.add(null);
}
Iterator<?> it = map.iterator();
while (it.hasNext())
{
K key = (K)it.next();
result.set(map.get(key), key);
}
return result;
}
}