diff options
Diffstat (limited to 'src/main/java/bjc/esodata/PushdownMap.java')
| -rw-r--r-- | src/main/java/bjc/esodata/PushdownMap.java | 135 |
1 files changed, 74 insertions, 61 deletions
diff --git a/src/main/java/bjc/esodata/PushdownMap.java b/src/main/java/bjc/esodata/PushdownMap.java index 54ae939..76dd2db 100644 --- a/src/main/java/bjc/esodata/PushdownMap.java +++ b/src/main/java/bjc/esodata/PushdownMap.java @@ -1,12 +1,10 @@ package bjc.esodata; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; +import java.util.*; +import java.util.function.*; -import bjc.funcdata.FunctionalMap; -import bjc.funcdata.IList; -import bjc.funcdata.IMap; +import bjc.data.*; +import bjc.funcdata.*; /** * A variant of a map where inserting a duplicate key shadows the existing value @@ -22,22 +20,22 @@ import bjc.funcdata.IMap; * @param <ValueType> * The values in the map. */ -public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> { +public class PushdownMap<KeyType, ValueType> implements MapEx<KeyType, ValueType> { /* Our backing storage. */ - private final IMap<KeyType, Stack<ValueType>> backing; + private final MapEx<KeyType, Stack<ValueType>> backing; + private boolean isFrozen = false; + private boolean thawEnabled = true; + /** Create a new empty stack-based map. */ public PushdownMap() { backing = new FunctionalMap<>(); } - /** Create a new empty stack-based map using the specified backing. */ - private PushdownMap(final IMap<KeyType, Stack<ValueType>> back) { - backing = back; - } - @Override public void clear() { + if (isFrozen) throw new ObjectFrozen("Can't clear frozen map"); + backing.clear(); } @@ -45,30 +43,15 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> public boolean containsKey(final KeyType key) { return backing.containsKey(key); } - - @Override - public IMap<KeyType, ValueType> extend() { - return new PushdownMap<>(backing.extend()); - } - + @Override public void forEach(final BiConsumer<KeyType, ValueType> action) { backing.forEach((key, stk) -> action.accept(key, stk.top())); } @Override - public void forEachKey(final Consumer<KeyType> action) { - backing.forEachKey(action); - } - - @Override - public void forEachValue(final Consumer<ValueType> action) { - backing.forEachValue(stk -> action.accept(stk.top())); - } - - @Override - public ValueType get(final KeyType key) { - return backing.get(key).top(); + public Optional<ValueType> get(final KeyType key) { + return backing.get(key).map((stack) -> stack.top()); } @Override @@ -77,23 +60,16 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> } @Override - public IList<KeyType> keyList() { + public ListEx<KeyType> keyList() { return backing.keyList(); } @Override - public <V2> IMap<KeyType, V2> transform(final Function<ValueType, V2> transformer) { - /* - * @NOTE Can and should we support this? More to the point, maybe this should be - * a map sub-type that does what it needs to? - */ - throw new UnsupportedOperationException("Cannot transform pushdown maps."); - } - - @Override public ValueType put(final KeyType key, final ValueType val) { + if (isFrozen) throw new ObjectFrozen("Can't insert key " + key + " into frozen map"); + if (backing.containsKey(key)) { - final Stack<ValueType> stk = backing.get(key); + final Stack<ValueType> stk = backing.get(key).get(); final ValueType vl = stk.top(); @@ -111,18 +87,19 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> @Override public ValueType remove(final KeyType key) { - final Stack<ValueType> stk = backing.get(key); + if (isFrozen) throw new ObjectFrozen("Can't remove key " + key + " from frozen map"); - if (stk.size() > 1) { - return stk.pop(); - } + Holder<ValueType> result = Holder.of(null); + + backing.get(key).ifPresent((stk) -> { + if (stk.size() > 1) { + result.replace(stk.pop()); + } else { + result.replace(backing.remove(key).top()); + } + }); - return backing.remove(key).top(); - } - - @Override - public IList<ValueType> valueList() { - return backing.valueList().map(Stack::top); + return result.getValue(); } @Override @@ -137,20 +114,17 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof PushdownMap<?, ?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof PushdownMap<?, ?>)) return false; final PushdownMap<?, ?> other = (PushdownMap<?, ?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } return true; } @@ -159,4 +133,43 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> public String toString() { return String.format("PushdownMap [backing=%s]", backing); } + + @Override + public boolean freeze() { + isFrozen = true; + + return true; + } + + @Override + public boolean thaw() { + if (thawEnabled) { + isFrozen = false; + return true; + } else { + return false; + } + } + + @Override + public boolean deepFreeze() { + thawEnabled = true; + + return freeze(); + } + + @Override + public boolean canFreeze() { + return true; + } + + @Override + public boolean canThaw() { + return thawEnabled; + } + + @Override + public boolean isFrozen() { + return isFrozen; + } } |
