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     */
017    
018    package org.apache.commons.pipeline.stage;
019    
020    import java.lang.reflect.InvocationTargetException;
021    import java.lang.reflect.Method;
022    
023    import org.apache.commons.pipeline.StageException;
024    
025    /**
026     * Runs a static method with the object (or array) being processed. The returned object 
027     * will be exqueued on the main pipeline if it is not null. If the returned
028     * object is null, this stage will attempt to place the original object on the 
029     * branch specified by {@link #setNullResultBranchTag(String)}.
030     */
031    public class InvokeStaticMethodStage extends BaseStage {
032        
033        // Branch upon which the original objects will be enqueued if the defined
034        // Method returned a null result.
035        private String nullResultBranchKey;
036    
037        // Method used to process objects in the queue
038        private Method method;
039        
040        /**
041         * Creates a new instance of InvokeStaticMethodStage
042         */
043        public InvokeStaticMethodStage(Method method) {
044            super();
045            this.method = method;
046        }
047        
048        /** 
049         * Convenience method to create the new stage with String description of className, methodName and argumentType
050         *
051         * @param className The fully qualified class name, such as "java.lang.String" of the class in which the method resides
052         * @param methodName The name of the method
053         * @param argumentType The argument type of the method (Sorry, this doesn't support multiple argument methods)
054         */
055        public InvokeStaticMethodStage(String className, String methodName, String... argumentTypeNames) throws ClassNotFoundException, NoSuchMethodException {
056            Class clazz = InvokeStaticMethodStage.class.getClassLoader().loadClass(className);
057            Class[] argTypes = new Class[argumentTypeNames.length];
058            for (int i = 0; i < argumentTypeNames.length; i++) {
059                argTypes[i] = Class.forName(argumentTypeNames[i]);
060            }
061            
062            this.method = clazz.getMethod(methodName, argTypes);
063        }
064        
065        /** 
066         * Returns the Method object for the method that will be used to process
067         * objects in the queue.
068         */
069        public Method getMethod(){
070            return this.method;
071        }
072        
073        /** 
074         * <p>Calls the defined static method and exqueues the returned object if it is 
075         * not null, otherwise placing the original object on the branch specified
076         * by the nullResultBranchKey property if nullResultBranchKey is not null.</p>
077         *
078         * @param obj The object to be processed.
079         */
080        public void process(Object obj) throws StageException {
081            try {
082                Object result = this.method.invoke(null, obj);
083                if (result != null){
084                    this.emit(result);
085                } else if (nullResultBranchKey != null) {
086                    this.context.getBranchFeeder(nullResultBranchKey).feed(obj);
087                }
088            } catch (IllegalAccessException e){
089                throw new StageException(this, e);
090            } catch (InvocationTargetException e){
091                throw new StageException(this, e);
092            }       
093        }
094    
095        /**
096         * Getter for property nullResultBranchKey.
097         *
098         * @return Value of property nullResultBranchKey.
099         */
100        public String getNullResultBranchKey() {
101            return this.nullResultBranchKey;
102        }
103    
104        /**
105         * Setter for property nullResultBranchKey. If set to null (default) 
106         * then objects generating null results are simply dropped from the stream.
107         *
108         * @param nullResultBranchKey New value of property nullResultBranchKey.
109         */
110        public void setNullResultBranchKey(String nullResultBranchKey) {
111            this.nullResultBranchKey = nullResultBranchKey;
112        }
113    }