KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > flowcontrol > call > InlineForEachTask


1 /**
2  * $Id: InlineForEachTask.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2002-2004 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your option) any
9  * later version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.flowcontrol.call;
30
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33
34 import org.apache.tools.ant.BuildException;
35 import org.apache.tools.ant.ComponentHelper;
36 import org.apache.tools.ant.Project;
37 import org.apache.tools.ant.Task;
38
39 import com.idaremedia.antx.AntXFixture;
40 import com.idaremedia.antx.AntX;
41 import com.idaremedia.antx.helpers.Empties;
42 import com.idaremedia.antx.helpers.SIDs;
43 import com.idaremedia.antx.helpers.Tk;
44 import com.idaremedia.antx.ownhelpers.TaskExaminer;
45 import com.idaremedia.antx.parameters.ExecutionMode;
46 import com.idaremedia.antx.parameters.FixturePassthru;
47
48 /**
49  * Special-case extension of a {@linkplain ForEachTask} task that allows the iteration
50  * steps to be nested inside the foreach taskset itself. This task exists to address some
51  * of the readability and maintenance issues lots of functions-masking-as-targets tend
52  * to create. Usally defined <span class="src">&lt;foreach&gt;</span>.
53  * <p>
54  * To use this task you <em>must</em> define the special AntX step-launch target unless
55  * the mode is set to "local"; see {@linkplain StepLauncherInstallTask}.
56  * <p>
57  * <b>Example Usage:</b><pre>
58  * &lt;target name="preview"&gt;
59  * ...
60  * &lt;foreach name="compile-test" i="build.type" list="debug,opt"
61  * haltiferror="no" tryeach="true"
62  * failproperty="notclean-compile-test"&gt;
63  *
64  * &lt;property name="_rootdir" value="${preview.root}/${build.type}"/&gt;
65  * &lt;callinline targets="--setup.${build.type}"/&gt;
66  *
67  * &lt;property name="_classes" value="${_rootdir}/classes"/&gt;
68  * &lt;mkdir dir="${_classes}"/&gt;
69  *
70  * &lt;javac srcdir="${_source}" destdir="${_classes}"
71  * debug="${javac.isdebug}" deprecation="${javac.isdebug}"
72  * optimize="${javac.isopt}"
73  * .../&gt;
74  * &lt;/foreach&gt;
75  * &lt;/target&gt;
76  * </pre>
77  *
78  * @since JWare/AntX 0.1
79  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
80  * @version 0.5
81  * @.safety single
82  * @.group api,helper
83  * @see StepLauncher
84  * @.caveat An inlined foreach task must be uniquely named within its <em>target's</em>
85  * scope so that a StepLauncher can find it (even it's nested within another task).
86  **/

87
88 public final class InlineForEachTask extends ForEachTask
89     implements InlinedTarget, InlinedTargetContainer
90 {
91     /**
92      * Maximum search depth for nested inlined-foreach tasks. This
93      * limit is hard-coded for now (until it's shown to be useful
94      * as a general parameter).
95      **/

96     public final static int MAX_SEARCH_DEPTH= 3;
97
98
99     /**
100      * Initializes new inline-foreach task.
101      **/

102     public InlineForEachTask()
103     {
104         super(AntX.flow+"foreach");
105     }
106
107
108     /**
109      * Initializes new CV-labeled inline-foreach task.
110      * @param iam CV-label (non-null)
111      **/

112     public InlineForEachTask(String JavaDoc iam)
113     {
114         super(iam);
115     }
116
117
118
119     /**
120      * Sets this task's inline step-name. Must be called before
121      * this task can be executed.
122      * @param name new name (non-null)
123      **/

124     public void setName(String JavaDoc name)
125     {
126         require_(name!=null,"setName- nonzro name");
127         m_name = name;
128     }
129
130
131
132     /**
133      * Returns this task's inline step-name; returns <i>null</i>
134      * if never set.
135      **/

136     public String JavaDoc getName()
137     {
138         return m_name;
139     }
140
141
142
143     /**
144      * Instructs this task what kinds of fixture informaton
145      * should be passed to the child project. By default only
146      * properties are passed on.
147      * @since JWare/AntX 0.4
148      **/

149     public void setPassthru(FixturePassthru passthru)
150     {
151         require_(passthru!=null,"setPassthru- nonzro option");
152         m_passthru = FixturePassthru.from(passthru.getIndex());//NB:normalize
153
}
154
155
156
157     /**
158      * Returns the fixture passthru setting to be used when this
159      * caller runs its targets. Never returns <i>null</i>;
160      * will return <span class="src">PROPERTIES</span> if
161      * not set explicitly.
162      * @since JWare/AntX 0.4
163      **/

164     public final FixturePassthru getPassthruOption()
165     {
166         return m_passthru;
167     }
168
169
170
171     /**
172      * Tells this task to execute self locally like a macrodef.
173      * @param Xmodestring either "local" or "isolated"
174      * @since JWare/AntX 0.5
175      **/

176     public void setMode(String JavaDoc Xmodestring)
177     {
178         require_(Xmodestring!=null,"setMode- nonzro string");
179         m_Xmode = ExecutionMode.from(Xmodestring,m_Xmode);
180         if (asMacrodef() && m_name==null) {
181             m_name = SIDs.next("foreach");
182             m_generatedName = true;
183         }
184     }
185
186
187
188     /**
189      * Returns this task's execution mode. Never returns <i>null</i>;
190      * will return <span class="src">ISOLATED</span> if never set.
191      * @since JWare/AntX 0.5
192      **/

193     public ExecutionMode getMode()
194     {
195         return m_Xmode;
196     }
197
198
199
200     /**
201      * @return True if this foreach should operation like a macrodef.
202      * @since JWare/AntX 0.5
203      **/

204     private boolean asMacrodef()
205     {
206         return ExecutionMode.LOCAL.equals(getMode());
207     }
208
209
210
211     /**
212      * Returns this task's implementation macrodef's name iff is
213      * set to execute in local mode. Will return <i>null</i> if
214      * set to work in isolated mode.
215      * @since JWare/AntX 0.5
216      **/

217     public String JavaDoc getMacroNamesList()
218     {
219         return asMacrodef() ? getName()+"_macrodef" : null;
220     }
221
222
223
224     /**
225      * Returns this task's step-name (can be the string "null").
226      **/

227     public String JavaDoc toString()
228     {
229         return getName();
230     }
231
232
233
234     /**
235      * Allow any task to be nested within this task. Note that there
236      * is no special processing for properties or reference.
237      * @param task task to be added (non-null)
238      **/

239     public void addTask(Task task)
240     {
241         m_nestedTasks.add(task);
242     }
243
244
245
246     /**
247      * Returns this taskset's list of nested tasks.
248      **/

249     protected final List JavaDoc getTasksList()
250     {
251         return m_nestedTasks;
252     }
253
254
255
256     /**
257      * Returns a new array of this taskset's nested tasks.
258      * The array is new, the tasks are live references.
259      **/

260     public Task[] getTasks()
261     {
262         return (Task[])getTasksList().toArray(Empties.EMPTY_TASK_ARRAY);
263     }
264
265
266
267
268     /**
269      * Returns an overlay keeper that redirects to this taskset's
270      * container. Never returns <i>null</i>.
271      * @since JWare/AntX 0.4
272      **/

273     protected OverlayParametersHelper getParametersKeeper()
274     {
275         if (m_paramsHelper==null) {
276             m_paramsHelper= new OverlayParametersHelper(getProject());
277             m_paramsHelper.addOverride(this);
278         }
279         return m_paramsHelper;
280     }
281
282
283
284     /**
285      * Always returns one (1) since the target steps are any tasks
286      * nested within this task itself.
287      **/

288     protected final int getKindOfRunnablesSpecified()
289     {
290         return 1;
291     }
292
293
294
295     /**
296      * Runs this task's nested tasks in order. Each task's
297      * <span class="src">perform()</span> method is called.
298      * @throws BuildException if any nested task does
299      **/

300     protected final void performTheTasksList()
301     {
302         Iterator JavaDoc itr = getTasksList().listIterator();
303         while (itr.hasNext()) {
304             Task nestedTask = (Task)itr.next();
305             nestedTask.perform();
306         }
307     }
308  
309
310
311     /**
312      * Ensures this foreach task has been named.
313      * @throws BuildException if this task has no step-name, loop-
314      * control, or is not in a valid target.
315      * @throws BuildException if is local mode and cannot install a
316      * matching macrodef.
317      **/

318     protected void verifyCanExecute_(String JavaDoc calr)
319         throws BuildException
320     {
321         if (Tk.isWhitespace(getName())) {
322             String JavaDoc ermsg = getAntXMsg("flow.task.needs.name",getTaskName());
323             log(ermsg, Project.MSG_ERR);
324             throw new BuildException(ermsg, getLocation());
325         }
326
327         super.verifyCanExecute_(calr);
328
329         if (asMacrodef()) {
330             if (!m_generatedName) {
331                 String JavaDoc ermsg = getAntXMsg("task.unsupported.attr",
332                     getTaskName()+"(mode=local)","name");
333                 log(ermsg, Project.MSG_ERR);
334                 throw new BuildException(ermsg, getLocation());
335             }
336             installMacrodef();
337         }
338     }
339
340
341
342     /**
343      * Returns a list-of-one TargetCaller that calls back into this
344      * foreach task via its '<i>run</i>' method.
345      * @throws BuildException if unable to create target caller
346      * @see #MAX_SEARCH_DEPTH
347      **/

348     protected List JavaDoc copyOfOrderedTargetCallers()
349         throws BuildException
350     {
351         TargetCaller caller;
352         
353         if (asMacrodef()) {
354             verify_(m_macrodefInstalled!=null,"getCalrs- macrodef inited");
355             MacroInstanceCaller mcaller = new MacroInstanceCaller(this);
356             mcaller.setTarget(m_macrodefInstalled);
357             caller = mcaller;
358         }
359         else {
360             String JavaDoc targetName = StepLauncherCaller.findSpecialTarget(this);
361             caller = StepLauncherCaller.create(this,true,targetName,
362                                           this.getName(),
363                                           InlineForEachTask.class.getName(),
364                                           MAX_SEARCH_DEPTH);
365         }
366
367         transferOverlayParameters(caller);
368
369         List JavaDoc l = AntXFixture.newList(2);
370         l.add(caller);
371
372         return l;
373     }
374
375
376
377     /**
378      * Performs this task's nested tasks from a StepLauncher's call.
379      * Unused if mode is local.
380      * @throws BuildException if any nested task does
381      **/

382     public void run() throws BuildException
383     {
384         performTheTasksList();
385     }
386
387
388
389     /**
390      * Executes foreach taskset. If local inlined, will also try to
391      * remove the macrodef we installed.
392      * @since JWare/AntX 0.5
393      **/

394     public void execute()
395     {
396         boolean uninstallMacrodef = asMacrodef();
397         super.execute();
398
399         if (uninstallMacrodef) {
400             String JavaDoc macroname = getMacroNamesList();
401             ComponentHelper ch = ComponentHelper.getComponentHelper(getProject());
402             Object JavaDoc was = ch.getAntTypeTable().remove(macroname);
403             if (was!=null) {
404                 log("Removed macrodef("+macroname+") from type table",
405                     Project.MSG_DEBUG);
406             } else {
407                 log("Unable to remove macrodef("+macroname+") from type table",
408                     Project.MSG_DEBUG);
409             }
410         }
411     }
412
413
414
415     /**
416      * Installs a macrodef comprised of our internals. This installation
417      * is done once in task's lifetime (on verify). If a foreach is run
418      * repeatedly as part of a macrodef itself, it installs a <em>single</em>
419      * macrodef the first time it is run. Subsequent calls to the foreach's
420      * parent macrodef reuses the previously installed foreach macrodef.
421      **/

422     private void installMacrodef()
423     {
424         if (m_macrodefInstalled==null) {
425             String JavaDoc macroname = getMacroNamesList();
426
427             ComponentHelper ch = ComponentHelper.getComponentHelper(getProject());
428             if (ch.getDefinition(macroname)==null) {
429                 InlineForEachMacroDef macrodefFactory = new InlineForEachMacroDef();
430                 TaskExaminer.initTaskFrom(macrodefFactory,this);
431
432                 macrodefFactory.setName(macroname);
433  
434                 Iterator JavaDoc itr = getTasksList().listIterator();
435                 while (itr.hasNext()) {
436                     Task nestedTask = (Task)itr.next();
437                     macrodefFactory.addTask(nestedTask);
438                 }
439     
440                 log("Installing macrodef("+macrodefFactory.getName()+
441                     ") as foreach implementation.",Project.MSG_DEBUG);
442     
443                 macrodefFactory.perform();
444
445             } else {
446                 log("Reusing existing macrodef("+macroname+
447                     ") as foreach implementation.",Project.MSG_DEBUG);
448             }
449             m_macrodefInstalled = macroname;//NB: latch
450
}
451     }
452
453
454     private FixturePassthru m_passthru = FixturePassthru.PROPERTIES;/* NB: Ant dflt */
455     private String JavaDoc m_name;//NB:required
456
private boolean m_generatedName;
457     private List JavaDoc m_nestedTasks= AntXFixture.newList(10);
458     private ExecutionMode m_Xmode= ExecutionMode.ISOLATED;
459     private String JavaDoc m_macrodefInstalled;//NB:null=> macrodef might need installin'
460
}
461
462 /* end-of-InlineForEachTask.java */
463
Popular Tags