package com.tapina.util; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.Map; import java.util.regex.Pattern; /** * A utility class providing transformation routines to convert one type to * another using Java 1.5 generics for type safety (unlike ConvertUtils) * and brevity. *

* Static methods on this class provide the utilities, and the class itself * provides the interface required to perform transformation. Users of the utilities * will need to therefore create concrete implementations of the class, which may * be anonymous if the transformer is not to be reused. An example follows: *

 *   List<Integer> numbers = (List<Integer>) Arrays.asList(1, 2, 3, 4);
 *   Set<String> strings = new HashSet<String>(numbers.size());
 *   Transformer.transform(numbers, strings, new Transformer() {
 *     public String transform(Number input) {
 *       return input.toString();
 *     }
 *   });
 * 
*

* A number of Transformer implementations are provided as constants. * * @param input object * @param output object */ public abstract class Transformer { public final static Transformer STRING_TO_LITERAL_PATTERN = new Transformer() { @Override public Pattern transform(String s) { return Pattern.compile(s, Pattern.LITERAL); } }; public final static Transformer FILE_TO_CANONICAL_PATH = new Transformer() { @Override public String transform(File file) { try { return file.getCanonicalPath(); } catch (IOException e) { return null; } } }; public final static Transformer FILE_TO_URI = new Transformer() { @Override public URI transform(File file) { return file.toURI(); } }; public final static Transformer TO_STRING = new Transformer() { @Override public String transform(Object input) { return input.toString(); } }; public final static Transformer STRING_TO_URI = new Transformer() { @Override public URI transform(String input) { return URI.create(input); } }; public final static Transformer PATH_TO_FILE = new Transformer() { @Override public File transform(String path) { return new File(path); } }; /** * Subclasses should implement this method to convert * an object of type I to an object of type O. * * @param input input object, of type I * @return output object, of type O */ public abstract O transform(I input); /** * Appends another transformation to this transformation to produce a single * transformer which combines both operations. * * @param

Output type of second transformer * @param chainedTransformer Transformer producing P from this transformer's output. * @return Composite transformer combining both operations. */ public final

Transformer followedBy(Transformer chainedTransformer) { return chain(this, chainedTransformer); } private static Transformer chain(final Transformer first, final Transformer second) { return new Transformer() { @Override public O transform(I input) { return second.transform(first.transform(input)); } }; } /** * Transforms a collection of objects to a collection of a different type. The * input and output collections must be passed to the method. *

* The output collection is not cleared before transformed objects are added. * * @param type of object in input collection * @param type of object in output collection * @param type of output collection (a collection capable of holding objects of type O) * @param inputs input collection * @param outputs output collection to be populated * @param transformer instance of this class capable of transforming I to O * @return output collection passed as argument, for convenience. */ public static > C transform(Collection inputs, C outputs, Transformer transformer) { for (I input : inputs) { outputs.add(transformer.transform(input)); } return outputs; } /** * Transforms an array to an array of a different type. The * input and output arrays must be passed to the method. *

* If the arrays are different sizes, the array of the shortest length dictates * the number of objects converted. * * @param type of object in input array * @param type of object in output array * @param inputs input array * @param outputs output array to be populated * @param transformer instance of this class capable of transforming I to O * @return output array passed as argument, for convenience. */ public static O[] transform(I[] inputs, O[] outputs, Transformer transformer) { for (int i = 0; i < outputs.length && i < inputs.length; i++) { outputs[i] = transformer.transform(inputs[i]); } return outputs; } /** * Transforms a map into an identically-keyed map of different typed values. * The input and output maps must be passed to the method. *

* The output map is not cleared before transformed entries are added. * * @param type of key, remains unchanged between input and output map * @param type of value in input map * @param type of value in output map * @param inputs input map * @param outputs output map to be populated * @param transformer instance of this class capable of transforming I to O * @return output array passed as argument, for convenience. */ public static Map transform(Map inputs, Map outputs, Transformer transformer) { for (Map.Entry entry : inputs.entrySet()) { outputs.put(entry.getKey(), transformer.transform(entry.getValue())); } return outputs; } }