Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DynamicLookupStaticMethodStage |
|
| 0.0;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 | } |