You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/05/16 15:41:10 UTC
cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections TransformerUtils.java FunctorException.java PredicateUtils.java FactoryUtils.java ClosureUtils.java Closure.java Transformer.java Predicate.java Factory.java
scolebourne 2003/05/16 06:41:10
Modified: collections/src/java/org/apache/commons/collections
Closure.java Transformer.java Predicate.java
Factory.java
Added: collections/src/java/org/apache/commons/collections
TransformerUtils.java FunctorException.java
PredicateUtils.java FactoryUtils.java
ClosureUtils.java
Log:
Add functor utility implementations
Revision Changes Path
1.6 +21 -12 jakarta-commons/collections/src/java/org/apache/commons/collections/Closure.java
Index: Closure.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/Closure.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Closure.java 11 May 2003 14:15:23 -0000 1.5
+++ Closure.java 16 May 2003 13:41:10 -0000 1.6
@@ -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$ $Date$
- *
- * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
+ *
+ * @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);
}
1.5 +28 -17 jakarta-commons/collections/src/java/org/apache/commons/collections/Transformer.java
Index: Transformer.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/Transformer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Transformer.java 12 Jun 2002 03:59:15 -0000 1.4
+++ Transformer.java 16 May 2003 13:41:10 -0000 1.5
@@ -1,13 +1,10 @@
/*
* $Header$
- * $Revision$
- * $Date$
- *
* ====================================================================
*
* 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$ $Date$
+ *
+ * @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);
+
}
1.6 +28 -21 jakarta-commons/collections/src/java/org/apache/commons/collections/Predicate.java
Index: Predicate.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/Predicate.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Predicate.java 15 Aug 2002 20:04:31 -0000 1.5
+++ Predicate.java 16 May 2003 13:41:10 -0000 1.6
@@ -1,13 +1,10 @@
/*
* $Header$
- * $Revision$
- * $Date$
- *
* ====================================================================
*
* 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$ $Date$
+ *
+ * @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);
+
}
1.4 +22 -23 jakarta-commons/collections/src/java/org/apache/commons/collections/Factory.java
Index: Factory.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/Factory.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Factory.java 12 Oct 2002 22:15:19 -0000 1.3
+++ Factory.java 16 May 2003 13:41:10 -0000 1.4
@@ -1,12 +1,10 @@
/*
* $Header$
- * $Revision$
- * $Date$
* ====================================================================
*
* 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$ $Date$
*
* @author Arron Bates
- * @version $Revision$
- * @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();
+
}
1.1 jakarta-commons/collections/src/java/org/apache/commons/collections/TransformerUtils.java
Index: TransformerUtils.java
===================================================================
/*
* $Header: /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);
}
}
}
}
1.1 jakarta-commons/collections/src/java/org/apache/commons/collections/FunctorException.java
Index: FunctorException.java
===================================================================
/*
* $Header: /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.7 +982 -279 jakarta-commons/collections/src/java/org/apache/commons/collections/PredicateUtils.java
1.7 +388 -123 jakarta-commons/collections/src/java/org/apache/commons/collections/FactoryUtils.java
1.1 jakarta-commons/collections/src/java/org/apache/commons/collections/ClosureUtils.java
Index: ClosureUtils.java
===================================================================
/*
* $Header: /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);
}
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org