package edu.berkeley.nlp.util;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* Gives unique integer serial numbers to a family of objects, identified
* by a name space. A Numberer is like a collection of {@link Index}es,
* and for
* many purposes it is more straightforward to use an Index, but
* Numberer can be useful precisely because it maintains a global name
* space for numbered object families, and provides facilities for mapping
* across numberings within that space. At any rate, it's widely used in
* some existing packages.
*
* @author Dan Klein
*/
public class Numberer implements Serializable {
private static Map numbererMap = new HashMap();
public static Map getNumberers() {
return numbererMap;
}
/** You need to call this after deserializing Numberer objects to
* restore the global namespace, since static objects aren't serialized.
*/
public static void setNumberers(Map numbs) {
numbererMap = numbs;
}
public static Numberer getGlobalNumberer(String type) {
Numberer n = (Numberer) numbererMap.get(type);
if (n == null) {
n = new Numberer();
numbererMap.put(type, n);
}
return n;
}
/** Get a number for an object in namespace type.
* This looks up the Numberer for <code>type</code> in the global
* namespace map (creating it if none previously existed), and then
* returns the appropriate number for the key.
*/
public static int number(String type, Object o) {
return getGlobalNumberer(type).number(o);
}
public static Object object(String type, int n) {
return getGlobalNumberer(type).object(n);
}
/**
* For an Object <i>o</i> that occurs in Numberers of type
* <i>sourceType</i> and <i>targetType</i>, translates the serial
* number <i>n</i> of <i>o</i> in the <i>sourceType</i> Numberer to
* the serial number in the <i>targetType</i> Numberer.
*/
public static int translate(String sourceType, String targetType, int n) {
return getGlobalNumberer(targetType).number(getGlobalNumberer(sourceType).object(n));
}
private int total;
private Map intToObject;
private Map objectToInt;
private MutableInteger tempInt;
private boolean locked = false;
public int total() {
return total;
}
public void lock() {
locked = true;
}
public boolean hasSeen(Object o) {
return objectToInt.keySet().contains(o);
}
public Set objects() {
return objectToInt.keySet();
}
public int size() {
return objectToInt.size();
}
public int number(Object o) {
MutableInteger i = (MutableInteger) objectToInt.get(o);
if (i == null) {
if (locked) {
throw new NoSuchElementException("no object: " + o);
}
i = new MutableInteger(total);
total++;
objectToInt.put(o, i);
intToObject.put(i, o);
}
return i.intValue();
}
public Object object(int n) {
tempInt.set(n);
return intToObject.get(tempInt);
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (int i = 0; i < total; i++) {
sb.append(i);
sb.append("->");
sb.append(object(i));
if (i < total - 1) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
public Numberer() {
total = 0;
tempInt = new MutableInteger();
intToObject = new HashMap();
objectToInt = new HashMap();
}
private static final long serialVersionUID = 1L;
}