com.tangosol.util.ConverterCollections Maven / Gradle / Ivy
Show all versions of coherence Show documentation
/*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/
package com.tangosol.util;
import com.oracle.coherence.common.base.Holder;
import com.oracle.coherence.common.base.NaturalHasher;
import com.tangosol.internal.net.NamedCacheDeactivationListener;
import com.tangosol.internal.util.processor.CacheProcessors;
import com.tangosol.io.Serializer;
import com.tangosol.net.BackingMapContext;
import com.tangosol.net.BackingMapManagerContext;
import com.tangosol.net.CacheService;
import com.tangosol.net.NamedCache;
import com.tangosol.net.cache.CacheEvent;
import com.tangosol.net.cache.CacheMap;
import com.tangosol.net.cache.ConfigurableCacheMap;
import com.tangosol.util.InvocableMap.EntryAggregator;
import com.tangosol.util.InvocableMap.EntryProcessor;
import com.tangosol.util.MapListenerSupport.WrapperListener;
import com.tangosol.util.function.Remote;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.function.BiFunction;
/**
* A collection of Collection implementation classes that use the Converter
* interface to convert the items stored in underlying collection objects.
*
* @author cp 2002.02.08
* @author jh 2007.09.28
*/
public abstract class ConverterCollections
{
// ----- factory methods ------------------------------------------------
/**
* Returns an instance of Iterator that uses a Converter to view an
* underlying Iterator.
*
* @param iter the underlying Iterator
* @param conv the Converter to view the underlying Iterator through
*
* @param the type of elements in the underlying Iterator
* @param the type that the elements should be converted to
*
* @return an Iterator that views the passed Iterator through the
* specified Converter
*/
public static Iterator getIterator(Iterator iter, Converter conv)
{
return new ConverterEnumerator<>(iter, conv);
}
/**
* Returns an instance of Collection that uses a Converter to view an
* underlying Collection.
*
* @param col the underlying Collection
* @param convUp the Converter to view the underlying Collection
* through
* @param convDown the Converter to pass items down to the underlying
* Collection through
*
* @param the type of elements in the underlying Collection
* @param the type that the elements should be converted to
*
* @return a Collection that views the passed Collection through the
* specified Converter
*/
public static ConverterCollection getCollection(Collection col, Converter convUp,
Converter convDown)
{
return new ConverterCollection<>(col, convUp, convDown);
}
/**
* Returns an instance of Set that uses a Converter to view an
* underlying Set.
*
* @param set the underlying Set
* @param convUp the Converter to view the underlying Set
* through
* @param convDown the Converter to pass items down to the underlying
* Set through
*
* @param the type of elements in the underlying Set
* @param the type that the elements should be converted to
*
* @return a Set that views the passed Set through the specified
* Converter
*/
public static ConverterSet getSet(Set set, Converter convUp, Converter convDown)
{
return new ConverterSet<>(set, convUp, convDown);
}
/**
* Returns an instance of SortedSet that uses a Converter to view an
* underlying SortedSet.
*
* @param set the underlying SortedSet
* @param convUp the Converter to view the underlying SortedSet
* through
* @param convDown the Converter to pass items down to the underlying
* SortedSet through
*
* @param the type of elements in the underlying SortedSet
* @param the type that the elements should be converted to
*
* @return a SortedSet that views the passed SortedSet through the
* specified Converter
*/
public static ConverterSortedSet getSortedSet(SortedSet set, Converter convUp,
Converter convDown)
{
return new ConverterSortedSet<>(set, convUp, convDown);
}
/**
* Returns a Converter instance of List.
*
* @param list the underlying List
* @param convUp the Converter to view the underlying List
* through
* @param convDown the Converter to pass items down to the underlying
* List through
*
* @param the type of elements in the underlying list
* @param the type that the elements should be converted to
*
* @return a List that views the passed List through the specified
* Converter
*/
public static ConverterList getList(List list, Converter convUp, Converter convDown)
{
return new ConverterList<>(list, convUp, convDown);
}
/**
* Returns a Converter instance of ListIterator.
*
* @param the type of elements in the underlying ListIterator
* @param the type that the elements should be converted to
*
* @param iter the underlying ListIterator
* @param convUp the Converter to view the underlying list
* through
* @param convDown the Converter to pass items down to the underlying
* ListIterator through
*
* @return a ListIterator that views the passed ListIterator through the
* specified Converter
*/
public static ConverterListIterator getListIterator(ListIterator iter, Converter convUp,
Converter convDown)
{
return new ConverterListIterator<>(iter, convUp, convDown);
}
/**
* Returns a Converter instance of Map.
*
* @param map the underlying Map
* @param convKeyUp the Converter to view the underlying Map's keys
* through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying Map
* @param convValUp the Converter to view the underlying Map's values
* through
* @param convValDown the Converter to use to pass values down to the
* underlying Map
*
* @param the type of the keys in the underlying Map
* @param the type that the keys should be converted to
* @param the type of the values in the underlying Map
* @param the type that the values should be converted to
*
* @return a Map that views the keys and values of the passed Map through
* the specified Converters
*/
public static ConverterMap getMap(Map map, Converter convKeyUp,
Converter convKeyDown, Converter convValUp, Converter convValDown)
{
return new ConverterMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of SortedMap.
*
* @param map the underlying SortedMap
* @param convKeyUp the Converter to view the underlying SortedMap's
* keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying SortedMap
* @param convValUp the Converter to view the underlying SortedMap's
* values through
* @param convValDown the Converter to use to pass values down to the
* underlying SortedMap
*
* @param the type of the keys in the underlying SortedMap
* @param the type that the keys should be converted to
* @param the type of the values in the underlying SortedMap
* @param the type that the values should be converted to
*
* @return a SortedMap that views the keys and values of the passed
* SortedMap through the specified Converters
*/
public static ConverterSortedMap getSortedMap(SortedMap map,
Converter convKeyUp, Converter convKeyDown, Converter convValUp,
Converter convValDown)
{
return new ConverterSortedMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of a Set that holds Entry objects for a
* ConverterMap.
*
* @param set the underlying Entry Set (or Collection of Map
* Entry objects)
* @param convKeyUp the Converter to view the underlying Entry Set's
* keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying Entry Set
* @param convValUp the Converter to view the underlying Entry Set's
* values through
* @param convValDown the Converter to use to pass values down to the
* underlying Entry Set
*
* @param the type of the keys in the underlying EntrySet
* @param the type that the keys should be converted to
* @param the type of the values in the underlying EntrySet
* @param the type that the values should be converted to
*
* @return a Converter Set that views the keys and values of the
* underlying Set's Map.Entry objects through the specified key
* and value Converters
*/
public static ConverterEntrySet getEntrySet(Collection> set,
Converter convKeyUp, Converter convKeyDown, Converter convValUp,
Converter convValDown)
{
return new ConverterEntrySet<>(set, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns an instance of a MapEntry that uses Converters to retrieve
* the Entry's data.
*
* @param entry the underlying Entry
* @param convKeyUp the Converter to view the underlying Entry's key
* @param convValUp the Converter to view the underlying Entry's value
* @param convValDown the Converter to change the underlying Entry's value
*
* @param the type of the keys in the underlying Entry
* @param the type that the keys should be converted to
* @param the type of the values in the underlying Entry
* @param the type that the values should be converted to
*
* @return a ConverterEntry that converts the passed entry data using the
* specified Converters
*/
public static ConverterEntry getEntry(Map.Entry entry,
Converter convKeyUp,
Converter convValUp, Converter convValDown)
{
return new ConverterEntry<>(entry, convKeyUp, convValUp, convValDown);
}
/**
* Returns a Converter instance of Holder..
*
* @param value the underlying value
* @param convUp the Converter to view the underlying value
*
* @param the type of the underlying value
* @param the type of the converted value
*
* @return a ConverterHolder that converts the passed value using the
* specified Converter.
*/
public static ConverterHolder getConverterHolder(F value, Converter convUp)
{
return new ConverterHolder<>(value, convUp);
}
/**
* Returns a LongArray storing values with type {@code F} and converting
* to type {@code V} as and when required.
*
* @param la the LongArray with raw types
* @param convUp a Converter to convert to the desired type
* @param convDown a Converter to convert to the raw type
*
* @param the raw type
* @param the desired type
*
* @return a LongArray storing values in a raw type and converting to the
* desired type
*/
public static LongArray getLongArray(LongArray la, Converter convUp, Converter convDown)
{
return new ConverterLongArray<>(la, convUp, convDown);
}
/**
* Returns a Converter instance of ConcurrentMap.
*
* @param map the underlying ConcurrentMap
* @param convKeyUp the Converter to view the underlying
* ConcurrentMap's keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying ConcurrentMap
* @param convValUp the Converter to view the underlying
* ConcurrentMap's values through
* @param convValDown the Converter to use to pass values down to the
* underlying ConcurrentMap
*
* @return a ConcurrentMap that views the keys and values of the passed
* ConcurrentMap through the specified Converters
*/
public static ConcurrentMap getConcurrentMap(
ConcurrentMap map, Converter convKeyUp, Converter convKeyDown,
Converter convValUp, Converter convValDown)
{
return new ConverterConcurrentMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of InvocableMap.
*
* @param map the underlying InvocableMap
* @param convKeyUp the Converter to view the underlying
* InvocableMap's keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying InvocableMap
* @param convValUp the Converter to view the underlying
* InvocableMap's values through
* @param convValDown the Converter to use to pass values down to the
* underlying InvocableMap
*
* @return an InvocableMap that views the keys and values of the passed
* InvocableMap through the specified Converters
*/
public static InvocableMap getInvocableMap(
InvocableMap map, Converter convKeyUp, Converter convKeyDown,
Converter convValUp, Converter convValDown)
{
return new ConverterInvocableMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of ObservableMap.
*
* @param map the underlying ObservableMap
* @param convKeyUp the Converter to view the underlying
* ObservableMap's keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying ObservableMap
* @param convValUp the Converter to view the underlying
* ObservableMap's values through
* @param convValDown the Converter to use to pass values down to the
* underlying ObservableMap
*
* @return an ObservableMap that views the keys and values of the passed
* ObservableMap through the specified Converters
*/
public static ObservableMap getObservableMap(ObservableMap map,
Converter convKeyUp, Converter convKeyDown,
Converter convValUp, Converter convValDown)
{
return new ConverterObservableMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of QueryMap.
*
* @param map the underlying QueryMap
* @param convKeyUp the Converter to view the underlying QueryMap's
* keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying QueryMap
* @param convValUp the Converter to view the underlying QueryMap's
* values through
* @param convValDown the Converter to use to pass values down to the
* underlying QueryMap
*
* @return a QueryMap that views the keys and values of the passed
* QueryMap through the specified Converters
*/
public static QueryMap getQueryMap(QueryMap map,
Converter convKeyUp, Converter convKeyDown,
Converter convValUp, Converter convValDown)
{
return new ConverterQueryMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of CacheMap.
*
* @param map the underlying CacheMap
* @param convKeyUp the Converter to view the underlying CacheMap's
* keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying CacheMap
* @param convValUp the Converter to view the underlying CacheMap's
* values through
* @param convValDown the Converter to use to pass values down to the
* underlying CacheMap
*
* @return a CacheMap that views the keys and values of the passed
* CacheMap through the specified Converters
*/
public static CacheMap getCacheMap(CacheMap map,
Converter convKeyUp, Converter convKeyDown,
Converter convValUp, Converter convValDown)
{
return new ConverterCacheMap<>(map, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns a Converter instance of NamedCache that converts between the raw/from
* types to the desired/to types.
*
* There is a strong disclaimer in the use of this implementation:
*
* This conversion is entirely performed locally and therefore when using
* methods such as {@link NamedCache#invoke(Object, EntryProcessor)
* invoke}, or {@link NamedCache#aggregate(EntryAggregator) aggregate}, or
* {@link NamedCache#entrySet(Filter) entrySet(Filter)}, the
* provided agent ({@link EntryProcessor EntryProcessor}, or {@link EntryAggregator
* EntryAggregator}, or {@link Filter}) do not go through the provided converters.
* Hence the given agent(s) must operate against the raw types.
*
* Streams are not supported.
*
* @param cache the underlying NamedCache
* @param convKeyUp the Converter to view the underlying NamedCache's
* keys through
* @param convKeyDown the Converter to use to pass keys down to the
* underlying NamedCache
* @param convValUp the Converter to view the underlying NamedCache's
* values through
* @param convValDown the Converter to use to pass values down to the
* underlying NamedCache
*
* @return a NamedCache that views the keys and values of the passed
* NamedCache through the specified Converters
*/
public static NamedCache getNamedCache(NamedCache cache,
Converter convKeyUp,
Converter convKeyDown,
Converter convValUp,
Converter convValDown)
{
return new ConverterNamedCache<>(cache, convKeyUp, convKeyDown, convValUp, convValDown);
}
/**
* Returns an instance of a MapEvent that uses Converters to retrieve
* the event's data.
*
* @param map the new event's source
* @param event the underlying MapEvent
* @param convKey the Converter to view the underlying MapEvent's key
* @param convVal the Converter to view the underlying MapEvent's values
*
* @return a MapEvent that converts the passed event data using the
* specified Converter
*/
public static MapEvent getMapEvent(ObservableMap map, MapEvent event, Converter convKey, Converter convVal)
{
return new ConverterMapEvent(map, event, convKey, convVal);
}
/**
* Returns an instance of a MapEvent that uses Converters to retrieve the
* event's data, and additionally provides access to the
* BackingMapManagerContext.
*
* @param map the new event's source
* @param event the underlying MapEvent
* @param convKey the Converter to view the underlying MapEvent's key
* @param convVal the Converter to view the underlying MapEvent's values
* @param context the BackingMapManagerContext used to deserialize the
* underlying values
*
* @return a MapEvent that converts the passed event data using the
* specified Converters
*/
public static MapEvent getMapEvent(ObservableMap map, MapEvent event,
Converter convKey, Converter convVal, BackingMapManagerContext context)
{
return new ConverterMapEvent(map, event, convKey, convVal, context);
}
/**
* Returns a converter listener for the specified listener and Converters.
*
* @param map the Map that should be the source for converted events
* @param listener the underlying MapListener
* @param convKey the Converter to view the underlying MapEvent's key
* @param convVal the Converter to view the underlying MapEvent's values
*
* @return the converting listener
*/
public static MapListener getMapListener(ObservableMap map, MapListener listener, Converter convKey, Converter convVal)
{
MapListener listenerConv = map instanceof NamedCache ?
new ConverterCacheListener((NamedCache) map, listener, convKey, convVal) :
new ConverterMapListener(map, listener, convKey, convVal);
return listener instanceof MapListenerSupport.SynchronousListener ?
new MapListenerSupport.WrapperSynchronousListener(listenerConv) :
listenerConv;
}
// ----- helpers --------------------------------------------------------
/**
* Convert the contents of the passed array. The conversion is done "in
* place" in the passed array.
*
* This helper method is intended to support the functionality of
* Collection.toArray.
*
* @param ao an array of Objects to convert
* @param conv the Converter to use to convert the objects
*
* @return the passed array
*/
public static Object[] convertArray(Object[] ao, Converter conv)
{
for (int i = 0, c = ao.length; i < c; ++i)
{
ao[i] = conv.convert(ao[i]);
}
return ao;
}
/**
* Convert the contents of the passed source array into an array with the
* component type of the passed destination array, using the destination
* array itself if it is large enough, and placing a null in the first
* unused element of the destination array if it is larger than the
* source array.
*
* This helper method is intended to support the functionality of
* Collection.toArray.
*
* @param aoSrc an array of Objects to convert
* @param conv the Converter to use to convert the objects
* @param aoDest the array to use to place the converted objects in if
* large enough, otherwise the array from which to obtain
* the component type to create a new array that is large
* enough
*
* @return an array whose component type is the same as the passed
* destination array and whose contents are the converted objects
*/
public static Object[] convertArray(Object[] aoSrc, Converter conv, Object[] aoDest)
{
int cSrc = aoSrc.length;
int cDest = aoDest.length;
if (cSrc > cDest)
{
cDest = cSrc;
aoDest = (Object[]) Array.newInstance(aoDest.getClass().getComponentType(), cDest);
}
if (cDest > cSrc)
{
aoDest[cSrc] = null;
}
for (int i = 0; i < cSrc; ++i)
{
aoDest[i] = conv.convert(aoSrc[i]);
}
return aoDest;
}
/**
* Create a new converter by combining two existing converters.
*
* @param converter1 the first converter
* @param converter2 the second converter
*
* @return a combining converter that applies the converters sequentially
*
* @param the "from" type for the first converter
* @param the "to" type for the first converter and the "from" type for the second
* @param the "to" type for the second converter
*/
public static Converter combine(Converter converter1, Converter converter2)
{
return (from) -> converter2.convert(converter1.convert(from));
}
// ----- inner class: ConverterEnumerator -------------------------------
/**
* Provide an implementation of an enumerator which converts each of the
* items which it enumerates.
*
* @param the type of elements in the underlying Enumeration
* @param the type that the elements should be converted to
*
*/
public static class ConverterEnumerator
implements Enumeration, Iterator
{
// ----- constructors -----------------------------------------------
/**
* Construct the Converter enumerator based on an Enumeration.
*
* @param enmr java.util.Enumeration of objects to convert
* @param conv a Converter
*/
public ConverterEnumerator(final Enumeration enmr, Converter conv)
{
this(new Iterator()
{
public boolean hasNext()
{
return enmr.hasMoreElements();
}
public F next()
{
return enmr.nextElement();
}
public void remove()
{
throw new UnsupportedOperationException();
}
}, conv);
}
/**
* Construct the Converter enumerator based on an Iterator.
*
* @param iter java.util.Iterator of objects to convert
* @param conv a Converter
*/
public ConverterEnumerator(Iterator iter, Converter conv)
{
m_iter = iter;
m_conv = conv;
}
/**
* Construct the Converter enumerator based on an array of objects.
*
* @param aoItem array of objects to enumerate
* @param conv a Converter
*/
public ConverterEnumerator(Object[] aoItem, Converter conv)
{
this(Arrays. asList((F[]) aoItem).iterator(), conv);
}
// ----- Enumeration interface --------------------------------------
/**
* Tests if this enumeration contains more elements.
*
* @return false if the enumeration has been exhausted
*/
public boolean hasMoreElements()
{
return hasNext();
}
/**
* Get the next element in the enumeration.
*
* @return the next element of this enumeration
*/
public T nextElement()
{
return next();
}
// ----- Iterator interface -----------------------------------------
/**
* Determine if this Iterator contains more elements.
*
* @return true if the Iterator contains more elements, false otherwise
*/
public boolean hasNext()
{
return m_iter.hasNext();
}
/**
* Returns the next element of this Iterator.
*
* @return the next element in the Iterator
*/
public T next()
{
return m_conv.convert(m_iter.next());
}
/**
* Remove the last-returned element that was returned by the Iterator.
*/
public void remove()
{
m_iter.remove();
}
// ----- data members -----------------------------------------------
/**
* Iterator of Objects to convert.
*/
protected Iterator m_iter;
/**
* Converter to convert each item.
*/
protected Converter m_conv;
}
// ----- inner class: ConverterCollection -------------------------------
/**
* A Converter Collection views an underlying Collection through a
* Converter.
*
* @param the type of elements in the underlying Collection
* @param the type that the elements should be converted to
*
*/
public static class ConverterCollection
implements Collection, Serializable
{
// ----- constructors -----------------------------------------------
/**
* Constructor.
*
* @param col the underlying Collection
* @param convUp the Converter from the underlying Collection
* @param convDown the Converter to the underlying Collection
*/
public ConverterCollection(Collection col, Converter convUp, Converter convDown)
{
assert(col != null && convUp != null && convDown != null);
m_col = col;
m_convUp = convUp;
m_convDown = convDown;
}
// ----- Collection interface ---------------------------------------
/**
* {@inheritDoc}
*/
@Override
public int size()
{
return getCollection().size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty()
{
return getCollection().isEmpty();
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean contains(Object o)
{
return getCollection().contains(getConverterDown().convert((T) o));
}
/**
* {@inheritDoc}
*/
@Override
public Iterator iterator()
{
return instantiateIterator(getCollection().iterator(),
getConverterUp());
}
/**
* {@inheritDoc}
*/
@Override
public Object[] toArray()
{
return convertArray(getCollection().toArray(), getConverterUp());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public E[] toArray(E[] aoDest)
{
return (E[]) convertArray(getCollection().toArray(),
getConverterUp(),
aoDest);
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T o)
{
return getCollection().add(getConverterDown().convert(o));
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o)
{
return getCollection().remove(getConverterDown().convert((T) o));
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean containsAll(Collection> col)
{
return getCollection().containsAll(
instantiateCollection((Collection) col,
getConverterDown(),
getConverterUp()));
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean addAll(Collection extends T> col)
{
return getCollection().addAll(
instantiateCollection((Collection) col,
getConverterDown(),
getConverterUp()));
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean removeAll(Collection> col)
{
return getCollection().removeAll(
instantiateCollection((Collection) col,
getConverterDown(),
getConverterUp()));
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean retainAll(Collection> col)
{
return getCollection().retainAll(
instantiateCollection((Collection) col,
getConverterDown(),
getConverterUp()));
}
/**
* {@inheritDoc}
*/
@Override
public void clear()
{
getCollection().clear();
}
// ----- Object methods ---------------------------------------------
/**
* Compares the specified object with this collection for equality.
* Obeys the general contract of Collection.equals.
*
* @param o Object to be compared for equality with this Collection
*
* @return true if the specified object is equal to this
* Collection
*/
@SuppressWarnings("rawtypes")
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (o instanceof ConverterCollection)
{
ConverterCollection that = (ConverterCollection) o;
return this.getCollection() .equals(that.getCollection() )
&& this.getConverterUp() .equals(that.getConverterUp() )
&& this.getConverterDown().equals(that.getConverterDown());
}
return false;
}
/**
* Return a String description for this collection.
*
* @return a String description of the Collection
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("ConverterCollection{");
boolean fFirst = true;
for (Object o : this)
{
if (fFirst)
{
fFirst = false;
}
else
{
sb.append(", ");
}
sb.append(o);
}
sb.append('}');
return sb.toString();
}
// ----- lifecycle --------------------------------------------------
/**
* Drop references to the underlying Collection and the Converters.
*/
public void invalidate()
{
m_col = null;
m_convUp = null;
m_convDown = null;
}
// ----- factory methods --------------------------------------------
/**
* Create a Converter Collection.
*
* @param col the underlying Collection
* @param convUp the Converter to view the underlying Collection
* through
* @param convDown the Converter to pass items down to the underlying
* Collection through
*
* @param the type of elements in the underlying Collection
* @param the type that the elements should be converted to
*
* @return a Converter Collection
*/
protected Collection instantiateCollection(Collection col, Converter convUp,
Converter convDown)
{
return ConverterCollections.getCollection(col, convUp, convDown);
}
/**
* Create a Converter Iterator.
*
* @param iter the underlying Iterator
* @param conv the Converter to view the underlying Iterator through
*
* @return a Converter Iterator
*/
protected Iterator instantiateIterator(Iterator iter, Converter conv)
{
return ConverterCollections.getIterator(iter, conv);
}
// ----- accessors --------------------------------------------------
/**
* Return the underlying Collection.
*
* @return the underlying Collection
*/
public Collection getCollection()
{
return m_col;
}
/**
* Return the Converter used to view the underlying Collection's
* values through.
*
* @return the Converter from the underlying Collection
*/
public Converter getConverterUp()
{
return m_convUp;
}
/**
* Return the Converter used to pass values down to the underlying
* Collection.
*
* @return the Converter to the underlying Collection
*/
public Converter getConverterDown()
{
return m_convDown;
}
// ----- data members -----------------------------------------------
/**
* The underlying Collection.
*/
protected Collection m_col;
/**
* The Converter from the underlying Collection to this Collection.
*/
protected Converter m_convUp;
/**
* The Converter from this Collection to the underlying Collection.
*/
protected Converter m_convDown;
}
// ----- inner class: ConverterSet --------------------------------------
/**
* A Converter Set views an underlying Set through a Converter.
*
* @param the type of elements in the underlying Set
* @param the type that the elements should be converted to
*/
public static class ConverterSet
extends ConverterCollection
implements Set, Serializable
{
// ----- constructors -----------------------------------------------
/**
* Constructor.
*
* @param col the underlying Collection
* @param convUp the Converter from the underlying Set
* @param convDown the Converter to the underlying Set
*/
// Note: we can not guarantee conformance to the Set contract as the
// the converter may return duplicates thus we widen the accepted
// type to be a Collection
public ConverterSet(Collection col, Converter convUp, Converter convDown)
{
super(col, convUp, convDown);
}
// ----- Object methods ---------------------------------------------
/**
* {@inheritDoc}
*/
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (o instanceof ConverterCollection)
{
ConverterCollection that = (ConverterCollection) o;
return this.getCollection() .equals(that.getCollection() )
&& this.getConverterUp() .equals(that.getConverterUp() )
&& this.getConverterDown().equals(that.getConverterDown());
}
if (o instanceof Set)
{
Set set = (Set) o;
return set.size() == this.size() && this.containsAll(set);
}
return false;
}
/**
* {@inheritDoc}
*/
public int hashCode()
{
int nHash = 0;
for (Object o : this.getCollection())
{
nHash += NaturalHasher.INSTANCE.hashCode(o);
}
return nHash;
}
}
// ----- inner class: ConverterSortedSet --------------------------------
/**
* A Converter SortedSet views an underlying SortedSet through a
* Converter.
*
* @param the type of elements in the underlying SortedSet
* @param the type that the elements should be converted to
*/
public static class ConverterSortedSet
extends ConverterSet
implements SortedSet, Serializable
{
// ----- constructors -----------------------------------------------
/**
* Constructor.
*
* @param set the underlying SortedSet
* @param convUp the Converter from the underlying SortedSet
* @param convDown the Converter to the underlying SortedSet
*/
public ConverterSortedSet(SortedSet set, Converter convUp, Converter convDown)
{
super(set, convUp, convDown);
}
// ----- SortedSet interface ----------------------------------------
/**
* {@inheritDoc}
*/
@Override
public Comparator comparator()
{
Comparator super F> comparator = getSortedSet().comparator();
return comparator == null
? null
: new ConverterComparator(comparator, m_convDown);
}
/**
* {@inheritDoc}
*/
@Override
public SortedSet subSet(T fromElement, T toElement)
{
SortedSet subset = getSortedSet().subSet(
getConverterDown().convert(fromElement),
getConverterDown().convert(toElement));
return instantiateSortedSet(subset, getConverterUp(), getConverterDown());
}
/**
* {@inheritDoc}
*/
@Override
public SortedSet headSet(T toElement)
{
SortedSet subset = getSortedSet().headSet(
getConverterDown().convert(toElement));
return instantiateSortedSet(subset, getConverterUp(), getConverterDown());
}
/**
* {@inheritDoc}
*/
@Override
public SortedSet tailSet(T fromElement)
{
SortedSet subset = getSortedSet().tailSet(
getConverterDown().convert(fromElement));
return instantiateSortedSet(subset, getConverterUp(), getConverterDown());
}
/**
* {@inheritDoc}
*/
@Override
public T first()
{
return getConverterUp().convert(getSortedSet().first());
}
/**
* {@inheritDoc}
*/
@Override
public T last()
{
return getConverterUp().convert(getSortedSet().last());
}
// ----- factory methods --------------------------------------------
/**
* Create a Converter SortedSet.
*
* @param set the underlying SortedSet
* @param convUp the Converter to view the underlying SortedSet
* through
* @param convDown the Converter to pass items down to the underlying
* SortedSet through
*
* @return a Converter SortedSet
*/
protected SortedSet instantiateSortedSet(SortedSet set, Converter convUp, Converter convDown)
{
return ConverterCollections.getSortedSet(set, convUp, convDown);
}
// ----- accessors --------------------------------------------------
/**
* Return the underlying SortedSet.
*
* @return the underlying SortedSet
*/
public SortedSet getSortedSet()
{
return (SortedSet) getCollection();
}
}
// ----- inner class: ConverterList -------------------------------------
/**
* A Converter List views an underlying List through a Converter.
*
* @param the type of elements in the underlying List
* @param the type that the elements should be converted to
*/
public static class ConverterList
extends ConverterCollection
implements List, Serializable
{
// ----- constructors -----------------------------------------------
/**
* Constructor.
*
* @param list the underlying List
* @param convUp the Converter from the underlying List
* @param convDown the Converter to the underlying List
*/
public ConverterList(List list, Converter convUp, Converter convDown)
{
super(list, convUp, convDown);
}
// ----- List interface ---------------------------------------------
/**
* {@inheritDoc}
*/
public T get(int index)
{
return getConverterUp().convert(getList().get(index));
}
/**
* {@inheritDoc}
*/
public T set(int index, T element)
{
return getConverterUp().convert(getList().set(index,
getConverterDown().convert(element)));
}
/**
* {@inheritDoc}
*/
public void add(int index, T element)
{
getList().add(index, getConverterDown().convert(element));
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public boolean addAll(int index, Collection extends T> col)
{
return getList().addAll(index,
instantiateCollection((Collection) col,
getConverterDown(),
getConverterUp()));
}
/**
* {@inheritDoc}
*/
@Override
public T remove(int index)
{
return getConverterUp().convert(getList().remove(index));
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public int indexOf(Object o)
{
return getList().indexOf(getConverterDown().convert((T) o));
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public int lastIndexOf(Object o)
{
return getList().lastIndexOf(getConverterDown().convert((T) o));
}
/**
* {@inheritDoc}
*/
@Override
public ListIterator listIterator()
{
return instantiateListIterator(getList().listIterator(),
getConverterUp(),
getConverterDown());
}
/**
* {@inheritDoc}
*/
@Override
public ListIterator listIterator(int index)
{
return instantiateListIterator(getList().listIterator(index),
getConverterUp(),
getConverterDown());
}
/**
* {@inheritDoc}
*/
@Override
public List subList(int fromIndex, int toIndex)
{
return instantiateList(getList().subList(fromIndex, toIndex),
getConverterUp(),
getConverterDown());
}
// ----- Object methods ---------------------------------------------
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (o instanceof ConverterCollection)
{
ConverterCollection that = (ConverterCollection) o;
return this.getCollection() .equals(that.getCollection() )
&& this.getConverterUp() .equals(that.getConverterUp() )
&& this.getConverterDown().equals(that.getConverterDown());
}
if (o instanceof List)
{
Iterator iterThis = this.listIterator();
Iterator iterThat = ((List) o).listIterator();
while (iterThis.hasNext() && iterThat.hasNext())
{
if (!NaturalHasher.INSTANCE.equals(iterThis.next(), iterThat.next()))
{
return false;
}
}
return !(iterThis.hasNext() || iterThat.hasNext());
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public int hashCode()
{
int nHash = 1;
for (Iterator iter = this.listIterator(); iter.hasNext();)
{
nHash = 31 * nHash + NaturalHasher.INSTANCE.hashCode(iter.next());
}
return nHash;
}
// ----- factory methods --------------------------------------------
/**
* Create a Converter List.
*
* @param list the underlying List
* @param convUp the Converter to view the underlying List
* through
* @param convDown the Converter to pass items down to the underlying
* List through
*
* @param the type of elements in the underlying List
* @param the type that the elements should be converted to
*
* @return a Converter List
*/
protected List instantiateList(List list, Converter convUp, Converter convDown)
{
return ConverterCollections.getList(list, convUp, convDown);
}
/**
* Create a Converter ListIterator.
*
* @param iter the underlying ListIterator
* @param convUp the Converter to view the underlying ListIterator
* through
* @param convDown the Converter to pass items down to the underlying
* ListIterator through
*
* @param the type of elements in the underlying ListIterator
* @param