package edu.stanford.nlp.util;
import edu.stanford.nlp.util.logging.Redwood;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Set;
/**
* For interning (canonicalizing) things.
* <p/>
* It maps any object to a unique interned version which .equals the
* presented object. If presented with a new object which has no
* previous interned version, the presented object becomes the
* interned version. You can tell if your object has been chosen as
* the new unique representative by checking whether o == intern(o).
* The interners use WeakHashMap, meaning that if the only pointers
* to an interned item are the interners' backing maps, that item can
* still be garbage collected. Since the gc thread can silently
* remove things from the backing map, there's no public way to get
* the backing map, but feel free to add one at your own risk.
* <p/>
* Note that in general it is just as good or better to use the
* static Interner.globalIntern() method rather than making an
* instance of Interner and using the instance-level intern().
* <p/>
* Author: Dan Klein
* Date: 9/28/03
*
* @author Dan Klein
*/
public class Interner<T> {
/** A logger for this class */
private static Redwood.RedwoodChannels log = Redwood.channels(Interner.class);
protected static Interner<Object> interner = Generics.newInterner();
/**
* For getting the instance that global methods use.
*/
public static Interner<Object> getGlobal() {
return interner;
}
/**
* For supplying a new instance for the global methods to use.
*
* @return the previous global interner.
*/
public static Interner<Object> setGlobal(Interner<Object> interner) {
Interner<Object> oldInterner = Interner.interner;
Interner.interner = interner;
return oldInterner;
}
/**
* Returns a unique object o' that .equals the argument o. If o
* itself is returned, this is the first request for an object
* .equals to o.
*/
@SuppressWarnings("unchecked")
public static <T> T globalIntern(T o) {
return (T) getGlobal().intern(o);
}
protected Map<T,WeakReference<T>> map = Generics.newWeakHashMap();
public void clear() { map = Generics.newWeakHashMap(); }
/**
* Returns a unique object o' that .equals the argument o. If o
* itself is returned, this is the first request for an object
* .equals to o.
*/
public synchronized T intern(T o) {
WeakReference<T> ref = map.get(o);
if (ref == null) {
ref = Generics.newWeakReference(o);
map.put(o, ref);
}
// else {
// log.info("Found dup for " + o);
// }
return ref.get();
}
/**
* Returns a <code>Set</code> such that each element in the returned set
* is a unique object e' that .equals the corresponding element e in the
* original set.
*/
public Set<T> internAll(Set<T> s) {
Set<T> result = Generics.newHashSet();
for (T o : s) {
result.add(intern(o));
}
return result;
}
public int size() {
return map.size();
}
/**
* Test method: interns its arguments and says whether they == themselves.
*/
public static void main(String[] args) {
for (String str : args) {
System.out.println(Interner.globalIntern(str) == str);
}
}
}