package no.uio.ifi.refaktor.prefix; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; /** * A set for collecting prefixes (see {@link Prefix}}). * * It can increment a counter in a prefix each time an equal * prefix is registered with the set. In addition * it can produce the set that is this set, minus the * prefixes from another set that are enclosed by the * prefixes in this set. */ public class PrefixSet implements Iterable { private final Map prefixes = new HashMap(); public PrefixSet() { } private PrefixSet(PrefixSet initialElements) { prefixes.putAll(initialElements.prefixes); } public void add(Prefix prefix) { assert prefix != null: "A " + this.getClass().getName() + " will not accept a null value"; if (!contains(prefix)) prefixes.put(prefix, prefix); } private void remove(Prefix prefix) { prefixes.remove(prefix); } public boolean contains(Prefix prefix) { boolean res = prefixes.containsKey(prefix); // TODO: Show prefixes in debugging output as well? if (res) assert get(prefix) != null : prefix; else assert get(prefix) == null : prefix; return res; } @Override public Iterator iterator() { return prefixes.values().iterator(); } public boolean isEmpty() { return prefixes.isEmpty(); } public LinkedList toList() { return new LinkedList(prefixes.values()); } public Prefix get(Prefix prefix) { return prefixes.get(prefix); } public void registerAllSubPrefixesOf(Prefix prefix) { for (Prefix p: prefix.getSubPrefixes()) register(p); } private void register(Prefix prefix) { Prefix prefixFromMap = get(prefix); if (prefixFromMap != null) { prefixFromMap.incrementCount(); } else { add(prefix); } } @Override public String toString() { String str = ""; for (Prefix p: this) { str += p.toString() + " (" + p.getCount() + ")\n"; } return str; } /** * Creates a set of prefixes that are the prefixes of this set, * minus the prefixes that are enclosing the prefixes of the * other set. A prefix is enclosing another if the other prefix * is a sub-prefix of the first prefix. * * @param other The set of prefixes that are to be checked against this one. * @return The set of prefixes that are not enclosing the ones in the other set. */ public PrefixSet minusEnclosedPrefixesFrom(PrefixSet other) { PrefixSet prefixSet = shallowCopy(); removeEnclosingPrefixesFromPrefixSet(prefixSet, other); return prefixSet; } private PrefixSet shallowCopy() { return new PrefixSet(this); } private void removeEnclosingPrefixesFromPrefixSet(PrefixSet prefixSet, PrefixSet other) { for (Prefix p: other) { for (Prefix prefix: this) { if (prefix.hasSubPrefix(p)) prefixSet.remove(prefix); } } } public void clear() { prefixes.clear(); } public int size() { return prefixes.size(); } }