Add functor utility implementations
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131079 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0d490de07c
commit
17cfa3461b
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Closure.java,v 1.5 2003/05/11 14:15:23 scolebourne Exp $
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Closure.java,v 1.6 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
|
@ -57,21 +57,30 @@
|
|||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
/**
|
||||
* An interface to represent some Closure, a block of code which is executed
|
||||
* from inside some block, function or iteration which operates on an input
|
||||
* object.
|
||||
*
|
||||
/**
|
||||
* <code>Closure</code> defines an interface implemented by classes that
|
||||
* do something.
|
||||
* <p>
|
||||
* A Closure represents a block of code which is executed from inside some
|
||||
* block, function or iteration. It operates an input object.
|
||||
*
|
||||
* @since Commons Collections 1.0
|
||||
* @version $Revision: 1.5 $ $Date: 2003/05/11 14:15:23 $
|
||||
*
|
||||
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
|
||||
* @version $Revision: 1.6 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Nicola Ken Barozzi
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public interface Closure {
|
||||
|
||||
/**
|
||||
* Performs some operation on the input object.
|
||||
|
||||
/**
|
||||
* Performs an action on the specified input object.
|
||||
*
|
||||
* @param input the input to execute on
|
||||
* @throws ClassCastException (runtime) if the input is the wrong class
|
||||
* @throws IllegalArgumentException (runtime) if the input is invalid
|
||||
* @throws FunctorException (runtime) if any other error occurs
|
||||
*/
|
||||
void execute(Object input);
|
||||
public void execute(Object input);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/ClosureUtils.java,v 1.1 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <code>ClosureUtils</code> provides reference implementations and utilities
|
||||
* for the Closure functor interface. The supplied closures are:
|
||||
* <ul>
|
||||
* <li>Invoker - invokes a method on the input object
|
||||
* <li>For - repeatedly calls a closure for a fixed number of times
|
||||
* <li>While - repeatedly calls a closure while a predicate is true
|
||||
* <li>DoWhile - repeatedly calls a closure while a predicate is true
|
||||
* <li>Chained - chains two or more closures together
|
||||
* <li>Switch - calls one closure based on one or more predicates
|
||||
* <li>SwitchMap - calls one closure looked up from a Map
|
||||
* <li>Transformer - wraps a Transformer as a Closure
|
||||
* <li>NOP - does nothing
|
||||
* <li>Exception - always throws an exception
|
||||
* </ul>
|
||||
* All the supplied closures are Serializable.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.1 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class ClosureUtils {
|
||||
|
||||
/**
|
||||
* A Closure that always throws an exception
|
||||
*/
|
||||
private static final Closure EXCEPTION_CLOSURE = new ExceptionClosure();
|
||||
/**
|
||||
* A Closure that does nothing
|
||||
*/
|
||||
private static final Closure NOP_CLOSURE = new NOPClosure();
|
||||
|
||||
/**
|
||||
* This class is not normally instantiated.
|
||||
*/
|
||||
public ClosureUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Closure that always throws an exception.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the closure
|
||||
*/
|
||||
public static Closure exceptionClosure() {
|
||||
return EXCEPTION_CLOSURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Closure that will do nothing.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the closure
|
||||
*/
|
||||
public static Closure nopClosure() {
|
||||
return NOP_CLOSURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that calls a Transformer each time it is called.
|
||||
* The transformer will be called using the closure's input object.
|
||||
* The transformer's result will be ignored.
|
||||
*
|
||||
* @param transformer the transformer to run each time in the closure
|
||||
* @return the closure.
|
||||
*/
|
||||
public static Closure asClosure(Transformer transformer) {
|
||||
if (transformer == null) {
|
||||
throw new IllegalArgumentException("The transformer must not be null");
|
||||
}
|
||||
return new TransformerClosure(transformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that will call the closure <code>count</code> times.
|
||||
*
|
||||
* @param count the number of times to loop
|
||||
* @param closure the closure to call repeatedly
|
||||
* @return the <code>for</code> closure
|
||||
* @throws IllegalArgumentException if either argument is null
|
||||
*/
|
||||
public static Closure forClosure(int count, Closure closure) {
|
||||
if (count < 0) {
|
||||
throw new IllegalArgumentException("The loop count must not be less than zero, it was " + count);
|
||||
}
|
||||
if (closure == null) {
|
||||
throw new IllegalArgumentException("The closure must not be null");
|
||||
}
|
||||
return new ForClosure(count, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that will call the closure repeatedly until the
|
||||
* predicate returns false.
|
||||
*
|
||||
* @param predicate the predicate to use as an end of loop test
|
||||
* @param closure the closure to call repeatedly
|
||||
* @return the <code>while</code> closure
|
||||
* @throws IllegalArgumentException if either argument is null
|
||||
*/
|
||||
public static Closure whileClosure(Predicate predicate, Closure closure) {
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
if (closure == null) {
|
||||
throw new IllegalArgumentException("The closure must not be null");
|
||||
}
|
||||
return new WhileClosure(predicate, closure, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that will call the closure once and then repeatedly
|
||||
* until the predicate returns false.
|
||||
*
|
||||
* @param closure the closure to call repeatedly
|
||||
* @param predicate the predicate to use as an end of loop test
|
||||
* @return the <code>do-while</code> closure
|
||||
* @throws IllegalArgumentException if either argument is null
|
||||
*/
|
||||
public static Closure doWhileClosure(Closure closure, Predicate predicate) {
|
||||
if (closure == null) {
|
||||
throw new IllegalArgumentException("The closure must not be null");
|
||||
}
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new WhileClosure(predicate, closure, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that will invoke a specific method on the closure's
|
||||
* input object by reflection.
|
||||
*
|
||||
* @param methodName the name of the method
|
||||
* @return the <code>invoker</code> closure
|
||||
* @throws IllegalArgumentException if the method name is null
|
||||
*/
|
||||
public static Closure invokerClosure(String methodName) {
|
||||
// reuse transformer as it has caching - this is lazy really, should have inner class here
|
||||
return asClosure(TransformerUtils.invokerTransformer(methodName, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Closure that will invoke a specific method on the closure's
|
||||
* input object by reflection.
|
||||
*
|
||||
* @param methodName the name of the method
|
||||
* @param paramTypes the parameter types
|
||||
* @param args the arguments
|
||||
* @return the <code>invoker</code> closure
|
||||
* @throws IllegalArgumentException if the method name is null
|
||||
* @throws IllegalArgumentException if the paramTypes and args don't match
|
||||
*/
|
||||
public static Closure invokerClosure(String methodName, Class[] paramTypes, Object[] args) {
|
||||
// reuse transformer as it has caching - this is lazy really, should have inner class here
|
||||
return asClosure(TransformerUtils.invokerTransformer(methodName, paramTypes, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls two Closures, passing the result of
|
||||
* the first into the second.
|
||||
*
|
||||
* @param closure1 the first closure
|
||||
* @param closure2 the second closure
|
||||
* @return the <code>chained</code> closure
|
||||
* @throws IllegalArgumentException if either closure is null
|
||||
*/
|
||||
public static Closure chainedClosure(Closure closure1, Closure closure2) {
|
||||
Closure[] closures = new Closure[] { closure1, closure2 };
|
||||
validate(closures);
|
||||
return new ChainedClosure(closures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls each closure in turn, passing the
|
||||
* result into the next closure.
|
||||
*
|
||||
* @param closures an array of closures to chain
|
||||
* @return the <code>chained</code> closure
|
||||
* @throws IllegalArgumentException if the closures array is null
|
||||
* @throws IllegalArgumentException if the closures array has 0 elements
|
||||
* @throws IllegalArgumentException if any closure in the array is null
|
||||
*/
|
||||
public static Closure chainedClosure(Closure[] closures) {
|
||||
closures = copy(closures);
|
||||
validate(closures);
|
||||
return new ChainedClosure(closures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls each closure in turn, passing the
|
||||
* result into the next closure. The ordering is that of the iterator()
|
||||
* method on the collection.
|
||||
*
|
||||
* @param closures a collection of closures to chain
|
||||
* @return the <code>chained</code> closure
|
||||
* @throws IllegalArgumentException if the closures collection is null
|
||||
* @throws IllegalArgumentException if the closures collection is empty
|
||||
* @throws IllegalArgumentException if any closure in the collection is null
|
||||
*/
|
||||
public static Closure chainedClosure(Collection closures) {
|
||||
if (closures == null) {
|
||||
throw new IllegalArgumentException("The closure collection must not be null");
|
||||
}
|
||||
// convert to array like this to guarantee iterator() ordering
|
||||
Closure[] cmds = new Closure[closures.size()];
|
||||
int i = 0;
|
||||
for (Iterator it = closures.iterator(); it.hasNext();) {
|
||||
cmds[i++] = (Closure) it.next();
|
||||
}
|
||||
validate(cmds);
|
||||
return new ChainedClosure(cmds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls one of two closures depending
|
||||
* on the specified predicate.
|
||||
*
|
||||
* @param predicate the predicate to switch on
|
||||
* @param trueClosure the closure called if the predicate is true
|
||||
* @param falseClosure the closure called if the predicate is false
|
||||
* @return the <code>switch</code> closure
|
||||
* @throws IllegalArgumentException if the predicate is null
|
||||
* @throws IllegalArgumentException if either closure is null
|
||||
*/
|
||||
public static Closure switchClosure(Predicate predicate, Closure trueClosure, Closure falseClosure) {
|
||||
return switchClosureInternal(new Predicate[] { predicate }, new Closure[] { trueClosure }, falseClosure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls one of the closures depending
|
||||
* on the predicates.
|
||||
* <p>
|
||||
* The closure at array location 0 is called if the predicate at array
|
||||
* location 0 returned true. Each predicate is evaluated
|
||||
* until one returns true.
|
||||
*
|
||||
* @param predicates an array of predicates to check
|
||||
* @param closures an array of closures to call
|
||||
* @return the <code>switch</code> closure
|
||||
* @throws IllegalArgumentException if the either array is null
|
||||
* @throws IllegalArgumentException if the either array has 0 elements
|
||||
* @throws IllegalArgumentException if any element in the arrays is null
|
||||
* @throws IllegalArgumentException if the arrays are different sizes
|
||||
*/
|
||||
public static Closure switchClosure(Predicate[] predicates, Closure[] closures) {
|
||||
return switchClosureInternal(copy(predicates), copy(closures), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls one of the closures depending
|
||||
* on the predicates.
|
||||
* <p>
|
||||
* The closure at array location 0 is called if the predicate at array
|
||||
* location 0 returned true. Each predicate is evaluated
|
||||
* until one returns true. If no predicates evaluate to true, the default
|
||||
* closure is called.
|
||||
*
|
||||
* @param predicates an array of predicates to check
|
||||
* @param closures an array of closures to call
|
||||
* @param defaultClosure the default to call if no predicate matches
|
||||
* @return the <code>switch</code> closure
|
||||
* @throws IllegalArgumentException if the either array is null
|
||||
* @throws IllegalArgumentException if the either array has 0 elements
|
||||
* @throws IllegalArgumentException if any element in the arrays is null
|
||||
* @throws IllegalArgumentException if the arrays are different sizes
|
||||
*/
|
||||
public static Closure switchClosure(Predicate[] predicates, Closure[] closures, Closure defaultClosure) {
|
||||
return switchClosureInternal(copy(predicates), copy(closures), defaultClosure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that calls one of the closures depending
|
||||
* on the predicates.
|
||||
* <p>
|
||||
* The Map consists of Predicate keys and Closure values. A closure
|
||||
* is called if its matching predicate returns true. Each predicate is evaluated
|
||||
* until one returns true. If no predicates evaluate to true, the default
|
||||
* closure is called. The default closure is set in the map with a
|
||||
* null key. The ordering is that of the iterator() method on the entryset
|
||||
* collection of the map.
|
||||
*
|
||||
* @param predicatesAndClosures a map of predicates to closures
|
||||
* @return the <code>switch</code> closure
|
||||
* @throws IllegalArgumentException if the map is null
|
||||
* @throws IllegalArgumentException if the map is empty
|
||||
* @throws IllegalArgumentException if any closure in the map is null
|
||||
* @throws ClassCastException if the map elements are of the wrong type
|
||||
*/
|
||||
public static Closure switchClosure(Map predicatesAndClosures) {
|
||||
Closure[] trs = null;
|
||||
Predicate[] preds = null;
|
||||
if (predicatesAndClosures == null) {
|
||||
throw new IllegalArgumentException("The predicate and closure map must not be null");
|
||||
}
|
||||
// convert to array like this to guarantee iterator() ordering
|
||||
Closure def = (Closure) predicatesAndClosures.remove(null);
|
||||
int size = predicatesAndClosures.size();
|
||||
trs = new Closure[size];
|
||||
preds = new Predicate[size];
|
||||
int i = 0;
|
||||
for (Iterator it = predicatesAndClosures.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
preds[i] = (Predicate) entry.getKey();
|
||||
trs[i] = (Closure) entry.getValue();
|
||||
i++;
|
||||
}
|
||||
return switchClosureInternal(preds, trs, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate input and create closure.
|
||||
*
|
||||
* @param predicates an array of predicates to check
|
||||
* @param closures an array of closures to call
|
||||
* @param defaultClosure the default to call if no predicate matches
|
||||
* @return the <code>switch</code> closure
|
||||
* @throws IllegalArgumentException if the either array is null
|
||||
* @throws IllegalArgumentException if the either array has 0 elements
|
||||
* @throws IllegalArgumentException if any element in the arrays is null
|
||||
* @throws IllegalArgumentException if the arrays are different sizes
|
||||
*/
|
||||
private static Closure switchClosureInternal(Predicate[] predicates, Closure[] closures, Closure defaultClosure) {
|
||||
validate(predicates);
|
||||
validate(closures);
|
||||
if (predicates.length != closures.length) {
|
||||
throw new IllegalArgumentException("The predicate and closure arrays must be the same size");
|
||||
}
|
||||
if (defaultClosure == null) {
|
||||
defaultClosure = nopClosure();
|
||||
}
|
||||
return new SwitchClosure(predicates, closures, defaultClosure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that uses the input object as a key to find the
|
||||
* closure to call.
|
||||
* <p>
|
||||
* The Map consists of object keys and Closure values. A closure
|
||||
* is called if the input object equals the key. If there is no match, the
|
||||
* default closure is called. The default closure is set in the map
|
||||
* using a null key.
|
||||
*
|
||||
* @param objectsAndClosures a map of objects to closures
|
||||
* @return the closure
|
||||
* @throws IllegalArgumentException if the map is null
|
||||
* @throws IllegalArgumentException if the map is empty
|
||||
* @throws IllegalArgumentException if any closure in the map is null
|
||||
*/
|
||||
public static Closure switchMapClosure(Map objectsAndClosures) {
|
||||
Closure[] trs = null;
|
||||
Predicate[] preds = null;
|
||||
if (objectsAndClosures == null) {
|
||||
throw new IllegalArgumentException("The obejct and closure map must not be null");
|
||||
}
|
||||
Closure def = (Closure) objectsAndClosures.remove(null);
|
||||
int size = objectsAndClosures.size();
|
||||
trs = new Closure[size];
|
||||
preds = new Predicate[size];
|
||||
int i = 0;
|
||||
for (Iterator it = objectsAndClosures.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
preds[i] = PredicateUtils.equalPredicate(entry.getKey());
|
||||
trs[i] = (Closure) entry.getValue();
|
||||
i++;
|
||||
}
|
||||
return switchClosure(preds, trs, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the predicates to ensure that the internal reference can't be messed with.
|
||||
*
|
||||
* @param predicates the predicates to copy
|
||||
* @return the cloned predicates
|
||||
*/
|
||||
private static Predicate[] copy(Predicate[] predicates) {
|
||||
if (predicates == null) {
|
||||
return null;
|
||||
}
|
||||
return (Predicate[]) predicates.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the predicates to ensure that all is well.
|
||||
*
|
||||
* @param predicates the predicates to validate
|
||||
* @return the validated predicates
|
||||
*/
|
||||
private static void validate(Predicate[] predicates) {
|
||||
if (predicates == null) {
|
||||
throw new IllegalArgumentException("The predicate array must not be null");
|
||||
}
|
||||
if (predicates.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 1 predicate must be specified in the predicate array, size was " + predicates.length);
|
||||
}
|
||||
for (int i = 0; i < predicates.length; i++) {
|
||||
if (predicates[i] == null) {
|
||||
throw new IllegalArgumentException("The predicate array must not contain a null predicate, index " + i + " was null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the closures to ensure that the internal reference can't be messed with.
|
||||
*
|
||||
* @param closures the closures to copy
|
||||
* @return the cloned closures
|
||||
*/
|
||||
private static Closure[] copy(Closure[] closures) {
|
||||
if (closures == null) {
|
||||
return null;
|
||||
}
|
||||
return (Closure[]) closures.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the closures to ensure that all is well.
|
||||
*
|
||||
* @param closures the closures to validate
|
||||
* @return the validated closures
|
||||
*/
|
||||
private static void validate(Closure[] closures) {
|
||||
if (closures == null) {
|
||||
throw new IllegalArgumentException("The closure array must not be null");
|
||||
}
|
||||
if (closures.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 1 closure must be specified in the closure array, size was " + closures.length);
|
||||
}
|
||||
for (int i = 0; i < closures.length; i++) {
|
||||
if (closures[i] == null) {
|
||||
throw new IllegalArgumentException("The closure array must not contain a null closure, index " + i + " was null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ExceptionClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ExceptionClosure always throws an exception
|
||||
*/
|
||||
private static class ExceptionClosure implements Closure, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ExceptionClosure() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always throw an exception
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
throw new FunctorException("ExceptionClosure invoked");
|
||||
}
|
||||
}
|
||||
|
||||
// NOPClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NOPClosure does nothing
|
||||
*/
|
||||
private static class NOPClosure implements Closure, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NOPClosure() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// TransformerClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TransformerClosure calls a Transformer using the input object and ignore the result.
|
||||
*/
|
||||
private static class TransformerClosure implements Closure, Serializable {
|
||||
/** The transformer to wrap */
|
||||
private final Transformer iTransformer;
|
||||
|
||||
/**
|
||||
* Constructor to store transformer
|
||||
*/
|
||||
private TransformerClosure(Transformer transformer) {
|
||||
super();
|
||||
iTransformer = transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the transformer
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
iTransformer.transform(input);
|
||||
}
|
||||
}
|
||||
|
||||
// ChainedClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ChainedClosure calls a list of closures.
|
||||
*/
|
||||
private static class ChainedClosure implements Closure, Serializable {
|
||||
/** The closures to call in turn */
|
||||
private final Closure[] iClosures;
|
||||
|
||||
/**
|
||||
* Constructor to store params
|
||||
*/
|
||||
private ChainedClosure(Closure[] closures) {
|
||||
super();
|
||||
iClosures = closures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a list of closures
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
for (int i = 0; i < iClosures.length; i++) {
|
||||
iClosures[i].execute(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SwitchClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* SwitchClosure calls the closure whose predicate returns true.
|
||||
*/
|
||||
private static class SwitchClosure implements Closure, Serializable {
|
||||
/** The tests to consider */
|
||||
private final Predicate[] iPredicates;
|
||||
/** The matching closures to call */
|
||||
private final Closure[] iClosures;
|
||||
/** The default closure to call if no tests match */
|
||||
private final Closure iDefault;
|
||||
|
||||
/**
|
||||
* Constructor to store params
|
||||
*/
|
||||
private SwitchClosure(Predicate[] predicates, Closure[] closures, Closure defaultClosure) {
|
||||
super();
|
||||
iPredicates = predicates;
|
||||
iClosures = closures;
|
||||
iDefault = defaultClosure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the closure whose predicate returns true
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
for (int i = 0; i < iPredicates.length; i++) {
|
||||
if (iPredicates[i].evaluate(input) == true) {
|
||||
iClosures[i].execute(input);
|
||||
return;
|
||||
}
|
||||
}
|
||||
iDefault.execute(input);
|
||||
}
|
||||
}
|
||||
|
||||
// ForClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ForClosure calls the closure a fixed nunmber of times.
|
||||
*/
|
||||
private static class ForClosure implements Closure, Serializable {
|
||||
/** The number of times to loop */
|
||||
private final int iCount;
|
||||
/** The closure to call */
|
||||
private final Closure iClosure;
|
||||
|
||||
/**
|
||||
* Constructor to store params
|
||||
*/
|
||||
private ForClosure(int count, Closure closure) {
|
||||
super();
|
||||
iCount = count;
|
||||
iClosure = closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the closure count times
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
for (int i = 0; i < iCount; i++) {
|
||||
iClosure.execute(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WhileClosure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* WhileClosure calls the closure until the predicate is false.
|
||||
*/
|
||||
private static class WhileClosure implements Closure, Serializable {
|
||||
/** The test condition */
|
||||
private final Predicate iPredicate;
|
||||
/** The closure to call */
|
||||
private final Closure iClosure;
|
||||
/** The flag, true is a do loop, false is a while */
|
||||
private final boolean iDoLoop;
|
||||
|
||||
/**
|
||||
* Constructor to store params
|
||||
*/
|
||||
private WhileClosure(Predicate predicate, Closure closure, boolean doLoop) {
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
iClosure = closure;
|
||||
iDoLoop = doLoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the closure until the predicate is false
|
||||
*/
|
||||
public void execute(Object input) {
|
||||
if (iDoLoop) {
|
||||
iClosure.execute(input);
|
||||
}
|
||||
while (iPredicate.evaluate(input)) {
|
||||
iClosure.execute(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Factory.java,v 1.3 2002/10/12 22:15:19 scolebourne Exp $
|
||||
* $Revision: 1.3 $
|
||||
* $Date: 2002/10/12 22:15:19 $
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Factory.java,v 1.4 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -22,20 +20,20 @@
|
|||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowlegement:
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowlegement may appear in the software itself,
|
||||
* if and wherever such third-party acknowlegements normally appear.
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Struts", and "Apache Software
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -59,23 +57,24 @@
|
|||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Factory
|
||||
* A simple interface that describes the most basic means of having the ability
|
||||
* to create an object.
|
||||
* <code>Factory</code> defines an interface implemented by classes that
|
||||
* create objects.
|
||||
*
|
||||
* @since Commons Collections 2.1
|
||||
* @version $Revision: 1.4 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Arron Bates
|
||||
* @version $Revision: 1.3 $
|
||||
* @since 2.1
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public interface Factory {
|
||||
|
||||
/** Simple method from which will come the new object from the factory.
|
||||
*
|
||||
* @return Object reference to the new object.
|
||||
*/
|
||||
public Object create();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new object.
|
||||
*
|
||||
* @return a new object
|
||||
* @throws FunctorException (runtime) if the factory cannot create an object
|
||||
*/
|
||||
public Object create();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,446 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/FactoryUtils.java,v 1.7 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* <code>FactoryUtils</code> provides reference implementations and utilities
|
||||
* for the Factory functor interface. The supplied factories are:
|
||||
* <ul>
|
||||
* <li>Prototype - clones a specified object
|
||||
* <li>Reflection - creates objects using reflection
|
||||
* <li>Constant - always returns the same object
|
||||
* <li>Null - always returns null
|
||||
* <li>Exception - always throws an exception
|
||||
* </ul>
|
||||
* All the supplied factories are Serializable.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.7 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class FactoryUtils {
|
||||
|
||||
/**
|
||||
* A factory that always throws an exception
|
||||
*/
|
||||
private static final Factory EXCEPTION_FACTORY = new ExceptionFactory();
|
||||
/**
|
||||
* A factory that always returns null
|
||||
*/
|
||||
private static final Factory NULL_FACTORY = new ConstantFactory(null);
|
||||
|
||||
/**
|
||||
* This class is not normally instantiated.
|
||||
*/
|
||||
public FactoryUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Factory that always throws an exception.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the factory
|
||||
*/
|
||||
public static Factory exceptionFactory() {
|
||||
return EXCEPTION_FACTORY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Factory that will return null each time the factory is used.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the factory
|
||||
*/
|
||||
public static Factory nullFactory() {
|
||||
return NULL_FACTORY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Factory that will return the same object each time the factory
|
||||
* is used. No check is made that the object is immutable. In general, only
|
||||
* immutable objects should use the constant factory. Mutable objects should
|
||||
* use the prototype factory.
|
||||
*
|
||||
* @param constantToReturn the constant object to return each time in the factory
|
||||
* @return the <code>constant</code> factory.
|
||||
*/
|
||||
public static Factory constantFactory(Object constantToReturn) {
|
||||
return new ConstantFactory(constantToReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Factory that will return a clone of the same prototype object
|
||||
* each time the factory is used. The prototype will be cloned using one of these
|
||||
* techniques (in order):
|
||||
* <ul>
|
||||
* <li>public clone method
|
||||
* <li>public copy constructor
|
||||
* <li>serialization clone
|
||||
* <ul>
|
||||
*
|
||||
* @param prototype the object to clone each time in the factory
|
||||
* @return the <code>prototype</code> factory
|
||||
* @throws IllegalArgumentException if the prototype is null
|
||||
* @throws IllegalArgumentException if the prototype cannot be cloned
|
||||
*/
|
||||
public static Factory prototypeFactory(Object prototype) {
|
||||
if (prototype == null) {
|
||||
throw new IllegalArgumentException("The prototype must not be null");
|
||||
}
|
||||
try {
|
||||
prototype.getClass().getMethod("clone", null);
|
||||
return new PrototypeCloneFactory(prototype);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
try {
|
||||
prototype.getClass().getConstructor(new Class[] { prototype.getClass()});
|
||||
return new ReflectionFactory(prototype.getClass(), new Class[] { prototype.getClass()}, new Object[] { prototype });
|
||||
|
||||
} catch (NoSuchMethodException ex2) {
|
||||
if (prototype instanceof Serializable) {
|
||||
return new PrototypeSerializationFactory((Serializable) prototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("The prototype must be cloneable via a public clone method");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Factory that can create objects of a specific type using
|
||||
* a no-args constructor.
|
||||
*
|
||||
* @param classToInstantiate the Class to instantiate each time in the factory
|
||||
* @return the <code>reflection</code> factory
|
||||
* @throws IllegalArgumentException if the classToInstantiate is null
|
||||
*/
|
||||
public static Factory reflectionFactory(Class classToInstantiate) {
|
||||
return new ReflectionFactory(classToInstantiate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Factory that can create objects of a specific type using
|
||||
* the arguments specified to this method.
|
||||
*
|
||||
* @param classToInstantiate the Class to instantiate each time in the factory
|
||||
* @param paramTypes parameter types for the constructor, can be null
|
||||
* @param args the arguments to pass to the constructor, can be null
|
||||
* @return the <code>reflection</code> factory
|
||||
* @throws IllegalArgumentException if the classToInstantiate is null
|
||||
* @throws IllegalArgumentException if the paramTypes and args don't match
|
||||
* @throws IllegalArgumentException if the constructor doesn't exist
|
||||
*/
|
||||
public static Factory reflectionFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
|
||||
return new ReflectionFactory(classToInstantiate, paramTypes, args);
|
||||
}
|
||||
|
||||
// ExceptionFactory
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ExceptionFactory always throws an exception
|
||||
*/
|
||||
private static class ExceptionFactory implements Factory, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ExceptionFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always throw an exception
|
||||
*/
|
||||
public Object create() {
|
||||
throw new FunctorException("ExceptionFactory invoked");
|
||||
}
|
||||
}
|
||||
|
||||
// ConstantFactory
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ConstantFactory returns the same instance each time.
|
||||
*/
|
||||
private static class ConstantFactory implements Factory, Serializable {
|
||||
/** The constant to return each time */
|
||||
private final Object iConstant;
|
||||
|
||||
/**
|
||||
* Constructor to store constant
|
||||
*/
|
||||
private ConstantFactory(Object constant) {
|
||||
super();
|
||||
iConstant = constant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always return constant
|
||||
*/
|
||||
public Object create() {
|
||||
return iConstant;
|
||||
}
|
||||
}
|
||||
|
||||
// PrototypeCloneFactory
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* PrototypeCloneFactory creates objects by copying a prototype using the clone method.
|
||||
*/
|
||||
private static class PrototypeCloneFactory implements Factory, Serializable {
|
||||
/** The object to clone each time */
|
||||
private final Object iPrototype;
|
||||
/** The method used to clone */
|
||||
private transient Method iCloneMethod;
|
||||
|
||||
/**
|
||||
* Constructor to store prototype
|
||||
*/
|
||||
private PrototypeCloneFactory(Object prototype) {
|
||||
super();
|
||||
if (prototype == null) {
|
||||
throw new IllegalArgumentException("PrototypeCloneFactory: The prototype must not be null");
|
||||
}
|
||||
iPrototype = prototype;
|
||||
|
||||
findCloneMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Clone method for the class specified.
|
||||
*/
|
||||
private void findCloneMethod() {
|
||||
try {
|
||||
iCloneMethod = iPrototype.getClass().getMethod("clone", null);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new IllegalArgumentException("PrototypeCloneFactory: The clone method must exist and be public ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return clone of prototype
|
||||
*/
|
||||
public Object create() {
|
||||
// needed for post-serialization
|
||||
if (iCloneMethod == null) {
|
||||
findCloneMethod();
|
||||
}
|
||||
|
||||
try {
|
||||
return iCloneMethod.invoke(iPrototype, null);
|
||||
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new FunctorException("PrototypeCloneFactory: Clone method must be public", ex);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new FunctorException("PrototypeCloneFactory: Clone method threw an exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrototypeSerializationFactory
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* PrototypeSerializationFactory creates objects by cloning a prototype using serialization.
|
||||
*/
|
||||
private static class PrototypeSerializationFactory implements Factory, Serializable {
|
||||
/** The object to clone via serialization each time */
|
||||
private final Serializable iPrototype;
|
||||
|
||||
/**
|
||||
* Constructor to store prototype
|
||||
*/
|
||||
private PrototypeSerializationFactory(Serializable prototype) {
|
||||
super();
|
||||
if (prototype == null) {
|
||||
throw new IllegalArgumentException("PrototypeSerializationFactory: The prototype must not be null");
|
||||
}
|
||||
iPrototype = prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return clone of prototype by serialization
|
||||
*/
|
||||
public Object create() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
|
||||
ByteArrayInputStream bais = null;
|
||||
try {
|
||||
ObjectOutputStream out = new ObjectOutputStream(baos);
|
||||
out.writeObject(iPrototype);
|
||||
|
||||
bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream in = new ObjectInputStream(bais);
|
||||
return in.readObject();
|
||||
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new FunctorException(ex);
|
||||
} catch (IOException ex) {
|
||||
throw new FunctorException(ex);
|
||||
} finally {
|
||||
try {
|
||||
if (bais != null) {
|
||||
bais.close();
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
try {
|
||||
if (baos != null) {
|
||||
baos.close();
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReflectionFactory
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ReflectionFactory creates objects using reflection.
|
||||
*/
|
||||
private static class ReflectionFactory implements Factory, Serializable {
|
||||
/** The class to create */
|
||||
private final Class iClassToInstantiate;
|
||||
/** The constructor parameter types */
|
||||
private final Class[] iParamTypes;
|
||||
/** The constructor arguments */
|
||||
private final Object[] iArgs;
|
||||
/** The constructor */
|
||||
private transient Constructor iConstructor = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ReflectionFactory(Class classToInstantiate) {
|
||||
this(classToInstantiate, null, null);
|
||||
}
|
||||
|
||||
/* builds the object factory taking all the options needed to provide
|
||||
* arguments to a constructor.
|
||||
*/
|
||||
public ReflectionFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
|
||||
super();
|
||||
if (classToInstantiate == null) {
|
||||
throw new IllegalArgumentException("ReflectionFactory: The class to instantiate must not be null");
|
||||
}
|
||||
if (((paramTypes == null) && (args != null))
|
||||
|| ((paramTypes != null) && (args == null))
|
||||
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
|
||||
throw new IllegalArgumentException("ReflectionFactory: The parameter types must match the arguments");
|
||||
}
|
||||
|
||||
iClassToInstantiate = classToInstantiate;
|
||||
if ((paramTypes == null) && (args == null)) {
|
||||
iParamTypes = null;
|
||||
iArgs = null;
|
||||
} else {
|
||||
iParamTypes = (Class[]) paramTypes.clone();
|
||||
iArgs = (Object[]) args.clone();
|
||||
}
|
||||
|
||||
findConstructor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Constructor for the class specified.
|
||||
*/
|
||||
private void findConstructor() {
|
||||
try {
|
||||
iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new IllegalArgumentException("ReflectionFactory: The constructor must exist and be public ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the object using a constructor
|
||||
*/
|
||||
public Object create() {
|
||||
// needed for post-serialization
|
||||
if (iConstructor == null) {
|
||||
findConstructor();
|
||||
}
|
||||
|
||||
try {
|
||||
return iConstructor.newInstance(iArgs);
|
||||
|
||||
} catch (InstantiationException ex) {
|
||||
throw new FunctorException("ReflectionFactory: InstantiationException", ex);
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new FunctorException("ReflectionFactory: Constructor must be public", ex);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new FunctorException("ReflectionFactory: Constructor threw an exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/FunctorException.java,v 1.1 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Exception thrown from functors.
|
||||
* If required, a root cause error can be wrapped within this one.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.1 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class FunctorException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Does JDK support nested exceptions
|
||||
*/
|
||||
private static final boolean JDK_SUPPORTS_NESTED;
|
||||
|
||||
static {
|
||||
boolean flag = false;
|
||||
try {
|
||||
Throwable.class.getDeclaredMethod("getCause", new Class[0]);
|
||||
flag = true;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
flag = false;
|
||||
}
|
||||
JDK_SUPPORTS_NESTED = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Root cause of the exception
|
||||
*/
|
||||
private final Throwable iThrowable;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FunctorException</code> without specified
|
||||
* detail message.
|
||||
*/
|
||||
public FunctorException() {
|
||||
super();
|
||||
iThrowable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FunctorException</code> with specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the error message.
|
||||
*/
|
||||
public FunctorException(String msg) {
|
||||
super(msg);
|
||||
iThrowable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FunctorException</code> with specified
|
||||
* nested <code>Throwable</code> root cause.
|
||||
*
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
*/
|
||||
public FunctorException(Throwable rootCause) {
|
||||
super((rootCause == null ? null : rootCause.getMessage()));
|
||||
iThrowable = rootCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FunctorException</code> with specified
|
||||
* detail message and nested <code>Throwable</code> root cause.
|
||||
*
|
||||
* @param msg the error message.
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
*/
|
||||
public FunctorException(String msg, Throwable rootCause) {
|
||||
super(msg);
|
||||
iThrowable = rootCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause of this throwable.
|
||||
*
|
||||
* @return the cause of this throwable, or <code>null</code>
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return iThrowable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the standard error stream.
|
||||
*/
|
||||
public void printStackTrace() {
|
||||
printStackTrace(System.err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified stream.
|
||||
*
|
||||
* @param out the <code>PrintStream</code> to use for output
|
||||
*/
|
||||
public void printStackTrace(PrintStream out) {
|
||||
synchronized (out) {
|
||||
PrintWriter pw = new PrintWriter(out, false);
|
||||
printStackTrace(pw);
|
||||
// Flush the PrintWriter before it's GC'ed.
|
||||
pw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified writer.
|
||||
*
|
||||
* @param out the <code>PrintWriter</code> to use for output
|
||||
*/
|
||||
public void printStackTrace(PrintWriter out) {
|
||||
synchronized (out) {
|
||||
super.printStackTrace(out);
|
||||
if (iThrowable != null && JDK_SUPPORTS_NESTED == false) {
|
||||
out.print("Caused by: ");
|
||||
iThrowable.printStackTrace(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Predicate.java,v 1.5 2002/08/15 20:04:31 pjack Exp $
|
||||
* $Revision: 1.5 $
|
||||
* $Date: 2002/08/15 20:04:31 $
|
||||
*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Predicate.java,v 1.6 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
|
||||
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -23,11 +20,11 @@
|
|||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowlegement:
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowlegement may appear in the software itself,
|
||||
* if and wherever such third-party acknowlegements normally appear.
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
|
@ -36,7 +33,7 @@
|
|||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -60,18 +57,28 @@
|
|||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
/** Performs some predicate which returns true or false based on the input object.
|
||||
* Predicate instances can be used to implement queries or to do filtering.
|
||||
*
|
||||
* @since 1.0
|
||||
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
|
||||
*/
|
||||
/**
|
||||
* <code>Predicate</code> defines an interface implemented by classes that
|
||||
* perform a predicate test on an object. Predicate instances can be used
|
||||
* to implement queries or to do filtering.
|
||||
*
|
||||
* @since Commons Collections 1.0
|
||||
* @version $Revision: 1.6 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public interface Predicate {
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the input object matches this predicate.
|
||||
*
|
||||
* @return true if the input object matches this predicate, else returns false
|
||||
*/
|
||||
public boolean evaluate(Object input);
|
||||
* Use the specified parameter to perform a test that returns true or false.
|
||||
*
|
||||
* @param object the object to evaluate
|
||||
* @return true or false
|
||||
* @throws ClassCastException (runtime) if the input is the wrong class
|
||||
* @throws IllegalArgumentException (runtime) if the input is invalid
|
||||
* @throws FunctorException (runtime) if the predicate encounters a problem
|
||||
*/
|
||||
public boolean evaluate(Object object);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,982 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/PredicateUtils.java,v 1.7 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <code>PredicateUtils</code> provides reference implementations and utilities
|
||||
* for the Predicate functor interface. The supplied predicates are:
|
||||
* <ul>
|
||||
* <li>Invoker - returns the result of a method call on the input object
|
||||
* <li>InstanceOf - true if the object is an instanceof a class
|
||||
* <li>Equal - true if the object equals() a specified object
|
||||
* <li>Identity - true if the object == a specified object
|
||||
* <li>Null - true if the object is null
|
||||
* <li>NotNull - true if the object is not null
|
||||
* <li>Unique - true if the object has not already been evaluated
|
||||
* <li>And/All - true if all of the predicates are true
|
||||
* <li>Or/Any - true if any of the predicates is true
|
||||
* <li>Either/One - true if only one of the predicate is true
|
||||
* <li>Neither/None - true if none of the predicates are true
|
||||
* <li>Not - true if the predicate is false, and vice versa
|
||||
* <li>Transformer - wraps a Transformer as a Predicate
|
||||
* <li>True - always return true
|
||||
* <li>False - always return false
|
||||
* <li>Exception - always throws an exception
|
||||
* <li>NullIsException/NullIsFalse/NullIsTrue - check for null input
|
||||
* </ul>
|
||||
* All the supplied predicates are Serializable.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.7 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
* @author Ola Berg
|
||||
*/
|
||||
public class PredicateUtils {
|
||||
|
||||
/**
|
||||
* A predicate that always throws an exception
|
||||
*/
|
||||
private static final Predicate EXCEPTION_PREDICATE = new ExceptionPredicate();
|
||||
/**
|
||||
* A predicate that always returns true
|
||||
*/
|
||||
private static final Predicate TRUE_PREDICATE = new ConstantPredicate(true);
|
||||
/**
|
||||
* A predicate that always returns false
|
||||
*/
|
||||
private static final Predicate FALSE_PREDICATE = new ConstantPredicate(false);
|
||||
/**
|
||||
* A predicate that returns true if the object is null
|
||||
*/
|
||||
private static final Predicate NULL_PREDICATE = new IdentityPredicate(null);
|
||||
/**
|
||||
* A predicate that returns true if the object is not null
|
||||
*/
|
||||
private static final Predicate NOT_NULL_PREDICATE = new NotPredicate(NULL_PREDICATE);
|
||||
|
||||
/**
|
||||
* This class is not normally instantiated.
|
||||
*/
|
||||
public PredicateUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
// Simple predicates
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets a Predicate that always throws an exception.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate exceptionPredicate() {
|
||||
return EXCEPTION_PREDICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that always returns true.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate truePredicate() {
|
||||
return TRUE_PREDICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that always returns false.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate falsePredicate() {
|
||||
return FALSE_PREDICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that checks if the input object passed in is null.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate nullPredicate() {
|
||||
return NULL_PREDICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that checks if the input object passed in is not null.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate notNullPredicate() {
|
||||
return NOT_NULL_PREDICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that checks if the input object is equal to the
|
||||
* specified object using equals().
|
||||
*
|
||||
* @param value the value to compare against
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate equalPredicate(Object value) {
|
||||
if (value == null) {
|
||||
return NULL_PREDICATE;
|
||||
}
|
||||
return new EqualPredicate(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that checks if the input object is equal to the
|
||||
* specified object by identity.
|
||||
*
|
||||
* @param value the value to compare against
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate identityPredicate(Object value) {
|
||||
if (value == null) {
|
||||
return NULL_PREDICATE;
|
||||
}
|
||||
return new IdentityPredicate(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that checks if the object passed in is of
|
||||
* a particular type, using instanceof. A <code>null</code> input
|
||||
* object will return <code>false</code>.
|
||||
*
|
||||
* @param type the type to check for, may not be null
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the class is null
|
||||
*/
|
||||
public static Predicate instanceofPredicate(Class type) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("The type to check instanceof must not be null");
|
||||
}
|
||||
return new InstanceofPredicate(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that returns true the first time an object is
|
||||
* encoutered, and false if the same object is received
|
||||
* again. The comparison is by equals(). A <code>null</code> input object
|
||||
* is accepted and will return true the first time, and false subsequently
|
||||
* as well.
|
||||
*
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate uniquePredicate() {
|
||||
// must return new instance each time
|
||||
return new UniquePredicate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that invokes a method on the input object.
|
||||
* The method must return either a boolean or a non-null Boolean,
|
||||
* and have no parameters. If the input object is null, a
|
||||
* PredicateException is thrown.
|
||||
* <p>
|
||||
* For example, <code>PredicateUtils.invokerPredicate("isEmpty");</code>
|
||||
* will call the <code>isEmpty</code> method on the input object to
|
||||
* determine the predicate result.
|
||||
*
|
||||
* @param methodName the method name to call on the input object, may not be null
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the methodName is null.
|
||||
*/
|
||||
public static Predicate invokerPredicate(String methodName){
|
||||
// reuse transformer as it has caching - this is lazy really, should have inner class here
|
||||
return asPredicate(TransformerUtils.invokerTransformer(methodName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Predicate that invokes a method on the input object.
|
||||
* The method must return either a boolean or a non-null Boolean,
|
||||
* and have no parameters. If the input object is null, a
|
||||
* PredicateException is thrown.
|
||||
* <p>
|
||||
* For example, <code>PredicateUtils.invokerPredicate("isEmpty");</code>
|
||||
* will call the <code>isEmpty</code> method on the input object to
|
||||
* determine the predicate result.
|
||||
*
|
||||
* @param methodName the method name to call on the input object, may not be null
|
||||
* @param paramTypes the parameter types
|
||||
* @param args the arguments
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the method name is null
|
||||
* @throws IllegalArgumentException if the paramTypes and args don't match
|
||||
*/
|
||||
public static Predicate invokerPredicate(String methodName, Class[] paramTypes, Object[] args){
|
||||
// reuse transformer as it has caching - this is lazy really, should have inner class here
|
||||
return asPredicate(TransformerUtils.invokerTransformer(methodName, paramTypes, args));
|
||||
}
|
||||
|
||||
// Boolean combinations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true only if both of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicate1 the first predicate, may not be null
|
||||
* @param predicate2 the second predicate, may not be null
|
||||
* @return the <code>and</code> predicate
|
||||
* @throws IllegalArgumentException if either predicate is null
|
||||
*/
|
||||
public static Predicate andPredicate(Predicate predicate1, Predicate predicate2) {
|
||||
return allPredicate(new Predicate[] { predicate1, predicate2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true only if all of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicates an array of predicates to check, may not be null
|
||||
* @return the <code>all</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates array is null
|
||||
* @throws IllegalArgumentException if the predicates array has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the array is null
|
||||
*/
|
||||
public static Predicate allPredicate(Predicate[] predicates) {
|
||||
return new AllPredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true only if all of the specified
|
||||
* predicates are true. The predicates are checked in iterator order.
|
||||
*
|
||||
* @param predicates a collection of predicates to check, may not be null
|
||||
* @return the <code>all</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates collection is null
|
||||
* @throws IllegalArgumentException if the predicates collection has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the collection is null
|
||||
*/
|
||||
public static Predicate allPredicate(Collection predicates) {
|
||||
return new AllPredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if either of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicate1 the first predicate, may not be null
|
||||
* @param predicate2 the second predicate, may not be null
|
||||
* @return the <code>or</code> predicate
|
||||
* @throws IllegalArgumentException if either predicate is null
|
||||
*/
|
||||
public static Predicate orPredicate(Predicate predicate1, Predicate predicate2) {
|
||||
return anyPredicate(new Predicate[] { predicate1, predicate2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if any of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicates an array of predicates to check, may not be null
|
||||
* @return the <code>any</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates array is null
|
||||
* @throws IllegalArgumentException if the predicates array has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the array is null
|
||||
*/
|
||||
public static Predicate anyPredicate(Predicate[] predicates) {
|
||||
return new AnyPredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if any of the specified
|
||||
* predicates are true. The predicates are checked in iterator order.
|
||||
*
|
||||
* @param predicates a collection of predicates to check, may not be null
|
||||
* @return the <code>any</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates collection is null
|
||||
* @throws IllegalArgumentException if the predicates collection has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the collection is null
|
||||
*/
|
||||
public static Predicate anyPredicate(Collection predicates) {
|
||||
return new AnyPredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if one, but not both, of the
|
||||
* specified predicates are true.
|
||||
*
|
||||
* @param predicate1 the first predicate, may not be null
|
||||
* @param predicate2 the second predicate, may not be null
|
||||
* @return the <code>either</code> predicate
|
||||
* @throws IllegalArgumentException if either predicate is null
|
||||
*/
|
||||
public static Predicate eitherPredicate(Predicate predicate1, Predicate predicate2) {
|
||||
return onePredicate(new Predicate[] { predicate1, predicate2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if only one of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicates an array of predicates to check, may not be null
|
||||
* @return the <code>one</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates array is null
|
||||
* @throws IllegalArgumentException if the predicates array has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the array is null
|
||||
*/
|
||||
public static Predicate onePredicate(Predicate[] predicates) {
|
||||
return new OnePredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if only one of the specified
|
||||
* predicates are true. The predicates are checked in iterator order.
|
||||
*
|
||||
* @param predicates a collection of predicates to check, may not be null
|
||||
* @return the <code>one</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates collection is null
|
||||
* @throws IllegalArgumentException if the predicates collection has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the collection is null
|
||||
*/
|
||||
public static Predicate onePredicate(Collection predicates) {
|
||||
return new OnePredicate(validate(predicates));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if neither of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicate1 the first predicate, may not be null
|
||||
* @param predicate2 the second predicate, may not be null
|
||||
* @return the <code>neither</code> predicate
|
||||
* @throws IllegalArgumentException if either predicate is null
|
||||
*/
|
||||
public static Predicate neitherPredicate(Predicate predicate1, Predicate predicate2) {
|
||||
return nonePredicate(new Predicate[] { predicate1, predicate2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if none of the specified
|
||||
* predicates are true.
|
||||
*
|
||||
* @param predicates an array of predicates to check, may not be null
|
||||
* @return the <code>none</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates array is null
|
||||
* @throws IllegalArgumentException if the predicates array has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the array is null
|
||||
*/
|
||||
public static Predicate nonePredicate(Predicate[] predicates) {
|
||||
Predicate[] preds = validate(predicates);
|
||||
for (int i = 0; i < preds.length; i++) {
|
||||
preds[i] = notPredicate(preds[i]);
|
||||
}
|
||||
return new AllPredicate(preds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if none of the specified
|
||||
* predicates are true. The predicates are checked in iterator order.
|
||||
*
|
||||
* @param predicates a collection of predicates to check, may not be null
|
||||
* @return the <code>none</code> predicate
|
||||
* @throws IllegalArgumentException if the predicates collection is null
|
||||
* @throws IllegalArgumentException if the predicates collection has less than 2 elements
|
||||
* @throws IllegalArgumentException if any predicate in the collection is null
|
||||
*/
|
||||
public static Predicate nonePredicate(Collection predicates) {
|
||||
Predicate[] preds = validate(predicates);
|
||||
for (int i = 0; i < preds.length; i++) {
|
||||
preds[i] = notPredicate(preds[i]);
|
||||
}
|
||||
return new AllPredicate(preds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Predicate that returns true if the specified predicate
|
||||
* returns false and vice versa.
|
||||
*
|
||||
* @param predicate the predicate to not
|
||||
* @return the <code>not</code> predicate
|
||||
* @throws IllegalArgumentException if the predicate is null
|
||||
*/
|
||||
public static Predicate notPredicate(Predicate predicate) {
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new NotPredicate(predicate);
|
||||
}
|
||||
|
||||
// Adaptors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new Predicate that wraps a Transformer. The Transformer must
|
||||
* return either Boolean.TRUE or Boolean.FALSE otherwise a PredicateException
|
||||
* will be thrown.
|
||||
*
|
||||
* @param transformer the transformer to wrap, may not be null
|
||||
* @return the transformer wrapping predicate
|
||||
* @throws IllegalArgumentException if the transformer is null
|
||||
*/
|
||||
public static Predicate asPredicate(Transformer transformer) {
|
||||
if (transformer == null) {
|
||||
throw new IllegalArgumentException("The transformer to call must not be null");
|
||||
}
|
||||
return new TransformerPredicate(transformer);
|
||||
}
|
||||
|
||||
// Null handlers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets a Predicate that throws an exception if the input object is null,
|
||||
* otherwise it calls the specified Predicate. This allows null handling
|
||||
* behaviour to be added to Predicates that don't support nulls.
|
||||
*
|
||||
* @param predicate the predicate to wrap, may not be null
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the predicate is null.
|
||||
*/
|
||||
public static Predicate nullIsExceptionPredicate(Predicate predicate){
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new NullIsExceptionPredicate( predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that returns false if the input object is null, otherwise
|
||||
* it calls the specified Predicate. This allows null handling behaviour to
|
||||
* be added to Predicates that don't support nulls.
|
||||
*
|
||||
* @param predicate the predicate to wrap, may not be null
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the predicate is null.
|
||||
*/
|
||||
public static Predicate nullIsFalsePredicate(Predicate predicate){
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new NullIsFalsePredicate(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Predicate that returns true if the input object is null, otherwise
|
||||
* it calls the specified Predicate. This allows null handling behaviour to
|
||||
* be added to Predicates that don't support nulls.
|
||||
*
|
||||
* @param predicate the predicate to wrap, may not be null
|
||||
* @return the predicate
|
||||
* @throws IllegalArgumentException if the predicate is null.
|
||||
*/
|
||||
public static Predicate nullIsTruePredicate(Predicate predicate){
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new NullIsTruePredicate(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a collection to an array using the iterator.
|
||||
*
|
||||
* @param predicates the predicates to validate
|
||||
* @return predicate array
|
||||
*/
|
||||
private static Predicate[] validate(Collection predicates) {
|
||||
if (predicates == null) {
|
||||
throw new IllegalArgumentException("The predicate collection must not be null");
|
||||
}
|
||||
if (predicates.size() < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 2 predicates must be specified in the predicate collection, size was " + predicates.size());
|
||||
}
|
||||
// convert to array like this to guarantee iterator() ordering
|
||||
Predicate[] preds = new Predicate[predicates.size()];
|
||||
int i = 0;
|
||||
for (Iterator it = predicates.iterator(); it.hasNext();) {
|
||||
preds[i] = (Predicate) it.next();
|
||||
if (preds[i] == null) {
|
||||
throw new IllegalArgumentException("The predicate collection must not contain a null predicate, index " + i + " was null");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return preds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate method shared amongst predicate implementations.
|
||||
*
|
||||
* @param predicates the predicates to validate
|
||||
* @return predicate array (copy)
|
||||
*/
|
||||
private static Predicate[] validate(Predicate[] predicates) {
|
||||
if (predicates == null) {
|
||||
throw new IllegalArgumentException("The predicate array must not be null");
|
||||
}
|
||||
if (predicates.length < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 2 predicates must be specified in the predicate array, size was " + predicates.length);
|
||||
}
|
||||
Predicate[] preds = new Predicate[predicates.length];
|
||||
for (int i = 0; i < predicates.length; i++) {
|
||||
if (predicates[i] == null) {
|
||||
throw new IllegalArgumentException("The predicate array must not contain a null predicate, index " + i + " was null");
|
||||
}
|
||||
preds[i] = predicates[i];
|
||||
}
|
||||
return preds;
|
||||
}
|
||||
|
||||
// ExceptionPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ExceptionPredicate always throws an exception
|
||||
*/
|
||||
private static class ExceptionPredicate implements Predicate, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ExceptionPredicate() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always throw an exception
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
throw new FunctorException("ExceptionPredicate invoked");
|
||||
}
|
||||
}
|
||||
|
||||
// ConstantPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ConstantPredicate returns the same instance each time.
|
||||
*/
|
||||
private static class ConstantPredicate implements Predicate, Serializable {
|
||||
/** The constant value to return each time */
|
||||
private final boolean iConstant;
|
||||
|
||||
/**
|
||||
* Constructor to store constant
|
||||
*/
|
||||
private ConstantPredicate(boolean constant) {
|
||||
super();
|
||||
iConstant = constant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always return constant
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return iConstant;
|
||||
}
|
||||
}
|
||||
|
||||
// AllPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* AllPredicate returns true if all predicates return true
|
||||
*/
|
||||
private static class AllPredicate implements Predicate, Serializable {
|
||||
/** The array of predicates to call */
|
||||
private final Predicate[] iPredicates;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private AllPredicate(Predicate[] predicates) {
|
||||
super();
|
||||
iPredicates = predicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if all predicates return true
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
for (int i = 0; i < iPredicates.length; i++) {
|
||||
if (iPredicates[i].evaluate(object) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// AnyPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* AnyPredicate returns true if one of the predicates return true
|
||||
*/
|
||||
private static class AnyPredicate implements Predicate, Serializable {
|
||||
/** The array of predicates to call */
|
||||
private final Predicate[] iPredicates;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private AnyPredicate(Predicate[] predicates) {
|
||||
super();
|
||||
iPredicates = predicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if one of the predicates returns true
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
for (int i = 0; i < iPredicates.length; i++) {
|
||||
if (iPredicates[i].evaluate(object)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// OnePredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* OnePredicate returns true if only one of the predicates return true
|
||||
*/
|
||||
private static class OnePredicate implements Predicate, Serializable {
|
||||
/** The array of predicates to call */
|
||||
private final Predicate[] iPredicates;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private OnePredicate(Predicate[] predicates) {
|
||||
super();
|
||||
iPredicates = predicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if only one of the predicates returns true
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
boolean match = false;
|
||||
for (int i = 0; i < iPredicates.length; i++) {
|
||||
if (iPredicates[i].evaluate(object)) {
|
||||
if (match) {
|
||||
return false;
|
||||
}
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
// NotPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NotPredicate returns the opposite of the wrapped predicate
|
||||
*/
|
||||
private static class NotPredicate implements Predicate, Serializable {
|
||||
/** The predicate to call */
|
||||
private final Predicate iPredicate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NotPredicate(Predicate predicate) {
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the wrapped predicate returns false, and vice versa
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return !iPredicate.evaluate(object);
|
||||
}
|
||||
}
|
||||
|
||||
// InstanceofPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* InstanceofPredicate checks the type of an object
|
||||
*/
|
||||
private static class InstanceofPredicate implements Predicate, Serializable {
|
||||
/** The type to check for */
|
||||
private final Class iType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public InstanceofPredicate(Class type) {
|
||||
super();
|
||||
iType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the object is an instanceof the type of the predicate.
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return iType.isInstance(object);
|
||||
}
|
||||
}
|
||||
|
||||
// EqualPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* EqualPredicate that checks if the object is a particular value by equals().
|
||||
*/
|
||||
private static class EqualPredicate implements Predicate, Serializable {
|
||||
/** The object to compare to */
|
||||
private final Object iValue;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public EqualPredicate(Object value) {
|
||||
super();
|
||||
iValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the object is equals() to the value stored in the predicate.
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return iValue.equals(object);
|
||||
}
|
||||
}
|
||||
|
||||
// IdentityPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* IdentityPredicate that checks if the object is a particular value by identity.
|
||||
*/
|
||||
private static class IdentityPredicate implements Predicate, Serializable {
|
||||
/** The object to compare identity to */
|
||||
private final Object iValue;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public IdentityPredicate(Object value) {
|
||||
super();
|
||||
iValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the object is equals() to the value stored in the predicate.
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return iValue == object;
|
||||
}
|
||||
}
|
||||
|
||||
// UniquePredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* UniquePredicate returns true the first time an object is
|
||||
* encoutered, and false if the same object is received
|
||||
* again using equals().
|
||||
*/
|
||||
private static class UniquePredicate implements Predicate, Serializable {
|
||||
/** The set of previously seen objects */
|
||||
private final Set iSet = new HashSet();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public UniquePredicate() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true the first time, and false subsequant times
|
||||
* that an object is encountered, using equals().
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
return iSet.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
// TransformerPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TransformerPredicate returns the result of the Transformer as a boolean.
|
||||
*/
|
||||
private static class TransformerPredicate implements Predicate, Serializable {
|
||||
/** The transformer to call */
|
||||
private final Transformer iTransformer;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TransformerPredicate(Transformer transformer) {
|
||||
super();
|
||||
iTransformer = transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean result of a Transformer
|
||||
*/
|
||||
public boolean evaluate(Object object) {
|
||||
Object result = iTransformer.transform(object);
|
||||
if (result instanceof Boolean == false) {
|
||||
throw new FunctorException(
|
||||
"TransformerPredicate: Transformer must return an instanceof Boolean, it was a "
|
||||
+ (result == null ? "null object" : result.getClass().getName()));
|
||||
}
|
||||
return ((Boolean) result).booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
// NullIsExceptionPredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NullIsExceptionPredicate returns an exception if null is passed in.
|
||||
*/
|
||||
private static class NullIsExceptionPredicate implements Predicate, Serializable {
|
||||
/** The predicate to call */
|
||||
private final Predicate iPredicate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NullIsExceptionPredicate(Predicate predicate){
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an exception if null
|
||||
*/
|
||||
public boolean evaluate(Object object){
|
||||
if (object == null) {
|
||||
throw new FunctorException("NullIsExceptionPredicate: Input Object must not be null");
|
||||
}
|
||||
return iPredicate.evaluate(object);
|
||||
}
|
||||
};
|
||||
|
||||
// NullIsFalsePredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NullIsFalsePredicate returns false if null is passed in.
|
||||
*/
|
||||
private static class NullIsFalsePredicate implements Predicate, Serializable {
|
||||
/** The predicate to call */
|
||||
private final Predicate iPredicate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NullIsFalsePredicate(Predicate predicate){
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return false if null
|
||||
*/
|
||||
public boolean evaluate(Object object){
|
||||
if (object == null) {
|
||||
return false;
|
||||
}
|
||||
return iPredicate.evaluate(object);
|
||||
}
|
||||
};
|
||||
|
||||
// NullIsTruePredicate
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NullIsTruePredicate returns true if null is passed in.
|
||||
*/
|
||||
private static class NullIsTruePredicate implements Predicate, Serializable {
|
||||
/** The predicate to call */
|
||||
private final Predicate iPredicate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NullIsTruePredicate(Predicate predicate){
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if null
|
||||
*/
|
||||
public boolean evaluate(Object object){
|
||||
if (object == null) {
|
||||
return true;
|
||||
}
|
||||
return iPredicate.evaluate(object);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Transformer.java,v 1.4 2002/06/12 03:59:15 mas Exp $
|
||||
* $Revision: 1.4 $
|
||||
* $Date: 2002/06/12 03:59:15 $
|
||||
*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Transformer.java,v 1.5 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
|
||||
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -23,11 +20,11 @@
|
|||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowlegement:
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowlegement may appear in the software itself,
|
||||
* if and wherever such third-party acknowlegements normally appear.
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
|
@ -36,7 +33,7 @@
|
|||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -60,15 +57,29 @@
|
|||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
/** An object capable of transforming an input object into some output object.
|
||||
*
|
||||
* @since 1.0
|
||||
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
|
||||
*/
|
||||
/**
|
||||
* <code>Transformer</code> defines an interface implemented by classes that
|
||||
* transform one object into another. The original object is left unchanged.
|
||||
* Transformers are typically used for type conversions, or extracting data
|
||||
* from an object.
|
||||
*
|
||||
* @since Commons Collections 1.0
|
||||
* @version $Revision: 1.5 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public interface Transformer {
|
||||
|
||||
/** Transforms the input object (leaving it unchanged) into some output object.
|
||||
* @return the transformation of the input object to the output object
|
||||
*/
|
||||
/**
|
||||
* Transforms the input object (leaving it unchanged) into some output object.
|
||||
*
|
||||
* @param input the object to be transformed
|
||||
* @return a transformed object
|
||||
* @throws ClassCastException (runtime) if the input is the wrong class
|
||||
* @throws IllegalArgumentException (runtime) if the input is invalid
|
||||
* @throws FunctorException (runtime) if the transform cannot be completed
|
||||
*/
|
||||
public Object transform(Object input);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,938 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/TransformerUtils.java,v 1.1 2003/05/16 13:41:10 scolebourne Exp $
|
||||
* ====================================================================
|
||||
*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if
|
||||
* any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
|
||||
* Foundation" must not be used to endorse or promote products derived
|
||||
* from this software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <code>TransformerUtils</code> provides reference implementations and
|
||||
* utilities for the Transformer functor interface. The supplied transformers are:
|
||||
* <ul>
|
||||
* <li>Invoker - returns the result of a method call on the input object
|
||||
* <li>Clone - returns a clone of the input object
|
||||
* <li>Constant - always returns the same object
|
||||
* <li>Closure - performs a Closure and returns the input object
|
||||
* <li>Predicate - returns the result of the predicate as a Boolean
|
||||
* <li>Factory - returns a new object from a factory
|
||||
* <li>Chained - chains two or more transformers together
|
||||
* <li>Switch - calls one transformer based on one or more predicates
|
||||
* <li>SwitchMap - calls one transformer looked up from a Map
|
||||
* <li>Instantiate - the Class input object is instantiated
|
||||
* <li>Map - returns an object from a supplied Map
|
||||
* <li>Null - always returns null
|
||||
* <li>NOP - returns the input object, which should be immutable
|
||||
* <li>Exception - always throws an exception
|
||||
* </ul>
|
||||
* All the supplied transformers are Serializable.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.1 $ $Date: 2003/05/16 13:41:10 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class TransformerUtils {
|
||||
|
||||
/**
|
||||
* A transformer that always throws an exception
|
||||
*/
|
||||
private static final Transformer EXCEPTION_TRANSFORMER = new ExceptionTransformer();
|
||||
/**
|
||||
* A transformer that always returns null
|
||||
*/
|
||||
private static final Transformer NULL_TRANSFORMER = new ConstantTransformer(null);
|
||||
/**
|
||||
* A transformer that returns the input object
|
||||
*/
|
||||
private static final Transformer NOP_TRANSFORMER = new NOPTransformer();
|
||||
/**
|
||||
* A transformer that clones the input object
|
||||
*/
|
||||
private static final Transformer CLONE_TRANSFORMER = new CloneTransformer();
|
||||
/**
|
||||
* A transformer that creates an object from a Class
|
||||
*/
|
||||
private static final Transformer INSTANTIATE_TRANSFORMER = new InstantiateTransformer(null, null);
|
||||
|
||||
/**
|
||||
* This class is not normally instantiated.
|
||||
*/
|
||||
public TransformerUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transformer that always throws an exception.
|
||||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @return the transformer
|
||||
*/
|
||||
public static Transformer exceptionTransformer() {
|
||||
return EXCEPTION_TRANSFORMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transformer that always returns null.
|
||||
*
|
||||
* @return the transformer
|
||||
*/
|
||||
public static Transformer nullTransformer() {
|
||||
return NULL_TRANSFORMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transformer that returns the input object.
|
||||
* The input object should be immutable to maintain the
|
||||
* contract of Transformer (although this is not checked).
|
||||
*
|
||||
* @return the transformer
|
||||
*/
|
||||
public static Transformer nopTransformer() {
|
||||
return NOP_TRANSFORMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transformer that returns a clone of the input
|
||||
* object. The input object will be cloned using one of these
|
||||
* techniques (in order):
|
||||
* <ul>
|
||||
* <li>public clone method
|
||||
* <li>public copy constructor
|
||||
* <li>serialization clone
|
||||
* <ul>
|
||||
*
|
||||
* @return the transformer
|
||||
*/
|
||||
public static Transformer cloneTransformer() {
|
||||
return CLONE_TRANSFORMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that will return the same object each time the
|
||||
* transformer is used.
|
||||
*
|
||||
* @param constantToReturn the constant object to return each time in the transformer
|
||||
* @return the transformer.
|
||||
*/
|
||||
public static Transformer constantTransformer(Object constantToReturn) {
|
||||
return new ConstantTransformer(constantToReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that calls a Closure each time the transformer is used.
|
||||
* The transformer returns the input object.
|
||||
*
|
||||
* @param command the command to run each time in the transformer
|
||||
* @return the transformer.
|
||||
*/
|
||||
public static Transformer asTransformer(Closure closure) {
|
||||
if (closure == null) {
|
||||
throw new IllegalArgumentException("The closure must not be null");
|
||||
}
|
||||
return new ClosureTransformer(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that calls a Predicate each time the transformer is used.
|
||||
* The transformer will return either Boolean.TRUE or Boolean.FALSE.
|
||||
*
|
||||
* @param predicate the predicate to run each time in the transformer
|
||||
* @return the transformer.
|
||||
*/
|
||||
public static Transformer asTransformer(Predicate predicate) {
|
||||
if (predicate == null) {
|
||||
throw new IllegalArgumentException("The predicate must not be null");
|
||||
}
|
||||
return new PredicateTransformer(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that calls a Factory each time the transformer is used.
|
||||
* The transformer will return the value returned by the factory.
|
||||
*
|
||||
* @param factory the factory to run each time in the transformer
|
||||
* @return the transformer.
|
||||
*/
|
||||
public static Transformer asTransformer(Factory factory) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("The factory must not be null");
|
||||
}
|
||||
return new FactoryTransformer(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls two transformers, passing the result of
|
||||
* the first into the second.
|
||||
*
|
||||
* @param transformer1 the first transformer
|
||||
* @param transformer2 the second transformer
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if either transformer is null
|
||||
*/
|
||||
public static Transformer chainedTransformer(Transformer transformer1, Transformer transformer2) {
|
||||
Transformer[] trs = new Transformer[] {transformer1, transformer2};
|
||||
validate(trs);
|
||||
return new ChainedTransformer(trs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls each transformer in turn, passing the
|
||||
* result into the next transformer.
|
||||
*
|
||||
* @param transformers an array of transformers to chain
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the transformers array is null
|
||||
* @throws IllegalArgumentException if the transformers array has 0 elements
|
||||
* @throws IllegalArgumentException if any transformer in the array is null
|
||||
*/
|
||||
public static Transformer chainedTransformer(Transformer[] transformers) {
|
||||
Transformer[] trs = copy(transformers);
|
||||
validate(trs);
|
||||
return new ChainedTransformer(trs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls each transformer in turn, passing the
|
||||
* result into the next transformer. The ordering is that of the iterator()
|
||||
* method on the collection.
|
||||
*
|
||||
* @param transformers a collection of transformers to chain
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the transformers collection is null
|
||||
* @throws IllegalArgumentException if the transformers collection is empty
|
||||
* @throws IllegalArgumentException if any transformer in the collection is null
|
||||
*/
|
||||
public static Transformer chainedTransformer(Collection transformers) {
|
||||
Transformer[] trs = null;
|
||||
if (transformers == null) {
|
||||
throw new IllegalArgumentException("The transformer collection must not be null");
|
||||
}
|
||||
// convert to array like this to guarantee iterator() ordering
|
||||
trs = new Transformer[transformers.size()];
|
||||
int i = 0;
|
||||
for (Iterator it = transformers.iterator(); it.hasNext();) {
|
||||
trs[i++] = (Transformer) it.next();
|
||||
}
|
||||
validate(trs);
|
||||
return new ChainedTransformer(trs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls one of two transformers depending
|
||||
* on the specified predicate.
|
||||
*
|
||||
* @param predicate the predicate to switch on
|
||||
* @param trueTransformer the transformer called if the predicate is true
|
||||
* @param falseTransformer the transformer called if the predicate is false
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the predicate is null
|
||||
* @throws IllegalArgumentException if either transformer is null
|
||||
*/
|
||||
public static Transformer switchTransformer(Predicate predicate, Transformer trueTransformer, Transformer falseTransformer) {
|
||||
return switchTransformerInternal(new Predicate[] { predicate }, new Transformer[] { trueTransformer }, falseTransformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls one of the transformers depending
|
||||
* on the predicates. The transformer at array location 0 is called if the
|
||||
* predicate at array location 0 returned true. Each predicate is evaluated
|
||||
* until one returns true. If no predicates evaluate to true, null is returned.
|
||||
*
|
||||
* @param predicates an array of predicates to check
|
||||
* @param transformers an array of transformers to call
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the either array is null
|
||||
* @throws IllegalArgumentException if the either array has 0 elements
|
||||
* @throws IllegalArgumentException if any element in the arrays is null
|
||||
* @throws IllegalArgumentException if the arrays are different sizes
|
||||
*/
|
||||
public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers) {
|
||||
return switchTransformerInternal(copy(predicates), copy(transformers), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls one of the transformers depending
|
||||
* on the predicates. The transformer at array location 0 is called if the
|
||||
* predicate at array location 0 returned true. Each predicate is evaluated
|
||||
* until one returns true. If no predicates evaluate to true, the default
|
||||
* transformer is called.
|
||||
*
|
||||
* @param predicates an array of predicates to check
|
||||
* @param transformers an array of transformers to call
|
||||
* @param defaultTransformer the default to call if no predicate matches
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the either array is null
|
||||
* @throws IllegalArgumentException if the either array has 0 elements
|
||||
* @throws IllegalArgumentException if any element in the arrays is null
|
||||
* @throws IllegalArgumentException if the arrays are different sizes
|
||||
*/
|
||||
public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers, Transformer defaultTransformer) {
|
||||
return switchTransformerInternal(copy(predicates), copy(transformers), defaultTransformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that calls one of the transformers depending
|
||||
* on the predicates.
|
||||
* <p>
|
||||
* The Map consists of Predicate keys and Transformer values. A transformer
|
||||
* is called if its matching predicate returns true. Each predicate is evaluated
|
||||
* until one returns true. If no predicates evaluate to true, the default
|
||||
* transformer is called. The default transformer is set in the map with a
|
||||
* null key. If no default transformer is set, null will be returned in a default
|
||||
* case. The ordering is that of the iterator() method on the entryset collection
|
||||
* of the map.
|
||||
*
|
||||
* @param predicatesAndTransformers a map of predicates to transformers
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the map is null
|
||||
* @throws IllegalArgumentException if the map is empty
|
||||
* @throws IllegalArgumentException if any transformer in the map is null
|
||||
* @throws ClassCastException if the map elements are of the wrong type
|
||||
*/
|
||||
public static Transformer switchTransformer(Map predicatesAndTransformers) {
|
||||
Transformer[] trs = null;
|
||||
Predicate[] preds = null;
|
||||
if (predicatesAndTransformers == null) {
|
||||
throw new IllegalArgumentException("The predicate and transformer map must not be null");
|
||||
}
|
||||
// convert to array like this to guarantee iterator() ordering
|
||||
Transformer def = (Transformer) predicatesAndTransformers.remove(null);
|
||||
int size = predicatesAndTransformers.size();
|
||||
trs = new Transformer[size];
|
||||
preds = new Predicate[size];
|
||||
int i = 0;
|
||||
for (Iterator it = predicatesAndTransformers.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
preds[i] = (Predicate) entry.getKey();
|
||||
trs[i] = (Transformer) entry.getValue();
|
||||
i++;
|
||||
}
|
||||
return switchTransformerInternal(preds, trs, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate input and create transformer
|
||||
*/
|
||||
private static Transformer switchTransformerInternal(Predicate[] predicates, Transformer[] transformers, Transformer defaultTransformer) {
|
||||
validate(predicates);
|
||||
validate(transformers);
|
||||
if (predicates.length != transformers.length) {
|
||||
throw new IllegalArgumentException("The predicate and transformer arrays must be the same size");
|
||||
}
|
||||
if (defaultTransformer == null) {
|
||||
defaultTransformer = nullTransformer();
|
||||
}
|
||||
return new SwitchTransformer(predicates, transformers, defaultTransformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transformer that uses the input object as a key to find the
|
||||
* transformer to call.
|
||||
* <p>
|
||||
* The Map consists of object keys and Transformer values. A transformer
|
||||
* is called if the input object equals the key. If there is no match, the
|
||||
* default transformer is called. The default transformer is set in the map
|
||||
* using a null key. If no default is set, null will be returned in a default case.
|
||||
*
|
||||
* @param objectsAndTransformers a map of objects to transformers
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the map is null
|
||||
* @throws IllegalArgumentException if the map is empty
|
||||
* @throws IllegalArgumentException if any transformer in the map is null
|
||||
*/
|
||||
public static Transformer switchMapTransformer(Map objectsAndTransformers) {
|
||||
Transformer[] trs = null;
|
||||
Predicate[] preds = null;
|
||||
if (objectsAndTransformers == null) {
|
||||
throw new IllegalArgumentException("The obejct and transformer map must not be null");
|
||||
}
|
||||
Transformer def = (Transformer) objectsAndTransformers.remove(null);
|
||||
int size = objectsAndTransformers.size();
|
||||
trs = new Transformer[size];
|
||||
preds = new Predicate[size];
|
||||
int i = 0;
|
||||
for (Iterator it = objectsAndTransformers.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
preds[i] = PredicateUtils.equalPredicate(entry.getKey());
|
||||
trs[i] = (Transformer) entry.getValue();
|
||||
i++;
|
||||
}
|
||||
return switchTransformer(preds, trs, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Transformer that expects an input Class object that it will instantiate.
|
||||
*
|
||||
* @return the transformer
|
||||
*/
|
||||
public static Transformer instantiateTransformer() {
|
||||
return INSTANTIATE_TRANSFORMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that expects an input Class object that it will
|
||||
* instantiate. The constructor used is determined by the arguments specified
|
||||
* to this method.
|
||||
*
|
||||
* @param paramTypes parameter types for the constructor, can be null
|
||||
* @param args the arguments to pass to the constructor, can be null
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the paramTypes and args don't match
|
||||
*/
|
||||
public static Transformer instantiateTransformer(Class[] paramTypes, Object[] args) {
|
||||
return new InstantiateTransformer(paramTypes, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transformer that uses the passed in Map to transform the input
|
||||
* object (as a simple lookup).
|
||||
*
|
||||
* @param map the map to use to transform the objects
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the map is null
|
||||
*/
|
||||
public static Transformer mapTransformer(Map map) {
|
||||
if (map == null) {
|
||||
throw new IllegalArgumentException("The map must not be null");
|
||||
}
|
||||
return new MapTransformer(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Transformer that invokes a method on the input object.
|
||||
* The method must have no parameters. If the input object is null,
|
||||
* null is returned.
|
||||
* <p>
|
||||
* For example, <code>TransformerUtils.invokerTransformer("getName");</code>
|
||||
* will call the <code>getName/code> method on the input object to
|
||||
* determine the transformer result.
|
||||
*
|
||||
* @param methodName the method name to call on the input object, may not be null
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the methodName is null.
|
||||
*/
|
||||
public static Transformer invokerTransformer(String methodName){
|
||||
return new InvokerTransformer(methodName, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Transformer that invokes a method on the input object.
|
||||
* The method parameters are specified. If the input object is null,
|
||||
* null is returned.
|
||||
*
|
||||
* @param methodName the name of the method
|
||||
* @param paramTypes the parameter types
|
||||
* @param args the arguments
|
||||
* @return the transformer
|
||||
* @throws IllegalArgumentException if the method name is null
|
||||
* @throws IllegalArgumentException if the paramTypes and args don't match
|
||||
*/
|
||||
public static Transformer invokerTransformer(String methodName, Class[] paramTypes, Object[] args){
|
||||
return new InvokerTransformer(methodName, paramTypes, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy method
|
||||
*
|
||||
* @param predicates the predicates to copy
|
||||
*/
|
||||
private static Predicate[] copy(Predicate[] predicates) {
|
||||
if (predicates == null) {
|
||||
return null;
|
||||
}
|
||||
return (Predicate[]) predicates.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate method
|
||||
*
|
||||
* @param predicates the predicates to validate
|
||||
*/
|
||||
private static void validate(Predicate[] predicates) {
|
||||
if (predicates == null) {
|
||||
throw new IllegalArgumentException("The predicate array must not be null");
|
||||
}
|
||||
if (predicates.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 1 predicate must be specified in the predicate array, size was " + predicates.length);
|
||||
}
|
||||
for (int i = 0; i < predicates.length; i++) {
|
||||
if (predicates[i] == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"The predicate array must not contain a null predicate, index " + i + " was null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy method
|
||||
*
|
||||
* @param transformers the transformers to copy
|
||||
*/
|
||||
private static Transformer[] copy(Transformer[] transformers) {
|
||||
if (transformers == null) {
|
||||
return null;
|
||||
}
|
||||
return (Transformer[]) transformers.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate method
|
||||
*
|
||||
* @param transformers the transformers to validate
|
||||
*/
|
||||
private static void validate(Transformer[] transformers) {
|
||||
if (transformers == null) {
|
||||
throw new IllegalArgumentException("The transformer array must not be null");
|
||||
}
|
||||
if (transformers.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"At least 1 transformer must be specified in the transformer array, size was " + transformers.length);
|
||||
}
|
||||
for (int i = 0; i < transformers.length; i++) {
|
||||
if (transformers[i] == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"The transformer array must not contain a null transformer, index " + i + " was null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ExceptionTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ExceptionTransformer always throws an exception.
|
||||
*/
|
||||
private static class ExceptionTransformer implements Transformer, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ExceptionTransformer() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always throw exception
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
throw new FunctorException("ExceptionTransformer invoked");
|
||||
}
|
||||
}
|
||||
|
||||
// NOPTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NOPTransformer returns the input object.
|
||||
*/
|
||||
private static class NOPTransformer implements Transformer, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private NOPTransformer() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the input object
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// CloneTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* CloneTransformer returns a clone of the input object.
|
||||
*/
|
||||
private static class CloneTransformer implements Transformer, Serializable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private CloneTransformer() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clone of the input object
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
return FactoryUtils.prototypeFactory(input).create();
|
||||
}
|
||||
}
|
||||
|
||||
// ConstantTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ConstantTransformer returns the same instance each time.
|
||||
*/
|
||||
private static class ConstantTransformer implements Transformer, Serializable {
|
||||
/** The constant to return each time */
|
||||
private final Object iConstant;
|
||||
|
||||
/**
|
||||
* Constructor to store constant.
|
||||
*/
|
||||
private ConstantTransformer(Object constant) {
|
||||
super();
|
||||
iConstant = constant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always return constant.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
return iConstant;
|
||||
}
|
||||
}
|
||||
|
||||
// ClosureTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ClosureTransformer executes a Closure object.
|
||||
*/
|
||||
private static class ClosureTransformer implements Transformer, Serializable {
|
||||
/** The closure to call each time */
|
||||
private final Closure iClosure;
|
||||
|
||||
/**
|
||||
* Constructor to store closure.
|
||||
*/
|
||||
private ClosureTransformer(Closure closure) {
|
||||
super();
|
||||
iClosure = closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceute the closure and return the input.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
iClosure.execute(input);
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// PredicateTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* PredicateTransformer evaluates a Predicate object.
|
||||
*/
|
||||
private static class PredicateTransformer implements Transformer, Serializable {
|
||||
/** The predicate to call each time */
|
||||
private final Predicate iPredicate;
|
||||
|
||||
/**
|
||||
* Constructor to store predicate.
|
||||
*/
|
||||
private PredicateTransformer(Predicate predicate) {
|
||||
super();
|
||||
iPredicate = predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the predicate and return the result as a Boolean.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
return new Boolean(iPredicate.evaluate(input));
|
||||
}
|
||||
}
|
||||
|
||||
// FactoryTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* FactoryTransformer returns the result of calling a Factory.
|
||||
*/
|
||||
private static class FactoryTransformer implements Transformer, Serializable {
|
||||
/** The factory to call each time */
|
||||
private final Factory iFactory;
|
||||
|
||||
/**
|
||||
* Constructor to store factory.
|
||||
*/
|
||||
private FactoryTransformer(Factory factory) {
|
||||
super();
|
||||
iFactory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result of calling the factory.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
return iFactory.create();
|
||||
}
|
||||
}
|
||||
|
||||
// ChainedTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ChainedTransformer returns the result of calling a list of transformers.
|
||||
*/
|
||||
private static class ChainedTransformer implements Transformer, Serializable {
|
||||
/** The array of transformers to call */
|
||||
private final Transformer[] iTransformers;
|
||||
|
||||
/**
|
||||
* Constructor to store params.
|
||||
*/
|
||||
private ChainedTransformer(Transformer[] transformers) {
|
||||
super();
|
||||
iTransformers = transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of calling a list of transformers.
|
||||
*/
|
||||
public Object transform(Object object) {
|
||||
for (int i = 0; i < iTransformers.length; i++) {
|
||||
object = iTransformers[i].transform(object);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
// SwitchTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* SwitchTransformer returns the result of the transformer whose predicate returns true.
|
||||
*/
|
||||
private static class SwitchTransformer implements Transformer, Serializable {
|
||||
/** The array of predicates to switch on */
|
||||
private final Predicate[] iPredicates;
|
||||
/** The array of transformers to call */
|
||||
private final Transformer[] iTransformers;
|
||||
/** The default transformer called if no predicate matches */
|
||||
private final Transformer iDefault;
|
||||
|
||||
/**
|
||||
* Constructor to store params.
|
||||
*/
|
||||
private SwitchTransformer(Predicate[] predicates, Transformer[] transformers, Transformer defaultTransformer) {
|
||||
super();
|
||||
iPredicates = predicates;
|
||||
iTransformers = transformers;
|
||||
iDefault = defaultTransformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the transformer whose predicate returns true.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
for (int i = 0; i < iPredicates.length; i++) {
|
||||
if (iPredicates[i].evaluate(input) == true) {
|
||||
return iTransformers[i].transform(input);
|
||||
}
|
||||
}
|
||||
return iDefault.transform(input);
|
||||
}
|
||||
}
|
||||
|
||||
// InstantiateTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* InstantiateTransformer returns the result of instantiating the input Class object.
|
||||
*/
|
||||
private static class InstantiateTransformer implements Transformer, Serializable {
|
||||
/** The array of reflection parameter types */
|
||||
private final Class[] iParamTypes;
|
||||
/** The array of reflection arguments */
|
||||
private final Object[] iArgs;
|
||||
|
||||
/**
|
||||
* Constructor to store params.
|
||||
*/
|
||||
private InstantiateTransformer(Class[] paramTypes, Object[] args) {
|
||||
super();
|
||||
if (((paramTypes == null) && (args != null))
|
||||
|| ((paramTypes != null) && (args == null))
|
||||
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
|
||||
throw new IllegalArgumentException("InstantiateTransformer: The parameter types must match the arguments");
|
||||
}
|
||||
if ((paramTypes == null) && (args == null)) {
|
||||
iParamTypes = null;
|
||||
iArgs = null;
|
||||
} else {
|
||||
iParamTypes = (Class[]) paramTypes.clone();
|
||||
iArgs = (Object[]) args.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result of instantiating the input Class object.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
try {
|
||||
if (input instanceof Class == false) {
|
||||
throw new FunctorException(
|
||||
"InstantiateTransformer: Input object was not an instanceof Class, it was a "
|
||||
+ (input == null ? "null object" : input.getClass().getName()));
|
||||
}
|
||||
return FactoryUtils.reflectionFactory((Class) input, iParamTypes, iArgs).create();
|
||||
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new FunctorException("InstantiateTransformer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MapTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* MapTransformer returns the result by looking up in the map.
|
||||
*/
|
||||
private static class MapTransformer implements Transformer, Serializable {
|
||||
/** The map of data to lookup in */
|
||||
private final Map iMap;
|
||||
|
||||
/**
|
||||
* Constructor to store map.
|
||||
*/
|
||||
private MapTransformer(Map map) {
|
||||
super();
|
||||
iMap = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result by looking up in the map.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
return iMap.get(input);
|
||||
}
|
||||
}
|
||||
|
||||
// InvokerTransformer
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* InvokerTransformer returns the result of invoking the specified method on
|
||||
* the input object.
|
||||
*/
|
||||
private static class InvokerTransformer implements Transformer, Serializable {
|
||||
/** The method name to call */
|
||||
private final String iMethodName;
|
||||
/** The array of reflection parameter types */
|
||||
private final Class[] iParamTypes;
|
||||
/** The array of reflection arguments */
|
||||
private final Object[] iArgs;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
|
||||
super();
|
||||
if (methodName == null) {
|
||||
throw new IllegalArgumentException("InvokerTransformer: The method to invoke must not be null");
|
||||
}
|
||||
if (((paramTypes == null) && (args != null))
|
||||
|| ((paramTypes != null) && (args == null))
|
||||
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
|
||||
throw new IllegalArgumentException("InvokerTransformer: The parameter types must match the arguments");
|
||||
}
|
||||
|
||||
iMethodName = methodName;
|
||||
if ((paramTypes == null) && (args == null)) {
|
||||
iParamTypes = null;
|
||||
iArgs = null;
|
||||
} else {
|
||||
iParamTypes = (Class[]) paramTypes.clone();
|
||||
iArgs = (Object[]) args.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified method on the input object.
|
||||
*/
|
||||
public Object transform(Object input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Class cls = input.getClass();
|
||||
Method method = cls.getMethod(iMethodName, iParamTypes);
|
||||
return method.invoke(input, iArgs);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue