source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 13.6 KB
Line 
1/*
2 * Copyright 2003-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
18package org.apache.tools.ant.taskdefs;
19
20import java.util.ArrayList;
21import java.util.List;
22import java.util.Iterator;
23import java.util.Locale;
24import java.util.Map;
25import java.util.Set;
26import java.util.HashSet;
27import java.util.HashMap;
28import java.util.Hashtable;
29import java.util.Enumeration;
30
31import org.apache.tools.ant.BuildException;
32import org.apache.tools.ant.DynamicAttribute;
33import org.apache.tools.ant.ProjectHelper;
34import org.apache.tools.ant.RuntimeConfigurable;
35import org.apache.tools.ant.Target;
36import org.apache.tools.ant.Task;
37import org.apache.tools.ant.TaskContainer;
38import org.apache.tools.ant.UnknownElement;
39
40/**
41 * The class to be placed in the ant type definition.
42 * It is given a pointer to the template definition,
43 * and makes a copy of the unknown element, substituting
44 * the parameter values in attributes and text.
45 * @since Ant 1.6
46 */
47public class MacroInstance extends Task implements DynamicAttribute, TaskContainer {
48 private MacroDef macroDef;
49 private Map map = new HashMap();
50 private Map nsElements = null;
51 private Map presentElements;
52 private Hashtable localProperties;
53 private String text = null;
54 private String implicitTag = null;
55 private List unknownElements = new ArrayList();
56
57 /**
58 * Called from MacroDef.MyAntTypeDefinition#create()
59 *
60 * @param macroDef a <code>MacroDef</code> value
61 */
62 public void setMacroDef(MacroDef macroDef) {
63 this.macroDef = macroDef;
64 }
65
66 /**
67 * @return the macro definition object for this macro instance.
68 */
69 public MacroDef getMacroDef() {
70 return macroDef;
71 }
72
73 /**
74 * A parameter name value pair as a xml attribute.
75 *
76 * @param name the name of the attribute
77 * @param value the value of the attribute
78 */
79 public void setDynamicAttribute(String name, String value) {
80 map.put(name, value);
81 }
82
83 /**
84 * Method present for BC purposes.
85 * @param name not used
86 * @return nothing
87 * @deprecated
88 * @throws BuildException always
89 */
90 public Object createDynamicElement(String name) throws BuildException {
91 throw new BuildException("Not implemented any more");
92 }
93
94 private Map getNsElements() {
95 if (nsElements == null) {
96 nsElements = new HashMap();
97 for (Iterator i = macroDef.getElements().entrySet().iterator();
98 i.hasNext();) {
99 Map.Entry entry = (Map.Entry) i.next();
100 nsElements.put((String) entry.getKey(),
101 entry.getValue());
102 MacroDef.TemplateElement te = (MacroDef.TemplateElement)
103 entry.getValue();
104 if (te.isImplicit()) {
105 implicitTag = te.getName();
106 }
107 }
108 }
109 return nsElements;
110 }
111
112 /**
113 * Add a unknownElement for the macro instances nested elements.
114 *
115 * @param nestedTask a nested element.
116 */
117 public void addTask(Task nestedTask) {
118 unknownElements.add(nestedTask);
119 }
120
121 private void processTasks() {
122 if (implicitTag != null) {
123 return;
124 }
125 for (Iterator i = unknownElements.iterator(); i.hasNext();) {
126 UnknownElement ue = (UnknownElement) i.next();
127 String name = ProjectHelper.extractNameFromComponentName(
128 ue.getTag()).toLowerCase(Locale.US);
129 if (getNsElements().get(name) == null) {
130 throw new BuildException("unsupported element " + name);
131 }
132 if (presentElements.get(name) != null) {
133 throw new BuildException("Element " + name + " already present");
134 }
135 presentElements.put(name, ue.getChildren());
136 }
137 }
138
139 /**
140 * Embedded element in macro instance
141 */
142 public static class Element implements TaskContainer {
143 private List unknownElements = new ArrayList();
144
145 /**
146 * Add an unknown element (to be snipped into the macroDef instance)
147 *
148 * @param nestedTask an unknown element
149 */
150 public void addTask(Task nestedTask) {
151 unknownElements.add(nestedTask);
152 }
153
154 /**
155 * @return the list of unknown elements
156 */
157 public List getUnknownElements() {
158 return unknownElements;
159 }
160 }
161
162 private static final int STATE_NORMAL = 0;
163 private static final int STATE_EXPECT_BRACKET = 1;
164 private static final int STATE_EXPECT_NAME = 2;
165
166 private String macroSubs(String s, Map macroMapping) {
167 if (s == null) {
168 return null;
169 }
170 StringBuffer ret = new StringBuffer();
171 StringBuffer macroName = null;
172 boolean inMacro = false;
173 int state = STATE_NORMAL;
174 for (int i = 0; i < s.length(); ++i) {
175 char ch = s.charAt(i);
176 switch (state) {
177 case STATE_NORMAL:
178 if (ch == '@') {
179 state = STATE_EXPECT_BRACKET;
180 } else {
181 ret.append(ch);
182 }
183 break;
184 case STATE_EXPECT_BRACKET:
185 if (ch == '{') {
186 state = STATE_EXPECT_NAME;
187 macroName = new StringBuffer();
188 } else if (ch == '@') {
189 state = STATE_NORMAL;
190 ret.append('@');
191 } else {
192 state = STATE_NORMAL;
193 ret.append('@');
194 ret.append(ch);
195 }
196 break;
197 case STATE_EXPECT_NAME:
198 if (ch == '}') {
199 state = STATE_NORMAL;
200 String name = macroName.toString().toLowerCase(Locale.US);
201 String value = (String) macroMapping.get(name);
202 if (value == null) {
203 ret.append("@{" + name + "}");
204 } else {
205 ret.append(value);
206 }
207 macroName = null;
208 } else {
209 macroName.append(ch);
210 }
211 break;
212 default:
213 break;
214 }
215 }
216 switch (state) {
217 case STATE_NORMAL:
218 break;
219 case STATE_EXPECT_BRACKET:
220 ret.append('@');
221 break;
222 case STATE_EXPECT_NAME:
223 ret.append("@{");
224 ret.append(macroName.toString());
225 break;
226 default:
227 break;
228 }
229
230 return ret.toString();
231 }
232
233 /**
234 * Set the text contents for the macro.
235 * @param text the text to be added to the macro.
236 */
237
238 public void addText(String text) {
239 this.text = text;
240 }
241
242 private UnknownElement copy(UnknownElement ue) {
243 UnknownElement ret = new UnknownElement(ue.getTag());
244 ret.setNamespace(ue.getNamespace());
245 ret.setProject(getProject());
246 ret.setQName(ue.getQName());
247 ret.setTaskType(ue.getTaskType());
248 ret.setTaskName(ue.getTaskName());
249 ret.setLocation(ue.getLocation());
250 if (getOwningTarget() == null) {
251 Target t = new Target();
252 t.setProject(getProject());
253 ret.setOwningTarget(t);
254 } else {
255 ret.setOwningTarget(getOwningTarget());
256 }
257 RuntimeConfigurable rc = new RuntimeConfigurable(
258 ret, ue.getTaskName());
259 rc.setPolyType(ue.getWrapper().getPolyType());
260 Map map = ue.getWrapper().getAttributeMap();
261 for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
262 Map.Entry entry = (Map.Entry) i.next();
263 rc.setAttribute(
264 (String) entry.getKey(),
265 macroSubs((String) entry.getValue(), localProperties));
266 }
267 rc.addText(macroSubs(ue.getWrapper().getText().toString(),
268 localProperties));
269
270 Enumeration e = ue.getWrapper().getChildren();
271 while (e.hasMoreElements()) {
272 RuntimeConfigurable r = (RuntimeConfigurable) e.nextElement();
273 UnknownElement unknownElement = (UnknownElement) r.getProxy();
274 String tag = unknownElement.getTaskType();
275 if (tag != null) {
276 tag = tag.toLowerCase(Locale.US);
277 }
278 MacroDef.TemplateElement templateElement =
279 (MacroDef.TemplateElement) getNsElements().get(tag);
280 if (templateElement == null) {
281 UnknownElement child = copy(unknownElement);
282 rc.addChild(child.getWrapper());
283 ret.addChild(child);
284 } else if (templateElement.isImplicit()) {
285 if (unknownElements.size() == 0 && !templateElement.isOptional()) {
286 throw new BuildException(
287 "Missing nested elements for implicit element "
288 + templateElement.getName());
289 }
290 for (Iterator i = unknownElements.iterator();
291 i.hasNext();) {
292 UnknownElement child = (UnknownElement) i.next();
293 rc.addChild(child.getWrapper());
294 ret.addChild(child);
295 }
296 } else {
297 List list = (List) presentElements.get(tag);
298 if (list == null) {
299 if (!templateElement.isOptional()) {
300 throw new BuildException(
301 "Required nested element "
302 + templateElement.getName() + " missing");
303 }
304 continue;
305 }
306 for (Iterator i = list.iterator();
307 i.hasNext();) {
308 UnknownElement child = (UnknownElement) i.next();
309 rc.addChild(child.getWrapper());
310 ret.addChild(child);
311 }
312 }
313 }
314 return ret;
315 }
316
317 /**
318 * Execute the templates instance.
319 * Copies the unknown element, substitutes the attributes,
320 * and calls perform on the unknown element.
321 *
322 */
323 public void execute() {
324 presentElements = new HashMap();
325 getNsElements();
326 processTasks();
327 localProperties = new Hashtable();
328 Set copyKeys = new HashSet(map.keySet());
329 for (Iterator i = macroDef.getAttributes().iterator(); i.hasNext();) {
330 MacroDef.Attribute attribute = (MacroDef.Attribute) i.next();
331 String value = (String) map.get(attribute.getName());
332 if (value == null && "description".equals(attribute.getName())) {
333 value = getDescription();
334 }
335 if (value == null) {
336 value = attribute.getDefault();
337 value = macroSubs(value, localProperties);
338 }
339 if (value == null) {
340 throw new BuildException(
341 "required attribute " + attribute.getName() + " not set");
342 }
343 localProperties.put(attribute.getName(), value);
344 copyKeys.remove(attribute.getName());
345 }
346 if (copyKeys.contains("id")) {
347 copyKeys.remove("id");
348 }
349 if (macroDef.getText() != null) {
350 if (text == null) {
351 if (!macroDef.getText().getOptional()) {
352 throw new BuildException(
353 "required text missing");
354 }
355 text = "";
356 }
357 if (macroDef.getText().getTrim()) {
358 text = text.trim();
359 }
360 localProperties.put(macroDef.getText().getName(), text);
361 } else {
362 if (text != null && !text.trim().equals("")) {
363 throw new BuildException(
364 "The \"" + getTaskName() + "\" macro does not support"
365 + " nested text data.");
366 }
367 }
368 if (copyKeys.size() != 0) {
369 throw new BuildException(
370 "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
371 + copyKeys);
372 }
373
374 // need to set the project on unknown element
375 UnknownElement c = copy(macroDef.getNestedTask());
376 c.init();
377 try {
378 c.perform();
379 } catch (BuildException ex) {
380 throw ProjectHelper.addLocationToBuildException(
381 ex, getLocation());
382 }
383 presentElements = null;
384 localProperties = null;
385 }
386}
Note: See TracBrowser for help on using the repository browser.