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. import java.util.Collection;
  18. import java.util.Iterator;
  19. import java.util.Map;
  20. import org.apache.commons.collections.functors.ChainedTransformer;
  21. import org.apache.commons.collections.functors.CloneTransformer;
  22. import org.apache.commons.collections.functors.ClosureTransformer;
  23. import org.apache.commons.collections.functors.ConstantTransformer;
  24. import org.apache.commons.collections.functors.EqualPredicate;
  25. import org.apache.commons.collections.functors.ExceptionTransformer;
  26. import org.apache.commons.collections.functors.FactoryTransformer;
  27. import org.apache.commons.collections.functors.InstantiateTransformer;
  28. import org.apache.commons.collections.functors.InvokerTransformer;
  29. import org.apache.commons.collections.functors.MapTransformer;
  30. import org.apache.commons.collections.functors.NOPTransformer;
  31. import org.apache.commons.collections.functors.PredicateTransformer;
  32. import org.apache.commons.collections.functors.StringValueTransformer;
  33. import org.apache.commons.collections.functors.SwitchTransformer;
  34. /**
  35. * <code>TransformerUtils</code> provides reference implementations and
  36. * utilities for the Transformer functor interface. The supplied transformers are:
  37. * <ul>
  38. * <li>Invoker - returns the result of a method call on the input object
  39. * <li>Clone - returns a clone of the input object
  40. * <li>Constant - always returns the same object
  41. * <li>Closure - performs a Closure and returns the input object
  42. * <li>Predicate - returns the result of the predicate as a Boolean
  43. * <li>Factory - returns a new object from a factory
  44. * <li>Chained - chains two or more transformers together
  45. * <li>Switch - calls one transformer based on one or more predicates
  46. * <li>SwitchMap - calls one transformer looked up from a Map
  47. * <li>Instantiate - the Class input object is instantiated
  48. * <li>Map - returns an object from a supplied Map
  49. * <li>Null - always returns null
  50. * <li>NOP - returns the input object, which should be immutable
  51. * <li>Exception - always throws an exception
  52. * <li>StringValue - returns a <code>java.lang.String</code> representation of the input object
  53. * </ul>
  54. * All the supplied transformers are Serializable.
  55. *
  56. * @since Commons Collections 3.0
  57. * @version $Revision: 1.13 $ $Date: 2004/05/26 21:50:52 $
  58. *
  59. * @author Stephen Colebourne
  60. * @author James Carman
  61. */
  62. public class TransformerUtils {
  63. /**
  64. * This class is not normally instantiated.
  65. */
  66. public TransformerUtils() {
  67. super();
  68. }
  69. /**
  70. * Gets a transformer that always throws an exception.
  71. * This could be useful during testing as a placeholder.
  72. *
  73. * @see org.apache.commons.collections.functors.ExceptionTransformer
  74. *
  75. * @return the transformer
  76. */
  77. public static Transformer exceptionTransformer() {
  78. return ExceptionTransformer.INSTANCE;
  79. }
  80. /**
  81. * Gets a transformer that always returns null.
  82. *
  83. * @see org.apache.commons.collections.functors.ConstantTransformer
  84. *
  85. * @return the transformer
  86. */
  87. public static Transformer nullTransformer() {
  88. return ConstantTransformer.NULL_INSTANCE;
  89. }
  90. /**
  91. * Gets a transformer that returns the input object.
  92. * The input object should be immutable to maintain the
  93. * contract of Transformer (although this is not checked).
  94. *
  95. * @see org.apache.commons.collections.functors.NOPTransformer
  96. *
  97. * @return the transformer
  98. */
  99. public static Transformer nopTransformer() {
  100. return NOPTransformer.INSTANCE;
  101. }
  102. /**
  103. * Gets a transformer that returns a clone of the input
  104. * object. The input object will be cloned using one of these
  105. * techniques (in order):
  106. * <ul>
  107. * <li>public clone method
  108. * <li>public copy constructor
  109. * <li>serialization clone
  110. * <ul>
  111. *
  112. * @see org.apache.commons.collections.functors.CloneTransformer
  113. *
  114. * @return the transformer
  115. */
  116. public static Transformer cloneTransformer() {
  117. return CloneTransformer.INSTANCE;
  118. }
  119. /**
  120. * Creates a Transformer that will return the same object each time the
  121. * transformer is used.
  122. *
  123. * @see org.apache.commons.collections.functors.ConstantTransformer
  124. *
  125. * @param constantToReturn the constant object to return each time in the transformer
  126. * @return the transformer.
  127. */
  128. public static Transformer constantTransformer(Object constantToReturn) {
  129. return ConstantTransformer.getInstance(constantToReturn);
  130. }
  131. /**
  132. * Creates a Transformer that calls a Closure each time the transformer is used.
  133. * The transformer returns the input object.
  134. *
  135. * @see org.apache.commons.collections.functors.ClosureTransformer
  136. *
  137. * @param closure the closure to run each time in the transformer, not null
  138. * @return the transformer
  139. * @throws IllegalArgumentException if the closure is null
  140. */
  141. public static Transformer asTransformer(Closure closure) {
  142. return ClosureTransformer.getInstance(closure);
  143. }
  144. /**
  145. * Creates a Transformer that calls a Predicate each time the transformer is used.
  146. * The transformer will return either Boolean.TRUE or Boolean.FALSE.
  147. *
  148. * @see org.apache.commons.collections.functors.PredicateTransformer
  149. *
  150. * @param predicate the predicate to run each time in the transformer, not null
  151. * @return the transformer
  152. * @throws IllegalArgumentException if the predicate is null
  153. */
  154. public static Transformer asTransformer(Predicate predicate) {
  155. return PredicateTransformer.getInstance(predicate);
  156. }
  157. /**
  158. * Creates a Transformer that calls a Factory each time the transformer is used.
  159. * The transformer will return the value returned by the factory.
  160. *
  161. * @see org.apache.commons.collections.functors.FactoryTransformer
  162. *
  163. * @param factory the factory to run each time in the transformer, not null
  164. * @return the transformer
  165. * @throws IllegalArgumentException if the factory is null
  166. */
  167. public static Transformer asTransformer(Factory factory) {
  168. return FactoryTransformer.getInstance(factory);
  169. }
  170. /**
  171. * Create a new Transformer that calls two transformers, passing the result of
  172. * the first into the second.
  173. *
  174. * @see org.apache.commons.collections.functors.ChainedTransformer
  175. *
  176. * @param transformer1 the first transformer
  177. * @param transformer2 the second transformer
  178. * @return the transformer
  179. * @throws IllegalArgumentException if either transformer is null
  180. */
  181. public static Transformer chainedTransformer(Transformer transformer1, Transformer transformer2) {
  182. return ChainedTransformer.getInstance(transformer1, transformer2);
  183. }
  184. /**
  185. * Create a new Transformer that calls each transformer in turn, passing the
  186. * result into the next transformer.
  187. *
  188. * @see org.apache.commons.collections.functors.ChainedTransformer
  189. *
  190. * @param transformers an array of transformers to chain
  191. * @return the transformer
  192. * @throws IllegalArgumentException if the transformers array is null
  193. * @throws IllegalArgumentException if any transformer in the array is null
  194. */
  195. public static Transformer chainedTransformer(Transformer[] transformers) {
  196. return ChainedTransformer.getInstance(transformers);
  197. }
  198. /**
  199. * Create a new Transformer that calls each transformer in turn, passing the
  200. * result into the next transformer. The ordering is that of the iterator()
  201. * method on the collection.
  202. *
  203. * @see org.apache.commons.collections.functors.ChainedTransformer
  204. *
  205. * @param transformers a collection of transformers to chain
  206. * @return the transformer
  207. * @throws IllegalArgumentException if the transformers collection is null
  208. * @throws IllegalArgumentException if any transformer in the collection is null
  209. */
  210. public static Transformer chainedTransformer(Collection transformers) {
  211. return ChainedTransformer.getInstance(transformers);
  212. }
  213. /**
  214. * Create a new Transformer that calls one of two transformers depending
  215. * on the specified predicate.
  216. *
  217. * @see org.apache.commons.collections.functors.SwitchTransformer
  218. *
  219. * @param predicate the predicate to switch on
  220. * @param trueTransformer the transformer called if the predicate is true
  221. * @param falseTransformer the transformer called if the predicate is false
  222. * @return the transformer
  223. * @throws IllegalArgumentException if the predicate is null
  224. * @throws IllegalArgumentException if either transformer is null
  225. */
  226. public static Transformer switchTransformer(Predicate predicate, Transformer trueTransformer, Transformer falseTransformer) {
  227. return SwitchTransformer.getInstance(new Predicate[] { predicate }, new Transformer[] { trueTransformer }, falseTransformer);
  228. }
  229. /**
  230. * Create a new Transformer that calls one of the transformers depending
  231. * on the predicates. The transformer at array location 0 is called if the
  232. * predicate at array location 0 returned true. Each predicate is evaluated
  233. * until one returns true. If no predicates evaluate to true, null is returned.
  234. *
  235. * @see org.apache.commons.collections.functors.SwitchTransformer
  236. *
  237. * @param predicates an array of predicates to check
  238. * @param transformers an array of transformers to call
  239. * @return the transformer
  240. * @throws IllegalArgumentException if the either array is null
  241. * @throws IllegalArgumentException if the either array has 0 elements
  242. * @throws IllegalArgumentException if any element in the arrays is null
  243. * @throws IllegalArgumentException if the arrays are different sizes
  244. */
  245. public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers) {
  246. return SwitchTransformer.getInstance(predicates, transformers, null);
  247. }
  248. /**
  249. * Create a new Transformer that calls one of the transformers depending
  250. * on the predicates. The transformer at array location 0 is called if the
  251. * predicate at array location 0 returned true. Each predicate is evaluated
  252. * until one returns true. If no predicates evaluate to true, the default
  253. * transformer is called. If the default transformer is null, null is returned.
  254. *
  255. * @see org.apache.commons.collections.functors.SwitchTransformer
  256. *
  257. * @param predicates an array of predicates to check
  258. * @param transformers an array of transformers to call
  259. * @param defaultTransformer the default to call if no predicate matches, null means return null
  260. * @return the transformer
  261. * @throws IllegalArgumentException if the either array is null
  262. * @throws IllegalArgumentException if the either array has 0 elements
  263. * @throws IllegalArgumentException if any element in the arrays is null
  264. * @throws IllegalArgumentException if the arrays are different sizes
  265. */
  266. public static Transformer switchTransformer(Predicate[] predicates, Transformer[] transformers, Transformer defaultTransformer) {
  267. return SwitchTransformer.getInstance(predicates, transformers, defaultTransformer);
  268. }
  269. /**
  270. * Create a new Transformer that calls one of the transformers depending
  271. * on the predicates.
  272. * <p>
  273. * The Map consists of Predicate keys and Transformer values. A transformer
  274. * is called if its matching predicate returns true. Each predicate is evaluated
  275. * until one returns true. If no predicates evaluate to true, the default
  276. * transformer is called. The default transformer is set in the map with a
  277. * null key. If no default transformer is set, null will be returned in a default
  278. * case. The ordering is that of the iterator() method on the entryset collection
  279. * of the map.
  280. *
  281. * @see org.apache.commons.collections.functors.SwitchTransformer
  282. *
  283. * @param predicatesAndTransformers a map of predicates to transformers
  284. * @return the transformer
  285. * @throws IllegalArgumentException if the map is null
  286. * @throws IllegalArgumentException if the map is empty
  287. * @throws IllegalArgumentException if any transformer in the map is null
  288. * @throws ClassCastException if the map elements are of the wrong type
  289. */
  290. public static Transformer switchTransformer(Map predicatesAndTransformers) {
  291. return SwitchTransformer.getInstance(predicatesAndTransformers);
  292. }
  293. /**
  294. * Create a new Transformer that uses the input object as a key to find the
  295. * transformer to call.
  296. * <p>
  297. * The Map consists of object keys and Transformer values. A transformer
  298. * is called if the input object equals the key. If there is no match, the
  299. * default transformer is called. The default transformer is set in the map
  300. * using a null key. If no default is set, null will be returned in a default case.
  301. *
  302. * @see org.apache.commons.collections.functors.SwitchTransformer
  303. *
  304. * @param objectsAndTransformers a map of objects to transformers
  305. * @return the transformer
  306. * @throws IllegalArgumentException if the map is null
  307. * @throws IllegalArgumentException if the map is empty
  308. * @throws IllegalArgumentException if any transformer in the map is null
  309. */
  310. public static Transformer switchMapTransformer(Map objectsAndTransformers) {
  311. Transformer[] trs = null;
  312. Predicate[] preds = null;
  313. if (objectsAndTransformers == null) {
  314. throw new IllegalArgumentException("The object and transformer map must not be null");
  315. }
  316. Transformer def = (Transformer) objectsAndTransformers.remove(null);
  317. int size = objectsAndTransformers.size();
  318. trs = new Transformer[size];
  319. preds = new Predicate[size];
  320. int i = 0;
  321. for (Iterator it = objectsAndTransformers.entrySet().iterator(); it.hasNext();) {
  322. Map.Entry entry = (Map.Entry) it.next();
  323. preds[i] = EqualPredicate.getInstance(entry.getKey());
  324. trs[i] = (Transformer) entry.getValue();
  325. i++;
  326. }
  327. return switchTransformer(preds, trs, def);
  328. }
  329. /**
  330. * Gets a Transformer that expects an input Class object that it will instantiate.
  331. *
  332. * @see org.apache.commons.collections.functors.InstantiateTransformer
  333. *
  334. * @return the transformer
  335. */
  336. public static Transformer instantiateTransformer() {
  337. return InstantiateTransformer.NO_ARG_INSTANCE;
  338. }
  339. /**
  340. * Creates a Transformer that expects an input Class object that it will
  341. * instantiate. The constructor used is determined by the arguments specified
  342. * to this method.
  343. *
  344. * @see org.apache.commons.collections.functors.InstantiateTransformer
  345. *
  346. * @param paramTypes parameter types for the constructor, can be null
  347. * @param args the arguments to pass to the constructor, can be null
  348. * @return the transformer
  349. * @throws IllegalArgumentException if the paramTypes and args don't match
  350. */
  351. public static Transformer instantiateTransformer(Class[] paramTypes, Object[] args) {
  352. return InstantiateTransformer.getInstance(paramTypes, args);
  353. }
  354. /**
  355. * Creates a Transformer that uses the passed in Map to transform the input
  356. * object (as a simple lookup).
  357. *
  358. * @see org.apache.commons.collections.functors.MapTransformer
  359. *
  360. * @param map the map to use to transform the objects
  361. * @return the transformer
  362. * @throws IllegalArgumentException if the map is null
  363. */
  364. public static Transformer mapTransformer(Map map) {
  365. return MapTransformer.getInstance(map);
  366. }
  367. /**
  368. * Gets a Transformer that invokes a method on the input object.
  369. * The method must have no parameters. If the input object is null,
  370. * null is returned.
  371. * <p>
  372. * For example, <code>TransformerUtils.invokerTransformer("getName");</code>
  373. * will call the <code>getName/code> method on the input object to
  374. * determine the transformer result.
  375. *
  376. * @see org.apache.commons.collections.functors.InvokerTransformer
  377. *
  378. * @param methodName the method name to call on the input object, may not be null
  379. * @return the transformer
  380. * @throws IllegalArgumentException if the methodName is null.
  381. */
  382. public static Transformer invokerTransformer(String methodName){
  383. return InvokerTransformer.getInstance(methodName, null, null);
  384. }
  385. /**
  386. * Gets a Transformer that invokes a method on the input object.
  387. * The method parameters are specified. If the input object is null,
  388. * null is returned.
  389. *
  390. * @see org.apache.commons.collections.functors.InvokerTransformer
  391. *
  392. * @param methodName the name of the method
  393. * @param paramTypes the parameter types
  394. * @param args the arguments
  395. * @return the transformer
  396. * @throws IllegalArgumentException if the method name is null
  397. * @throws IllegalArgumentException if the paramTypes and args don't match
  398. */
  399. public static Transformer invokerTransformer(String methodName, Class[] paramTypes, Object[] args){
  400. return InvokerTransformer.getInstance(methodName, paramTypes, args);
  401. }
  402. /**
  403. * Gets a transformer that returns a <code>java.lang.String</code>
  404. * representation of the input object. This is achieved via the
  405. * <code>toString</code> method, <code>null</code> returns 'null'.
  406. *
  407. * @see org.apache.commons.collections.functors.StringValueTransformer
  408. *
  409. * @return the transformer
  410. */
  411. public static Transformer stringValueTransformer() {
  412. return StringValueTransformer.INSTANCE;
  413. }
  414. }