1. /*
  2. * Copyright 2001-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.functors;
  17. import java.io.Serializable;
  18. import java.lang.reflect.InvocationTargetException;
  19. import java.lang.reflect.Method;
  20. import org.apache.commons.collections.FunctorException;
  21. import org.apache.commons.collections.Transformer;
  22. /**
  23. * Transformer implementation that creates a new object instance by reflection.
  24. *
  25. * @since Commons Collections 3.0
  26. * @version $Revision: 1.7 $ $Date: 2004/05/26 21:44:05 $
  27. *
  28. * @author Stephen Colebourne
  29. */
  30. public class InvokerTransformer implements Transformer, Serializable {
  31. /** The serial version */
  32. static final long serialVersionUID = -8653385846894047688L;
  33. /** The method name to call */
  34. private final String iMethodName;
  35. /** The array of reflection parameter types */
  36. private final Class[] iParamTypes;
  37. /** The array of reflection arguments */
  38. private final Object[] iArgs;
  39. /**
  40. * Gets an instance of this transformer calling a specific method with no arguments.
  41. *
  42. * @param methodName the method name to call
  43. * @return an invoker transformer
  44. * @since Commons Collections 3.1
  45. */
  46. public static Transformer getInstance(String methodName) {
  47. if (methodName == null) {
  48. throw new IllegalArgumentException("The method to invoke must not be null");
  49. }
  50. return new InvokerTransformer(methodName);
  51. }
  52. /**
  53. * Gets an instance of this transformer calling a specific method with specific values.
  54. *
  55. * @param methodName the method name to call
  56. * @param paramTypes the parameter types of the method
  57. * @param args the arguments to pass to the method
  58. * @return an invoker transformer
  59. */
  60. public static Transformer getInstance(String methodName, Class[] paramTypes, Object[] args) {
  61. if (methodName == null) {
  62. throw new IllegalArgumentException("The method to invoke must not be null");
  63. }
  64. if (((paramTypes == null) && (args != null))
  65. || ((paramTypes != null) && (args == null))
  66. || ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
  67. throw new IllegalArgumentException("The parameter types must match the arguments");
  68. }
  69. if (paramTypes == null || paramTypes.length == 0) {
  70. return new InvokerTransformer(methodName);
  71. } else {
  72. paramTypes = (Class[]) paramTypes.clone();
  73. args = (Object[]) args.clone();
  74. return new InvokerTransformer(methodName, paramTypes, args);
  75. }
  76. }
  77. /**
  78. * Constructor for no arg instance.
  79. *
  80. * @param methodName the method to call
  81. */
  82. private InvokerTransformer(String methodName) {
  83. super();
  84. iMethodName = methodName;
  85. iParamTypes = null;
  86. iArgs = null;
  87. }
  88. /**
  89. * Constructor that performs no validation.
  90. * Use <code>getInstance</code> if you want that.
  91. *
  92. * @param methodName the method to call
  93. * @param paramTypes the constructor parameter types, not cloned
  94. * @param args the constructor arguments, not cloned
  95. */
  96. public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
  97. super();
  98. iMethodName = methodName;
  99. iParamTypes = paramTypes;
  100. iArgs = args;
  101. }
  102. /**
  103. * Transforms the input to result by invoking a method on the input.
  104. *
  105. * @param input the input object to transform
  106. * @return the transformed result, null if null input
  107. */
  108. public Object transform(Object input) {
  109. if (input == null) {
  110. return null;
  111. }
  112. try {
  113. Class cls = input.getClass();
  114. Method method = cls.getMethod(iMethodName, iParamTypes);
  115. return method.invoke(input, iArgs);
  116. } catch (NoSuchMethodException ex) {
  117. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
  118. } catch (IllegalAccessException ex) {
  119. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
  120. } catch (InvocationTargetException ex) {
  121. throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
  122. }
  123. }
  124. }