Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ConstructStep |
|
| 3.8333333333333335;3.833 |
1 | /* | |
2 | * Copyright 1999-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 | ||
17 | package org.apache.commons.workflow.core; | |
18 | ||
19 | ||
20 | import java.lang.reflect.Constructor; | |
21 | import org.apache.commons.workflow.Context; | |
22 | import org.apache.commons.workflow.Descriptor; | |
23 | import org.apache.commons.workflow.StepException; | |
24 | import org.apache.commons.workflow.base.DescriptorStep; | |
25 | ||
26 | ||
27 | /** | |
28 | * <p>Create a new object of the specified class, using the constructor that | |
29 | * accepts the arguments specified by the associated <code>Descriptor</code> | |
30 | * objects. The <strong>first</strong> descriptor must identify the | |
31 | * <code>java.lang.Class</code> object to be used to construct the new | |
32 | * object.</p> | |
33 | * | |
34 | * <p><strong>FIXME</strong> - Constructors that take primitive arguments are | |
35 | * not recognized and matched up to the wrapper classes.</p> | |
36 | * | |
37 | * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $ | |
38 | * @author Craig R. McClanahan | |
39 | */ | |
40 | ||
41 | public class ConstructStep extends DescriptorStep { | |
42 | ||
43 | ||
44 | // ----------------------------------------------------------= Constructors | |
45 | ||
46 | ||
47 | /** | |
48 | * Construct a default instance of this Step. | |
49 | */ | |
50 | public ConstructStep() { | |
51 | ||
52 | 0 | super(); |
53 | ||
54 | 0 | } |
55 | ||
56 | ||
57 | /** | |
58 | * Construct an instance of this Step with the specified identifier. | |
59 | * | |
60 | * @param id Step identifier | |
61 | */ | |
62 | public ConstructStep(String id) { | |
63 | ||
64 | 0 | super(); |
65 | 0 | setId(id); |
66 | ||
67 | 0 | } |
68 | ||
69 | ||
70 | /** | |
71 | * Construct an instance of this Step with the specified identifier | |
72 | * and associated Descriptor. | |
73 | * | |
74 | * @param id Step identifier | |
75 | * @param descriptor Initial descriptor | |
76 | */ | |
77 | public ConstructStep(String id, Descriptor descriptor) { | |
78 | ||
79 | 0 | super(); |
80 | 0 | setId(id); |
81 | 0 | addDescriptor(descriptor); |
82 | ||
83 | 0 | } |
84 | ||
85 | ||
86 | // --------------------------------------------------------- Public Methods | |
87 | ||
88 | ||
89 | /** | |
90 | * Perform the executable actions related to this Step, in the context of | |
91 | * the specified Context. | |
92 | * | |
93 | * @param context The Context that is tracking our execution state | |
94 | * | |
95 | * @exception StepException if a processing error has occurred | |
96 | */ | |
97 | public void execute(Context context) throws StepException { | |
98 | ||
99 | // Identify the Class object to be used for object construction | |
100 | 0 | Descriptor descriptors[] = findDescriptors(); |
101 | 0 | if (descriptors.length < 1) |
102 | 0 | throw new StepException |
103 | ("No descriptor for Class to construct", this); | |
104 | 0 | Class clazz = null; |
105 | try { | |
106 | 0 | clazz = (Class) descriptors[0].get(context); |
107 | 0 | if (clazz == null) |
108 | 0 | throw new StepException |
109 | ("No Class selected by first descriptor", this); | |
110 | 0 | } catch (ClassCastException e) { |
111 | 0 | throw new StepException |
112 | ("First descriptor does not select a Class", this); | |
113 | 0 | } |
114 | ||
115 | // Assemble arrays of the argument types and values | |
116 | 0 | Class[] types = new Class[descriptors.length - 1]; |
117 | 0 | Object[] values = new Object[descriptors.length - 1]; |
118 | 0 | for (int i = 1; i < descriptors.length; i++) { |
119 | 0 | values[i-1] = descriptors[i].get(context); |
120 | 0 | types[i-1] = descriptors[i].getType(); |
121 | 0 | if (types[i-1] == null) { |
122 | 0 | if (values[i-1] == null) |
123 | 0 | types[i-1] = Object.class; |
124 | else | |
125 | 0 | types[i-1] = values[i-1].getClass(); |
126 | } | |
127 | } | |
128 | ||
129 | // Find a constructor that accepts this set of types | |
130 | 0 | Constructor constructor = null; |
131 | try { | |
132 | 0 | constructor = clazz.getConstructor(types); |
133 | 0 | } catch (NoSuchMethodException e) { |
134 | 0 | throw new StepException |
135 | ("Cannot find constructor for " + | |
136 | signature(clazz.getName(), types), this); | |
137 | 0 | } |
138 | ||
139 | // Invoke the constructor to create a new object | |
140 | 0 | Object object = null; |
141 | try { | |
142 | 0 | object = constructor.newInstance(values); |
143 | 0 | } catch (Throwable t) { |
144 | 0 | throw new StepException |
145 | ("Exception from constructor " + | |
146 | signature(clazz.getName(), types), t, this); | |
147 | 0 | } |
148 | ||
149 | // Push the new object onto the evaluation stack and return | |
150 | 0 | context.push(object); |
151 | ||
152 | 0 | } |
153 | ||
154 | ||
155 | /** | |
156 | * Render a string representation of this Step. | |
157 | */ | |
158 | public String toString() { | |
159 | ||
160 | 0 | StringBuffer sb = new StringBuffer("<core:construct"); |
161 | 0 | if (getId() != null) { |
162 | 0 | sb.append(" id=\""); |
163 | 0 | sb.append(getId()); |
164 | 0 | sb.append("\""); |
165 | } | |
166 | 0 | sb.append(">"); |
167 | 0 | Descriptor descriptors[] = findDescriptors(); |
168 | 0 | for (int i = 0; i < descriptors.length; i++) |
169 | 0 | sb.append(descriptors[i].toString()); |
170 | 0 | sb.append("</core:construct>"); |
171 | 0 | return (sb.toString()); |
172 | ||
173 | } | |
174 | ||
175 | ||
176 | // ------------------------------------------------------ Protected Methods | |
177 | ||
178 | ||
179 | /** | |
180 | * Return a method signature useful in debugging and exception messages. | |
181 | * | |
182 | * @param name Method name | |
183 | * @param types Parameter types | |
184 | */ | |
185 | protected String signature(String name, Class types[]) { | |
186 | ||
187 | 0 | StringBuffer sb = new StringBuffer(name); |
188 | 0 | sb.append('('); |
189 | 0 | for (int i = 0; i < types.length; i++) { |
190 | 0 | if (i > 0) |
191 | 0 | sb.append(','); |
192 | 0 | sb.append(types[i].getName()); |
193 | } | |
194 | 0 | sb.append(')'); |
195 | 0 | return (sb.toString()); |
196 | ||
197 | } | |
198 | ||
199 | ||
200 | } |