package freeboogie.tc;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import freeboogie.util.Closure;
/**
* Used to map usage of a name to the deinition of that name.
* Unlike a simple hash it allows quick retrieval of all usages
* of a definition.
*
* @author rgrig
* @author reviewed by TODO
* @param <U> the type of the usage object
* @param <D> the type of the definition object
*/
public class UsageToDefMap<U, D> {
private HashMap<U, D> usageToDef = new HashMap<U, D>();
private HashMap<D, HashSet<U>> defToUsage = new HashMap<D, HashSet<U>>();
private HashSet<U> getUsages(D d) {
HashSet<U> u = defToUsage.get(d);
if (u == null) {
u = new HashSet<U>();
defToUsage.put(d, u);
}
return u;
}
/**
* Connect usage {@code u} to the definition {@code d}.
* @param u the usage
* @param d the definition
*/
public void put(U u, D d) {
usageToDef.put(u, d);
HashSet<U> usages = getUsages(d);
usages.add(u);
defToUsage.put(d, usages);
}
/**
* Add {@code d} as a definition, if not already.
* @param d the definition
*/
public void seenDef(D d) {
getUsages(d);
}
/**
* Returns the definition of a usage.
* @param u the usage
* @return the definition of {@code u}
*/
public D def(U u) {
return usageToDef.get(u);
}
/**
* Returns the set of usages of a certaini definition. The user
* should not modify the result of this function.
* @param d the definition
* @return the usages of {@code d}
*/
public Set<U> usages(D d) {
return defToUsage.get(d);
}
/**
* Returns the number of definitions
* @return the number of definitions
*/
public int defCnt() {
return defToUsage.size();
}
/**
* Iterate over usages.
* @param f the function to be applied to each usage
*/
public void iterUsage(Closure<U> f) {
for (U k : usageToDef.keySet()) if (k != null) f.go(k);
}
/**
* Iterate over definitions.
* @param f the function to be applied to each definition
*/
public void iterDef(Closure<D> f) {
for (D v : defToUsage.keySet()) if (v != null) f.go(v);
}
}