diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/snapshot/SnapshotNavigableMap.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/snapshot/SnapshotNavigableMap.java new file mode 100644 index 00000000..022d5c02 --- /dev/null +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/snapshot/SnapshotNavigableMap.java @@ -0,0 +1,352 @@ +package com.usatiuk.objects.snapshot; + +import com.usatiuk.objects.iterators.IteratorStart; +import jakarta.annotation.Nullable; + +import java.util.*; + +public class SnapshotNavigableMap, V> implements NavigableMap { + + private record Bound>(K key, boolean inclusive) { + } + + private final Snapshot _snapshot; + @Nullable + private final Bound _lowerBound; + @Nullable + private final Bound _upperBound; + + private SnapshotNavigableMap(Snapshot snapshot, Bound lowerBound, Bound upperBound) { + _snapshot = snapshot; + _lowerBound = lowerBound; + _upperBound = upperBound; + } + + public SnapshotNavigableMap(Snapshot snapshot) { + this(snapshot, null, null); + } + + private final boolean checkBounds(K key) { + if (_lowerBound != null) { + if (_lowerBound.inclusive()) { + if (key.compareTo(_lowerBound.key()) < 0) { + return false; + } + } else { + if (key.compareTo(_lowerBound.key()) <= 0) { + return false; + } + } + } + if (_upperBound != null) { + if (_upperBound.inclusive()) { + if (key.compareTo(_upperBound.key()) > 0) { + return false; + } + } else { + if (key.compareTo(_upperBound.key()) >= 0) { + return false; + } + } + } + return true; + } + + @Override + public Entry lowerEntry(K key) { + try (var it = _snapshot.getIterator(IteratorStart.LT, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) >= 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public K lowerKey(K key) { + try (var it = _snapshot.getIterator(IteratorStart.LT, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) >= 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return realKey; + } + } + return null; + } + + @Override + public Entry floorEntry(K key) { + try (var it = _snapshot.getIterator(IteratorStart.LE, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) > 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public K floorKey(K key) { + try (var it = _snapshot.getIterator(IteratorStart.LE, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) > 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return realKey; + } + } + return null; + } + + @Override + public Entry ceilingEntry(K key) { + try (var it = _snapshot.getIterator(IteratorStart.GE, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) < 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public K ceilingKey(K key) { + try (var it = _snapshot.getIterator(IteratorStart.GE, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) < 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return realKey; + } + } + return null; + } + + @Override + public Entry higherEntry(K key) { + try (var it = _snapshot.getIterator(IteratorStart.GT, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) <= 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public K higherKey(K key) { + try (var it = _snapshot.getIterator(IteratorStart.GT, key)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (realKey.compareTo(key) <= 0) { + return null; + } + if (!checkBounds(realKey)) { + return null; + } + return realKey; + } + } + return null; + } + + @Override + public Entry firstEntry() { + var lb = _lowerBound == null ? null : _lowerBound.key(); + var start = _lowerBound != null ? (_lowerBound.inclusive() ? IteratorStart.GE : IteratorStart.GT) : IteratorStart.GE; + try (var it = _snapshot.getIterator(start, lb)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public Entry lastEntry() { + var b = _upperBound == null ? null : _upperBound.key(); + var start = _upperBound != null ? (_upperBound.inclusive() ? IteratorStart.LE : IteratorStart.LT) : IteratorStart.LE; + try (var it = _snapshot.getIterator(start, b)) { + if (it.hasNext()) { + var realKey = it.peekNextKey(); + if (!checkBounds(realKey)) { + return null; + } + return it.next(); + } + } + return null; + } + + @Override + public Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public NavigableMap descendingMap() { + return null; + } + + @Override + public NavigableSet navigableKeySet() { + return null; + } + + @Override + public NavigableSet descendingKeySet() { + return null; + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return null; + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return null; + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return null; + } + + @Override + public Comparator comparator() { + return null; + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return null; + } + + @Override + public SortedMap headMap(K toKey) { + return null; + } + + @Override + public SortedMap tailMap(K fromKey) { + return null; + } + + @Override + public K firstKey() { + return null; + } + + @Override + public K lastKey() { + return null; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public V get(Object key) { + return null; + } + + @Override + public V put(K key, V value) { + return null; + } + + @Override + public V remove(Object key) { + return null; + } + + @Override + public void putAll(Map m) { + + } + + @Override + public void clear() { + + } + + @Override + public Set keySet() { + return Set.of(); + } + + @Override + public Collection values() { + return List.of(); + } + + @Override + public Set> entrySet() { + return Set.of(); + } +}