KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > MacroInstance


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
19 package org.apache.tools.ant.taskdefs;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Locale JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Enumeration JavaDoc;
31
32 import org.apache.tools.ant.BuildException;
33 import org.apache.tools.ant.DynamicAttribute;
34 import org.apache.tools.ant.ProjectHelper;
35 import org.apache.tools.ant.RuntimeConfigurable;
36 import org.apache.tools.ant.Target;
37 import org.apache.tools.ant.Task;
38 import org.apache.tools.ant.TaskContainer;
39 import org.apache.tools.ant.UnknownElement;
40
41 /**
42  * The class to be placed in the ant type definition.
43  * It is given a pointer to the template definition,
44  * and makes a copy of the unknown element, substituting
45  * the parameter values in attributes and text.
46  * @since Ant 1.6
47  */

48 public class MacroInstance extends Task implements DynamicAttribute, TaskContainer {
49     private MacroDef macroDef;
50     private Map JavaDoc map = new HashMap JavaDoc();
51     private Map JavaDoc nsElements = null;
52     private Map JavaDoc presentElements;
53     private Hashtable JavaDoc localAttributes;
54     private String JavaDoc text = null;
55     private String JavaDoc implicitTag = null;
56     private List JavaDoc unknownElements = new ArrayList JavaDoc();
57
58     /**
59      * Called from MacroDef.MyAntTypeDefinition#create()
60      *
61      * @param macroDef a <code>MacroDef</code> value
62      */

63     public void setMacroDef(MacroDef macroDef) {
64         this.macroDef = macroDef;
65     }
66
67     /**
68      * @return the macro definition object for this macro instance.
69      */

70     public MacroDef getMacroDef() {
71         return macroDef;
72     }
73
74     /**
75      * A parameter name value pair as a xml attribute.
76      *
77      * @param name the name of the attribute
78      * @param value the value of the attribute
79      */

80     public void setDynamicAttribute(String JavaDoc name, String JavaDoc value) {
81         map.put(name, value);
82     }
83
84     /**
85      * Method present for BC purposes.
86      * @param name not used
87      * @return nothing
88      * @deprecated since 1.6.x.
89      * @throws BuildException always
90      */

91     public Object JavaDoc createDynamicElement(String JavaDoc name) throws BuildException {
92         throw new BuildException("Not implemented any more");
93     }
94
95     private Map JavaDoc getNsElements() {
96         if (nsElements == null) {
97             nsElements = new HashMap JavaDoc();
98             for (Iterator JavaDoc i = macroDef.getElements().entrySet().iterator();
99                  i.hasNext();) {
100                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
101                 nsElements.put((String JavaDoc) entry.getKey(),
102                                entry.getValue());
103                 MacroDef.TemplateElement te = (MacroDef.TemplateElement)
104                     entry.getValue();
105                 if (te.isImplicit()) {
106                     implicitTag = te.getName();
107                 }
108             }
109         }
110         return nsElements;
111     }
112
113     /**
114      * Add a unknownElement for the macro instances nested elements.
115      *
116      * @param nestedTask a nested element.
117      */

118     public void addTask(Task nestedTask) {
119         unknownElements.add(nestedTask);
120     }
121
122     private void processTasks() {
123         if (implicitTag != null) {
124             return;
125         }
126         for (Iterator JavaDoc i = unknownElements.iterator(); i.hasNext();) {
127             UnknownElement ue = (UnknownElement) i.next();
128             String JavaDoc name = ProjectHelper.extractNameFromComponentName(
129                 ue.getTag()).toLowerCase(Locale.US);
130             if (getNsElements().get(name) == null) {
131                 throw new BuildException("unsupported element " + name);
132             }
133             if (presentElements.get(name) != null) {
134                 throw new BuildException("Element " + name + " already present");
135             }
136             presentElements.put(name, ue);
137         }
138     }
139
140     /**
141      * Embedded element in macro instance
142      */

143     public static class Element implements TaskContainer {
144         private List JavaDoc unknownElements = new ArrayList JavaDoc();
145
146         /**
147          * Add an unknown element (to be snipped into the macroDef instance)
148          *
149          * @param nestedTask an unknown element
150          */

151         public void addTask(Task nestedTask) {
152             unknownElements.add(nestedTask);
153         }
154
155         /**
156          * @return the list of unknown elements
157          */

158         public List JavaDoc getUnknownElements() {
159             return unknownElements;
160         }
161     }
162
163     private static final int STATE_NORMAL = 0;
164     private static final int STATE_EXPECT_BRACKET = 1;
165     private static final int STATE_EXPECT_NAME = 2;
166
167     private String JavaDoc macroSubs(String JavaDoc s, Map JavaDoc macroMapping) {
168         if (s == null) {
169             return null;
170         }
171         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
172         StringBuffer JavaDoc macroName = null;
173
174         int state = STATE_NORMAL;
175         for (int i = 0; i < s.length(); ++i) {
176             char ch = s.charAt(i);
177             switch (state) {
178                 case STATE_NORMAL:
179                     if (ch == '@') {
180                         state = STATE_EXPECT_BRACKET;
181                     } else {
182                         ret.append(ch);
183                     }
184                     break;
185                 case STATE_EXPECT_BRACKET:
186                     if (ch == '{') {
187                         state = STATE_EXPECT_NAME;
188                         macroName = new StringBuffer JavaDoc();
189                     } else if (ch == '@') {
190                         state = STATE_NORMAL;
191                         ret.append('@');
192                     } else {
193                         state = STATE_NORMAL;
194                         ret.append('@');
195                         ret.append(ch);
196                     }
197                     break;
198                 case STATE_EXPECT_NAME:
199                     if (ch == '}') {
200                         state = STATE_NORMAL;
201                         String JavaDoc name = macroName.toString().toLowerCase(Locale.US);
202                         String JavaDoc value = (String JavaDoc) macroMapping.get(name);
203                         if (value == null) {
204                             ret.append("@{");
205                             ret.append(name);
206                             ret.append("}");
207                         } else {
208                             ret.append(value);
209                         }
210                         macroName = null;
211                     } else {
212                         macroName.append(ch);
213                     }
214                     break;
215                 default:
216                     break;
217             }
218         }
219         switch (state) {
220             case STATE_NORMAL:
221                 break;
222             case STATE_EXPECT_BRACKET:
223                 ret.append('@');
224                 break;
225             case STATE_EXPECT_NAME:
226                 ret.append("@{");
227                 ret.append(macroName.toString());
228                 break;
229             default:
230                 break;
231         }
232
233         return ret.toString();
234     }
235
236     /**
237      * Set the text contents for the macro.
238      * @param text the text to be added to the macro.
239      */

240
241     public void addText(String JavaDoc text) {
242         this.text = text;
243     }
244
245     private UnknownElement copy(UnknownElement ue) {
246         UnknownElement ret = new UnknownElement(ue.getTag());
247         ret.setNamespace(ue.getNamespace());
248         ret.setProject(getProject());
249         ret.setQName(ue.getQName());
250         ret.setTaskType(ue.getTaskType());
251         ret.setTaskName(ue.getTaskName());
252         ret.setLocation(
253             macroDef.getBackTrace() ? ue.getLocation() : getLocation());
254         if (getOwningTarget() == null) {
255             Target t = new Target();
256             t.setProject(getProject());
257             ret.setOwningTarget(t);
258         } else {
259             ret.setOwningTarget(getOwningTarget());
260         }
261         RuntimeConfigurable rc = new RuntimeConfigurable(
262             ret, ue.getTaskName());
263         rc.setPolyType(ue.getWrapper().getPolyType());
264         Map JavaDoc m = ue.getWrapper().getAttributeMap();
265         for (Iterator JavaDoc i = m.entrySet().iterator(); i.hasNext();) {
266             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
267             rc.setAttribute(
268                 (String JavaDoc) entry.getKey(),
269                 macroSubs((String JavaDoc) entry.getValue(), localAttributes));
270         }
271         rc.addText(macroSubs(ue.getWrapper().getText().toString(),
272                              localAttributes));
273
274         Enumeration JavaDoc e = ue.getWrapper().getChildren();
275         while (e.hasMoreElements()) {
276             RuntimeConfigurable r = (RuntimeConfigurable) e.nextElement();
277             UnknownElement unknownElement = (UnknownElement) r.getProxy();
278             String JavaDoc tag = unknownElement.getTaskType();
279             if (tag != null) {
280                 tag = tag.toLowerCase(Locale.US);
281             }
282             MacroDef.TemplateElement templateElement =
283                 (MacroDef.TemplateElement) getNsElements().get(tag);
284             if (templateElement == null) {
285                 UnknownElement child = copy(unknownElement);
286                 rc.addChild(child.getWrapper());
287                 ret.addChild(child);
288             } else if (templateElement.isImplicit()) {
289                 if (unknownElements.size() == 0 && !templateElement.isOptional()) {
290                     throw new BuildException(
291                         "Missing nested elements for implicit element "
292                         + templateElement.getName());
293                 }
294                 for (Iterator JavaDoc i = unknownElements.iterator();
295                      i.hasNext();) {
296                     UnknownElement child = copy((UnknownElement) i.next());
297                     rc.addChild(child.getWrapper());
298                     ret.addChild(child);
299                 }
300             } else {
301                 UnknownElement presentElement =
302                     (UnknownElement) presentElements.get(tag);
303                 if (presentElement == null) {
304                     if (!templateElement.isOptional()) {
305                         throw new BuildException(
306                             "Required nested element "
307                             + templateElement.getName() + " missing");
308                     }
309                     continue;
310                 }
311                 String JavaDoc presentText =
312                     presentElement.getWrapper().getText().toString();
313                 if (!"".equals(presentText)) {
314                     rc.addText(macroSubs(presentText, localAttributes));
315                 }
316                 List JavaDoc list = presentElement.getChildren();
317                 if (list != null) {
318                     for (Iterator JavaDoc i = list.iterator();
319                          i.hasNext();) {
320                         UnknownElement child = copy((UnknownElement) i.next());
321                         rc.addChild(child.getWrapper());
322                         ret.addChild(child);
323                     }
324                 }
325             }
326         }
327         return ret;
328     }
329
330     /**
331      * Execute the templates instance.
332      * Copies the unknown element, substitutes the attributes,
333      * and calls perform on the unknown element.
334      *
335      */

336     public void execute() {
337         presentElements = new HashMap JavaDoc();
338         getNsElements();
339         processTasks();
340         localAttributes = new Hashtable JavaDoc();
341         Set JavaDoc copyKeys = new HashSet JavaDoc(map.keySet());
342         for (Iterator JavaDoc i = macroDef.getAttributes().iterator(); i.hasNext();) {
343             MacroDef.Attribute attribute = (MacroDef.Attribute) i.next();
344             String JavaDoc value = (String JavaDoc) map.get(attribute.getName());
345             if (value == null && "description".equals(attribute.getName())) {
346                 value = getDescription();
347             }
348             if (value == null) {
349                 value = attribute.getDefault();
350                 value = macroSubs(value, localAttributes);
351             }
352             if (value == null) {
353                 throw new BuildException(
354                     "required attribute " + attribute.getName() + " not set");
355             }
356             localAttributes.put(attribute.getName(), value);
357             copyKeys.remove(attribute.getName());
358         }
359         if (copyKeys.contains("id")) {
360             copyKeys.remove("id");
361         }
362         if (macroDef.getText() != null) {
363             if (text == null) {
364                 if (!macroDef.getText().getOptional()) {
365                     throw new BuildException(
366                         "required text missing");
367                 }
368                 text = "";
369             }
370             if (macroDef.getText().getTrim()) {
371                 text = text.trim();
372             }
373             localAttributes.put(macroDef.getText().getName(), text);
374         } else {
375             if (text != null && !text.trim().equals("")) {
376                 throw new BuildException(
377                     "The \"" + getTaskName() + "\" macro does not support"
378                     + " nested text data.");
379             }
380         }
381         if (copyKeys.size() != 0) {
382             throw new BuildException(
383                 "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
384                 + copyKeys);
385         }
386
387         // need to set the project on unknown element
388
UnknownElement c = copy(macroDef.getNestedTask());
389         c.init();
390         try {
391             c.perform();
392         } catch (BuildException ex) {
393             if (macroDef.getBackTrace()) {
394                 throw ProjectHelper.addLocationToBuildException(
395                     ex, getLocation());
396             } else {
397                 ex.setLocation(getLocation());
398                 throw ex;
399             }
400         } finally {
401             presentElements = null;
402             localAttributes = null;
403         }
404     }
405 }
406
Popular Tags