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 */ 017package org.apache.commons.collections4; 018 019import java.util.Collection; 020import java.util.Map; 021 022import org.apache.commons.collections4.functors.ChainedTransformer; 023import org.apache.commons.collections4.functors.CloneTransformer; 024import org.apache.commons.collections4.functors.ClosureTransformer; 025import org.apache.commons.collections4.functors.ConstantTransformer; 026import org.apache.commons.collections4.functors.EqualPredicate; 027import org.apache.commons.collections4.functors.ExceptionTransformer; 028import org.apache.commons.collections4.functors.FactoryTransformer; 029import org.apache.commons.collections4.functors.IfTransformer; 030import org.apache.commons.collections4.functors.InstantiateTransformer; 031import org.apache.commons.collections4.functors.InvokerTransformer; 032import org.apache.commons.collections4.functors.MapTransformer; 033import org.apache.commons.collections4.functors.NOPTransformer; 034import org.apache.commons.collections4.functors.PredicateTransformer; 035import org.apache.commons.collections4.functors.StringValueTransformer; 036import org.apache.commons.collections4.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>If - calls one transformer or another based on a predicate 050 * <li>Switch - calls one transformer based on one or more predicates 051 * <li>SwitchMap - calls one transformer looked up from a Map 052 * <li>Instantiate - the Class input object is instantiated 053 * <li>Map - returns an object from a supplied Map 054 * <li>Null - always returns null 055 * <li>NOP - returns the input object, which should be immutable 056 * <li>Exception - always throws an exception 057 * <li>StringValue - returns a <code>java.lang.String</code> representation of the input object 058 * </ul> 059 * <p> 060 * Since v4.1 only transformers which are considered to be safe are 061 * Serializable. Transformers considered to be unsafe for serialization are: 062 * <ul> 063 * <li>Invoker 064 * <li>Clone 065 * <li>Instantiate 066 * </ul> 067 * 068 * @since 3.0 069 */ 070public class TransformerUtils { 071 072 /** 073 * This class is not normally instantiated. 074 */ 075 private TransformerUtils() {} 076 077 /** 078 * Gets a transformer that always throws an exception. 079 * This could be useful during testing as a placeholder. 080 * 081 * @param <I> the input type 082 * @param <O> the output type 083 * @return the transformer 084 * @see ExceptionTransformer 085 */ 086 public static <I, O> Transformer<I, O> exceptionTransformer() { 087 return ExceptionTransformer.exceptionTransformer(); 088 } 089 090 /** 091 * Gets a transformer that always returns null. 092 * 093 * @param <I> the input type 094 * @param <O> the output type 095 * @return the transformer 096 * @see ConstantTransformer 097 */ 098 public static <I, O> Transformer<I, O> nullTransformer() { 099 return ConstantTransformer.nullTransformer(); 100 } 101 102 /** 103 * Gets a transformer that returns the input object. 104 * The input object should be immutable to maintain the 105 * contract of Transformer (although this is not checked). 106 * 107 * @param <T> the input/output type 108 * @return the transformer 109 * @see NOPTransformer 110 */ 111 public static <T> Transformer<T, T> nopTransformer() { 112 return NOPTransformer.nopTransformer(); 113 } 114 115 /** 116 * Gets a transformer that returns a clone of the input object. 117 * The input object will be cloned using one of these techniques (in order): 118 * <ul> 119 * <li>public clone method</li> 120 * <li>public copy constructor</li> 121 * <li>serialization clone</li> 122 * </ul> 123 * 124 * @param <T> the input/output type 125 * @return the transformer 126 * @see CloneTransformer 127 */ 128 public static <T> Transformer<T, T> cloneTransformer() { 129 return CloneTransformer.cloneTransformer(); 130 } 131 132 /** 133 * Creates a Transformer that will return the same object each time the 134 * transformer is used. 135 * 136 * @param <I> the input type 137 * @param <O> the output type 138 * @param constantToReturn the constant object to return each time in the transformer 139 * @return the transformer. 140 * @see ConstantTransformer 141 */ 142 public static <I, O> Transformer<I, O> constantTransformer(final O constantToReturn) { 143 return ConstantTransformer.constantTransformer(constantToReturn); 144 } 145 146 /** 147 * Creates a Transformer that calls a Closure each time the transformer is used. 148 * The transformer returns the input object. 149 * 150 * @param <T> the input/output type 151 * @param closure the closure to run each time in the transformer, not null 152 * @return the transformer 153 * @throws NullPointerException if the closure is null 154 * @see ClosureTransformer 155 */ 156 public static <T> Transformer<T, T> asTransformer(final Closure<? super T> closure) { 157 return ClosureTransformer.closureTransformer(closure); 158 } 159 160 /** 161 * Creates a Transformer that calls a Predicate each time the transformer is used. 162 * The transformer will return either Boolean.TRUE or Boolean.FALSE. 163 * 164 * @param <T> the input type 165 * @param predicate the predicate to run each time in the transformer, not null 166 * @return the transformer 167 * @throws NullPointerException if the predicate is null 168 * @see PredicateTransformer 169 */ 170 public static <T> Transformer<T, Boolean> asTransformer(final Predicate<? super T> predicate) { 171 return PredicateTransformer.predicateTransformer(predicate); 172 } 173 174 /** 175 * Creates a Transformer that calls a Factory each time the transformer is used. 176 * The transformer will return the value returned by the factory. 177 * 178 * @param <I> the input type 179 * @param <O> the output type 180 * @param factory the factory to run each time in the transformer, not null 181 * @return the transformer 182 * @throws NullPointerException if the factory is null 183 * @see FactoryTransformer 184 */ 185 public static <I, O> Transformer<I, O> asTransformer(final Factory<? extends O> factory) { 186 return FactoryTransformer.factoryTransformer(factory); 187 } 188 189 /** 190 * Create a new Transformer that calls each transformer in turn, passing the 191 * result into the next transformer. 192 * 193 * @param <T> the input/output type 194 * @param transformers an array of transformers to chain 195 * @return the transformer 196 * @throws NullPointerException if the transformers array or any of the transformers is null 197 * @see ChainedTransformer 198 */ 199 public static <T> Transformer<T, T> chainedTransformer( 200 final Transformer<? super T, ? extends T>... transformers) { 201 return ChainedTransformer.chainedTransformer(transformers); 202 } 203 204 /** 205 * Create a new Transformer that calls each transformer in turn, passing the 206 * result into the next transformer. The ordering is that of the iterator() 207 * method on the collection. 208 * 209 * @param <T> the input/output type 210 * @param transformers a collection of transformers to chain 211 * @return the transformer 212 * @throws NullPointerException if the transformers collection or any of the transformers is null 213 * @see ChainedTransformer 214 */ 215 public static <T> Transformer<T, T> chainedTransformer( 216 final Collection<? extends Transformer<? super T, ? extends T>> transformers) { 217 return ChainedTransformer.chainedTransformer(transformers); 218 } 219 220 /** 221 * Create a new Transformer that calls the transformer if the predicate is true, 222 * otherwise the input object is returned unchanged. 223 * 224 * @param <T> the input / output type 225 * @param predicate the predicate to switch on 226 * @param trueTransformer the transformer called if the predicate is true 227 * @return the transformer 228 * @throws NullPointerException if either the predicate or transformer is null 229 * @see IfTransformer 230 * @since 4.1 231 */ 232 public static <T> Transformer<T, T> ifTransformer(final Predicate<? super T> predicate, 233 final Transformer<? super T, ? extends T> trueTransformer) { 234 return IfTransformer.ifTransformer(predicate, trueTransformer); 235 } 236 237 /** 238 * Create a new Transformer that calls one of two transformers depending 239 * on the specified predicate. 240 * 241 * @param <I> the input type 242 * @param <O> the output type 243 * @param predicate the predicate to switch on 244 * @param trueTransformer the transformer called if the predicate is true 245 * @param falseTransformer the transformer called if the predicate is false 246 * @return the transformer 247 * @throws NullPointerException if either the predicate or transformer is null 248 * @see IfTransformer 249 * @since 4.1 250 */ 251 public static <I, O> Transformer<I, O> ifTransformer(final Predicate<? super I> predicate, 252 final Transformer<? super I, ? extends O> trueTransformer, 253 final Transformer<? super I, ? extends O> falseTransformer) { 254 return IfTransformer.ifTransformer(predicate, trueTransformer, falseTransformer); 255 } 256 257 /** 258 * Create a new Transformer that calls one of two transformers depending 259 * on the specified predicate. 260 * 261 * @param <I> the input type 262 * @param <O> the output type 263 * @param predicate the predicate to switch on 264 * @param trueTransformer the transformer called if the predicate is true 265 * @param falseTransformer the transformer called if the predicate is false 266 * @return the transformer 267 * @throws NullPointerException if either the predicate or transformer is null 268 * @see SwitchTransformer 269 * @deprecated as of 4.1, use {@link #ifTransformer(Predicate, Transformer, Transformer)} 270 */ 271 @SuppressWarnings("unchecked") 272 @Deprecated 273 public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I> predicate, 274 final Transformer<? super I, ? extends O> trueTransformer, 275 final Transformer<? super I, ? extends O> falseTransformer) { 276 return SwitchTransformer.switchTransformer(new Predicate[] { predicate }, 277 new Transformer[] { trueTransformer }, falseTransformer); 278 } 279 280 /** 281 * Create a new Transformer that calls one of the transformers depending 282 * on the predicates. The transformer at array location 0 is called if the 283 * predicate at array location 0 returned true. Each predicate is evaluated 284 * until one returns true. If no predicates evaluate to true, null is returned. 285 * 286 * @param <I> the input type 287 * @param <O> the output type 288 * @param predicates an array of predicates to check 289 * @param transformers an array of transformers to call 290 * @return the transformer 291 * @throws NullPointerException if the either array is null 292 * @throws NullPointerException if any element in the arrays is null 293 * @throws IllegalArgumentException if the arrays have different sizes 294 * @see SwitchTransformer 295 */ 296 public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I>[] predicates, 297 final Transformer<? super I, ? extends O>[] transformers) { 298 return SwitchTransformer.switchTransformer(predicates, transformers, null); 299 } 300 301 /** 302 * Create a new Transformer that calls one of the transformers depending 303 * on the predicates. The transformer at array location 0 is called if the 304 * predicate at array location 0 returned true. Each predicate is evaluated 305 * until one returns true. If no predicates evaluate to true, the default 306 * transformer is called. If the default transformer is null, null is returned. 307 * 308 * @param <I> the input type 309 * @param <O> the output type 310 * @param predicates an array of predicates to check 311 * @param transformers an array of transformers to call 312 * @param defaultTransformer the default to call if no predicate matches, null means return null 313 * @return the transformer 314 * @throws NullPointerException if the either array is null 315 * @throws NullPointerException if any element in the arrays is null 316 * @throws IllegalArgumentException if the arrays have different sizes 317 * @see SwitchTransformer 318 */ 319 public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I>[] predicates, 320 final Transformer<? super I, ? extends O>[] transformers, 321 final Transformer<? super I, ? extends O> defaultTransformer) { 322 return SwitchTransformer.switchTransformer(predicates, transformers, defaultTransformer); 323 } 324 325 /** 326 * Create a new Transformer that calls one of the transformers depending 327 * on the predicates. 328 * <p> 329 * The Map consists of Predicate keys and Transformer values. A transformer 330 * is called if its matching predicate returns true. Each predicate is evaluated 331 * until one returns true. If no predicates evaluate to true, the default 332 * transformer is called. The default transformer is set in the map with a 333 * null key. If no default transformer is set, null will be returned in a default 334 * case. The ordering is that of the iterator() method on the entryset collection 335 * of the map. 336 * 337 * @param <I> the input type 338 * @param <O> the output type 339 * @param predicatesAndTransformers a map of predicates to transformers 340 * @return the transformer 341 * @throws NullPointerException if the map is null 342 * @throws NullPointerException if any transformer in the map is null 343 * @throws ClassCastException if the map elements are of the wrong type 344 * @see SwitchTransformer 345 */ 346 public static <I, O> Transformer<I, O> switchTransformer( 347 final Map<Predicate<I>, Transformer<I, O>> predicatesAndTransformers) { 348 return SwitchTransformer.switchTransformer(predicatesAndTransformers); 349 } 350 351 /** 352 * Create a new Transformer that uses the input object as a key to find the 353 * transformer to call. 354 * <p> 355 * The Map consists of object keys and Transformer values. A transformer 356 * is called if the input object equals the key. If there is no match, the 357 * default transformer is called. The default transformer is set in the map 358 * using a null key. If no default is set, null will be returned in a default case. 359 * 360 * @param <I> the input type 361 * @param <O> the output type 362 * @param objectsAndTransformers a map of objects to transformers 363 * @return the transformer 364 * @throws NullPointerException if the map is null 365 * @throws NullPointerException if any transformer in the map is null 366 * @see SwitchTransformer 367 */ 368 @SuppressWarnings("unchecked") 369 public static <I, O> Transformer<I, O> switchMapTransformer( 370 final Map<I, Transformer<I, O>> objectsAndTransformers) { 371 372 if (objectsAndTransformers == null) { 373 throw new NullPointerException("The object and transformer map must not be null"); 374 } 375 final Transformer<? super I, ? extends O> def = objectsAndTransformers.remove(null); 376 final int size = objectsAndTransformers.size(); 377 final Transformer<? super I, ? extends O>[] trs = new Transformer[size]; 378 final Predicate<I>[] preds = new Predicate[size]; 379 int i = 0; 380 for (final Map.Entry<I, Transformer<I, O>> entry : objectsAndTransformers.entrySet()) { 381 preds[i] = EqualPredicate.<I>equalPredicate(entry.getKey()); 382 trs[i++] = entry.getValue(); 383 } 384 return TransformerUtils.switchTransformer(preds, trs, def); 385 } 386 387 /** 388 * Gets a Transformer that expects an input Class object that it will instantiate. 389 * 390 * @param <T> the output type 391 * @return the transformer 392 * @see InstantiateTransformer 393 */ 394 public static <T> Transformer<Class<? extends T>, T> instantiateTransformer() { 395 return InstantiateTransformer.instantiateTransformer(); 396 } 397 398 /** 399 * Creates a Transformer that expects an input Class object that it will 400 * instantiate. The constructor used is determined by the arguments specified 401 * to this method. 402 * 403 * @param <T> the output type 404 * @param paramTypes parameter types for the constructor, can be null 405 * @param args the arguments to pass to the constructor, can be null 406 * @return the transformer 407 * @throws IllegalArgumentException if the paramTypes and args don't match 408 * @see InstantiateTransformer 409 */ 410 public static <T> Transformer<Class<? extends T>, T> instantiateTransformer( 411 final Class<?>[] paramTypes, final Object[] args) { 412 return InstantiateTransformer.instantiateTransformer(paramTypes, args); 413 } 414 415 /** 416 * Creates a Transformer that uses the passed in Map to transform the input 417 * object (as a simple lookup). 418 * 419 * @param <I> the input type 420 * @param <O> the output type 421 * @param map the map to use to transform the objects 422 * @return the transformer, or {@link ConstantTransformer#nullTransformer()} if the 423 * {@code map} is {@code null} 424 * @see MapTransformer 425 */ 426 public static <I, O> Transformer<I, O> mapTransformer(final Map<? super I, ? extends O> map) { 427 return MapTransformer.mapTransformer(map); 428 } 429 430 /** 431 * Gets a Transformer that invokes a method on the input object. 432 * The method must have no parameters. If the input object is {@code null}, 433 * {@code null} is returned. 434 * 435 * <p> 436 * For example, <code>TransformerUtils.invokerTransformer("getName");</code> 437 * will call the <code>getName</code> method on the input object to 438 * determine the transformer result. 439 * </p> 440 * 441 * @param <I> the input type 442 * @param <O> the output type 443 * @param methodName the method name to call on the input object, may not be null 444 * @return the transformer 445 * @throws NullPointerException if the methodName is null. 446 * @see InvokerTransformer 447 */ 448 public static <I, O> Transformer<I, O> invokerTransformer(final String methodName) { 449 return InvokerTransformer.invokerTransformer(methodName, null, null); 450 } 451 452 /** 453 * Gets a Transformer that invokes a method on the input object. 454 * The method parameters are specified. If the input object is {@code null}, 455 * {@code null} is returned. 456 * 457 * @param <I> the input type 458 * @param <O> the output type 459 * @param methodName the name of the method 460 * @param paramTypes the parameter types 461 * @param args the arguments 462 * @return the transformer 463 * @throws NullPointerException if the method name is null 464 * @throws IllegalArgumentException if the paramTypes and args don't match 465 * @see InvokerTransformer 466 */ 467 public static <I, O> Transformer<I, O> invokerTransformer(final String methodName, final Class<?>[] paramTypes, 468 final Object[] args) { 469 return InvokerTransformer.invokerTransformer(methodName, paramTypes, args); 470 } 471 472 /** 473 * Gets a transformer that returns a <code>java.lang.String</code> 474 * representation of the input object. This is achieved via the 475 * <code>toString</code> method, <code>null</code> returns 'null'. 476 * 477 * @param <T> the input type 478 * @return the transformer 479 * @see StringValueTransformer 480 */ 481 public static <T> Transformer<T, String> stringValueTransformer() { 482 return StringValueTransformer.stringValueTransformer(); 483 } 484 485}