KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > jobs > structural > ForEachJob


1 package org.oddjob.jobs.structural;
2
3 import java.io.ByteArrayInputStream JavaDoc;
4 import java.io.ByteArrayOutputStream JavaDoc;
5 import java.util.ArrayList JavaDoc;
6 import java.util.Arrays JavaDoc;
7 import java.util.List JavaDoc;
8
9 import org.oddjob.Stoppable;
10 import org.oddjob.arooa.ArooaHandler;
11 import org.oddjob.arooa.ArooaContext;
12 import org.oddjob.arooa.ArooaConstants;
13 import org.oddjob.arooa.handlers.DefaultComponentHandler;
14 import org.oddjob.arooa.handlers.MainHandler;
15 import org.oddjob.arooa.handlers.SkipLevelHandler;
16 import org.oddjob.arooa.handlers.XmlHandler;
17 import org.oddjob.arooa.registry.ComponentRegistry;
18 import org.oddjob.arooa.registry.Path;
19 import org.oddjob.arooa.xml.XMLDefinitionHelper;
20 import org.oddjob.framework.StructuralJob;
21 import org.xml.sax.InputSource JavaDoc;
22
23
24 /**
25  * @oddjob.description A job which executes its child jobs for
26  * each of the provided values. The child job can access the current
27  * value using the psudo property 'current' to gain access to the
28  * current value. The psudo property 'index' is also available.
29  * <p>
30  * The return state of this job depends on the return state
31  * of the children (like {@link SequentialJob}). Hard resetting this job
32  * will cause the children to be destroyed and recreated on the next run
33  * (with possibly new values). Soft resetting this job will reset the
34  * children but when re-run will not reconfigure the values.
35  *
36  *
37  * @oddjob.example
38  *
39  * <pre><code>
40  * &lt;oddjob id="this"&gt;
41  * &lt;foreach id="copy-reps"&gt;
42  * &lt;values&gt;
43  * &lt;file file="${this.dir}/data/demo1.rep"/&gt;
44  * &lt;file file="${this.dir}/data/demo2.rep"/&gt;
45  * &lt;file file="${this.dir}/data/demo3.rep"/&gt;
46  * &lt;/values&gt;
47  * &lt;child&gt;
48  * &lt;copy from="${copy-reps.current}"
49  * to="${this.dir}/work"/&gt;
50  * &lt;/child&gt;
51  * &lt;/foreach&gt;
52  * &lt;/oddjob&gt;
53  * </code></pre>
54  */

55
56 public class ForEachJob extends StructuralJob
57 implements Stoppable {
58     
59     /**
60      * @oddjob.property values
61      * @oddjob.description Any value.
62      * @oddjob.required No.
63      */

64     private List JavaDoc types = new ArrayList JavaDoc();
65             
66     /**
67      * @oddjob.property
68      * @oddjob.description The current value
69      * @oddjob.required R/O.
70      */

71     private Object JavaDoc current;
72
73     /**
74      * @oddjob.property
75      * @oddjob.description The current index in the
76      * values.
77      * @oddjob.required R/O.
78      */

79     private int index;
80         
81     /**
82      * @oddjob.property
83      * @oddjob.description If true this job will only load the
84      * child jobs for each value - it will not run them. Useful for
85      * testing scripts.
86      * @oddjob.required No.
87      */

88     private boolean loadOnly;
89     
90     private ByteArrayOutputStream JavaDoc storedXml;
91     private ArooaContext storedContext;
92     private ComponentRegistry realRegisty;
93     private String JavaDoc id;
94     
95     private volatile boolean loaded;
96     
97     
98     /**
99      * @oddjob.element child
100      * @oddjob.description The child to execute for each type.
101      * @oddjob.required Yes.
102      */

103     public void addComponentChild(Runnable JavaDoc child) {
104         childHelper.addChild(child);
105     }
106     
107     /**
108      * The current value.
109      *
110      * @return The current value.
111      */

112     public Object JavaDoc getCurrent() {
113         return current;
114     }
115     
116     /**
117      * Add a type. This will be called during parsing by the
118      * handler to add a type for each element.
119      *
120      * @param type The type.
121      */

122     public void setValues(Object JavaDoc[] values) {
123         lock.accquire("Setting values");
124         try {
125             types = Arrays.asList(values);
126         } finally {
127             lock.release();
128         }
129     }
130
131     protected void load() {
132         logger().debug("Creating children from: " + storedXml.toString());
133         
134         // load child jobs for each value
135
for (int i = 0; i < types.size(); ++i) {
136             Object JavaDoc o = types.get(i);
137             logger().debug("creating child for [" + o + "]");
138             PsudoRegistry pr = new PsudoRegistry(i, o);
139             storedContext.set(ArooaConstants.COMPONENT_REGISTRY, pr);
140             storedContext.set(ArooaConstants.ELEMENT_NAME, "child");
141             XMLDefinitionHelper ph = new XMLDefinitionHelper(storedContext);
142             ph.parse(new InputSource JavaDoc(new ByteArrayInputStream JavaDoc(storedXml.toByteArray())),
143                     new MainHandler(new SkipLevelHandler(new DefaultComponentHandler())));
144         }
145         childHelper.initialise();
146         loaded = true;
147     }
148     
149     public boolean configure() {
150         // don't configure if loaded (will have been configured)
151
// once before loading.
152
if (loaded) {
153             return true;
154         }
155         return super.configure();
156     }
157     
158     /*
159      * (non-Javadoc)
160      * @see org.oddjob.jobs.AbstractJob#execute()
161      */

162     protected void execute() throws Exception JavaDoc {
163         if (types == null) {
164             throw new IllegalStateException JavaDoc("No values supplied.");
165         }
166         if (storedXml.size() == 0) {
167             throw new IllegalStateException JavaDoc("No child jobs to run");
168         }
169         if (!loaded) {
170             load();
171         }
172         if (loadOnly) {
173             return;
174         }
175
176         // execute
177
Object JavaDoc[] children = childHelper.getChildren();
178         for (index = 0; index < types.size() && !stop; ++index) {
179             current = types.get(index);
180             if (childHelper.anyNotComplete()) {
181                 return;
182             }
183             if (childHelper.anyExceptions() != null) {
184                 return;
185             }
186             
187             Runnable JavaDoc job = (Runnable JavaDoc) children[index];
188             job.run();
189         }
190     }
191         
192     /**
193      * Provide our own handler for the child element.
194      *
195      * @param context The context.
196      * @return Our handler.
197      */

198     public ArooaHandler handlerForChild(ArooaContext context) {
199         storedXml = new ByteArrayOutputStream JavaDoc();
200         storedContext = context;
201         realRegisty = (ComponentRegistry) context.get(ArooaConstants.COMPONENT_REGISTRY);
202         return new XmlHandler(storedXml);
203     }
204     
205     /**
206      * @return Returns the index.
207      */

208     public int getIndex() {
209         return index;
210     }
211         
212     /**
213      * This povides a bean for current properties.
214      */

215     public static class LocalBean {
216         private final int index;
217         private final Object JavaDoc current;
218         LocalBean (int index, Object JavaDoc value) {
219             this.index = index;
220             this.current = value;
221         }
222         public Object JavaDoc getCurrent() {
223             return current;
224         }
225         public int getIndex() {
226             return index;
227         }
228     }
229     
230     public class PsudoRegistry extends ComponentRegistry {
231                 
232         PsudoRegistry(int index, Object JavaDoc value) {
233             if (id != null) {
234                 register(id, new LocalBean(index, value));
235             }
236         }
237                 
238         /**
239          * First try our local registry then the parent.
240          *
241          */

242         public Object JavaDoc objectForPath(Path path) {
243             Object JavaDoc component = super.objectForPath(path);
244             if (component == null) {
245                 return realRegisty.objectForPath(path);
246             }
247             return component;
248         }
249                 
250         /**
251          * This stops serialisation working for child components. Need to revisit
252          * this if it becomes a requirement!
253          */

254         public String JavaDoc getIdForComponent(Object JavaDoc component) {
255             return null;
256         }
257     }
258     
259     /**
260      * @param id The id to set.
261      */

262     public void setId(String JavaDoc id) {
263         this.id = id;
264     }
265     /**
266      * @return Returns the onlyLoad.
267      */

268     public boolean isLoadOnly() {
269         return loadOnly;
270     }
271     /**
272      * @param onlyLoad The onlyLoad to set.
273      */

274     public void setLoadOnly(boolean onlyLoad) {
275         this.loadOnly = onlyLoad;
276     }
277
278     /**
279      * Perform a hard reset on the job.
280      */

281     public void hardReset() {
282         lock.accquire("Hard Reset in progress.");
283         try {
284             childHelper.destroyAll();
285             stop = false;
286             loaded = false;
287         } finally {
288             lock.release();
289         }
290     }
291 }
292
293
Popular Tags