/** * */ package cz.cuni.mff.peckam.java.origamist.unused.utils; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import cz.cuni.mff.peckam.java.origamist.math.Vector; /** * An epsilon-map backed by an {@link IntervalTree}. * * @author Martin Pecka */ public abstract class EpsilonMapFromIntervalTree<K extends Comparable<? super K>, V> implements EpsilonMap<Vector<K>, V> { /** */ private static final long serialVersionUID = -3579305443938365894L; /** The backing map. */ protected MultiDimIntervalTree<K, V> map; public EpsilonMapFromIntervalTree(int dim) { map = new MultiDimIntervalTree<K, V>(dim); } /** * Return the epsilon-interval for the given key. * * @param key The key to return the interval for. * @return The epsilon-interval for the given key. */ protected abstract EpsilonInterval getEpsilonInterval(Vector<K> key); /** * @return The comparator that can compare keys. */ protected abstract Comparator<? super K> getKeyComparator(); /** * Return the value that represents the center of the given epsilon-interval of values. * * @param epsilonInterval The interval to get the center of. * @return The value that represents the center of the given epsilon-interval of values. */ protected Vector<K> getCenter(EpsilonInterval epsilonInterval) { return epsilonInterval.getCenter(); } protected abstract K getCenter(Interval<K> epsilonInterval); @Override public V epsilonGet(Vector<K> key) { return map.get(getEpsilonInterval(key)); } @Override public V epsilonPut(Vector<K> key, V value) { return map.put(getEpsilonInterval(key), value); } @Override public V epsilonRemove(Vector<K> key) { return map.remove(getEpsilonInterval(key)); } @Override public boolean epsilonContainsKey(Vector<K> key) { return map.contains(getEpsilonInterval(key)); } @Override public void epsilonPutAll(Map<? extends Vector<K>, ? extends V> map) { for (Entry<? extends Vector<K>, ? extends V> e : map.entrySet()) { epsilonPut(e.getKey(), e.getValue()); } } @Override public boolean epsilonEquals(Map<? extends Vector<K>, ? extends V> map) { throw new UnsupportedOperationException(); } @Override public int size() { return this.map.size(); } @Override public boolean isEmpty() { return this.map.isEmpty(); } /** * Not implemented. */ @Override public boolean containsKey(Object key) { throw new UnsupportedOperationException(); } /** * Not implemented. */ @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } /** * Not implemented. */ @Override public V get(Object key) { throw new UnsupportedOperationException(); } /** * Not implemented. */ @Override public V put(Vector<K> key, V value) { throw new UnsupportedOperationException(); } /** * Not implemented. */ @Override public V remove(Object key) { throw new UnsupportedOperationException(); } /** * Not implemented. */ @Override public void putAll(Map<? extends Vector<K>, ? extends V> m) { throw new UnsupportedOperationException(); } @Override public void clear() { this.map.clear(); } @Override public Set<Vector<K>> keySet() { return new AbstractSet<Vector<K>>() { @Override public Iterator<Vector<K>> iterator() { return new Iterator<Vector<K>>() { protected Iterator<Map.Entry<Vector<K>, V>> entryIt = EpsilonMapFromIntervalTree.this.entrySet() .iterator(); @Override public boolean hasNext() { return entryIt.hasNext(); } @Override public Vector<K> next() { return entryIt.next().getKey(); } @Override public void remove() { entryIt.remove(); } }; } @Override public int size() { return EpsilonMapFromIntervalTree.this.size(); } }; } @Override public Collection<V> values() { return new AbstractCollection<V>() { @Override public Iterator<V> iterator() { return new Iterator<V>() { protected Iterator<Map.Entry<Vector<K>, V>> entryIt = EpsilonMapFromIntervalTree.this.entrySet() .iterator(); @Override public boolean hasNext() { return entryIt.hasNext(); } @Override public V next() { return entryIt.next().getValue(); } @Override public void remove() { entryIt.remove(); } }; } @Override public int size() { return EpsilonMapFromIntervalTree.this.size(); } }; } @Override public Set<Map.Entry<Vector<K>, V>> entrySet() { return new AbstractSet<Map.Entry<Vector<K>, V>>() { @Override public Iterator<Map.Entry<Vector<K>, V>> iterator() { return new Iterator<Map.Entry<Vector<K>, V>>() { protected List<Iterator<Map.Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree>>> iters = null; protected List<K> key = new ArrayList<K>( map.getDimension()); protected int i = 0; { for (int i = 0; i < map.getDimension(); i++) key.add(null); } @Override public boolean hasNext() { if (iters == null) return map.size() != 0; for (int i = 0; i < iters.size(); i++) { if (iters.get(i).hasNext()) return true; } return false; } @Override public Map.Entry<Vector<K>, V> next() { i++; if (iters == null) { iters = new ArrayList<Iterator<Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree>>>( map.getDimension()); iters.add(map.entrySet().iterator()); Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree> e = null; for (int i = 1; i < map.getDimension(); i++) { e = iters.get(i - 1).next(); key.set(i - 1, getCenter(e.getKey())); iters.add(e.getValue().tree.entrySet().iterator()); } e = iters.get(map.getDimension() - 1).next(); key.set(map.getDimension() - 1, getCenter(e.getKey())); return new ExportEntry(new InnerVector(key), e); } for (int i = iters.size() - 1; i >= 0; i--) { if (iters.get(i).hasNext()) { Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree> e = iters.get(i).next(); key.set(i, getCenter(e.getKey())); if (i < iters.size() - 1) { Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree> en = null; iters.set(i + 1, e.getValue().tree.entrySet().iterator()); for (int j = i + 1; j < iters.size(); j++) { en = iters.get(j).next(); key.set(j, getCenter(en.getKey())); if (j < iters.size() - 1) { iters.set(j + 1, en.getValue().tree.entrySet().iterator()); } } return new ExportEntry(new InnerVector(key), en); } return new ExportEntry(new InnerVector(key), e); } } throw new NoSuchElementException(); } @Override public void remove() { throw new UnsupportedOperationException(); } class ExportEntry implements Map.Entry<Vector<K>, V> { Vector<K> key; Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree> origEntry; public ExportEntry(Vector<K> key, Entry<Interval<K>, MultiDimIntervalTree<K, V>.ValueOrTree> origEntry) { this.key = key; this.origEntry = origEntry; } @Override public Vector<K> getKey() { return key; } @Override public V getValue() { return origEntry.getValue().value; } @Override public V setValue(V value) { return origEntry.setValue(map.new ValueOrTree(value)).value; } } class InnerVector implements Vector<K> { /** */ private static final long serialVersionUID = 1L; K[] values; @SuppressWarnings("unchecked") public InnerVector(List<K> values) { this.values = values.toArray(emptyArray()); } private K[] emptyArray(K... vals) { return vals; } @Override public Iterator<K> iterator() { return new Iterator<K>() { protected int i = 0; @Override public boolean hasNext() { return i + 1 < map.getDimension(); } @Override public K next() { return values[i++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int getDimension() { return map.getDimension(); } @Override public K get(int index) { return values[index]; } @Override public K set(int index, K value) { K oldVal = values[index]; values[index] = value; return oldVal; } @Override public String toString() { return "InnerVector [" + Arrays.toString(values) + "]"; } @Override public int hashCode() { return Arrays.hashCode(values); } @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { Vector<K> vec = null; try { vec = (Vector<K>) obj; } catch (ClassCastException e) { return false; } if (vec.getDimension() != this.getDimension()) return false; for (int i = 0; i < this.getDimension(); i++) { if ((this.get(i) == null) != (vec.get(i) == null) || (this.get(i) != null && !this.get(i).equals(vec.get(i)))) return false; } return true; } } }; } @Override public int size() { return EpsilonMapFromIntervalTree.this.size(); } }; } protected class EpsilonInterval implements Vector<Interval<K>> { /** */ private static final long serialVersionUID = 3337664415256021420L; protected Vector<K> min; protected Vector<K> max; protected Vector<K> center; public EpsilonInterval(Vector<K> min, Vector<K> max, Vector<K> center) { this.min = min; this.max = max; this.center = center; } /** * @return The center of the interval. */ public Vector<K> getCenter() { return center; } @Override public Iterator<Interval<K>> iterator() { return new Iterator<Interval<K>>() { protected int i = 0; @Override public boolean hasNext() { return i + 1 < getDimension(); } @Override public Interval<K> next() { return get(i++); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int getDimension() { return center.getDimension(); } @Override public Interval<K> get(int index) { return new InnerInterval(index); } @Override public Interval<K> set(int index, Interval<K> value) { Interval<K> oldVal = get(index); min.set(index, value.getMin()); max.set(index, value.getMax()); return oldVal; } protected class InnerInterval implements Interval<K> { protected int index; public InnerInterval(int index) { this.index = index; } @Override public K getMin() { return min.get(index); } @Override public K getMax() { return max.get(index); } @Override public boolean overlapsWith(Interval<K> other) { return (getMin().compareTo(other.getMin()) >= 0 && getMin().compareTo(other.getMax()) <= 0) || (getMax().compareTo(other.getMin()) >= 0 && getMax().compareTo(other.getMax()) <= 0) || (other.getMin().compareTo(getMin()) >= 0 && other.getMin().compareTo(getMax()) <= 0) || (other.getMax().compareTo(getMin()) >= 0 && other.getMax().compareTo(getMax()) <= 0); } @Override public String toString() { return "InnerInterval [index=" + index + ", min=" + getMin() + ", max=" + getMax() + "]"; } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((center == null) ? 0 : center.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; @SuppressWarnings("unchecked") EpsilonInterval other = (EpsilonInterval) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (center == null) { if (other.center != null) return false; } else if (!center.equals(other.center)) return false; return true; } private EpsilonMapFromIntervalTree<?, ?> getOuterType() { return EpsilonMapFromIntervalTree.this; } @Override public String toString() { return "EpsilonInterval [min=" + min + ", max=" + max + ", center=" + center + "]"; } } }