1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.util.ArrayList ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.Locale ; 25 import java.util.HashMap ; 26 import java.util.Iterator ; 27 28 import org.apache.tools.ant.AntTypeDefinition; 29 import org.apache.tools.ant.BuildException; 30 import org.apache.tools.ant.ComponentHelper; 31 import org.apache.tools.ant.Project; 32 import org.apache.tools.ant.ProjectHelper; 33 import org.apache.tools.ant.RuntimeConfigurable; 34 import org.apache.tools.ant.Task; 35 import org.apache.tools.ant.TaskContainer; 36 import org.apache.tools.ant.UnknownElement; 37 38 43 public class MacroDef extends AntlibDefinition { 44 45 private NestedSequential nestedSequential; 46 private String name; 47 private boolean backTrace = true; 48 private List attributes = new ArrayList (); 49 private Map elements = new HashMap (); 50 private String textName = null; 51 private Text text = null; 52 private boolean hasImplicitElement = false; 53 54 58 public void setName(String name) { 59 this.name = name; 60 } 61 62 67 public void addConfiguredText(Text text) { 68 if (this.text != null) { 69 throw new BuildException( 70 "Only one nested text element allowed"); 71 } 72 if (text.getName() == null) { 73 throw new BuildException( 74 "the text nested element needed a \"name\" attribute"); 75 } 76 for (Iterator i = attributes.iterator(); i.hasNext();) { 78 Attribute attribute = (Attribute) i.next(); 79 if (text.getName().equals(attribute.getName())) { 80 throw new BuildException( 81 "the name \"" + text.getName() 82 + "\" is already used as an attribute"); 83 } 84 } 85 this.text = text; 86 this.textName = text.getName(); 87 } 88 89 93 public Text getText() { 94 return text; 95 } 96 97 107 public void setBackTrace(boolean backTrace) { 108 this.backTrace = backTrace; 109 } 110 111 115 public boolean getBackTrace() { 116 return backTrace; 117 } 118 119 124 public NestedSequential createSequential() { 125 if (this.nestedSequential != null) { 126 throw new BuildException("Only one sequential allowed"); 127 } 128 this.nestedSequential = new NestedSequential(); 129 return this.nestedSequential; 130 } 131 132 136 public static class NestedSequential implements TaskContainer { 137 private List nested = new ArrayList (); 138 139 144 public void addTask(Task task) { 145 nested.add(task); 146 } 147 148 151 public List getNested() { 152 return nested; 153 } 154 155 163 public boolean similar(NestedSequential other) { 164 if (nested.size() != other.nested.size()) { 165 return false; 166 } 167 for (int i = 0; i < nested.size(); ++i) { 168 UnknownElement me = (UnknownElement) nested.get(i); 169 UnknownElement o = (UnknownElement) other.nested.get(i); 170 if (!me.similar(o)) { 171 return false; 172 } 173 } 174 return true; 175 } 176 } 177 178 182 public UnknownElement getNestedTask() { 183 UnknownElement ret = new UnknownElement("sequential"); 184 ret.setTaskName("sequential"); 185 ret.setNamespace(""); 186 ret.setQName("sequential"); 187 new RuntimeConfigurable(ret, "sequential"); 188 for (int i = 0; i < nestedSequential.getNested().size(); ++i) { 189 UnknownElement e = 190 (UnknownElement) nestedSequential.getNested().get(i); 191 ret.addChild(e); 192 ret.getWrapper().addChild(e.getWrapper()); 193 } 194 return ret; 195 } 196 197 202 public List getAttributes() { 203 return attributes; 204 } 205 206 212 public Map getElements() { 213 return elements; 214 } 215 216 224 public static boolean isValidNameCharacter(char c) { 225 return Character.isLetterOrDigit(c) || c == '.' || c == '-'; 227 } 228 229 235 private static boolean isValidName(String name) { 236 if (name.length() == 0) { 237 return false; 238 } 239 for (int i = 0; i < name.length(); ++i) { 240 if (!isValidNameCharacter(name.charAt(i))) { 241 return false; 242 } 243 } 244 return true; 245 } 246 247 252 public void addConfiguredAttribute(Attribute attribute) { 253 if (attribute.getName() == null) { 254 throw new BuildException( 255 "the attribute nested element needed a \"name\" attribute"); 256 } 257 if (attribute.getName().equals(textName)) { 258 throw new BuildException( 259 "the name \"" + attribute.getName() 260 + "\" has already been used by the text element"); 261 } 262 for (int i = 0; i < attributes.size(); ++i) { 263 Attribute att = (Attribute) attributes.get(i); 264 if (att.getName().equals(attribute.getName())) { 265 throw new BuildException( 266 "the name \"" + attribute.getName() 267 + "\" has already been used in " 268 + "another attribute element"); 269 } 270 } 271 attributes.add(attribute); 272 } 273 274 279 public void addConfiguredElement(TemplateElement element) { 280 if (element.getName() == null) { 281 throw new BuildException( 282 "the element nested element needed a \"name\" attribute"); 283 } 284 if (elements.get(element.getName()) != null) { 285 throw new BuildException( 286 "the element " + element.getName() 287 + " has already been specified"); 288 } 289 if (hasImplicitElement 290 || (element.isImplicit() && elements.size() != 0)) { 291 throw new BuildException( 292 "Only one element allowed when using implicit elements"); 293 } 294 hasImplicitElement = element.isImplicit(); 295 elements.put(element.getName(), element); 296 } 297 298 301 public void execute() { 302 if (nestedSequential == null) { 303 throw new BuildException("Missing sequential element"); 304 } 305 if (name == null) { 306 throw new BuildException("Name not specified"); 307 } 308 309 name = ProjectHelper.genComponentName(getURI(), name); 310 311 MyAntTypeDefinition def = new MyAntTypeDefinition(this); 312 def.setName(name); 313 def.setClass(MacroInstance.class); 314 315 ComponentHelper helper = ComponentHelper.getComponentHelper( 316 getProject()); 317 318 helper.addDataTypeDefinition(def); 319 log("creating macro " + name, Project.MSG_VERBOSE); 320 } 321 322 323 327 public static class Attribute { 328 private String name; 329 private String defaultValue; 330 private String description; 331 332 337 public void setName(String name) { 338 if (!isValidName(name)) { 339 throw new BuildException( 340 "Illegal name [" + name + "] for attribute"); 341 } 342 this.name = name.toLowerCase(Locale.US); 343 } 344 345 348 public String getName() { 349 return name; 350 } 351 352 358 public void setDefault(String defaultValue) { 359 this.defaultValue = defaultValue; 360 } 361 362 365 public String getDefault() { 366 return defaultValue; 367 } 368 369 373 public void setDescription(String desc) { 374 description = desc; 375 } 376 377 382 public String getDescription() { 383 return description; 384 } 385 386 392 public boolean equals(Object obj) { 393 if (obj == null) { 394 return false; 395 } 396 if (obj.getClass() != getClass()) { 397 return false; 398 } 399 Attribute other = (Attribute) obj; 400 if (name == null) { 401 if (other.name != null) { 402 return false; 403 } 404 } else if (!name.equals(other.name)) { 405 return false; 406 } 407 if (defaultValue == null) { 408 if (other.defaultValue != null) { 409 return false; 410 } 411 } else if (!defaultValue.equals(other.defaultValue)) { 412 return false; 413 } 414 return true; 415 } 416 417 420 public int hashCode() { 421 return objectHashCode(defaultValue) + objectHashCode(name); 422 } 423 } 424 425 429 public static class Text { 430 private String name; 431 private boolean optional; 432 private boolean trim; 433 private String description; 434 435 440 public void setName(String name) { 441 if (!isValidName(name)) { 442 throw new BuildException( 443 "Illegal name [" + name + "] for attribute"); 444 } 445 this.name = name.toLowerCase(Locale.US); 446 } 447 448 451 public String getName() { 452 return name; 453 } 454 455 460 public void setOptional(boolean optional) { 461 this.optional = optional; 462 } 463 464 467 public boolean getOptional() { 468 return optional; 469 } 470 471 477 public void setTrim(boolean trim) { 478 this.trim = trim; 479 } 480 481 484 public boolean getTrim() { 485 return trim; 486 } 487 488 491 public void setDescription(String desc) { 492 description = desc; 493 } 494 495 499 public String getDescription() { 500 return description; 501 } 502 503 509 public boolean equals(Object obj) { 510 if (obj == null) { 511 return false; 512 } 513 if (obj.getClass() != getClass()) { 514 return false; 515 } 516 Text other = (Text) obj; 517 if (name == null) { 518 if (other.name != null) { 519 return false; 520 } 521 } else if (!name.equals(other.name)) { 522 return false; 523 } 524 if (optional != other.optional) { 525 return false; 526 } 527 if (trim != other.trim) { 528 return false; 529 } 530 return true; 531 } 532 533 536 public int hashCode() { 537 return objectHashCode(name); 538 } 539 } 540 541 544 public static class TemplateElement { 545 546 private String name; 547 private String description; 548 private boolean optional = false; 549 private boolean implicit = false; 550 551 556 public void setName(String name) { 557 if (!isValidName(name)) { 558 throw new BuildException( 559 "Illegal name [" + name + "] for macro element"); 560 } 561 this.name = name.toLowerCase(Locale.US); 562 } 563 564 569 public String getName() { 570 return name; 571 } 572 573 580 public void setDescription(String desc) { 581 description = desc; 582 } 583 584 591 public String getDescription() { 592 return description; 593 } 594 595 601 public void setOptional(boolean optional) { 602 this.optional = optional; 603 } 604 605 610 public boolean isOptional() { 611 return optional; 612 } 613 614 620 public void setImplicit(boolean implicit) { 621 this.implicit = implicit; 622 } 623 624 629 public boolean isImplicit() { 630 return implicit; 631 } 632 633 639 public boolean equals(Object obj) { 640 if (obj == this) { 641 return true; 642 } 643 if (obj == null || !obj.getClass().equals(getClass())) { 644 return false; 645 } 646 TemplateElement t = (TemplateElement) obj; 647 return 648 (name == null ? t.name == null : name.equals(t.name)) 649 && optional == t.optional 650 && implicit == t.implicit; 651 } 652 653 656 public int hashCode() { 657 return objectHashCode(name) 658 + (optional ? 1 : 0) + (implicit ? 1 : 0); 659 } 660 661 } 663 671 private boolean sameOrSimilar(Object obj, boolean same) { 672 if (obj == this) { 673 return true; 674 } 675 676 if (obj == null) { 677 return false; 678 } 679 if (!obj.getClass().equals(getClass())) { 680 return false; 681 } 682 MacroDef other = (MacroDef) obj; 683 if (name == null) { 684 return other.name == null; 685 } 686 if (!name.equals(other.name)) { 687 return false; 688 } 689 if (other.getLocation() != null 692 && other.getLocation().equals(getLocation()) 693 && !same) { 694 return true; 695 } 696 if (text == null) { 697 if (other.text != null) { 698 return false; 699 } 700 } else { 701 if (!text.equals(other.text)) { 702 return false; 703 } 704 } 705 if (getURI() == null || getURI().equals("") 706 || getURI().equals(ProjectHelper.ANT_CORE_URI)) { 707 if (!(other.getURI() == null || other.getURI().equals("") 708 || other.getURI().equals(ProjectHelper.ANT_CORE_URI))) { 709 return false; 710 } 711 } else { 712 if (!getURI().equals(other.getURI())) { 713 return false; 714 } 715 } 716 717 if (!nestedSequential.similar(other.nestedSequential)) { 718 return false; 719 } 720 if (!attributes.equals(other.attributes)) { 721 return false; 722 } 723 if (!elements.equals(other.elements)) { 724 return false; 725 } 726 return true; 727 } 728 729 735 public boolean similar(Object obj) { 736 return sameOrSimilar(obj, false); 737 } 738 739 745 public boolean sameDefinition(Object obj) { 746 return sameOrSimilar(obj, true); 747 } 748 749 754 private static class MyAntTypeDefinition extends AntTypeDefinition { 755 private MacroDef macroDef; 756 757 762 public MyAntTypeDefinition(MacroDef macroDef) { 763 this.macroDef = macroDef; 764 } 765 766 772 public Object create(Project project) { 773 Object o = super.create(project); 774 if (o == null) { 775 return null; 776 } 777 ((MacroInstance) o).setMacroDef(macroDef); 778 return o; 779 } 780 781 788 public boolean sameDefinition(AntTypeDefinition other, Project project) { 789 if (!super.sameDefinition(other, project)) { 790 return false; 791 } 792 MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; 793 return macroDef.sameDefinition(otherDef.macroDef); 794 } 795 796 803 public boolean similarDefinition( 804 AntTypeDefinition other, Project project) { 805 if (!super.similarDefinition(other, project)) { 806 return false; 807 } 808 MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; 809 return macroDef.similar(otherDef.macroDef); 810 } 811 } 812 813 private static int objectHashCode(Object o) { 814 if (o == null) { 815 return 0; 816 } else { 817 return o.hashCode(); 818 } 819 } 820 821 } 822 | Popular Tags |