1 5 package xdoclet; 6 7 import java.io.File ; 8 import java.net.MalformedURLException ; 9 import java.net.URL ; 10 import java.text.MessageFormat ; 11 import java.util.*; 12 13 import org.apache.commons.logging.Log; 14 15 import xjavadoc.*; 16 17 import xdoclet.tagshandler.PackageTagsHandler; 18 import xdoclet.tagshandler.TypeTagsHandler; 19 import xdoclet.template.TemplateEngine; 20 import xdoclet.template.TemplateException; 21 import xdoclet.template.XDocletTemplateMessages; 22 import xdoclet.util.LogUtil; 23 import xdoclet.util.Translator; 24 25 39 public class TemplateSubTask extends SubTask 40 { 41 private final static String SUBTASK_NAME = "template"; 42 43 private URL templateURL = null; 44 45 private transient TemplateEngine engine = null; 46 47 private boolean prefixWithPackageStructure = true; 48 49 private boolean acceptInterfaces = true; 50 private boolean acceptAbstractClasses = true; 51 private String docEncoding = null; 52 53 57 private String destinationFile = null; 58 59 69 private List ofType = new ArrayList(); 70 71 80 private String extent = "hierarchy"; 81 82 88 private String havingClassTag = null; 89 90 93 private String subTaskClassName = null; 94 95 private ArrayList packageSubstitutions = new ArrayList(); 96 97 private boolean packageSubstitutionInheritanceSupported = true; 98 99 private GenerationManager generationManager; 100 101 public TemplateSubTask() 102 { 103 super(); 104 DocletTask.registerSubTaskName(this, SUBTASK_NAME); 105 } 106 107 114 protected static String javaFile(String className) 115 { 116 return className.replace('.', '/') + ".java"; 117 } 118 119 public boolean getAcceptInterfaces() 120 { 121 return acceptInterfaces; 122 } 123 124 public boolean getAcceptAbstractClasses() 125 { 126 return acceptAbstractClasses; 127 } 128 129 public GenerationManager getGenerationManager() 130 { 131 return generationManager; 132 } 133 134 139 public ArrayList getPackageSubstitutions() 140 { 141 return packageSubstitutions; 142 } 143 144 150 public boolean isPackageSubstitutionInheritanceSupported() 151 { 152 return packageSubstitutionInheritanceSupported; 153 } 154 155 160 public String getSubTaskClassName() 161 { 162 return subTaskClassName; 163 } 164 165 170 public TemplateEngine getEngine() 171 { 172 if (engine == null) { 173 throw new IllegalStateException ("Engine is null?!"); 174 } 175 return engine; 176 } 177 178 183 public URL getTemplateURL() 184 { 185 return templateURL; 186 } 187 188 193 public String getDestinationFile() 194 { 195 return destinationFile; 196 } 197 198 203 public String [] getOfType() 204 { 205 String [] result = new String [ofType.size()]; 206 207 for (int i = 0; i < ofType.size(); i++) { 208 result[i] = ((OfType) ofType.get(i)).getType(); 209 } 210 211 return result; 212 } 213 214 219 public String getExtent() 220 { 221 return extent; 222 } 223 224 229 public String getHavingClassTag() 230 { 231 return havingClassTag; 232 } 233 234 239 public boolean isPrefixWithPackageStructure() 240 { 241 return prefixWithPackageStructure; 242 } 243 244 250 public void setAcceptInterfaces(boolean acceptInterfaces) 251 { 252 this.acceptInterfaces = acceptInterfaces; 253 } 254 255 261 public void setAcceptAbstractClasses(boolean acceptAbstractClasses) 262 { 263 this.acceptAbstractClasses = acceptAbstractClasses; 264 } 265 266 271 public void setPackageSubstitutions(ArrayList packageSubstitutions) 272 { 273 this.packageSubstitutions = packageSubstitutions; 274 } 275 276 282 public void setPackageSubstitutionInheritanceSupported(boolean packageSubstitutionInheritanceSupported) 283 { 284 this.packageSubstitutionInheritanceSupported = packageSubstitutionInheritanceSupported; 285 } 286 287 293 public void setSubTaskClassName(String subTaskClassName) 294 { 295 this.subTaskClassName = subTaskClassName; 296 } 297 298 304 public void setPrefixWithPackageStructure(boolean prefixWithPackageStructure) 305 { 306 this.prefixWithPackageStructure = prefixWithPackageStructure; 307 } 308 309 315 public void setEngine(TemplateEngine engine) 316 { 317 this.engine = engine; 318 } 319 320 327 public void setDestinationFile(String destinationFile) 328 { 329 this.destinationFile = destinationFile; 330 } 331 332 339 public void setTemplateURL(URL templateURL) 340 { 341 this.templateURL = templateURL; 342 } 343 344 351 public void setTemplateFile(File templateFile) throws XDocletException 352 { 353 if (templateFile.exists()) { 354 try { 355 setTemplateURL(templateFile.toURL()); 356 } 357 catch (MalformedURLException e) { 358 throw new XDocletException(e.getMessage()); 359 } 360 } 361 else { 362 throw new XDocletException("Couldn't find template: " + templateFile.getAbsolutePath()); 363 } 364 } 365 366 380 public void setExtent(ExtentTypes extent) 381 { 382 this.extent = extent.getValue(); 383 } 384 385 390 public void setHavingClassTag(String havingClassTag) 391 { 392 this.havingClassTag = havingClassTag; 393 } 394 395 public void setOfType(String ofType) 396 { 397 StringTokenizer st = new StringTokenizer(ofType, ","); 398 399 while (st.hasMoreTokens()) { 400 String type = st.nextToken(); 401 402 OfType new_oftype = new OfType(); 403 404 new_oftype.setType(type); 405 addOfType(new_oftype); 406 } 407 } 408 409 public void addOfType(OfType ofType) 410 { 411 this.ofType.add(ofType); 412 } 413 414 419 public void addPackageSubstitution(xdoclet.tagshandler.PackageTagsHandler.PackageSubstitution ps) 420 { 421 packageSubstitutions.add(ps); 422 } 423 424 429 public void copyAttributesFrom(TemplateSubTask src) 430 { 431 setTemplateURL(src.getTemplateURL()); 432 setPrefixWithPackageStructure(src.isPrefixWithPackageStructure()); 433 setAcceptInterfaces(src.getAcceptInterfaces()); 434 setAcceptAbstractClasses(src.getAcceptAbstractClasses()); 435 setDestinationFile(src.getDestinationFile()); 436 for (int i = 0; i < src.ofType.size(); i++) { 437 addOfType((OfType) src.ofType.get(i)); 438 } 439 setExtentValue(src.getExtent()); 440 setHavingClassTag(src.getHavingClassTag()); 441 setSubTaskClassName(src.getSubTaskClassName()); 442 for (int i = 0; i < src.packageSubstitutions.size(); i++) { 443 addPackageSubstitution((PackageTagsHandler.PackageSubstitution) src.packageSubstitutions.get(i)); 444 } 445 setPackageSubstitutionInheritanceSupported(src.isPackageSubstitutionInheritanceSupported()); 446 setGenerationManager(src.getGenerationManager()); 447 } 448 449 455 public void init(XJavaDoc xJavaDoc) throws XDocletException 456 { 457 super.init(xJavaDoc); 458 TemplateEngine.getEngineInstance().setXJavaDoc(getXJavaDoc()); 459 setEngine(TemplateEngine.getEngineInstance()); 460 } 461 462 467 public void validateOptions() throws XDocletException 468 { 469 super.validateOptions(); 470 471 if (getTemplateURL() == null) { 472 throw new XDocletException(Translator.getString(XDocletTemplateMessages.class, XDocletTemplateMessages.TEMPLATE_PARAMETER_MISSING, new String []{"templateFile"})); 473 } 474 475 if (getDestinationFile() == null) { 476 throw new XDocletException(Translator.getString(XDocletTemplateMessages.class, XDocletTemplateMessages.TEMPLATE_PARAMETER_MISSING, new String []{"destinationFile"})); 477 } 478 } 479 480 485 public void execute() throws XDocletException 486 { 487 startProcess(); 488 } 489 490 498 protected String getGeneratedFileName(XClass clazz) throws XDocletException 499 { 500 Log log = LogUtil.getLog(TemplateSubTask.class, "getGeneratedFileName"); 501 502 XPackage pak = clazz.getContainingPackage(); 503 String package_structure = null; 504 505 if (isPrefixWithPackageStructure() == true) 506 package_structure = PackageTagsHandler.packageNameAsPathFor(pak); 508 else 509 package_structure = null; 510 511 String packageName = isPackageSubstitutionInheritanceSupported() == true ? package_structure : null; 512 513 String name = clazz.getTransformedName(); 514 515 String destinationFile = MessageFormat.format(getDestinationFile(), new Object []{name}); 516 517 if (log.isDebugEnabled()) { 518 log.debug("clazz.getName()=" + clazz.getName()); 519 log.debug("clazz.getQualifiedName()=" + clazz.getQualifiedName()); 520 log.debug("pak=" + pak); 521 log.debug("packageName=" + packageName); 522 log.debug("destinationFile=" + destinationFile); 523 } 524 525 return new File (packageName, destinationFile).toString(); 526 } 527 528 533 protected void setGenerationManager(GenerationManager gM) 534 { 535 this.generationManager = gM; 536 } 537 538 543 protected void setExtentValue(String extent) 544 { 545 this.extent = extent; 546 } 547 548 555 protected final void startEngine(URL templateURL, File outputFile) throws TemplateException 556 { 557 engineStarted(); 558 559 getEngine().setOutput(outputFile); 560 getEngine().setTemplateURL(templateURL); 561 562 getEngine().start(); 563 564 engineFinished(); 565 } 566 567 protected void addOfType(String ofType) 568 { 569 OfType new_oftype = new OfType(); 570 571 new_oftype.setType(ofType); 572 573 this.ofType.add(new_oftype); 574 } 575 576 581 protected void startProcess() throws XDocletException 582 { 583 Log log = LogUtil.getLog(TemplateSubTask.class, "startProcess"); 584 585 if (log.isDebugEnabled()) { 586 log.debug("docEncoding=" + docEncoding); 587 log.debug("destDir.toString()=" + getDestDir()); 588 log.debug("getTemplateURL()=" + getTemplateURL()); 589 log.debug("getDestinationfile()=" + getDestinationFile()); 590 log.debug("getOfType()=" + getOfType()); 591 log.debug("getExtent()=" + getExtent()); 592 log.debug("getHavingClassTag()=" + getHavingClassTag()); 593 } 594 595 if (isGenerationPerClass()) { 596 startProcessPerClass(); 597 } 598 else { 599 startProcessForAll(); 600 } 601 } 602 603 protected void startProcessForAll() throws XDocletException 604 { 605 Log log = LogUtil.getLog(TemplateSubTask.class, "startProcessForAll"); 606 607 if (log.isDebugEnabled()) { 608 log.debug("Not per class."); 609 } 610 611 getEngine().setTemplateURL(getTemplateURL()); 612 613 File outputFile = new File (getDestDir(), getDestinationFile()); 614 615 try { 616 setGenerationManager(new GenerationManager(getXJavaDoc(), this)); 617 if (generationManager.isGenerationNeeded(outputFile)) { 618 startEngine(getTemplateURL(), outputFile); 619 } 620 } 621 catch (TemplateException e) { 622 if (e instanceof XDocletException) { 623 throw (XDocletException) e; 624 } 625 else { 626 if (log.isDebugEnabled()) { 627 log.debug("startProcess()"); 628 } 629 throw new XDocletException(e, Translator.getString(XDocletMessages.class, XDocletMessages.RUNNING_FAILED)); 630 } 631 } 632 } 633 634 640 protected boolean processInnerClasses() 641 { 642 return false; 643 } 644 645 protected void startProcessPerClass() throws XDocletException 646 { 647 Log log = LogUtil.getLog(TemplateSubTask.class, "startProcessPerClass"); 648 649 if (log.isDebugEnabled()) { 650 log.debug("Per class."); 651 } 652 653 659 Collection classes; 660 XJavaDoc xjavadoc = getXJavaDoc(); 661 662 xjavadoc.setUseNodeParser(false); 663 if (processInnerClasses()) { 665 classes = xjavadoc.getSourceClasses(); 666 } 667 else { 668 classes = xjavadoc.getSourceClasses(new XJavaDoc.NoInnerClassesPredicate()); 669 } 670 671 for (Iterator i = classes.iterator(); i.hasNext(); ) { 672 XClass clazz = (XClass) i.next(); 673 674 setCurrentClass(clazz); 675 if (matchesGenerationRules(clazz)) { 676 if (log.isDebugEnabled()) { 677 log.debug("Working on " + clazz); 678 } 679 generateForClass(clazz); 680 } 681 } 682 } 683 684 692 protected boolean matchesGenerationRules(XClass clazz) throws XDocletException 693 { 694 Log log = LogUtil.getLog(TemplateSubTask.class, "matchesGenerationRules"); 695 696 if (clazz.getContainingClass() != null && !processInnerClasses()) { 698 return false; 699 } 700 701 if (isDocletGenerated(clazz)) { 703 if (log.isDebugEnabled()) { 704 log.debug("Reject file '" + clazz.getQualifiedName() + "' because it is a doclet generated one."); 705 } 706 return false; 707 } 708 709 if (acceptInterfaces == false && clazz.isInterface()) { 710 if (log.isDebugEnabled()) { 711 log.debug("Reject file '" + clazz.getQualifiedName() + "' because it is an interface and acceptInterfaces=false."); 712 } 713 return false; 714 } 715 716 if (acceptAbstractClasses == false && clazz.isAbstract()) { 717 if (log.isDebugEnabled()) { 718 log.debug("Reject file '" + clazz.getQualifiedName() + "' because it is an abstract class and acceptAbstractClasses=false."); 719 } 720 return false; 721 } 722 723 if (ofType.size() > 0 && classIsntOfOneOfTheTypes(clazz, log)) 724 return false; 725 726 if (getHavingClassTag() != null) { 727 if (!clazz.getDoc().hasTag(getHavingClassTag(), false)) { 728 if (log.isDebugEnabled()) { 729 log.debug("Reject class '" + clazz.getQualifiedName() + "' because it doesn't have class tag '" + getHavingClassTag() + "'."); 730 } 731 return false; 732 } 733 else { 734 if (log.isDebugEnabled()) { 735 log.debug("Accept class '" + clazz.getQualifiedName() + "' because it has class tag '" + getHavingClassTag() + "'."); 736 } 737 } 738 } 739 740 return true; 741 } 742 743 749 protected void generateForClass(XClass clazz) throws XDocletException 750 { 751 Log log = LogUtil.getLog(TemplateSubTask.class, "generateForClass"); 752 753 File file = new File (getDestDir().toString(), getGeneratedFileName(clazz)); 754 755 if (log.isDebugEnabled()) { 756 log.debug("destDir.toString()=" + getDestDir().toString()); 757 log.debug("getGeneratedFileName()=" + getGeneratedFileName(clazz)); 758 log.debug("file=" + file); 759 } 760 761 if (file.exists()) { 762 log.debug("File exists."); 763 764 setGenerationManager(new GenerationManager(getXJavaDoc(), this)); 766 767 boolean isGenerationNeeded = generationManager.isGenerationNeeded(clazz, file, true); 768 769 if (!isGenerationNeeded) { 770 return; 771 } 772 } 773 774 file.getParentFile().mkdirs(); 775 776 try { 777 setCurrentPackage(clazz.getContainingPackage()); 778 setCurrentClass(clazz); 779 startEngine(getTemplateURL(), new File (getDestDir(), getGeneratedFileName(clazz))); 780 } 781 catch (TemplateException e) { 782 if (e instanceof XDocletException) { 783 throw (XDocletException) e; 784 } 785 else { 786 log.debug("generateForClass()"); 787 e.printStackTrace(); 788 throw new XDocletException(e, Translator.getString(XDocletMessages.class, XDocletMessages.RUNNING_FAILED)); 789 } 790 } 791 } 792 793 798 protected void engineStarted() throws XDocletException 799 { 800 Log log = LogUtil.getLog(TemplateSubTask.class, "engineStarted"); 801 802 if (isGenerationPerClass()) { 803 log.info(Translator.getString(XDocletMessages.class, XDocletMessages.GENERATING_TEMPLATE_OUTPUT_PER_CLASS, new String []{getCurrentClass().getQualifiedName(), getTemplateURL().toString()})); 804 } 805 else { 806 log.info(Translator.getString(XDocletMessages.class, XDocletMessages.GENERATING_TEMPLATE_OUTPUT_SINGLE_FILE, new String []{getDestinationFile(), getTemplateURL().toString()})); 807 } 808 809 if (log.isDebugEnabled()) { 810 log.debug("getCurrentClass()=" + getCurrentClass()); 811 log.debug("isGenerationPerClass()=" + isGenerationPerClass()); 812 } 813 } 814 815 820 protected void engineFinished() throws TemplateException 821 { 822 } 823 824 829 private boolean isGenerationPerClass() 830 { 831 return getDestinationFile().indexOf("{0}") != -1; 832 } 833 834 private boolean classIsntOfOneOfTheTypes(XClass clazz, Log log) 835 { 836 boolean match = false; 837 String type = null; 838 int extent_value = TypeTagsHandler.extractExtentType(getExtent()); 839 840 for (Iterator it = ofType.iterator(); it.hasNext(); ) { 841 type = ((OfType) it.next()).getType(); 842 843 if (TypeTagsHandler.isOfType(clazz, type, extent_value) == true) { 844 845 match = true; 846 break; 847 } 848 } 849 850 if (!match) { 851 if (log.isDebugEnabled()) { 852 log.debug("Reject class '" + clazz.getQualifiedName() + "' because it is not of the specified types according to extent='" + getExtent() + "'."); 853 } 854 855 return true; 856 } 857 else { 858 if (log.isDebugEnabled()) { 859 log.debug("Accept class '" + clazz.getQualifiedName() + "' because it is of type '" + type + "'."); 860 } 861 862 return false; 863 } 864 } 865 866 870 public final static class ExtentTypes extends org.apache.tools.ant.types.EnumeratedAttribute 871 { 872 public final static String EXTENT_TYPE_CONCRETE_TYPE = "concrete-type"; 873 public final static String EXTENT_TYPE_SUPERCLASS = "superclass"; 874 public final static String EXTENT_TYPE_HIERARCHY = "hierarchy"; 875 876 public java.lang.String [] getValues() 877 { 878 return (new java.lang.String []{EXTENT_TYPE_CONCRETE_TYPE, EXTENT_TYPE_SUPERCLASS, EXTENT_TYPE_HIERARCHY}); 879 } 880 } 881 882 889 public final static class OfType 890 { 891 private String type; 892 893 public String getType() 894 { 895 return type; 896 } 897 898 public void setType(String type) 899 { 900 this.type = type; 901 } 902 } 903 } 904 | Popular Tags |