package de.axone.tools;
import java.util.ArrayList;
import java.util.Collection;
public abstract class Col {
/**
* Try to make an empty clone of a collection
*
* This is done using reflection. Note that this method fails if the given
* collections doesn't habe a public contructor
*
* @param <V>
* @param <C>
* @param collection to clone
* @return an empty clone
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static <V,C extends Collection<V>> C emptyClone( C collection )
throws InstantiationException, IllegalAccessException{
@SuppressWarnings( "unchecked" ) // This should work without warning ...
Class<? extends C> clazz = (Class<? extends C>)collection.getClass();
C result = clazz.newInstance();
return result;
}
/**
* Processes every element in a Collection using the given Processor
*
* The elements are taken from src, then processed and then
* put into dst
*
* @param <V>
* @param <Cd>
* @param <Cs>
* @param dst destination
* @param src source
* @param processor to use for processing
* @return a the Collection given as dst with the processed elements
*/
public static <V,Cd extends Collection<V>, Cs extends Collection<V>>
Cd process( Cd dst, Cs src, Processor<V> processor ){
for( V value : src ){
dst.add( processor.process( value ) );
}
return dst;
}
/**
* Process every element in a Collection and return a new Collection
* of the same type with the processed elements.
*
* This is done using reflection. Note that this method fails if the given
* collections doesn't habe a public contructor
*
* @param <V>
* @param <C>
* @param src
* @param processor to use for processing
* @return a new Collection with the processed elements
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static <V,C extends Collection<V>> C process( C src, Processor<V> processor )
throws InstantiationException, IllegalAccessException{
C dst = emptyClone( src );
for( V value : src ){
dst.add( processor.process( value ) );
}
return dst;
}
/**
* Processes every element in the Collection using the give Processor
*
* WARNING: The Collections must be editable. This is not necessarily the
* case. E.g. wrapped Arrays are immutable.
*
* @param <V>
* @param <C>
* @param collection
* @param processor
* @return the given collection (no copy) with the elements processed
*/
public static <V, C extends Collection<V>> C processInPlace( C collection, Processor<V> processor ){
ArrayList<V> temp = new ArrayList<V>( collection );
collection.clear();
for( V value : temp ){
collection.add( processor.process( value ) );
}
return collection;
}
/**
* Process every element in a Collection and return a new Collection
* of the same type with the processed elements.
*
* This is like process but does throw Errors instead of catchable exceptions.
*
* WARNING: This method should be used with extreme care. It will fail e.g. for
* <code>process( Arrays.asList( new String[]{ "A", "B", "C" } ) )</code> because
* the resulting Arrays#ArrayList has no public empty constructor.
*
* @param <V>
* @param <C>
* @param src
* @param conv
* @see #process(Collection, Collection, Processor)
* @return the given collection (no copy) with the elements processed
*/
public static <V,C extends Collection<V>> C processUnchecked( C src, Processor<V> conv ){
try {
return process( src, conv );
} catch( InstantiationException e ) {
throw new Error( "Instantiation error while converting", e );
} catch( IllegalAccessException e ) {
throw new Error( "Access error while converting", e );
}
}
public interface Processor<T> {
public T process( T value );
}
}