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