KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > ClosureUtils


1 /*
2  * Copyright 2002-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections;
17
18 import java.util.Collection JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.apache.commons.collections.functors.ChainedClosure;
23 import org.apache.commons.collections.functors.EqualPredicate;
24 import org.apache.commons.collections.functors.ExceptionClosure;
25 import org.apache.commons.collections.functors.ForClosure;
26 import org.apache.commons.collections.functors.IfClosure;
27 import org.apache.commons.collections.functors.InvokerTransformer;
28 import org.apache.commons.collections.functors.NOPClosure;
29 import org.apache.commons.collections.functors.SwitchClosure;
30 import org.apache.commons.collections.functors.TransformerClosure;
31 import org.apache.commons.collections.functors.WhileClosure;
32
33 /**
34  * <code>ClosureUtils</code> provides reference implementations and utilities
35  * for the Closure functor interface. The supplied closures are:
36  * <ul>
37  * <li>Invoker - invokes a method on the input object
38  * <li>For - repeatedly calls a closure for a fixed number of times
39  * <li>While - repeatedly calls a closure while a predicate is true
40  * <li>DoWhile - repeatedly calls a closure while a predicate is true
41  * <li>Chained - chains two or more closures together
42  * <li>Switch - calls one closure based on one or more predicates
43  * <li>SwitchMap - calls one closure looked up from a Map
44  * <li>Transformer - wraps a Transformer as a Closure
45  * <li>NOP - does nothing
46  * <li>Exception - always throws an exception
47  * </ul>
48  * All the supplied closures are Serializable.
49  *
50  * @since Commons Collections 3.0
51  * @version $Revision: 1.9 $ $Date: 2004/05/26 21:50:52 $
52  *
53  * @author Stephen Colebourne
54  */

55 public class ClosureUtils {
56
57     /**
58      * This class is not normally instantiated.
59      */

60     public ClosureUtils() {
61         super();
62     }
63
64     /**
65      * Gets a Closure that always throws an exception.
66      * This could be useful during testing as a placeholder.
67      *
68      * @see org.apache.commons.collections.functors.ExceptionClosure
69      *
70      * @return the closure
71      */

72     public static Closure exceptionClosure() {
73         return ExceptionClosure.INSTANCE;
74     }
75
76     /**
77      * Gets a Closure that will do nothing.
78      * This could be useful during testing as a placeholder.
79      *
80      * @see org.apache.commons.collections.functors.NOPClosure
81      *
82      * @return the closure
83      */

84     public static Closure nopClosure() {
85         return NOPClosure.INSTANCE;
86     }
87
88     /**
89      * Creates a Closure that calls a Transformer each time it is called.
90      * The transformer will be called using the closure's input object.
91      * The transformer's result will be ignored.
92      *
93      * @see org.apache.commons.collections.functors.TransformerClosure
94      *
95      * @param transformer the transformer to run each time in the closure, null means nop
96      * @return the closure
97      */

98     public static Closure asClosure(Transformer transformer) {
99         return TransformerClosure.getInstance(transformer);
100     }
101
102     /**
103      * Creates a Closure that will call the closure <code>count</code> times.
104      * <p>
105      * A null closure or zero count returns the <code>NOPClosure</code>.
106      *
107      * @see org.apache.commons.collections.functors.ForClosure
108      *
109      * @param count the number of times to loop
110      * @param closure the closure to call repeatedly
111      * @return the <code>for</code> closure
112      */

113     public static Closure forClosure(int count, Closure closure) {
114         return ForClosure.getInstance(count, closure);
115     }
116
117     /**
118      * Creates a Closure that will call the closure repeatedly until the
119      * predicate returns false.
120      *
121      * @see org.apache.commons.collections.functors.WhileClosure
122      *
123      * @param predicate the predicate to use as an end of loop test, not null
124      * @param closure the closure to call repeatedly, not null
125      * @return the <code>while</code> closure
126      * @throws IllegalArgumentException if either argument is null
127      */

128     public static Closure whileClosure(Predicate predicate, Closure closure) {
129         return WhileClosure.getInstance(predicate, closure, false);
130     }
131
132     /**
133      * Creates a Closure that will call the closure once and then repeatedly
134      * until the predicate returns false.
135      *
136      * @see org.apache.commons.collections.functors.WhileClosure
137      *
138      * @param closure the closure to call repeatedly, not null
139      * @param predicate the predicate to use as an end of loop test, not null
140      * @return the <code>do-while</code> closure
141      * @throws IllegalArgumentException if either argument is null
142      */

143     public static Closure doWhileClosure(Closure closure, Predicate predicate) {
144         return WhileClosure.getInstance(predicate, closure, true);
145     }
146
147     /**
148      * Creates a Closure that will invoke a specific method on the closure's
149      * input object by reflection.
150      *
151      * @see org.apache.commons.collections.functors.InvokerTransformer
152      * @see org.apache.commons.collections.functors.TransformerClosure
153      *
154      * @param methodName the name of the method
155      * @return the <code>invoker</code> closure
156      * @throws IllegalArgumentException if the method name is null
157      */

158     public static Closure invokerClosure(String JavaDoc methodName) {
159         // reuse transformer as it has caching - this is lazy really, should have inner class here
160
return asClosure(InvokerTransformer.getInstance(methodName));
161     }
162
163     /**
164      * Creates a Closure that will invoke a specific method on the closure's
165      * input object by reflection.
166      *
167      * @see org.apache.commons.collections.functors.InvokerTransformer
168      * @see org.apache.commons.collections.functors.TransformerClosure
169      *
170      * @param methodName the name of the method
171      * @param paramTypes the parameter types
172      * @param args the arguments
173      * @return the <code>invoker</code> closure
174      * @throws IllegalArgumentException if the method name is null
175      * @throws IllegalArgumentException if the paramTypes and args don't match
176      */

177     public static Closure invokerClosure(String JavaDoc methodName, Class JavaDoc[] paramTypes, Object JavaDoc[] args) {
178         // reuse transformer as it has caching - this is lazy really, should have inner class here
179
return asClosure(InvokerTransformer.getInstance(methodName, paramTypes, args));
180     }
181
182     /**
183      * Create a new Closure that calls two Closures, passing the result of
184      * the first into the second.
185      *
186      * @see org.apache.commons.collections.functors.ChainedClosure
187      *
188      * @param closure1 the first closure
189      * @param closure2 the second closure
190      * @return the <code>chained</code> closure
191      * @throws IllegalArgumentException if either closure is null
192      */

193     public static Closure chainedClosure(Closure closure1, Closure closure2) {
194         return ChainedClosure.getInstance(closure1, closure2);
195     }
196
197     /**
198      * Create a new Closure that calls each closure in turn, passing the
199      * result into the next closure.
200      *
201      * @see org.apache.commons.collections.functors.ChainedClosure
202      *
203      * @param closures an array of closures to chain
204      * @return the <code>chained</code> closure
205      * @throws IllegalArgumentException if the closures array is null
206      * @throws IllegalArgumentException if any closure in the array is null
207      */

208     public static Closure chainedClosure(Closure[] closures) {
209         return ChainedClosure.getInstance(closures);
210     }
211
212     /**
213      * Create a new Closure that calls each closure in turn, passing the
214      * result into the next closure. The ordering is that of the iterator()
215      * method on the collection.
216      *
217      * @see org.apache.commons.collections.functors.ChainedClosure
218      *
219      * @param closures a collection of closures to chain
220      * @return the <code>chained</code> closure
221      * @throws IllegalArgumentException if the closures collection is null
222      * @throws IllegalArgumentException if the closures collection is empty
223      * @throws IllegalArgumentException if any closure in the collection is null
224      */

225     public static Closure chainedClosure(Collection JavaDoc closures) {
226         return ChainedClosure.getInstance(closures);
227     }
228
229     /**
230      * Create a new Closure that calls one of two closures depending
231      * on the specified predicate.
232      *
233      * @see org.apache.commons.collections.functors.IfClosure
234      *
235      * @param predicate the predicate to switch on
236      * @param trueClosure the closure called if the predicate is true
237      * @param falseClosure the closure called if the predicate is false
238      * @return the <code>switch</code> closure
239      * @throws IllegalArgumentException if the predicate is null
240      * @throws IllegalArgumentException if either closure is null
241      */

242     public static Closure ifClosure(Predicate predicate, Closure trueClosure, Closure falseClosure) {
243         return IfClosure.getInstance(predicate, trueClosure, falseClosure);
244     }
245
246     /**
247      * Create a new Closure that calls one of the closures depending
248      * on the predicates.
249      * <p>
250      * The closure at array location 0 is called if the predicate at array
251      * location 0 returned true. Each predicate is evaluated
252      * until one returns true.
253      *
254      * @see org.apache.commons.collections.functors.SwitchClosure
255      *
256      * @param predicates an array of predicates to check, not null
257      * @param closures an array of closures to call, not null
258      * @return the <code>switch</code> closure
259      * @throws IllegalArgumentException if the either array is null
260      * @throws IllegalArgumentException if any element in the arrays is null
261      * @throws IllegalArgumentException if the arrays are different sizes
262      */

263     public static Closure switchClosure(Predicate[] predicates, Closure[] closures) {
264         return SwitchClosure.getInstance(predicates, closures, null);
265     }
266
267     /**
268      * Create a new Closure that calls one of the closures depending
269      * on the predicates.
270      * <p>
271      * The closure at array location 0 is called if the predicate at array
272      * location 0 returned true. Each predicate is evaluated
273      * until one returns true. If no predicates evaluate to true, the default
274      * closure is called.
275      *
276      * @see org.apache.commons.collections.functors.SwitchClosure
277      *
278      * @param predicates an array of predicates to check, not null
279      * @param closures an array of closures to call, not null
280      * @param defaultClosure the default to call if no predicate matches
281      * @return the <code>switch</code> closure
282      * @throws IllegalArgumentException if the either array is null
283      * @throws IllegalArgumentException if any element in the arrays is null
284      * @throws IllegalArgumentException if the arrays are different sizes
285      */

286     public static Closure switchClosure(Predicate[] predicates, Closure[] closures, Closure defaultClosure) {
287         return SwitchClosure.getInstance(predicates, closures, defaultClosure);
288     }
289     
290     /**
291      * Create a new Closure that calls one of the closures depending
292      * on the predicates.
293      * <p>
294      * The Map consists of Predicate keys and Closure values. A closure
295      * is called if its matching predicate returns true. Each predicate is evaluated
296      * until one returns true. If no predicates evaluate to true, the default
297      * closure is called. The default closure is set in the map with a
298      * null key. The ordering is that of the iterator() method on the entryset
299      * collection of the map.
300      *
301      * @see org.apache.commons.collections.functors.SwitchClosure
302      *
303      * @param predicatesAndClosures a map of predicates to closures
304      * @return the <code>switch</code> closure
305      * @throws IllegalArgumentException if the map is null
306      * @throws IllegalArgumentException if the map is empty
307      * @throws IllegalArgumentException if any closure in the map is null
308      * @throws ClassCastException if the map elements are of the wrong type
309      */

310     public static Closure switchClosure(Map JavaDoc predicatesAndClosures) {
311         return SwitchClosure.getInstance(predicatesAndClosures);
312     }
313
314     /**
315      * Create a new Closure that uses the input object as a key to find the
316      * closure to call.
317      * <p>
318      * The Map consists of object keys and Closure values. A closure
319      * is called if the input object equals the key. If there is no match, the
320      * default closure is called. The default closure is set in the map
321      * using a null key.
322      *
323      * @see org.apache.commons.collections.functors.SwitchClosure
324      *
325      * @param objectsAndClosures a map of objects to closures
326      * @return the closure
327      * @throws IllegalArgumentException if the map is null
328      * @throws IllegalArgumentException if the map is empty
329      * @throws IllegalArgumentException if any closure in the map is null
330      */

331     public static Closure switchMapClosure(Map JavaDoc objectsAndClosures) {
332         Closure[] trs = null;
333         Predicate[] preds = null;
334         if (objectsAndClosures == null) {
335             throw new IllegalArgumentException JavaDoc("The object and closure map must not be null");
336         }
337         Closure def = (Closure) objectsAndClosures.remove(null);
338         int size = objectsAndClosures.size();
339         trs = new Closure[size];
340         preds = new Predicate[size];
341         int i = 0;
342         for (Iterator JavaDoc it = objectsAndClosures.entrySet().iterator(); it.hasNext();) {
343             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
344             preds[i] = EqualPredicate.getInstance(entry.getKey());
345             trs[i] = (Closure) entry.getValue();
346             i++;
347         }
348         return switchClosure(preds, trs, def);
349     }
350
351 }
352
Popular Tags