/*
* Copyright 2005-2010 Roger Kapsi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ardverk.collection;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
/**
* A collection of {@link Trie} utilities
*/
public class Tries {
/**
* Returns true if bitIndex is a {@link KeyAnalyzer#OUT_OF_BOUNDS_BIT_KEY}
*/
static boolean isOutOfBoundsIndex(int bitIndex) {
return bitIndex == KeyAnalyzer.OUT_OF_BOUNDS_BIT_KEY;
}
/**
* Returns true if bitIndex is a {@link KeyAnalyzer#EQUAL_BIT_KEY}
*/
static boolean isEqualBitKey(int bitIndex) {
return bitIndex == KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* Returns true if bitIndex is a {@link KeyAnalyzer#NULL_BIT_KEY}
*/
static boolean isNullBitKey(int bitIndex) {
return bitIndex == KeyAnalyzer.NULL_BIT_KEY;
}
/**
* Returns true if the given bitIndex is valid. Indices
* are considered valid if they're between 0 and
* {@link Integer#MAX_VALUE}
*/
static boolean isValidBitIndex(int bitIndex) {
return 0 <= bitIndex && bitIndex <= Integer.MAX_VALUE;
}
/**
* Returns true if both values are either null or equal
*/
static boolean areEqual(Object a, Object b) {
return (a == null ? b == null : a.equals(b));
}
/**
* Throws a {@link NullPointerException} with the given message if
* the argument is null.
*/
static <T> T notNull(T o, String message) {
if (o == null) {
throw new NullPointerException(message);
}
return o;
}
/**
* A utility method to cast keys. It actually doesn't
* cast anything. It's just fooling the compiler!
*/
@SuppressWarnings("unchecked")
static <K> K cast(Object key) {
return (K)key;
}
private Tries() {}
/**
* Returns a synchronized instance of a {@link Trie}
*
* @see Collections#synchronizedMap(Map)
*/
public static <K, V> Trie<K, V> synchronizedTrie(Trie<K, V> trie) {
if (trie instanceof SynchronizedTrie) {
return trie;
}
return new SynchronizedTrie<K, V>(trie);
}
/**
* Returns an unmodifiable instance of a {@link Trie}
*
* @see Collections#unmodifiableMap(Map)
*/
public static <K, V> Trie<K, V> unmodifiableTrie(Trie<K, V> trie) {
if (trie instanceof UnmodifiableTrie) {
return trie;
}
return new UnmodifiableTrie<K, V>(trie);
}
/**
* A synchronized {@link Trie}
*/
private static class SynchronizedTrie<K, V> implements Trie<K, V>, Serializable {
private static final long serialVersionUID = 3121878833178676939L;
private final Trie<K, V> delegate;
public SynchronizedTrie(Trie<K, V> delegate) {
this.delegate = Tries.notNull(delegate, "delegate");
}
public synchronized Entry<K, V> select(K key,
Cursor<? super K, ? super V> cursor) {
return delegate.select(key, cursor);
}
public synchronized Entry<K, V> select(K key) {
return delegate.select(key);
}
public synchronized K selectKey(K key) {
return delegate.selectKey(key);
}
public synchronized V selectValue(K key) {
return delegate.selectValue(key);
}
public synchronized Entry<K, V> traverse(Cursor<? super K, ? super V> cursor) {
return delegate.traverse(cursor);
}
public synchronized Set<Entry<K, V>> entrySet() {
return new SynchronizedSet<Entry<K, V>>(this, delegate.entrySet());
}
public synchronized Set<K> keySet() {
return new SynchronizedSet<K>(this, delegate.keySet());
}
public synchronized Collection<V> values() {
return new SynchronizedCollection<V>(this,
delegate.values());
}
public synchronized void clear() {
delegate.clear();
}
public synchronized boolean containsKey(Object key) {
return delegate.containsKey(key);
}
public synchronized boolean containsValue(Object value) {
return delegate.containsValue(value);
}
public synchronized V get(Object key) {
return delegate.get(key);
}
public synchronized boolean isEmpty() {
return delegate.isEmpty();
}
public synchronized V put(K key, V value) {
return delegate.put(key, value);
}
public synchronized void putAll(Map<? extends K, ? extends V> m) {
delegate.putAll(m);
}
public synchronized V remove(Object key) {
return delegate.remove(key);
}
public synchronized K lastKey() {
return delegate.lastKey();
}
public synchronized SortedMap<K, V> subMap(K fromKey, K toKey) {
return new SynchronizedSortedMap<K, V>(this,
delegate.subMap(fromKey, toKey));
}
public synchronized SortedMap<K, V> tailMap(K fromKey) {
return new SynchronizedSortedMap<K, V>(this,
delegate.tailMap(fromKey));
}
public synchronized Comparator<? super K> comparator() {
return delegate.comparator();
}
public synchronized K firstKey() {
return delegate.firstKey();
}
public synchronized SortedMap<K, V> headMap(K toKey) {
return new SynchronizedSortedMap<K, V>(this, delegate.headMap(toKey));
}
public synchronized SortedMap<K, V> prefixMap(K prefix) {
return new SynchronizedSortedMap<K, V>(this,
delegate.prefixMap(prefix));
}
public synchronized int size() {
return delegate.size();
}
@Override
public synchronized int hashCode() {
return delegate.hashCode();
}
@Override
public synchronized boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public synchronized String toString() {
return delegate.toString();
}
}
/**
* A synchronized {@link Collection}
*/
private static class SynchronizedCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 2625364158304884729L;
private final Object lock;
private final Collection<E> delegate;
public SynchronizedCollection(Object lock, Collection<E> delegate) {
this.lock = Tries.notNull(lock, "lock");
this.delegate = Tries.notNull(delegate, "delegate");
}
public boolean add(E e) {
synchronized (lock) {
return delegate.add(e);
}
}
public boolean addAll(Collection<? extends E> c) {
synchronized (lock) {
return delegate.addAll(c);
}
}
public void clear() {
synchronized (lock) {
delegate.clear();
}
}
public boolean contains(Object o) {
synchronized (lock) {
return delegate.contains(o);
}
}
public boolean containsAll(Collection<?> c) {
synchronized (lock) {
return delegate.containsAll(c);
}
}
public boolean isEmpty() {
synchronized (lock) {
return delegate.isEmpty();
}
}
public Iterator<E> iterator() {
synchronized (lock) {
return delegate.iterator();
}
}
public boolean remove(Object o) {
synchronized (lock) {
return delegate.remove(o);
}
}
public boolean removeAll(Collection<?> c) {
synchronized (lock) {
return delegate.removeAll(c);
}
}
public boolean retainAll(Collection<?> c) {
synchronized (lock) {
return delegate.retainAll(c);
}
}
public int size() {
synchronized (lock) {
return delegate.size();
}
}
public Object[] toArray() {
synchronized (lock) {
return delegate.toArray();
}
}
public <T> T[] toArray(T[] a) {
synchronized (lock) {
return delegate.toArray(a);
}
}
@Override
public int hashCode() {
synchronized (delegate) {
return delegate.hashCode();
}
}
@Override
public boolean equals(Object obj) {
synchronized (delegate) {
return delegate.equals(obj);
}
}
@Override
public String toString() {
synchronized (lock) {
return delegate.toString();
}
}
}
/**
* A synchronized {@link Set}
*/
private static class SynchronizedSet<E> extends SynchronizedCollection<E>
implements Set<E> {
private static final long serialVersionUID = -6998017897934241309L;
public SynchronizedSet(Object lock, Collection<E> deleate) {
super(lock, deleate);
}
}
/**
* A synchronized {@link SortedMap}
*/
private static class SynchronizedSortedMap<K, V> implements SortedMap<K, V>, Serializable {
private static final long serialVersionUID = 3654589935305688739L;
private final Object lock;
private final SortedMap<K, V> delegate;
public SynchronizedSortedMap(Object lock, SortedMap<K, V> delegate) {
this.lock = Tries.notNull(lock, "lock");
this.delegate = Tries.notNull(delegate, "delegate");
}
public Comparator<? super K> comparator() {
synchronized (lock) {
return delegate.comparator();
}
}
public Set<Entry<K, V>> entrySet() {
synchronized (lock) {
return new SynchronizedSet<Entry<K,V>>(lock,
delegate.entrySet());
}
}
public K firstKey() {
synchronized (lock) {
return delegate.firstKey();
}
}
public SortedMap<K, V> headMap(K toKey) {
synchronized (lock) {
return new SynchronizedSortedMap<K, V>(lock,
delegate.headMap(toKey));
}
}
public Set<K> keySet() {
synchronized (lock) {
return new SynchronizedSet<K>(lock, delegate.keySet());
}
}
public K lastKey() {
synchronized (lock) {
return delegate.lastKey();
}
}
public SortedMap<K, V> subMap(K fromKey, K toKey) {
synchronized (lock) {
return new SynchronizedSortedMap<K, V>(lock,
delegate.subMap(fromKey, toKey));
}
}
public SortedMap<K, V> tailMap(K fromKey) {
synchronized (lock) {
return new SynchronizedSortedMap<K, V>(lock,
delegate.tailMap(fromKey));
}
}
public Collection<V> values() {
synchronized (lock) {
return new SynchronizedCollection<V>(lock, delegate.values());
}
}
public void clear() {
synchronized (lock) {
delegate.clear();
}
}
public boolean containsKey(Object key) {
synchronized (lock) {
return delegate.containsKey(key);
}
}
public boolean containsValue(Object value) {
synchronized (lock) {
return delegate.containsValue(value);
}
}
public V get(Object key) {
synchronized (lock) {
return delegate.get(key);
}
}
public boolean isEmpty() {
synchronized (lock) {
return delegate.isEmpty();
}
}
public V put(K key, V value) {
synchronized (lock) {
return delegate.put(key, value);
}
}
public void putAll(Map<? extends K, ? extends V> m) {
synchronized (lock) {
delegate.putAll(m);
}
}
public V remove(Object key) {
synchronized (lock) {
return delegate.remove(key);
}
}
public int size() {
synchronized (lock) {
return delegate.size();
}
}
public int hashCode() {
synchronized (delegate) {
return delegate.hashCode();
}
}
@Override
public boolean equals(Object obj) {
synchronized (delegate) {
return delegate.equals(obj);
}
}
@Override
public String toString() {
synchronized (lock) {
return delegate.toString();
}
}
}
/**
* An unmodifiable {@link Trie}
*/
private static class UnmodifiableTrie<K, V> implements Trie<K, V>, Serializable {
private static final long serialVersionUID = -7156426030315945159L;
private final Trie<K, V> delegate;
public UnmodifiableTrie(Trie<K, V> delegate) {
this.delegate = Tries.notNull(delegate, "delegate");
}
public Entry<K, V> select(K key, final Cursor<? super K, ? super V> cursor) {
Cursor<K, V> c = new Cursor<K, V>() {
public Decision select(Map.Entry<? extends K, ? extends V> entry) {
Decision decision = cursor.select(entry);
switch (decision) {
case REMOVE:
case REMOVE_AND_EXIT:
throw new UnsupportedOperationException();
}
return decision;
}
};
return delegate.select(key, c);
}
public Entry<K, V> select(K key) {
return delegate.select(key);
}
public K selectKey(K key) {
return delegate.selectKey(key);
}
public V selectValue(K key) {
return delegate.selectValue(key);
}
public Entry<K, V> traverse(final Cursor<? super K, ? super V> cursor) {
Cursor<K, V> c = new Cursor<K, V>() {
public Decision select(Map.Entry<? extends K, ? extends V> entry) {
Decision decision = cursor.select(entry);
switch (decision) {
case REMOVE:
case REMOVE_AND_EXIT:
throw new UnsupportedOperationException();
}
return decision;
}
};
return delegate.traverse(c);
}
public Set<Entry<K, V>> entrySet() {
return Collections.unmodifiableSet(delegate.entrySet());
}
public Set<K> keySet() {
return Collections.unmodifiableSet(delegate.keySet());
}
public Collection<V> values() {
return Collections.unmodifiableCollection(delegate.values());
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
public V get(Object key) {
return delegate.get(key);
}
public boolean isEmpty() {
return delegate.isEmpty();
}
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException();
}
public K firstKey() {
return delegate.firstKey();
}
public SortedMap<K, V> headMap(K toKey) {
return Collections.unmodifiableSortedMap(delegate.headMap(toKey));
}
public K lastKey() {
return delegate.lastKey();
}
public SortedMap<K, V> subMap(K fromKey, K toKey) {
return Collections.unmodifiableSortedMap(
delegate.subMap(fromKey, toKey));
}
public SortedMap<K, V> tailMap(K fromKey) {
return Collections.unmodifiableSortedMap(delegate.tailMap(fromKey));
}
public SortedMap<K, V> prefixMap(K prefix) {
return Collections.unmodifiableSortedMap(
delegate.prefixMap(prefix));
}
public Comparator<? super K> comparator() {
return delegate.comparator();
}
public int size() {
return delegate.size();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public String toString() {
return delegate.toString();
}
}
}