package edu.berkeley.sbp.util;
import edu.berkeley.sbp.util.*;
import edu.berkeley.sbp.*;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import java.lang.ref.*;
//
// This is a fairly crude implementation; if things need to be fast,
// you should implement a special-purpose class
//
/** a mapping from topologies over K to sets of values of type V */
public class TopologicalBag implements MapBag,V> {
// CRUCIAL INVARIANT: keys in this hashmap MUST be disjoint or the universe will implode
private final HashMap,HashSet> h = new HashMap,HashSet>();
public Iterator> iterator() { return h.keySet().iterator(); }
public void addAll(TopologicalBag tb) {
for(Topology k : tb)
addAll(k, tb.getAll(k));
}
public void add(Topology t, V v) { put(t, v); }
public void addAll(Topology k, Iterable vi) { putAll(k, vi); }
public void putAll(Topology k, Iterable vi) { if (vi!=null) for(V v : vi) put(k, v); }
public void put(Topology t, V v) {
for(Topology ht : h.keySet()) {
if (t.disjoint(ht)) continue;
if (t.containsAll(ht) && ht.containsAll(t)) {
h.get(ht).add(v);
return;
}
if (ht.containsAll(t)) {
HashSet v0 = h.get(ht);
HashSet v1 = new HashSet();
v1.addAll(v0);
h.remove(ht);
v1.add(v);
h.put(ht.intersect(t), v1);
h.put(ht.minus(t), v0);
return;
}
put(t.intersect(ht), v);
put(t.minus(ht), v);
return;
}
HashSet v1 = new HashSet();
v1.add(v);
h.put(t, v1);
}
public TopologicalBag subset(Topology t) {
TopologicalBag ret = new TopologicalBag();
for(Topology ht : h.keySet()) {
if (ht.disjoint(t)) continue;
Iterable it = h.get(ht);
Topology tk = ht.intersect(t);
ret.putAll(tk, it);
}
return ret;
}
public Map,HashSet> gett(Topology t) {
HashMap,HashSet> ret = new HashMap,HashSet>();
for(Topology ht : h.keySet()) {
if (ht.disjoint(t)) continue;
ret.put(ht.intersect(t), h.get(ht));
}
return ret;
}
public boolean empty(K k) {
for(Topology t : h.keySet())
if (t.contains(k) && h.get(t).size() > 0)
return false;
return true;
}
public boolean contains(K k) { return get(k).iterator().hasNext(); }
public boolean contains(K k, V v) {
for(Topology t : h.keySet())
if (t.contains(k))
return h.get(t).contains(v);
return false;
}
public boolean has(K k) {
for(Topology t : h.keySet())
if (t.contains(k) && !h.get(t).isEmpty())
return true;
return false;
}
private HashMap> cache = new HashMap>();
public Iterable getAll(Topology k) { return h.get(k); }
public Iterable get(K k) {
Iterable c = cache.get(k);
if (c != null) return c;
HashSet ret = null;
HashSet ret0 = null;
for(Topology t : h.keySet())
if (t.contains(k)) {
if (ret==null) {
ret0 = ret = h.get(t);
} else {
if (ret0 != null) {
ret = new HashSet();
ret.addAll(ret0);
ret0 = null;
}
ret.addAll(h.get(t));
}
}
if (ret==null) {
cache.put(k, emptyIterator);
return emptyIterator;
} else {
cache.put(k, new FastSet(ret));
return ret;
}
}
private final Iterable emptyIterator = new EmptyIterator();
}