src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java

Sat, 08 Sep 2012 22:43:38 -0700

author
bpatel
date
Sat, 08 Sep 2012 22:43:38 -0700
changeset 1324
fa85af323d97
parent 554
9d9f26857129
child 1339
0e5899f09dab
permissions
-rw-r--r--

7180906: Javadoc tool does not apply parameter -nosince
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.doclets.internal.toolkit.taglets;
    28 import com.sun.javadoc.*;
    29 import com.sun.tools.doclets.internal.toolkit.util.*;
    31 import java.io.*;
    32 import java.lang.reflect.*;
    33 import java.net.*;
    34 import java.util.*;
    36 /**
    37  * Manages the<code>Taglet</code>s used by doclets.
    38  *
    39  * This code is not part of an API.
    40  * It is implementation that is subject to change.
    41  * Do not use it as an API
    42  *
    43  * @author Jamie Ho
    44  * @since 1.4
    45  */
    47 public class TagletManager {
    49     /**
    50      * The default seperator for the simple tag option.
    51      */
    52     public static final char SIMPLE_TAGLET_OPT_SEPERATOR = ':';
    54     /**
    55      * The alternate seperator for simple tag options.  Use this
    56      * with you want the default seperator to be in the name of the
    57      * custom tag.
    58      */
    59     public static final String ALT_SIMPLE_TAGLET_OPT_SEPERATOR = "-";
    61     /**
    62      * The map of custom tags.
    63      */
    64     private LinkedHashMap<String,Taglet> customTags;
    66     /**
    67      * The array of custom tags that can appear in packages.
    68      */
    69     private Taglet[] packageTags;
    71     /**
    72      * The array of custom tags that can appear in classes or interfaces.
    73      */
    74     private Taglet[] typeTags;
    76     /**
    77      * The array of custom tags that can appear in fields.
    78      */
    79     private Taglet[] fieldTags;
    81     /**
    82      * The array of custom tags that can appear in constructors.
    83      */
    84     private Taglet[] constructorTags;
    86     /**
    87      * The array of custom tags that can appear in methods.
    88      */
    89     private Taglet[] methodTags;
    91     /**
    92      * The array of custom tags that can appear in the overview.
    93      */
    94     private Taglet[] overviewTags;
    96     /**
    97      * The array of custom tags that can appear in comments.
    98      */
    99     private Taglet[] inlineTags;
   101     /**
   102      * The array of custom tags that can appear in the serialized form.
   103      */
   104     private Taglet[] serializedFormTags;
   106     /**
   107      * The message retriever that will be used to print error messages.
   108      */
   109     private MessageRetriever message;
   111     /**
   112      * Keep track of standard tags.
   113      */
   114     private Set<String> standardTags;
   116     /**
   117      * Keep track of standard tags in lowercase to compare for better
   118      * error messages when a tag like @docRoot is mistakenly spelled
   119      * lowercase @docroot.
   120      */
   121     private Set<String> standardTagsLowercase;
   123     /**
   124      * Keep track of overriden standard tags.
   125      */
   126     private Set<String> overridenStandardTags;
   128     /**
   129      * Keep track of the tags that may conflict
   130      * with standard tags in the future (any custom tag without
   131      * a period in its name).
   132      */
   133     private Set<String> potentiallyConflictingTags;
   135     /**
   136      * The set of unseen custom tags.
   137      */
   138     private Set<String> unseenCustomTags;
   140     /**
   141      * True if we do not want to use @since tags.
   142      */
   143     private boolean nosince;
   145     /**
   146      * True if we want to use @version tags.
   147      */
   148     private boolean showversion;
   150     /**
   151      * True if we want to use @author tags.
   152      */
   153     private boolean showauthor;
   155     /**
   156      * Construct a new <code>TagletManager</code>.
   157      * @param nosince true if we do not want to use @since tags.
   158      * @param showversion true if we want to use @version tags.
   159      * @param showauthor true if we want to use @author tags.
   160      * @param message the message retriever to print warnings.
   161      */
   162     public TagletManager(boolean nosince, boolean showversion,
   163                          boolean showauthor, MessageRetriever message){
   164         overridenStandardTags = new HashSet<String>();
   165         potentiallyConflictingTags = new HashSet<String>();
   166         standardTags = new HashSet<String>();
   167         standardTagsLowercase = new HashSet<String>();
   168         unseenCustomTags = new HashSet<String>();
   169         customTags = new LinkedHashMap<String,Taglet>();
   170         this.nosince = nosince;
   171         this.showversion = showversion;
   172         this.showauthor = showauthor;
   173         this.message = message;
   174         initStandardTags();
   175         initStandardTagsLowercase();
   176     }
   178     /**
   179      * Add a new <code>CustomTag</code>.  This is used to add a Taglet from within
   180      * a Doclet.  No message is printed to indicate that the Taglet is properly
   181      * registered because these Taglets are typically added for every execution of the
   182      * Doclet.  We don't want to see this type of error message every time.
   183      * @param customTag the new <code>CustomTag</code> to add.
   184      */
   185     public void addCustomTag(Taglet customTag) {
   186         if (customTag != null) {
   187             String name = customTag.getName();
   188             if (customTags.containsKey(name)) {
   189                 customTags.remove(name);
   190             }
   191             customTags.put(name, customTag);
   192             checkTagName(name);
   193         }
   194     }
   196     /**
   197      * Add a new <code>Taglet</code>.  Print a message to indicate whether or not
   198      * the Taglet was registered properly.
   199      * @param classname  the name of the class representing the custom tag.
   200      * @param tagletPath  the path to the class representing the custom tag.
   201      */
   202     public void addCustomTag(String classname, String tagletPath) {
   203         try {
   204             Class<?> customTagClass = null;
   205             // construct class loader
   206             String cpString = null;   // make sure env.class.path defaults to dot
   208             // do prepends to get correct ordering
   209             cpString = appendPath(System.getProperty("env.class.path"), cpString);
   210             cpString = appendPath(System.getProperty("java.class.path"), cpString);
   211             cpString = appendPath(tagletPath, cpString);
   212             URLClassLoader appClassLoader = new URLClassLoader(pathToURLs(cpString));
   213             customTagClass = appClassLoader.loadClass(classname);
   214             Method meth = customTagClass.getMethod("register",
   215                                                    new Class<?>[] {java.util.Map.class});
   216             Object[] list = customTags.values().toArray();
   217             Taglet lastTag = (list != null && list.length > 0)
   218                 ? (Taglet) list[list.length-1] : null;
   219             meth.invoke(null, new Object[] {customTags});
   220             list = customTags.values().toArray();
   221             Object newLastTag = (list != null&& list.length > 0)
   222                 ? list[list.length-1] : null;
   223             if (lastTag != newLastTag) {
   224                 //New taglets must always be added to the end of the LinkedHashMap.
   225                 //If the current and previous last taglet are not equal, that
   226                 //means a new Taglet has been added.
   227                 message.notice("doclet.Notice_taglet_registered", classname);
   228                 if (newLastTag != null) {
   229                     checkTaglet(newLastTag);
   230                 }
   231             }
   232         } catch (Exception exc) {
   233             message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname);
   234         }
   236     }
   238     private String appendPath(String path1, String path2) {
   239         if (path1 == null || path1.length() == 0) {
   240             return path2 == null ? "." : path2;
   241         } else if (path2 == null || path2.length() == 0) {
   242             return path1;
   243         } else {
   244             return path1  + File.pathSeparator + path2;
   245         }
   246     }
   248     /**
   249      * Utility method for converting a search path string to an array
   250      * of directory and JAR file URLs.
   251      *
   252      * @param path the search path string
   253      * @return the resulting array of directory and JAR file URLs
   254      */
   255     private static URL[] pathToURLs(String path) {
   256         StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
   257         URL[] urls = new URL[st.countTokens()];
   258         int count = 0;
   259         while (st.hasMoreTokens()) {
   260             URL url = fileToURL(new File(st.nextToken()));
   261             if (url != null) {
   262                 urls[count++] = url;
   263             }
   264         }
   265         if (urls.length != count) {
   266             URL[] tmp = new URL[count];
   267             System.arraycopy(urls, 0, tmp, 0, count);
   268             urls = tmp;
   269         }
   270         return urls;
   271     }
   273     /**
   274      * Returns the directory or JAR file URL corresponding to the specified
   275      * local file name.
   276      *
   277      * @param file the File object
   278      * @return the resulting directory or JAR file URL, or null if unknown
   279      */
   280     private static URL fileToURL(File file) {
   281         String name;
   282         try {
   283             name = file.getCanonicalPath();
   284         } catch (IOException e) {
   285             name = file.getAbsolutePath();
   286         }
   287         name = name.replace(File.separatorChar, '/');
   288         if (!name.startsWith("/")) {
   289             name = "/" + name;
   290         }
   291         // If the file does not exist, then assume that it's a directory
   292         if (!file.isFile()) {
   293             name = name + "/";
   294         }
   295         try {
   296             return new URL("file", "", name);
   297         } catch (MalformedURLException e) {
   298             throw new IllegalArgumentException("file");
   299         }
   300     }
   303     /**
   304      * Add a new <code>SimpleTaglet</code>.  If this tag already exists
   305      * and the header passed as an argument is null, move tag to the back of the
   306      * list. If this tag already exists and the header passed as an argument is
   307      * not null, overwrite previous tag with new one.  Otherwise, add new
   308      * SimpleTaglet to list.
   309      * @param tagName the name of this tag
   310      * @param header the header to output.
   311      * @param locations the possible locations that this tag
   312      * can appear in.
   313      */
   314     public void addNewSimpleCustomTag(String tagName, String header, String locations) {
   315         if (tagName == null || locations == null) {
   316             return;
   317         }
   318         Taglet tag = customTags.get(tagName);
   319         locations = locations.toLowerCase();
   320         if (tag == null || header != null) {
   321             customTags.remove(tagName);
   322             customTags.put(tagName, new SimpleTaglet(tagName, header, locations));
   323             if (locations != null && locations.indexOf('x') == -1) {
   324                 checkTagName(tagName);
   325             }
   326         } else {
   327             //Move to back
   328             customTags.remove(tagName);
   329             customTags.put(tagName, tag);
   330         }
   331     }
   333     /**
   334      * Given a tag name, add it to the set of tags it belongs to.
   335      */
   336     private void checkTagName(String name) {
   337         if (standardTags.contains(name)) {
   338             overridenStandardTags.add(name);
   339         } else {
   340             if (name.indexOf('.') == -1) {
   341                 potentiallyConflictingTags.add(name);
   342             }
   343             unseenCustomTags.add(name);
   344         }
   345     }
   347     /**
   348      * Check the taglet to see if it is a legacy taglet.  Also
   349      * check its name for errors.
   350      */
   351     private void checkTaglet(Object taglet) {
   352         if (taglet instanceof Taglet) {
   353             checkTagName(((Taglet) taglet).getName());
   354         } else if (taglet instanceof com.sun.tools.doclets.Taglet) {
   355             com.sun.tools.doclets.Taglet legacyTaglet = (com.sun.tools.doclets.Taglet) taglet;
   356             customTags.remove(legacyTaglet.getName());
   357             customTags.put(legacyTaglet.getName(), new LegacyTaglet(legacyTaglet));
   358             checkTagName(legacyTaglet.getName());
   359         } else {
   360             throw new IllegalArgumentException("Given object is not a taglet.");
   361         }
   362     }
   364     /**
   365      * Given a name of a seen custom tag, remove it from the set of unseen
   366      * custom tags.
   367      * @param name the name of the seen custom tag.
   368      */
   369     public void seenCustomTag(String name) {
   370         unseenCustomTags.remove(name);
   371     }
   373     /**
   374      * Given an array of <code>Tag</code>s, check for spelling mistakes.
   375      * @param doc the Doc object that holds the tags.
   376      * @param tags the list of <code>Tag</code>s to check.
   377      * @param areInlineTags true if the array of tags are inline and false otherwise.
   378      */
   379     public void checkTags(Doc doc, Tag[] tags, boolean areInlineTags) {
   380         if (tags == null) {
   381             return;
   382         }
   383         Taglet taglet;
   384         for (int i = 0; i < tags.length; i++) {
   385             String name = tags[i].name();
   386             if (name.length() > 0 && name.charAt(0) == '@') {
   387                 name = name.substring(1, name.length());
   388             }
   389             if (! (standardTags.contains(name) || customTags.containsKey(name))) {
   390                 if (standardTagsLowercase.contains(name.toLowerCase())) {
   391                     message.warning(tags[i].position(), "doclet.UnknownTagLowercase", tags[i].name());
   392                     continue;
   393                 } else {
   394                     message.warning(tags[i].position(), "doclet.UnknownTag", tags[i].name());
   395                     continue;
   396                 }
   397             }
   398             //Check if this tag is being used in the wrong location.
   399             if ((taglet = customTags.get(name)) != null) {
   400                 if (areInlineTags && ! taglet.isInlineTag()) {
   401                     printTagMisuseWarn(taglet, tags[i], "inline");
   402                 }
   403                 if ((doc instanceof RootDoc) && ! taglet.inOverview()) {
   404                     printTagMisuseWarn(taglet, tags[i], "overview");
   405                 } else if ((doc instanceof PackageDoc) && ! taglet.inPackage()) {
   406                     printTagMisuseWarn(taglet, tags[i], "package");
   407                 } else if ((doc instanceof ClassDoc) && ! taglet.inType()) {
   408                     printTagMisuseWarn(taglet, tags[i], "class");
   409                 } else if ((doc instanceof ConstructorDoc) && ! taglet.inConstructor()) {
   410                     printTagMisuseWarn(taglet, tags[i], "constructor");
   411                 } else if ((doc instanceof FieldDoc) && ! taglet.inField()) {
   412                     printTagMisuseWarn(taglet, tags[i], "field");
   413                 } else if ((doc instanceof MethodDoc) && ! taglet.inMethod()) {
   414                     printTagMisuseWarn(taglet, tags[i], "method");
   415                 }
   416             }
   417         }
   418     }
   420     /**
   421      * Given the taglet, the tag and the type of documentation that the tag
   422      * was found in, print a tag misuse warning.
   423      * @param taglet the taglet representing the misused tag.
   424      * @param tag the misused tag.
   425      * @param holderType the type of documentation that the misused tag was found in.
   426      */
   427     private void printTagMisuseWarn(Taglet taglet, Tag tag, String holderType) {
   428         Set<String> locationsSet = new LinkedHashSet<String>();
   429         if (taglet.inOverview()) {
   430             locationsSet.add("overview");
   431         }
   432         if (taglet.inPackage()) {
   433             locationsSet.add("package");
   434         }
   435         if (taglet.inType()) {
   436             locationsSet.add("class/interface");
   437         }
   438         if (taglet.inConstructor())  {
   439             locationsSet.add("constructor");
   440         }
   441         if (taglet.inField()) {
   442             locationsSet.add("field");
   443         }
   444         if (taglet.inMethod()) {
   445             locationsSet.add("method");
   446         }
   447         if (taglet.isInlineTag()) {
   448             locationsSet.add("inline text");
   449         }
   450         String[] locations = locationsSet.toArray(new String[]{});
   451         if (locations == null || locations.length == 0) {
   452             //This known tag is excluded.
   453             return;
   454         }
   455         StringBuffer combined_locations = new StringBuffer();
   456         for (int i = 0; i < locations.length; i++) {
   457             if (i > 0) {
   458                 combined_locations.append(", ");
   459             }
   460             combined_locations.append(locations[i]);
   461         }
   462         message.warning(tag.position(), "doclet.tag_misuse",
   463             "@" + taglet.getName(), holderType, combined_locations.toString());
   464     }
   466     /**
   467      * Return the array of <code>Taglet</code>s that can
   468      * appear in packages.
   469      * @return the array of <code>Taglet</code>s that can
   470      * appear in packages.
   471      */
   472     public Taglet[] getPackageCustomTags() {
   473         if (packageTags == null) {
   474             initCustomTagArrays();
   475         }
   476         return packageTags;
   477     }
   479     /**
   480      * Return the array of <code>Taglet</code>s that can
   481      * appear in classes or interfaces.
   482      * @return the array of <code>Taglet</code>s that can
   483      * appear in classes or interfaces.
   484      */
   485     public Taglet[] getTypeCustomTags() {
   486         if (typeTags == null) {
   487             initCustomTagArrays();
   488         }
   489         return typeTags;
   490     }
   492     /**
   493      * Return the array of inline <code>Taglet</code>s that can
   494      * appear in comments.
   495      * @return the array of <code>Taglet</code>s that can
   496      * appear in comments.
   497      */
   498     public Taglet[] getInlineCustomTags() {
   499         if (inlineTags == null) {
   500             initCustomTagArrays();
   501         }
   502         return inlineTags;
   503     }
   505     /**
   506      * Return the array of <code>Taglet</code>s that can
   507      * appear in fields.
   508      * @return the array of <code>Taglet</code>s that can
   509      * appear in field.
   510      */
   511     public Taglet[] getFieldCustomTags() {
   512         if (fieldTags == null) {
   513             initCustomTagArrays();
   514         }
   515         return fieldTags;
   516     }
   518     /**
   519      * Return the array of <code>Taglet</code>s that can
   520      * appear in the serialized form.
   521      * @return the array of <code>Taglet</code>s that can
   522      * appear in the serialized form.
   523      */
   524     public Taglet[] getSerializedFormTags() {
   525         if (serializedFormTags == null) {
   526             initCustomTagArrays();
   527         }
   528         return serializedFormTags;
   529     }
   531     /**
   532      * @return the array of <code>Taglet</code>s that can
   533      * appear in the given Doc.
   534      */
   535     public Taglet[] getCustomTags(Doc doc) {
   536         if (doc instanceof ConstructorDoc) {
   537             return getConstructorCustomTags();
   538         } else if (doc instanceof MethodDoc) {
   539             return getMethodCustomTags();
   540         } else if (doc instanceof FieldDoc) {
   541             return getFieldCustomTags();
   542         } else if (doc instanceof ClassDoc) {
   543             return getTypeCustomTags();
   544         } else if (doc instanceof PackageDoc) {
   545             return getPackageCustomTags();
   546         } else if (doc instanceof RootDoc) {
   547             return getOverviewCustomTags();
   548         }
   549         return null;
   550     }
   552     /**
   553      * Return the array of <code>Taglet</code>s that can
   554      * appear in constructors.
   555      * @return the array of <code>Taglet</code>s that can
   556      * appear in constructors.
   557      */
   558     public Taglet[] getConstructorCustomTags() {
   559         if (constructorTags == null) {
   560             initCustomTagArrays();
   561         }
   562         return constructorTags;
   563     }
   565     /**
   566      * Return the array of <code>Taglet</code>s that can
   567      * appear in methods.
   568      * @return the array of <code>Taglet</code>s that can
   569      * appear in methods.
   570      */
   571     public Taglet[] getMethodCustomTags() {
   572         if (methodTags == null) {
   573             initCustomTagArrays();
   574         }
   575         return methodTags;
   576     }
   578     /**
   579      * Return the array of <code>Taglet</code>s that can
   580      * appear in an overview.
   581      * @return the array of <code>Taglet</code>s that can
   582      * appear in overview.
   583      */
   584     public Taglet[] getOverviewCustomTags() {
   585         if (overviewTags == null) {
   586             initCustomTagArrays();
   587         }
   588         return overviewTags;
   589     }
   591     /**
   592      * Initialize the custom tag arrays.
   593      */
   594     private void initCustomTagArrays() {
   595         Iterator<Taglet> it = customTags.values().iterator();
   596         ArrayList<Taglet> pTags = new ArrayList<Taglet>(customTags.size());
   597         ArrayList<Taglet> tTags = new ArrayList<Taglet>(customTags.size());
   598         ArrayList<Taglet> fTags = new ArrayList<Taglet>(customTags.size());
   599         ArrayList<Taglet> cTags = new ArrayList<Taglet>(customTags.size());
   600         ArrayList<Taglet> mTags = new ArrayList<Taglet>(customTags.size());
   601         ArrayList<Taglet> iTags = new ArrayList<Taglet>(customTags.size());
   602         ArrayList<Taglet> oTags = new ArrayList<Taglet>(customTags.size());
   603         ArrayList<Taglet> sTags = new ArrayList<Taglet>();
   604         Taglet current;
   605         while (it.hasNext()) {
   606             current = it.next();
   607             if (current.inPackage() && !current.isInlineTag()) {
   608                 pTags.add(current);
   609             }
   610             if (current.inType() && !current.isInlineTag()) {
   611                 tTags.add(current);
   612             }
   613             if (current.inField() && !current.isInlineTag()) {
   614                 fTags.add(current);
   615             }
   616             if (current.inConstructor() && !current.isInlineTag()) {
   617                 cTags.add(current);
   618             }
   619             if (current.inMethod() && !current.isInlineTag()) {
   620                 mTags.add(current);
   621             }
   622             if (current.isInlineTag()) {
   623                 iTags.add(current);
   624             }
   625             if (current.inOverview() && !current.isInlineTag()) {
   626                 oTags.add(current);
   627             }
   628         }
   629         packageTags = pTags.toArray(new Taglet[] {});
   630         typeTags = tTags.toArray(new Taglet[] {});
   631         fieldTags = fTags.toArray(new Taglet[] {});
   632         constructorTags = cTags.toArray(new Taglet[] {});
   633         methodTags = mTags.toArray(new Taglet[] {});
   634         overviewTags = oTags.toArray(new Taglet[] {});
   635         inlineTags = iTags.toArray(new Taglet[] {});
   637         //Init the serialized form tags
   638         sTags.add(customTags.get("serialData"));
   639         sTags.add(customTags.get("throws"));
   640         if (!nosince)
   641             sTags.add(customTags.get("since"));
   642         sTags.add(customTags.get("see"));
   643         serializedFormTags = sTags.toArray(new Taglet[] {});
   644     }
   646     /**
   647      * Initialize standard Javadoc tags for ordering purposes.
   648      */
   649     private void initStandardTags() {
   650         Taglet temp;
   651         customTags.put((temp = new ParamTaglet()).getName(), temp);
   652         customTags.put((temp = new ReturnTaglet()).getName(), temp);
   653         customTags.put((temp = new ThrowsTaglet()).getName(), temp);
   654         customTags.put((temp = new SimpleTaglet("exception",
   655             null, SimpleTaglet.METHOD + SimpleTaglet.CONSTRUCTOR)).getName(), temp);
   656         if (!nosince) {
   657             customTags.put((temp = new SimpleTaglet("since", message.getText("doclet.Since"),
   658                SimpleTaglet.ALL)).getName(), temp);
   659         }
   660         if (showversion) {
   661             customTags.put((temp = new SimpleTaglet("version", message.getText("doclet.Version"),
   662                 SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp);
   663         }
   664         if (showauthor) {
   665             customTags.put((temp = new SimpleTaglet("author", message.getText("doclet.Author"),
   666                 SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp);
   667         }
   668         customTags.put((temp = new SimpleTaglet("serialData", message.getText("doclet.SerialData"),
   669             SimpleTaglet.EXCLUDED)).getName(), temp);
   670         customTags.put((temp = new SimpleTaglet("factory", message.getText("doclet.Factory"),
   671             SimpleTaglet.METHOD)).getName(), temp);
   672         customTags.put((temp = new SeeTaglet()).getName(), temp);
   673         //Standard inline tags
   674         customTags.put((temp = new DocRootTaglet()).getName(), temp);
   675         customTags.put((temp = new InheritDocTaglet()).getName(), temp);
   676         customTags.put((temp = new ValueTaglet()).getName(), temp);
   677         customTags.put((temp = new LegacyTaglet(new LiteralTaglet())).getName(),
   678             temp);
   679         customTags.put((temp = new LegacyTaglet(new CodeTaglet())).getName(),
   680             temp);
   682         //Keep track of the names of standard tags for error
   683         //checking purposes.
   684         standardTags.add("param");
   685         standardTags.add("return");
   686         standardTags.add("throws");
   687         standardTags.add("exception");
   688         standardTags.add("since");
   689         standardTags.add("version");
   690         standardTags.add("author");
   691         standardTags.add("see");
   692         standardTags.add("deprecated");
   693         standardTags.add("link");
   694         standardTags.add("linkplain");
   695         standardTags.add("inheritDoc");
   696         standardTags.add("docRoot");
   697         standardTags.add("value");
   698         standardTags.add("serial");
   699         standardTags.add("serialData");
   700         standardTags.add("serialField");
   701         standardTags.add("Text");
   702         standardTags.add("literal");
   703         standardTags.add("code");
   704     }
   706     /**
   707      * Initialize lowercase version of standard Javadoc tags.
   708      */
   709     private void initStandardTagsLowercase() {
   710         Iterator<String> it = standardTags.iterator();
   711         while (it.hasNext()) {
   712             standardTagsLowercase.add(it.next().toLowerCase());
   713         }
   714     }
   716     public boolean isKnownCustomTag(String tagName) {
   717         return customTags.containsKey(tagName);
   718     }
   720     /**
   721      * Print a list of {@link Taglet}s that might conflict with
   722      * standard tags in the future and a list of standard tags
   723      * that have been overriden.
   724      */
   725     public void printReport() {
   726         printReportHelper("doclet.Notice_taglet_conflict_warn", potentiallyConflictingTags);
   727         printReportHelper("doclet.Notice_taglet_overriden", overridenStandardTags);
   728         printReportHelper("doclet.Notice_taglet_unseen", unseenCustomTags);
   729     }
   731     private void printReportHelper(String noticeKey, Set<String> names) {
   732         if (names.size() > 0) {
   733             String[] namesArray = names.toArray(new String[] {});
   734             String result = " ";
   735             for (int i = 0; i < namesArray.length; i++) {
   736                 result += "@" + namesArray[i];
   737                 if (i + 1 < namesArray.length) {
   738                     result += ", ";
   739                 }
   740             }
   741             message.notice(noticeKey, result);
   742         }
   743     }
   745     /**
   746      * Given the name of a tag, return the corresponding taglet.
   747      * Return null if the tag is unknown.
   748      *
   749      * @param name the name of the taglet to retrieve.
   750      * @return return the corresponding taglet. Return null if the tag is
   751      *         unknown.
   752      */
   753     public Taglet getTaglet(String name) {
   754         if (name.indexOf("@") == 0) {
   755             return customTags.get(name.substring(1));
   756         } else {
   757             return customTags.get(name);
   758         }
   760     }
   761 }

mercurial