001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.collections;
018
019 import java.util.Collection;
020 import java.util.Iterator;
021 import java.util.Map;
022
023 import org.apache.commons.collections.functors.ChainedTransformer;
024 import org.apache.commons.collections.functors.CloneTransformer;
025 import org.apache.commons.collections.functors.ClosureTransformer;
026 import org.apache.commons.collections.functors.ConstantTransformer;
027 import org.apache.commons.collections.functors.EqualPredicate;
028 import org.apache.commons.collections.functors.ExceptionTransformer;
029 import org.apache.commons.collections.functors.FactoryTransformer;
030 import org.apache.commons.collections.functors.InstantiateTransformer;
031 import org.apache.commons.collections.functors.InvokerTransformer;
032 import org.apache.commons.collections.functors.MapTransformer;
033 import org.apache.commons.collections.functors.NOPTransformer;
034 import org.apache.commons.collections.functors.PredicateTransformer;
035 import org.apache.commons.collections.functors.StringValueTransformer;
036 import org.apache.commons.collections.functors.SwitchTransformer;
037
038 /**
039 * <code>TransformerUtils</code> provides reference implementations and
040 * utilities for the Transformer functor interface. The supplied transformers are:
041 * <ul>
042 * <li>Invoker - returns the result of a method call on the input object
043 * <li>Clone - returns a clone of the input object
044 * <li>Constant - always returns the same object
045 * <li>Closure - performs a Closure and returns the input object
046 * <li>Predicate - returns the result of the predicate as a Boolean
047 * <li>Factory - returns a new object from a factory
048 * <li>Chained - chains two or more transformers together
049 * <li>Switch - calls one transformer based on one or more predicates
050 * <li>SwitchMap - calls one transformer looked up from a Map
051 * <li>Instantiate - the Class input object is instantiated
052 * <li>Map - returns an object from a supplied Map
053 * <li>Null - always returns null
054 * <li>NOP - returns the input object, which should be immutable
055 * <li>Exception - always throws an exception
056 * <li>StringValue - returns a <code>java.lang.String</code> representation of the input object
057 * </ul>
058 * All the supplied transformers are Serializable.
059 *
060 * @since Commons Collections 3.0
061 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
062 *
063 * @author Stephen Colebourne
064 * @author James Carman
065 */
066 public class TransformerUtils {
067
068 /**
069 * This class is not normally instantiated.
070 */
071 public TransformerUtils() {
072 super();
073 }
074
075 /**
076 * Gets a transformer that always throws an exception.
077 * This could be useful during testing as a placeholder.
078 *
079 * @see org.apache.commons.collections.functors.ExceptionTransformer
080 *
081 * @return the transformer
082 */
083 public static Transformer exceptionTransformer() {
084 return ExceptionTransformer.INSTANCE;
085 }
086
087 /**
088 * Gets a transformer that always returns null.
089 *
090 * @see org.apache.commons.collections.functors.ConstantTransformer
091 *
092 * @return the transformer
093 */
094 public static Transformer nullTransformer() {
095 return ConstantTransformer.NULL_INSTANCE;
096 }
097
098 /**
099 * Gets a transformer that returns the input object.
100 * The input object should be immutable to maintain the
101 * contract of Transformer (although this is not checked).
102 *
103 * @see org.apache.commons.collections.functors.NOPTransformer
104 *
105 * @return the transformer
106 */
107 public static Transformer nopTransformer() {
108 return NOPTransformer.INSTANCE;
109 }
110
111 /**
112 * Gets a transformer that returns a clone of the input
113 * object. The input object will be cloned using one of these
114 * techniques (in order):
115 * <ul>
116 * <li>public clone method
117 * <li>public copy constructor
118 * <li>serialization clone
119 * <ul>
120 *
121 * @see org.apache.commons.collections.functors.CloneTransformer
122 *
123 * @return the transformer
124 */
125 public static Transformer cloneTransformer() {
126 return CloneTransformer.INSTANCE;
127 }
128
129 /**
130 * Creates a Transformer that will return the same object each time the
131 * transformer is used.
132 *
133 * @see org.apache.commons.collections.functors.ConstantTransformer
134 *
135 * @param constantToReturn the constant object to return each time in the transformer
136 * @return the transformer.
137 */
138 public static Transformer constantTransformer(Object constantToReturn) {
139 return ConstantTransformer.getInstance(constantToReturn);
140 }
141
142 /**
143 * Creates a Transformer that calls a Closure each time the transformer is used.
144 * The transformer returns the input object.
145 *
146 * @see org.apache.commons.collections.functors.ClosureTransformer
147 *
148 * @param closure the closure to run each time in the transformer, not null
149 * @return the transformer
150 * @throws IllegalArgumentException if the closure is null
151 */
152 public static Transformer asTransformer(Closure closure) {
153 return ClosureTransformer.getInstance(closure);
154 }
155
156 /**
157 * Creates a Transformer that calls a Predicate each time the transformer is used.
158 * The transformer will return either Boolean.TRUE or Boolean.FALSE.
159 *
160 * @see org.apache.commons.collections.functors.PredicateTransformer
161 *
162 * @param predicate the predicate to run each time in the transformer, not null
163 * @return the transformer
164 * @throws IllegalArgumentException if the predicate is null
165 */
166 public static Transformer asTransformer(Predicate predicate) {
167 return PredicateTransformer.getInstance(predicate);
168 }
169
170 /**
171 * Creates a Transformer that calls a Factory each time the transformer is used.
172 * The transformer will return the value returned by the factory.
173 *
174 * @see org.apache.commons.collections.functors.FactoryTransformer
175 *
176 * @param factory the factory to run each time in the transformer, not null
177 * @return the transformer
178 * @throws IllegalArgumentException if the factory is null
179 */
180 public static Transformer asTransformer(Factory factory) {
181 return FactoryTransformer.getInstance(factory);
182 }
183
184 /**
185 * Create a new Transformer that calls two transformers, passing the result of
186 * the first into the second.
187 *
188 * @see org.apache.commons.collections.functors.ChainedTransformer
189 *
190 * @param transformer1 the first transformer
191 * @param transformer2 the second transformer
192 * @return the transformer
193 * @throws IllegalArgumentException if either transformer is null
194 */
195 public static Transformer chainedTransformer(Transformer transformer1, Transformer transformer2) {
196 return ChainedTransformer.getInstance(transformer1, transformer2);
197 }
198
199 /**
200 * Create a new Transformer that calls each transformer in turn, passing the
201 * result into the next transformer.
202 *
203 * @see org.apache.commons.collections.functors.ChainedTransformer
204 *
205 * @param transformers an array of transformers to chain
206 * @return the transformer
207 * @throws IllegalArgumentException if the transformers array is null
208 * @throws IllegalArgumentException if any transformer in the array is null
209 */
210 public static Transformer chainedTransformer(Transformer[] transformers) {
211 return ChainedTransformer.getInstance(transformers);
212 }
213
214 /**
215 * Create a new Transformer that calls each transformer in turn, passing the
216 * result into the next transformer. The ordering is that of the iterator()
217 * method on the collection.
218 *
219 * @see org.apache.commons.collections.functors.ChainedTransformer
220 *
221 * @param transformers a collection of transformers to chain
222 * @return the transformer
223 * @throws IllegalArgumentException if the transformers collection is null
224 * @throws IllegalArgumentException if any transformer in the collection is null
225 */
226 public static Transformer chainedTransformer(Collection transformers) {
227 return ChainedTransformer.getInstance(transformers);
228 }
229
230 /**
231 * Create a new Transformer that calls one of two transformers depending
232 * on the specified predicate.
233 *
234 * @see org.apache.commons.collections.functors.SwitchTransformer
235 *
236 * @param predicate the predicate to switch on
237 * @param trueTransformer the transformer called if the predicate is true
238 * @param falseTransformer the transformer called if the predicate is false
239 * @return the transformer
240 * @throws IllegalArgumentException if the predicate is null
241 * @throws IllegalArgumentException if either transformer is null
242 */
243 public static Transformer switchTransformer(Predicate predicate, Transformer trueTransformer, Transformer falseTransformer) {
244 return SwitchTransformer.getInstance(new Predicate[] { predicate }, new Transformer[] { trueTransformer }, falseTransformer);
245 }
246
247 /**
248 * Create a new Transformer that calls one of the transformers depending
249 * on the predicates. The transformer at array location 0 is called if the
250 * predicate at array location 0 returned true. Each predicate is evaluated
251 * until one returns true. If no predicates evaluate to true, null is returned.
252 *
253 * @see org.apache.commons.collections.functors.SwitchTransformer
254 *
255 * @param predicates an array of predicates to check
256 * @param transformers an array of transformers to call
257 * @return the transformer
258 * @throws IllegalArgumentException if the either array is null
259 * @throws IllegalArgumentException if the either array has 0 elements
260 * @throws IllegalArgumentException if any element in the arrays is null
261 * @throws IllegalArgumentException if the arrays are different sizes
262 */
263 public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers) {
264 return SwitchTransformer.getInstance(predicates, transformers, null);
265 }
266
267 /**
268 * Create a new Transformer that calls one of the transformers depending
269 * on the predicates. The transformer at array location 0 is called if the
270 * predicate at array location 0 returned true. Each predicate is evaluated
271 * until one returns true. If no predicates evaluate to true, the default
272 * transformer is called. If the default transformer is null, null is returned.
273 *
274 * @see org.apache.commons.collections.functors.SwitchTransformer
275 *
276 * @param predicates an array of predicates to check
277 * @param transformers an array of transformers to call
278 * @param defaultTransformer the default to call if no predicate matches, null means return null
279 * @return the transformer
280 * @throws IllegalArgumentException if the either array is null
281 * @throws IllegalArgumentException if the either array has 0 elements
282 * @throws IllegalArgumentException if any element in the arrays is null
283 * @throws IllegalArgumentException if the arrays are different sizes
284 */
285 public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers, Transformer defaultTransformer) {
286 return SwitchTransformer.getInstance(predicates, transformers, defaultTransformer);
287 }
288
289 /**
290 * Create a new Transformer that calls one of the transformers depending
291 * on the predicates.
292 * <p>
293 * The Map consists of Predicate keys and Transformer values. A transformer
294 * is called if its matching predicate returns true. Each predicate is evaluated
295 * until one returns true. If no predicates evaluate to true, the default
296 * transformer is called. The default transformer is set in the map with a
297 * null key. If no default transformer is set, null will be returned in a default
298 * case. The ordering is that of the iterator() method on the entryset collection
299 * of the map.
300 *
301 * @see org.apache.commons.collections.functors.SwitchTransformer
302 *
303 * @param predicatesAndTransformers a map of predicates to transformers
304 * @return the transformer
305 * @throws IllegalArgumentException if the map is null
306 * @throws IllegalArgumentException if the map is empty
307 * @throws IllegalArgumentException if any transformer in the map is null
308 * @throws ClassCastException if the map elements are of the wrong type
309 */
310 public static Transformer switchTransformer(Map predicatesAndTransformers) {
311 return SwitchTransformer.getInstance(predicatesAndTransformers);
312 }
313
314 /**
315 * Create a new Transformer that uses the input object as a key to find the
316 * transformer to call.
317 * <p>
318 * The Map consists of object keys and Transformer values. A transformer
319 * is called if the input object equals the key. If there is no match, the
320 * default transformer is called. The default transformer is set in the map
321 * using a null key. If no default is set, null will be returned in a default case.
322 *
323 * @see org.apache.commons.collections.functors.SwitchTransformer
324 *
325 * @param objectsAndTransformers a map of objects to transformers
326 * @return the transformer
327 * @throws IllegalArgumentException if the map is null
328 * @throws IllegalArgumentException if the map is empty
329 * @throws IllegalArgumentException if any transformer in the map is null
330 */
331 public static Transformer switchMapTransformer(Map objectsAndTransformers) {
332 Transformer[] trs = null;
333 Predicate[] preds = null;
334 if (objectsAndTransformers == null) {
335 throw new IllegalArgumentException("The object and transformer map must not be null");
336 }
337 Transformer def = (Transformer) objectsAndTransformers.remove(null);
338 int size = objectsAndTransformers.size();
339 trs = new Transformer[size];
340 preds = new Predicate[size];
341 int i = 0;
342 for (Iterator it = objectsAndTransformers.entrySet().iterator(); it.hasNext();) {
343 Map.Entry entry = (Map.Entry) it.next();
344 preds[i] = EqualPredicate.getInstance(entry.getKey());
345 trs[i] = (Transformer) entry.getValue();
346 i++;
347 }
348 return switchTransformer(preds, trs, def);
349 }
350
351 /**
352 * Gets a Transformer that expects an input Class object that it will instantiate.
353 *
354 * @see org.apache.commons.collections.functors.InstantiateTransformer
355 *
356 * @return the transformer
357 */
358 public static Transformer instantiateTransformer() {
359 return InstantiateTransformer.NO_ARG_INSTANCE;
360 }
361
362 /**
363 * Creates a Transformer that expects an input Class object that it will
364 * instantiate. The constructor used is determined by the arguments specified
365 * to this method.
366 *
367 * @see org.apache.commons.collections.functors.InstantiateTransformer
368 *
369 * @param paramTypes parameter types for the constructor, can be null
370 * @param args the arguments to pass to the constructor, can be null
371 * @return the transformer
372 * @throws IllegalArgumentException if the paramTypes and args don't match
373 */
374 public static Transformer instantiateTransformer(Class[] paramTypes, Object[] args) {
375 return InstantiateTransformer.getInstance(paramTypes, args);
376 }
377
378 /**
379 * Creates a Transformer that uses the passed in Map to transform the input
380 * object (as a simple lookup).
381 *
382 * @see org.apache.commons.collections.functors.MapTransformer
383 *
384 * @param map the map to use to transform the objects
385 * @return the transformer
386 * @throws IllegalArgumentException if the map is null
387 */
388 public static Transformer mapTransformer(Map map) {
389 return MapTransformer.getInstance(map);
390 }
391
392 /**
393 * Gets a Transformer that invokes a method on the input object.
394 * The method must have no parameters. If the input object is null,
395 * null is returned.
396 * <p>
397 * For example, <code>TransformerUtils.invokerTransformer("getName");</code>
398 * will call the <code>getName/code> method on the input object to
399 * determine the transformer result.
400 *
401 * @see org.apache.commons.collections.functors.InvokerTransformer
402 *
403 * @param methodName the method name to call on the input object, may not be null
404 * @return the transformer
405 * @throws IllegalArgumentException if the methodName is null.
406 */
407 public static Transformer invokerTransformer(String methodName){
408 return InvokerTransformer.getInstance(methodName, null, null);
409 }
410
411 /**
412 * Gets a Transformer that invokes a method on the input object.
413 * The method parameters are specified. If the input object is null,
414 * null is returned.
415 *
416 * @see org.apache.commons.collections.functors.InvokerTransformer
417 *
418 * @param methodName the name of the method
419 * @param paramTypes the parameter types
420 * @param args the arguments
421 * @return the transformer
422 * @throws IllegalArgumentException if the method name is null
423 * @throws IllegalArgumentException if the paramTypes and args don't match
424 */
425 public static Transformer invokerTransformer(String methodName, Class[] paramTypes, Object[] args){
426 return InvokerTransformer.getInstance(methodName, paramTypes, args);
427 }
428
429 /**
430 * Gets a transformer that returns a <code>java.lang.String</code>
431 * representation of the input object. This is achieved via the
432 * <code>toString</code> method, <code>null</code> returns 'null'.
433 *
434 * @see org.apache.commons.collections.functors.StringValueTransformer
435 *
436 * @return the transformer
437 */
438 public static Transformer stringValueTransformer() {
439 return StringValueTransformer.INSTANCE;
440 }
441
442 }