1 | /*
|
---|
2 | * Copyright 2003-2005 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 |
|
---|
18 | package org.apache.tools.ant.taskdefs;
|
---|
19 |
|
---|
20 | import java.util.ArrayList;
|
---|
21 | import java.util.List;
|
---|
22 | import java.util.Map;
|
---|
23 | import java.util.Locale;
|
---|
24 | import java.util.HashMap;
|
---|
25 | import java.util.Iterator;
|
---|
26 |
|
---|
27 | import org.apache.tools.ant.AntTypeDefinition;
|
---|
28 | import org.apache.tools.ant.BuildException;
|
---|
29 | import org.apache.tools.ant.ComponentHelper;
|
---|
30 | import org.apache.tools.ant.Project;
|
---|
31 | import org.apache.tools.ant.ProjectHelper;
|
---|
32 | import org.apache.tools.ant.RuntimeConfigurable;
|
---|
33 | import org.apache.tools.ant.Task;
|
---|
34 | import org.apache.tools.ant.TaskContainer;
|
---|
35 | import org.apache.tools.ant.UnknownElement;
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * Describe class <code>MacroDef</code> here.
|
---|
39 | *
|
---|
40 | * @since Ant 1.6
|
---|
41 | */
|
---|
42 | public class MacroDef extends AntlibDefinition {
|
---|
43 | private NestedSequential nestedSequential;
|
---|
44 | private String name;
|
---|
45 | private List attributes = new ArrayList();
|
---|
46 | private Map elements = new HashMap();
|
---|
47 | private String textName = null;
|
---|
48 | private Text text = null;
|
---|
49 | private boolean hasImplicitElement = false;
|
---|
50 |
|
---|
51 | /**
|
---|
52 | * Name of the definition
|
---|
53 | * @param name the name of the definition
|
---|
54 | */
|
---|
55 | public void setName(String name) {
|
---|
56 | this.name = name;
|
---|
57 | }
|
---|
58 |
|
---|
59 | /**
|
---|
60 | * Add the text element.
|
---|
61 | * @param text the nested text element to add
|
---|
62 | * @since ant 1.6.1
|
---|
63 | */
|
---|
64 | public void addConfiguredText(Text text) {
|
---|
65 | if (this.text != null) {
|
---|
66 | throw new BuildException(
|
---|
67 | "Only one nested text element allowed");
|
---|
68 | }
|
---|
69 | if (text.getName() == null) {
|
---|
70 | throw new BuildException(
|
---|
71 | "the text nested element needed a \"name\" attribute");
|
---|
72 | }
|
---|
73 | // Check if used by attributes
|
---|
74 | for (Iterator i = attributes.iterator(); i.hasNext();) {
|
---|
75 | Attribute attribute = (Attribute) i.next();
|
---|
76 | if (text.getName().equals(attribute.getName())) {
|
---|
77 | throw new BuildException(
|
---|
78 | "the name \"" + text.getName()
|
---|
79 | + "\" is already used as an attribute");
|
---|
80 | }
|
---|
81 | }
|
---|
82 | this.text = text;
|
---|
83 | this.textName = text.getName();
|
---|
84 | }
|
---|
85 |
|
---|
86 | /**
|
---|
87 | * @return the nested text element
|
---|
88 | * @since ant 1.6.1
|
---|
89 | */
|
---|
90 |
|
---|
91 | public Text getText() {
|
---|
92 | return text;
|
---|
93 | }
|
---|
94 |
|
---|
95 | /**
|
---|
96 | * This is the sequential nested element of the macrodef.
|
---|
97 | *
|
---|
98 | * @return a sequential element to be configured.
|
---|
99 | */
|
---|
100 | public NestedSequential createSequential() {
|
---|
101 | if (this.nestedSequential != null) {
|
---|
102 | throw new BuildException("Only one sequential allowed");
|
---|
103 | }
|
---|
104 | this.nestedSequential = new NestedSequential();
|
---|
105 | return this.nestedSequential;
|
---|
106 | }
|
---|
107 |
|
---|
108 | /**
|
---|
109 | * The class corresponding to the sequential nested element.
|
---|
110 | * This is a simple task container.
|
---|
111 | */
|
---|
112 | public static class NestedSequential implements TaskContainer {
|
---|
113 | private List nested = new ArrayList();
|
---|
114 |
|
---|
115 | /**
|
---|
116 | * Add a task or type to the container.
|
---|
117 | *
|
---|
118 | * @param task an unknown element.
|
---|
119 | */
|
---|
120 | public void addTask(Task task) {
|
---|
121 | nested.add(task);
|
---|
122 | }
|
---|
123 |
|
---|
124 | /**
|
---|
125 | * @return the list of unknown elements
|
---|
126 | */
|
---|
127 | public List getNested() {
|
---|
128 | return nested;
|
---|
129 | }
|
---|
130 |
|
---|
131 | /**
|
---|
132 | * A compare function to compare this with another
|
---|
133 | * NestedSequential.
|
---|
134 | * It calls similar on the nested unknown elements.
|
---|
135 | *
|
---|
136 | * @param other the nested sequential to compare with.
|
---|
137 | * @return true if they are similar, false otherwise
|
---|
138 | */
|
---|
139 | public boolean similar(NestedSequential other) {
|
---|
140 | if (nested.size() != other.nested.size()) {
|
---|
141 | return false;
|
---|
142 | }
|
---|
143 | for (int i = 0; i < nested.size(); ++i) {
|
---|
144 | UnknownElement me = (UnknownElement) nested.get(i);
|
---|
145 | UnknownElement o = (UnknownElement) other.nested.get(i);
|
---|
146 | if (!me.similar(o)) {
|
---|
147 | return false;
|
---|
148 | }
|
---|
149 | }
|
---|
150 | return true;
|
---|
151 | }
|
---|
152 | }
|
---|
153 |
|
---|
154 | /**
|
---|
155 | * Convert the nested sequential to an unknown element
|
---|
156 | * @return the nested sequential as an unknown element.
|
---|
157 | */
|
---|
158 | public UnknownElement getNestedTask() {
|
---|
159 | UnknownElement ret = new UnknownElement("sequential");
|
---|
160 | ret.setTaskName("sequential");
|
---|
161 | ret.setNamespace("");
|
---|
162 | ret.setQName("sequential");
|
---|
163 | new RuntimeConfigurable(ret, "sequential");
|
---|
164 | for (int i = 0; i < nestedSequential.getNested().size(); ++i) {
|
---|
165 | UnknownElement e =
|
---|
166 | (UnknownElement) nestedSequential.getNested().get(i);
|
---|
167 | ret.addChild(e);
|
---|
168 | ret.getWrapper().addChild(e.getWrapper());
|
---|
169 | }
|
---|
170 | return ret;
|
---|
171 | }
|
---|
172 |
|
---|
173 | /**
|
---|
174 | * @return the nested Attributes
|
---|
175 | */
|
---|
176 | public List getAttributes() {
|
---|
177 | return attributes;
|
---|
178 | }
|
---|
179 |
|
---|
180 | /**
|
---|
181 | * @return the nested elements
|
---|
182 | */
|
---|
183 | public Map getElements() {
|
---|
184 | return elements;
|
---|
185 | }
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * Check if a character is a valid character for an element or
|
---|
189 | * attribute name
|
---|
190 | * @param c the character to check
|
---|
191 | * @return true if the character is a letter or digit or '.' or '-'
|
---|
192 | * attribute name
|
---|
193 | */
|
---|
194 | public static boolean isValidNameCharacter(char c) {
|
---|
195 | // ? is there an xml api for this ?
|
---|
196 | return Character.isLetterOrDigit(c) || c == '.' || c == '-';
|
---|
197 | }
|
---|
198 |
|
---|
199 | /**
|
---|
200 | * Check if a string is a valid name for an element or
|
---|
201 | * attribute
|
---|
202 | * @param name the string to check
|
---|
203 | * @return true if the name consists of valid name characters
|
---|
204 | */
|
---|
205 | private static boolean isValidName(String name) {
|
---|
206 | if (name.length() == 0) {
|
---|
207 | return false;
|
---|
208 | }
|
---|
209 | for (int i = 0; i < name.length(); ++i) {
|
---|
210 | if (!isValidNameCharacter(name.charAt(i))) {
|
---|
211 | return false;
|
---|
212 | }
|
---|
213 | }
|
---|
214 | return true;
|
---|
215 | }
|
---|
216 |
|
---|
217 | /**
|
---|
218 | * Add an attribute element.
|
---|
219 | *
|
---|
220 | * @param attribute an attribute nested element.
|
---|
221 | */
|
---|
222 | public void addConfiguredAttribute(Attribute attribute) {
|
---|
223 | if (attribute.getName() == null) {
|
---|
224 | throw new BuildException(
|
---|
225 | "the attribute nested element needed a \"name\" attribute");
|
---|
226 | }
|
---|
227 | if (attribute.getName().equals(textName)) {
|
---|
228 | throw new BuildException(
|
---|
229 | "the attribute name \"" + attribute.getName()
|
---|
230 | + "\" has already been used by the text element");
|
---|
231 | }
|
---|
232 | for (int i = 0; i < attributes.size(); ++i) {
|
---|
233 | if (((Attribute) attributes.get(i)).getName().equals(
|
---|
234 | attribute.getName())) {
|
---|
235 | throw new BuildException(
|
---|
236 | "the attribute " + attribute.getName()
|
---|
237 | + " has already been specified");
|
---|
238 | }
|
---|
239 | }
|
---|
240 | attributes.add(attribute);
|
---|
241 | }
|
---|
242 |
|
---|
243 | /**
|
---|
244 | * Add an element element.
|
---|
245 | *
|
---|
246 | * @param element an element nested element.
|
---|
247 | */
|
---|
248 | public void addConfiguredElement(TemplateElement element) {
|
---|
249 | if (element.getName() == null) {
|
---|
250 | throw new BuildException(
|
---|
251 | "the element nested element needed a \"name\" attribute");
|
---|
252 | }
|
---|
253 | if (elements.get(element.getName()) != null) {
|
---|
254 | throw new BuildException(
|
---|
255 | "the element " + element.getName()
|
---|
256 | + " has already been specified");
|
---|
257 | }
|
---|
258 | if (hasImplicitElement
|
---|
259 | || (element.isImplicit() && elements.size() != 0)) {
|
---|
260 | throw new BuildException(
|
---|
261 | "Only one element allowed when using implicit elements");
|
---|
262 | }
|
---|
263 | hasImplicitElement = element.isImplicit();
|
---|
264 | elements.put(element.getName(), element);
|
---|
265 | }
|
---|
266 |
|
---|
267 | /**
|
---|
268 | * Create a new ant type based on the embedded tasks and types.
|
---|
269 | *
|
---|
270 | */
|
---|
271 | public void execute() {
|
---|
272 | if (nestedSequential == null) {
|
---|
273 | throw new BuildException("Missing sequential element");
|
---|
274 | }
|
---|
275 | if (name == null) {
|
---|
276 | throw new BuildException("Name not specified");
|
---|
277 | }
|
---|
278 |
|
---|
279 | name = ProjectHelper.genComponentName(getURI(), name);
|
---|
280 |
|
---|
281 | MyAntTypeDefinition def = new MyAntTypeDefinition(this);
|
---|
282 | def.setName(name);
|
---|
283 | def.setClass(MacroInstance.class);
|
---|
284 |
|
---|
285 | ComponentHelper helper = ComponentHelper.getComponentHelper(
|
---|
286 | getProject());
|
---|
287 |
|
---|
288 | helper.addDataTypeDefinition(def);
|
---|
289 | }
|
---|
290 |
|
---|
291 |
|
---|
292 | /**
|
---|
293 | * A nested element for the MacroDef task.
|
---|
294 | *
|
---|
295 | */
|
---|
296 | public static class Attribute {
|
---|
297 | private String name;
|
---|
298 | private String defaultValue;
|
---|
299 | private String description;
|
---|
300 |
|
---|
301 | /**
|
---|
302 | * The name of the attribute.
|
---|
303 | *
|
---|
304 | * @param name the name of the attribute
|
---|
305 | */
|
---|
306 | public void setName(String name) {
|
---|
307 | if (!isValidName(name)) {
|
---|
308 | throw new BuildException(
|
---|
309 | "Illegal name [" + name + "] for attribute");
|
---|
310 | }
|
---|
311 | this.name = name.toLowerCase(Locale.US);
|
---|
312 | }
|
---|
313 |
|
---|
314 | /**
|
---|
315 | * @return the name of the attribute
|
---|
316 | */
|
---|
317 | public String getName() {
|
---|
318 | return name;
|
---|
319 | }
|
---|
320 |
|
---|
321 | /**
|
---|
322 | * The default value to use if the parameter is not
|
---|
323 | * used in the templated instance.
|
---|
324 | *
|
---|
325 | * @param defaultValue the default value
|
---|
326 | */
|
---|
327 | public void setDefault(String defaultValue) {
|
---|
328 | this.defaultValue = defaultValue;
|
---|
329 | }
|
---|
330 |
|
---|
331 | /**
|
---|
332 | * @return the default value, null if not set
|
---|
333 | */
|
---|
334 | public String getDefault() {
|
---|
335 | return defaultValue;
|
---|
336 | }
|
---|
337 |
|
---|
338 | /**
|
---|
339 | * @param desc Description of the element.
|
---|
340 | * @since ant 1.6.1
|
---|
341 | */
|
---|
342 | public void setDescription(String desc) {
|
---|
343 | description = desc;
|
---|
344 | }
|
---|
345 |
|
---|
346 | /**
|
---|
347 | * @return the description of the element, or <code>null</code> if
|
---|
348 | * no description is available.
|
---|
349 | * @since ant 1.6.1
|
---|
350 | */
|
---|
351 | public String getDescription() {
|
---|
352 | return description;
|
---|
353 | }
|
---|
354 |
|
---|
355 | /**
|
---|
356 | * equality method
|
---|
357 | *
|
---|
358 | * @param obj an <code>Object</code> value
|
---|
359 | * @return a <code>boolean</code> value
|
---|
360 | */
|
---|
361 | public boolean equals(Object obj) {
|
---|
362 | if (obj == null) {
|
---|
363 | return false;
|
---|
364 | }
|
---|
365 | if (obj.getClass() != getClass()) {
|
---|
366 | return false;
|
---|
367 | }
|
---|
368 | Attribute other = (Attribute) obj;
|
---|
369 | if (name == null) {
|
---|
370 | if (other.name != null) {
|
---|
371 | return false;
|
---|
372 | }
|
---|
373 | } else if (!name.equals(other.name)) {
|
---|
374 | return false;
|
---|
375 | }
|
---|
376 | if (defaultValue == null) {
|
---|
377 | if (other.defaultValue != null) {
|
---|
378 | return false;
|
---|
379 | }
|
---|
380 | } else if (!defaultValue.equals(other.defaultValue)) {
|
---|
381 | return false;
|
---|
382 | }
|
---|
383 | return true;
|
---|
384 | }
|
---|
385 |
|
---|
386 | /**
|
---|
387 | * @return a hash code value for this object.
|
---|
388 | */
|
---|
389 | public int hashCode() {
|
---|
390 | return objectHashCode(defaultValue) + objectHashCode(name);
|
---|
391 | }
|
---|
392 | }
|
---|
393 |
|
---|
394 | /**
|
---|
395 | * A nested text element for the MacroDef task.
|
---|
396 | * @since ant 1.6.1
|
---|
397 | */
|
---|
398 | public static class Text {
|
---|
399 | private String name;
|
---|
400 | private boolean optional;
|
---|
401 | private boolean trim;
|
---|
402 | private String description;
|
---|
403 |
|
---|
404 | /**
|
---|
405 | * The name of the attribute.
|
---|
406 | *
|
---|
407 | * @param name the name of the attribute
|
---|
408 | */
|
---|
409 | public void setName(String name) {
|
---|
410 | if (!isValidName(name)) {
|
---|
411 | throw new BuildException(
|
---|
412 | "Illegal name [" + name + "] for attribute");
|
---|
413 | }
|
---|
414 | this.name = name.toLowerCase(Locale.US);
|
---|
415 | }
|
---|
416 |
|
---|
417 | /**
|
---|
418 | * @return the name of the attribute
|
---|
419 | */
|
---|
420 | public String getName() {
|
---|
421 | return name;
|
---|
422 | }
|
---|
423 |
|
---|
424 | /**
|
---|
425 | * The optional attribute of the text element.
|
---|
426 | *
|
---|
427 | * @param optional if true this is optional
|
---|
428 | */
|
---|
429 | public void setOptional(boolean optional) {
|
---|
430 | this.optional = optional;
|
---|
431 | }
|
---|
432 |
|
---|
433 | /**
|
---|
434 | * @return true if the text is optional
|
---|
435 | */
|
---|
436 | public boolean getOptional() {
|
---|
437 | return optional;
|
---|
438 | }
|
---|
439 |
|
---|
440 | /**
|
---|
441 | * The trim attribute of the text element.
|
---|
442 | *
|
---|
443 | * @param trim if true this String.trim() is called on
|
---|
444 | * the contents of the text element.
|
---|
445 | */
|
---|
446 | public void setTrim(boolean trim) {
|
---|
447 | this.trim = trim;
|
---|
448 | }
|
---|
449 |
|
---|
450 | /**
|
---|
451 | * @return true if the text is trim
|
---|
452 | */
|
---|
453 | public boolean getTrim() {
|
---|
454 | return trim;
|
---|
455 | }
|
---|
456 |
|
---|
457 | /**
|
---|
458 | * @param desc Description of the text.
|
---|
459 | */
|
---|
460 | public void setDescription(String desc) {
|
---|
461 | description = desc;
|
---|
462 | }
|
---|
463 |
|
---|
464 | /**
|
---|
465 | * @return the description of the text, or <code>null</code> if
|
---|
466 | * no description is available.
|
---|
467 | */
|
---|
468 | public String getDescription() {
|
---|
469 | return description;
|
---|
470 | }
|
---|
471 |
|
---|
472 | /**
|
---|
473 | * equality method
|
---|
474 | *
|
---|
475 | * @param obj an <code>Object</code> value
|
---|
476 | * @return a <code>boolean</code> value
|
---|
477 | */
|
---|
478 | public boolean equals(Object obj) {
|
---|
479 | if (obj == null) {
|
---|
480 | return false;
|
---|
481 | }
|
---|
482 | if (obj.getClass() != getClass()) {
|
---|
483 | return false;
|
---|
484 | }
|
---|
485 | Text other = (Text) obj;
|
---|
486 | if (name == null) {
|
---|
487 | if (other.name != null) {
|
---|
488 | return false;
|
---|
489 | }
|
---|
490 | } else if (!name.equals(other.name)) {
|
---|
491 | return false;
|
---|
492 | }
|
---|
493 | if (optional != other.optional) {
|
---|
494 | return false;
|
---|
495 | }
|
---|
496 | if (trim != other.trim) {
|
---|
497 | return false;
|
---|
498 | }
|
---|
499 | return true;
|
---|
500 | }
|
---|
501 |
|
---|
502 | /**
|
---|
503 | * @return a hash code value for this object.
|
---|
504 | */
|
---|
505 | public int hashCode() {
|
---|
506 | return objectHashCode(name);
|
---|
507 | }
|
---|
508 | }
|
---|
509 |
|
---|
510 | /**
|
---|
511 | * A nested element for the MacroDef task.
|
---|
512 | *
|
---|
513 | */
|
---|
514 | public static class TemplateElement {
|
---|
515 | private String name;
|
---|
516 | private boolean optional = false;
|
---|
517 | private boolean implicit = false;
|
---|
518 | private String description;
|
---|
519 |
|
---|
520 | /**
|
---|
521 | * The name of the element.
|
---|
522 | *
|
---|
523 | * @param name the name of the element.
|
---|
524 | */
|
---|
525 | public void setName(String name) {
|
---|
526 | if (!isValidName(name)) {
|
---|
527 | throw new BuildException(
|
---|
528 | "Illegal name [" + name + "] for attribute");
|
---|
529 | }
|
---|
530 | this.name = name.toLowerCase(Locale.US);
|
---|
531 | }
|
---|
532 |
|
---|
533 | /**
|
---|
534 | * @return the name of the element.
|
---|
535 | */
|
---|
536 | public String getName() {
|
---|
537 | return name;
|
---|
538 | }
|
---|
539 |
|
---|
540 | /**
|
---|
541 | * is this element optional ?
|
---|
542 | *
|
---|
543 | * @param optional if true this element may be left out, default
|
---|
544 | * is false.
|
---|
545 | */
|
---|
546 | public void setOptional(boolean optional) {
|
---|
547 | this.optional = optional;
|
---|
548 | }
|
---|
549 |
|
---|
550 | /**
|
---|
551 | * @return the optional attribute
|
---|
552 | */
|
---|
553 | public boolean isOptional() {
|
---|
554 | return optional;
|
---|
555 | }
|
---|
556 |
|
---|
557 | /**
|
---|
558 | * is this element implicit ?
|
---|
559 | *
|
---|
560 | * @param implicit if true this element may be left out, default
|
---|
561 | * is false.
|
---|
562 | */
|
---|
563 | public void setImplicit(boolean implicit) {
|
---|
564 | this.implicit = implicit;
|
---|
565 | }
|
---|
566 |
|
---|
567 | /**
|
---|
568 | * @return the implicit attribute
|
---|
569 | */
|
---|
570 | public boolean isImplicit() {
|
---|
571 | return implicit;
|
---|
572 | }
|
---|
573 |
|
---|
574 | /**
|
---|
575 | * @param desc Description of the element.
|
---|
576 | * @since ant 1.6.1
|
---|
577 | */
|
---|
578 | public void setDescription(String desc) {
|
---|
579 | description = desc;
|
---|
580 | }
|
---|
581 |
|
---|
582 | /**
|
---|
583 | * @return the description of the element, or <code>null</code> if
|
---|
584 | * no description is available.
|
---|
585 | * @since ant 1.6.1
|
---|
586 | */
|
---|
587 | public String getDescription() {
|
---|
588 | return description;
|
---|
589 | }
|
---|
590 |
|
---|
591 | /**
|
---|
592 | * equality method
|
---|
593 | *
|
---|
594 | * @param obj an <code>Object</code> value
|
---|
595 | * @return a <code>boolean</code> value
|
---|
596 | */
|
---|
597 | public boolean equals(Object obj) {
|
---|
598 | if (obj == null) {
|
---|
599 | return false;
|
---|
600 | }
|
---|
601 | if (obj.getClass() != getClass()) {
|
---|
602 | return false;
|
---|
603 | }
|
---|
604 | TemplateElement other = (TemplateElement) obj;
|
---|
605 | if (name == null) {
|
---|
606 | if (other.name != null) {
|
---|
607 | return false;
|
---|
608 | }
|
---|
609 | } else if (!name.equals(other.name)) {
|
---|
610 | return false;
|
---|
611 | }
|
---|
612 | return optional == other.optional && implicit == other.implicit;
|
---|
613 | }
|
---|
614 |
|
---|
615 | /**
|
---|
616 | * @return a hash code value for this object.
|
---|
617 | */
|
---|
618 | public int hashCode() {
|
---|
619 | return objectHashCode(name)
|
---|
620 | + (optional ? 1 : 0) + (implicit ? 1 : 0);
|
---|
621 | }
|
---|
622 | }
|
---|
623 |
|
---|
624 | /**
|
---|
625 | * same or similar equality method for macrodef, ignores project and
|
---|
626 | * runtime info.
|
---|
627 | *
|
---|
628 | * @param obj an <code>Object</code> value
|
---|
629 | * @param same if true test for sameness, otherwise just similiar
|
---|
630 | * @return a <code>boolean</code> value
|
---|
631 | */
|
---|
632 | private boolean sameOrSimilar(Object obj, boolean same) {
|
---|
633 | if (obj == this) {
|
---|
634 | return true;
|
---|
635 | }
|
---|
636 |
|
---|
637 | if (obj == null) {
|
---|
638 | return false;
|
---|
639 | }
|
---|
640 | if (!obj.getClass().equals(getClass())) {
|
---|
641 | return false;
|
---|
642 | }
|
---|
643 | MacroDef other = (MacroDef) obj;
|
---|
644 | if (name == null) {
|
---|
645 | return other.name == null;
|
---|
646 | }
|
---|
647 | if (!name.equals(other.name)) {
|
---|
648 | return false;
|
---|
649 | }
|
---|
650 | // Allow two macro definitions with the same location
|
---|
651 | // to be treated as similar - bugzilla 31215
|
---|
652 | if (other.getLocation() != null
|
---|
653 | && other.getLocation().equals(getLocation())
|
---|
654 | && !same) {
|
---|
655 | return true;
|
---|
656 | }
|
---|
657 | if (text == null) {
|
---|
658 | if (other.text != null) {
|
---|
659 | return false;
|
---|
660 | }
|
---|
661 | } else {
|
---|
662 | if (!text.equals(other.text)) {
|
---|
663 | return false;
|
---|
664 | }
|
---|
665 | }
|
---|
666 | if (getURI() == null || getURI().equals("")
|
---|
667 | || getURI().equals(ProjectHelper.ANT_CORE_URI)) {
|
---|
668 | if (!(other.getURI() == null || other.getURI().equals("")
|
---|
669 | || other.getURI().equals(ProjectHelper.ANT_CORE_URI))) {
|
---|
670 | return false;
|
---|
671 | }
|
---|
672 | } else {
|
---|
673 | if (!getURI().equals(other.getURI())) {
|
---|
674 | return false;
|
---|
675 | }
|
---|
676 | }
|
---|
677 |
|
---|
678 | if (!nestedSequential.similar(other.nestedSequential)) {
|
---|
679 | return false;
|
---|
680 | }
|
---|
681 | if (!attributes.equals(other.attributes)) {
|
---|
682 | return false;
|
---|
683 | }
|
---|
684 | if (!elements.equals(other.elements)) {
|
---|
685 | return false;
|
---|
686 | }
|
---|
687 | return true;
|
---|
688 | }
|
---|
689 |
|
---|
690 | /**
|
---|
691 | * Similar method for this definition
|
---|
692 | *
|
---|
693 | * @param obj another definition
|
---|
694 | * @return true if the definitions are similar
|
---|
695 | */
|
---|
696 | public boolean similar(Object obj) {
|
---|
697 | return sameOrSimilar(obj, false);
|
---|
698 | }
|
---|
699 |
|
---|
700 | /**
|
---|
701 | * Equality method for this definition
|
---|
702 | *
|
---|
703 | * @param obj another definition
|
---|
704 | * @return true if the definitions are the same
|
---|
705 | */
|
---|
706 | public boolean sameDefinition(Object obj) {
|
---|
707 | return sameOrSimilar(obj, true);
|
---|
708 | }
|
---|
709 |
|
---|
710 | /**
|
---|
711 | * extends AntTypeDefinition, on create
|
---|
712 | * of the object, the template macro definition
|
---|
713 | * is given.
|
---|
714 | */
|
---|
715 | private static class MyAntTypeDefinition extends AntTypeDefinition {
|
---|
716 | private MacroDef macroDef;
|
---|
717 |
|
---|
718 | /**
|
---|
719 | * Creates a new <code>MyAntTypeDefinition</code> instance.
|
---|
720 | *
|
---|
721 | * @param macroDef a <code>MacroDef</code> value
|
---|
722 | */
|
---|
723 | public MyAntTypeDefinition(MacroDef macroDef) {
|
---|
724 | this.macroDef = macroDef;
|
---|
725 | }
|
---|
726 |
|
---|
727 | /**
|
---|
728 | * create an instance of the definition.
|
---|
729 | * The instance may be wrapped in a proxy class.
|
---|
730 | * @param project the current project
|
---|
731 | * @return the created object
|
---|
732 | */
|
---|
733 | public Object create(Project project) {
|
---|
734 | Object o = super.create(project);
|
---|
735 | if (o == null) {
|
---|
736 | return null;
|
---|
737 | }
|
---|
738 | ((MacroInstance) o).setMacroDef(macroDef);
|
---|
739 | return o;
|
---|
740 | }
|
---|
741 |
|
---|
742 | /**
|
---|
743 | * Equality method for this definition
|
---|
744 | *
|
---|
745 | * @param other another definition
|
---|
746 | * @param project the current project
|
---|
747 | * @return true if the definitions are the same
|
---|
748 | */
|
---|
749 | public boolean sameDefinition(AntTypeDefinition other, Project project) {
|
---|
750 | if (!super.sameDefinition(other, project)) {
|
---|
751 | return false;
|
---|
752 | }
|
---|
753 | MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other;
|
---|
754 | return macroDef.sameDefinition(otherDef.macroDef);
|
---|
755 | }
|
---|
756 |
|
---|
757 | /**
|
---|
758 | * Similar method for this definition
|
---|
759 | *
|
---|
760 | * @param other another definition
|
---|
761 | * @param project the current project
|
---|
762 | * @return true if the definitions are the same
|
---|
763 | */
|
---|
764 | public boolean similarDefinition(
|
---|
765 | AntTypeDefinition other, Project project) {
|
---|
766 | if (!super.similarDefinition(other, project)) {
|
---|
767 | return false;
|
---|
768 | }
|
---|
769 | MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other;
|
---|
770 | return macroDef.similar(otherDef.macroDef);
|
---|
771 | }
|
---|
772 | }
|
---|
773 |
|
---|
774 | private static int objectHashCode(Object o) {
|
---|
775 | if (o == null) {
|
---|
776 | return 0;
|
---|
777 | } else {
|
---|
778 | return o.hashCode();
|
---|
779 | }
|
---|
780 | }
|
---|
781 | }
|
---|