Coverage Report - org.apache.commons.pipeline.stage.DynamicLookupStaticMethodStage
 
Classes in this File Line Coverage Branch Coverage Complexity
DynamicLookupStaticMethodStage
51%
19/37
56%
9/16
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.pipeline.stage;
 19  
 
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 
 23  
 import org.apache.commons.pipeline.StageException;
 24  
 
 25  
 /**
 26  
  * <p>
 27  
  * Provide this Stage with a class and a static method name and it will
 28  
  * dynamically look up the appropriate method to call based on the object type.
 29  
  * If the object type is an array, it will assume that the method that needs to
 30  
  * be called contains the method signature as described by the objects in the
 31  
  * array. The object returned from the method call will be exqueued.
 32  
  * </p>
 33  
  *
 34  
  * <p>
 35  
  * The resulting object will be exqueued on the main pipeline if it is not null.
 36  
  * If it is null, we will try to place the original object on the branch
 37  
  * specified by the nullResultBranchKey property. The default for this value is
 38  
  * "nullResult".
 39  
  * </p>
 40  
  */
 41  
 public class DynamicLookupStaticMethodStage extends BaseStage {
 42  
     
 43  
     // Branch upon which the original objects will be enqueued if the defined
 44  
     // Method returned a null result.
 45  
     private String nullResultBranchKey;
 46  
     
 47  
     // Name of the method to call to process the object.
 48  
     private String methodName;
 49  
     
 50  
     // Class containing the method.
 51  
     private Class clazz;
 52  
     
 53  
     /**
 54  
      * Creates a new instance of DynamicLookupStaticMethodStage
 55  
      *
 56  
      * @param clazz
 57  
      *            The class that defines the static method that will be used to
 58  
      *            process objects.
 59  
      * @param methodName
 60  
      *            The name of the method. This method may be overloaded.
 61  
      */
 62  1
     public DynamicLookupStaticMethodStage(Class clazz, String methodName) {
 63  1
         if (clazz == null) throw new IllegalArgumentException("Argument 'clazz' can not be null.");
 64  1
         if (methodName == null) throw new IllegalArgumentException("Argument 'methodName' can not be null.");
 65  
         
 66  1
         this.clazz = clazz;
 67  1
         this.methodName = methodName;
 68  1
     }
 69  
     
 70  
     /**
 71  
      * Creates a new DynamicLookupStaticMethodStage for the specified class and
 72  
      * static method.
 73  
      *
 74  
      * @param className
 75  
      *            The fully qualified class name of the class in which the
 76  
      *            static method that will be used to process objects is defined.
 77  
      * @param methodName
 78  
      *            The name of the method. This method may be overloaded.
 79  
      * @throws ClassNotFoundException
 80  
      *             if the specified class cannot be loaded.
 81  
      */
 82  
     public DynamicLookupStaticMethodStage(String className, String methodName) throws ClassNotFoundException {
 83  0
         this(Thread.currentThread().getContextClassLoader().loadClass(className), methodName);
 84  0
     }
 85  
     
 86  
     /**
 87  
      * <p>
 88  
      * Finds the appropriate method overloading for the method specified by
 89  
      * {@link #getMethodName() methodName}, calls it to process the object, and
 90  
      * exqueues any returned object. If the returned object is null, the
 91  
      * original object is enqueued on the branch specified by the
 92  
      * nullResultBranchKey property.
 93  
      * </p>
 94  
      *
 95  
      * @param obj
 96  
      *            The object to process.
 97  
      */
 98  
     public void process(Object obj) throws StageException {
 99  
         Class[] argTypes;
 100  3
         if (obj.getClass().isArray()) {
 101  1
             Object[] objs = (Object[]) obj;
 102  1
             argTypes = new Class[objs.length];
 103  3
             for (int i = 0; i < objs.length; i++) {
 104  2
                 argTypes[i] = objs[i].getClass();
 105  
             }
 106  1
         } else {
 107  2
             argTypes = new Class[] {obj.getClass()};
 108  
         }
 109  
         
 110  
         try {
 111  3
             Method method = this.clazz.getMethod(methodName, argTypes);
 112  
             
 113  
             // due to the way that varargs work, we need to ensure that we get
 114  
             // the correct compile-time overloading of method.invoke()
 115  3
             Object result = obj.getClass().isArray() ? method.invoke(null, (Object[]) obj) : method.invoke(null, obj);
 116  3
             if (result != null){
 117  3
                 this.emit(result);
 118  0
             } else if (this.nullResultBranchKey != null) {
 119  0
                 this.context.getBranchFeeder(this.nullResultBranchKey).feed(obj);
 120  
             }
 121  0
         } catch (NoSuchMethodException e){
 122  0
             StringBuilder message = new StringBuilder("No acceptable method " + methodName + " found with argument(s) of type: [ ");
 123  0
             for (Class<?> clazz : argTypes) message.append(clazz.getName()).append(" ");
 124  0
             message.append("]");
 125  
             
 126  0
             throw new StageException(this, message.toString() ,e);
 127  0
         } catch (IllegalAccessException e){
 128  0
             throw new StageException(this, e);
 129  0
         } catch (InvocationTargetException e){
 130  0
             throw new StageException(this, e);
 131  3
         }
 132  3
     }
 133  
     
 134  
     /** Returns the name of the method to be executed. */
 135  
     public String getMethodName(){
 136  0
         return this.methodName;
 137  
     }
 138  
     
 139  
     /** Returns the class containing the method to be executed */
 140  
     public Class getMethodClass(){
 141  0
         return this.clazz;
 142  
     }
 143  
     
 144  
     /**
 145  
      * Getter for property nullResultBranchKey.
 146  
      *
 147  
      * @return Value of property nullResultBranchKey.
 148  
      */
 149  
     public String getNullResultBranchKey() {
 150  0
         return this.nullResultBranchKey;
 151  
     }
 152  
     
 153  
     /**
 154  
      * Setter for property nullResultBranchKey.
 155  
      *
 156  
      * @param nullResultBranchKey
 157  
      *            New value of property nullResultBranchKey.
 158  
      */
 159  
     public void setNullResultBranchKey(String nullResultBranchKey) {
 160  0
         this.nullResultBranchKey = nullResultBranchKey;
 161  0
     }
 162  
     
 163  
 }