View Javadoc

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          super();
53  
54      }
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          super();
65          setId(id);
66  
67      }
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          super();
80          setId(id);
81          addDescriptor(descriptor);
82  
83      }
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         Descriptor descriptors[] = findDescriptors();
101         if (descriptors.length < 1)
102             throw new StepException
103                 ("No descriptor for Class to construct", this);
104         Class clazz = null;
105         try {
106             clazz = (Class) descriptors[0].get(context);
107             if (clazz == null)
108                 throw new StepException
109                     ("No Class selected by first descriptor", this);
110         } catch (ClassCastException e) {
111             throw new StepException
112                 ("First descriptor does not select a Class", this);
113         }
114 
115         // Assemble arrays of the argument types and values
116         Class[] types = new Class[descriptors.length - 1];
117         Object[] values = new Object[descriptors.length - 1];
118         for (int i = 1; i < descriptors.length; i++) {
119             values[i-1] = descriptors[i].get(context);
120             types[i-1] = descriptors[i].getType();
121             if (types[i-1] == null) {
122                 if (values[i-1] == null)
123                     types[i-1] = Object.class;
124                 else
125                     types[i-1] = values[i-1].getClass();
126             }
127         }
128 
129         // Find a constructor that accepts this set of types
130         Constructor constructor = null;
131         try {
132             constructor = clazz.getConstructor(types);
133         } catch (NoSuchMethodException e) {
134             throw new StepException
135                 ("Cannot find constructor for " +
136                  signature(clazz.getName(), types), this);
137         }
138 
139         // Invoke the constructor to create a new object
140         Object object = null;
141         try {
142             object = constructor.newInstance(values);
143         } catch (Throwable t) {
144             throw new StepException
145                 ("Exception from constructor " +
146                  signature(clazz.getName(), types), t, this);
147         }
148 
149         // Push the new object onto the evaluation stack and return
150         context.push(object);
151 
152     }
153 
154 
155     /**
156      * Render a string representation of this Step.
157      */
158     public String toString() {
159 
160         StringBuffer sb = new StringBuffer("<core:construct");
161         if (getId() != null) {
162             sb.append(" id=\"");
163             sb.append(getId());
164             sb.append("\"");
165         }
166         sb.append(">");
167         Descriptor descriptors[] = findDescriptors();
168         for (int i = 0; i < descriptors.length; i++)
169             sb.append(descriptors[i].toString());
170         sb.append("</core:construct>");
171         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         StringBuffer sb = new StringBuffer(name);
188         sb.append('(');
189         for (int i = 0; i < types.length; i++) {
190             if (i > 0)
191                 sb.append(',');
192             sb.append(types[i].getName());
193         }
194         sb.append(')');
195         return (sb.toString());
196 
197     }
198 
199 
200 }