| /* |
| * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.tools.doclets.internal.toolkit.taglets; |
| |
| import java.io.*; |
| import java.lang.reflect.*; |
| import java.net.*; |
| import java.util.*; |
| |
| import javax.tools.DocumentationTool; |
| import javax.tools.JavaFileManager; |
| |
| import com.sun.javadoc.*; |
| import com.sun.tools.doclets.internal.toolkit.util.*; |
| import com.sun.tools.javac.util.StringUtils; |
| |
| /** |
| * Manages the<code>Taglet</code>s used by doclets. |
| * |
| * <p><b>This is NOT part of any supported API. |
| * If you write code that depends on this, you do so at your own risk. |
| * This code and its internal interfaces are subject to change or |
| * deletion without notice.</b> |
| * |
| * @author Jamie Ho |
| * @since 1.4 |
| */ |
| |
| public class TagletManager { |
| |
| /** |
| * The default separator for the simple tag option. |
| */ |
| public static final char SIMPLE_TAGLET_OPT_SEPARATOR = ':'; |
| |
| /** |
| * The alternate separator for simple tag options. Use this |
| * when you want the default separator to be in the name of the |
| * custom tag. |
| */ |
| public static final String ALT_SIMPLE_TAGLET_OPT_SEPARATOR = "-"; |
| |
| /** |
| * The map of custom tags. |
| */ |
| private LinkedHashMap<String,Taglet> customTags; |
| |
| /** |
| * The array of custom tags that can appear in packages. |
| */ |
| private Taglet[] packageTags; |
| |
| /** |
| * The array of custom tags that can appear in classes or interfaces. |
| */ |
| private Taglet[] typeTags; |
| |
| /** |
| * The array of custom tags that can appear in fields. |
| */ |
| private Taglet[] fieldTags; |
| |
| /** |
| * The array of custom tags that can appear in constructors. |
| */ |
| private Taglet[] constructorTags; |
| |
| /** |
| * The array of custom tags that can appear in methods. |
| */ |
| private Taglet[] methodTags; |
| |
| /** |
| * The array of custom tags that can appear in the overview. |
| */ |
| private Taglet[] overviewTags; |
| |
| /** |
| * The array of custom tags that can appear in comments. |
| */ |
| private Taglet[] inlineTags; |
| |
| /** |
| * The array of custom tags that can appear in the serialized form. |
| */ |
| private Taglet[] serializedFormTags; |
| |
| /** |
| * The message retriever that will be used to print error messages. |
| */ |
| private MessageRetriever message; |
| |
| /** |
| * Keep track of standard tags. |
| */ |
| private Set<String> standardTags; |
| |
| /** |
| * Keep track of standard tags in lowercase to compare for better |
| * error messages when a tag like @docRoot is mistakenly spelled |
| * lowercase @docroot. |
| */ |
| private Set<String> standardTagsLowercase; |
| |
| /** |
| * Keep track of overriden standard tags. |
| */ |
| private Set<String> overridenStandardTags; |
| |
| /** |
| * Keep track of the tags that may conflict |
| * with standard tags in the future (any custom tag without |
| * a period in its name). |
| */ |
| private Set<String> potentiallyConflictingTags; |
| |
| /** |
| * The set of unseen custom tags. |
| */ |
| private Set<String> unseenCustomTags; |
| |
| /** |
| * True if we do not want to use @since tags. |
| */ |
| private boolean nosince; |
| |
| /** |
| * True if we want to use @version tags. |
| */ |
| private boolean showversion; |
| |
| /** |
| * True if we want to use @author tags. |
| */ |
| private boolean showauthor; |
| |
| /** |
| * True if we want to use JavaFX-related tags (@propertyGetter, |
| * @propertySetter, @propertyDescription, @defaultValue, @treatAsPrivate). |
| */ |
| private boolean javafx; |
| |
| /** |
| * Construct a new <code>TagletManager</code>. |
| * @param nosince true if we do not want to use @since tags. |
| * @param showversion true if we want to use @version tags. |
| * @param showauthor true if we want to use @author tags. |
| * @param message the message retriever to print warnings. |
| */ |
| public TagletManager(boolean nosince, boolean showversion, |
| boolean showauthor, boolean javafx, |
| MessageRetriever message) { |
| overridenStandardTags = new HashSet<>(); |
| potentiallyConflictingTags = new HashSet<>(); |
| standardTags = new HashSet<>(); |
| standardTagsLowercase = new HashSet<>(); |
| unseenCustomTags = new HashSet<>(); |
| customTags = new LinkedHashMap<>(); |
| this.nosince = nosince; |
| this.showversion = showversion; |
| this.showauthor = showauthor; |
| this.javafx = javafx; |
| this.message = message; |
| initStandardTaglets(); |
| initStandardTagsLowercase(); |
| } |
| |
| /** |
| * Add a new <code>CustomTag</code>. This is used to add a Taglet from within |
| * a Doclet. No message is printed to indicate that the Taglet is properly |
| * registered because these Taglets are typically added for every execution of the |
| * Doclet. We don't want to see this type of error message every time. |
| * @param customTag the new <code>CustomTag</code> to add. |
| */ |
| public void addCustomTag(Taglet customTag) { |
| if (customTag != null) { |
| String name = customTag.getName(); |
| if (customTags.containsKey(name)) { |
| customTags.remove(name); |
| } |
| customTags.put(name, customTag); |
| checkTagName(name); |
| } |
| } |
| |
| public Set<String> getCustomTagNames() { |
| return customTags.keySet(); |
| } |
| |
| /** |
| * Add a new <code>Taglet</code>. Print a message to indicate whether or not |
| * the Taglet was registered properly. |
| * @param classname the name of the class representing the custom tag. |
| * @param tagletPath the path to the class representing the custom tag. |
| */ |
| public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) { |
| try { |
| Class<?> customTagClass = null; |
| // construct class loader |
| String cpString = null; // make sure env.class.path defaults to dot |
| |
| ClassLoader tagClassLoader; |
| if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.TAGLET_PATH)) { |
| tagClassLoader = fileManager.getClassLoader(DocumentationTool.Location.TAGLET_PATH); |
| } else { |
| // do prepends to get correct ordering |
| cpString = appendPath(System.getProperty("env.class.path"), cpString); |
| cpString = appendPath(System.getProperty("java.class.path"), cpString); |
| cpString = appendPath(tagletPath, cpString); |
| tagClassLoader = new URLClassLoader(pathToURLs(cpString)); |
| } |
| |
| customTagClass = tagClassLoader.loadClass(classname); |
| Method meth = customTagClass.getMethod("register", |
| Map.class); |
| Object[] list = customTags.values().toArray(); |
| Taglet lastTag = (list != null && list.length > 0) |
| ? (Taglet) list[list.length-1] : null; |
| meth.invoke(null, customTags); |
| list = customTags.values().toArray(); |
| Object newLastTag = (list != null&& list.length > 0) |
| ? list[list.length-1] : null; |
| if (lastTag != newLastTag) { |
| //New taglets must always be added to the end of the LinkedHashMap. |
| //If the current and previous last taglet are not equal, that |
| //means a new Taglet has been added. |
| message.notice("doclet.Notice_taglet_registered", classname); |
| if (newLastTag != null) { |
| checkTaglet(newLastTag); |
| } |
| } |
| } catch (Exception exc) { |
| message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname); |
| } |
| |
| } |
| |
| private String appendPath(String path1, String path2) { |
| if (path1 == null || path1.length() == 0) { |
| return path2 == null ? "." : path2; |
| } else if (path2 == null || path2.length() == 0) { |
| return path1; |
| } else { |
| return path1 + File.pathSeparator + path2; |
| } |
| } |
| |
| /** |
| * Utility method for converting a search path string to an array |
| * of directory and JAR file URLs. |
| * |
| * @param path the search path string |
| * @return the resulting array of directory and JAR file URLs |
| */ |
| private URL[] pathToURLs(String path) { |
| Set<URL> urls = new LinkedHashSet<>(); |
| for (String s: path.split(File.pathSeparator)) { |
| if (s.isEmpty()) continue; |
| try { |
| urls.add(new File(s).getAbsoluteFile().toURI().toURL()); |
| } catch (MalformedURLException e) { |
| message.error("doclet.MalformedURL", s); |
| } |
| } |
| return urls.toArray(new URL[urls.size()]); |
| } |
| |
| |
| /** |
| * Add a new <code>SimpleTaglet</code>. If this tag already exists |
| * and the header passed as an argument is null, move tag to the back of the |
| * list. If this tag already exists and the header passed as an argument is |
| * not null, overwrite previous tag with new one. Otherwise, add new |
| * SimpleTaglet to list. |
| * @param tagName the name of this tag |
| * @param header the header to output. |
| * @param locations the possible locations that this tag |
| * can appear in. |
| */ |
| public void addNewSimpleCustomTag(String tagName, String header, String locations) { |
| if (tagName == null || locations == null) { |
| return; |
| } |
| Taglet tag = customTags.get(tagName); |
| locations = StringUtils.toLowerCase(locations); |
| if (tag == null || header != null) { |
| customTags.remove(tagName); |
| customTags.put(tagName, new SimpleTaglet(tagName, header, locations)); |
| if (locations != null && locations.indexOf('x') == -1) { |
| checkTagName(tagName); |
| } |
| } else { |
| //Move to back |
| customTags.remove(tagName); |
| customTags.put(tagName, tag); |
| } |
| } |
| |
| /** |
| * Given a tag name, add it to the set of tags it belongs to. |
| */ |
| private void checkTagName(String name) { |
| if (standardTags.contains(name)) { |
| overridenStandardTags.add(name); |
| } else { |
| if (name.indexOf('.') == -1) { |
| potentiallyConflictingTags.add(name); |
| } |
| unseenCustomTags.add(name); |
| } |
| } |
| |
| /** |
| * Check the taglet to see if it is a legacy taglet. Also |
| * check its name for errors. |
| */ |
| private void checkTaglet(Object taglet) { |
| if (taglet instanceof Taglet) { |
| checkTagName(((Taglet) taglet).getName()); |
| } else if (taglet instanceof com.sun.tools.doclets.Taglet) { |
| com.sun.tools.doclets.Taglet legacyTaglet = (com.sun.tools.doclets.Taglet) taglet; |
| customTags.remove(legacyTaglet.getName()); |
| customTags.put(legacyTaglet.getName(), new LegacyTaglet(legacyTaglet)); |
| checkTagName(legacyTaglet.getName()); |
| } else { |
| throw new IllegalArgumentException("Given object is not a taglet."); |
| } |
| } |
| |
| /** |
| * Given a name of a seen custom tag, remove it from the set of unseen |
| * custom tags. |
| * @param name the name of the seen custom tag. |
| */ |
| public void seenCustomTag(String name) { |
| unseenCustomTags.remove(name); |
| } |
| |
| /** |
| * Given an array of <code>Tag</code>s, check for spelling mistakes. |
| * @param doc the Doc object that holds the tags. |
| * @param tags the list of <code>Tag</code>s to check. |
| * @param areInlineTags true if the array of tags are inline and false otherwise. |
| */ |
| public void checkTags(Doc doc, Tag[] tags, boolean areInlineTags) { |
| if (tags == null) { |
| return; |
| } |
| Taglet taglet; |
| for (Tag tag : tags) { |
| String name = tag.name(); |
| if (name.length() > 0 && name.charAt(0) == '@') { |
| name = name.substring(1, name.length()); |
| } |
| if (! (standardTags.contains(name) || customTags.containsKey(name))) { |
| if (standardTagsLowercase.contains(StringUtils.toLowerCase(name))) { |
| message.warning(tag.position(), "doclet.UnknownTagLowercase", tag.name()); |
| continue; |
| } else { |
| message.warning(tag.position(), "doclet.UnknownTag", tag.name()); |
| continue; |
| } |
| } |
| //Check if this tag is being used in the wrong location. |
| if ((taglet = customTags.get(name)) != null) { |
| if (areInlineTags && ! taglet.isInlineTag()) { |
| printTagMisuseWarn(taglet, tag, "inline"); |
| } |
| if ((doc instanceof RootDoc) && ! taglet.inOverview()) { |
| printTagMisuseWarn(taglet, tag, "overview"); |
| } else if ((doc instanceof PackageDoc) && ! taglet.inPackage()) { |
| printTagMisuseWarn(taglet, tag, "package"); |
| } else if ((doc instanceof ClassDoc) && ! taglet.inType()) { |
| printTagMisuseWarn(taglet, tag, "class"); |
| } else if ((doc instanceof ConstructorDoc) && ! taglet.inConstructor()) { |
| printTagMisuseWarn(taglet, tag, "constructor"); |
| } else if ((doc instanceof FieldDoc) && ! taglet.inField()) { |
| printTagMisuseWarn(taglet, tag, "field"); |
| } else if ((doc instanceof MethodDoc) && ! taglet.inMethod()) { |
| printTagMisuseWarn(taglet, tag, "method"); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Given the taglet, the tag and the type of documentation that the tag |
| * was found in, print a tag misuse warning. |
| * @param taglet the taglet representing the misused tag. |
| * @param tag the misused tag. |
| * @param holderType the type of documentation that the misused tag was found in. |
| */ |
| private void printTagMisuseWarn(Taglet taglet, Tag tag, String holderType) { |
| Set<String> locationsSet = new LinkedHashSet<>(); |
| if (taglet.inOverview()) { |
| locationsSet.add("overview"); |
| } |
| if (taglet.inPackage()) { |
| locationsSet.add("package"); |
| } |
| if (taglet.inType()) { |
| locationsSet.add("class/interface"); |
| } |
| if (taglet.inConstructor()) { |
| locationsSet.add("constructor"); |
| } |
| if (taglet.inField()) { |
| locationsSet.add("field"); |
| } |
| if (taglet.inMethod()) { |
| locationsSet.add("method"); |
| } |
| if (taglet.isInlineTag()) { |
| locationsSet.add("inline text"); |
| } |
| String[] locations = locationsSet.toArray(new String[]{}); |
| if (locations == null || locations.length == 0) { |
| //This known tag is excluded. |
| return; |
| } |
| StringBuilder combined_locations = new StringBuilder(); |
| for (int i = 0; i < locations.length; i++) { |
| if (i > 0) { |
| combined_locations.append(", "); |
| } |
| combined_locations.append(locations[i]); |
| } |
| message.warning(tag.position(), "doclet.tag_misuse", |
| "@" + taglet.getName(), holderType, combined_locations.toString()); |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in packages. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in packages. |
| */ |
| public Taglet[] getPackageCustomTaglets() { |
| if (packageTags == null) { |
| initCustomTagletArrays(); |
| } |
| return packageTags; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in classes or interfaces. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in classes or interfaces. |
| */ |
| public Taglet[] getTypeCustomTaglets() { |
| if (typeTags == null) { |
| initCustomTagletArrays(); |
| } |
| return typeTags; |
| } |
| |
| /** |
| * Return the array of inline <code>Taglet</code>s that can |
| * appear in comments. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in comments. |
| */ |
| public Taglet[] getInlineCustomTaglets() { |
| if (inlineTags == null) { |
| initCustomTagletArrays(); |
| } |
| return inlineTags; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in fields. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in field. |
| */ |
| public Taglet[] getFieldCustomTaglets() { |
| if (fieldTags == null) { |
| initCustomTagletArrays(); |
| } |
| return fieldTags; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in the serialized form. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in the serialized form. |
| */ |
| public Taglet[] getSerializedFormTaglets() { |
| if (serializedFormTags == null) { |
| initCustomTagletArrays(); |
| } |
| return serializedFormTags; |
| } |
| |
| /** |
| * @return the array of <code>Taglet</code>s that can |
| * appear in the given Doc. |
| */ |
| public Taglet[] getCustomTaglets(Doc doc) { |
| if (doc instanceof ConstructorDoc) { |
| return getConstructorCustomTaglets(); |
| } else if (doc instanceof MethodDoc) { |
| return getMethodCustomTaglets(); |
| } else if (doc instanceof FieldDoc) { |
| return getFieldCustomTaglets(); |
| } else if (doc instanceof ClassDoc) { |
| return getTypeCustomTaglets(); |
| } else if (doc instanceof PackageDoc) { |
| return getPackageCustomTaglets(); |
| } else if (doc instanceof RootDoc) { |
| return getOverviewCustomTaglets(); |
| } |
| return null; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in constructors. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in constructors. |
| */ |
| public Taglet[] getConstructorCustomTaglets() { |
| if (constructorTags == null) { |
| initCustomTagletArrays(); |
| } |
| return constructorTags; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in methods. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in methods. |
| */ |
| public Taglet[] getMethodCustomTaglets() { |
| if (methodTags == null) { |
| initCustomTagletArrays(); |
| } |
| return methodTags; |
| } |
| |
| /** |
| * Return the array of <code>Taglet</code>s that can |
| * appear in an overview. |
| * @return the array of <code>Taglet</code>s that can |
| * appear in overview. |
| */ |
| public Taglet[] getOverviewCustomTaglets() { |
| if (overviewTags == null) { |
| initCustomTagletArrays(); |
| } |
| return overviewTags; |
| } |
| |
| /** |
| * Initialize the custom tag arrays. |
| */ |
| private void initCustomTagletArrays() { |
| Iterator<Taglet> it = customTags.values().iterator(); |
| ArrayList<Taglet> pTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> tTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> fTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> cTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> mTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> iTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> oTags = new ArrayList<>(customTags.size()); |
| ArrayList<Taglet> sTags = new ArrayList<>(); |
| Taglet current; |
| while (it.hasNext()) { |
| current = it.next(); |
| if (current.inPackage() && !current.isInlineTag()) { |
| pTags.add(current); |
| } |
| if (current.inType() && !current.isInlineTag()) { |
| tTags.add(current); |
| } |
| if (current.inField() && !current.isInlineTag()) { |
| fTags.add(current); |
| } |
| if (current.inConstructor() && !current.isInlineTag()) { |
| cTags.add(current); |
| } |
| if (current.inMethod() && !current.isInlineTag()) { |
| mTags.add(current); |
| } |
| if (current.isInlineTag()) { |
| iTags.add(current); |
| } |
| if (current.inOverview() && !current.isInlineTag()) { |
| oTags.add(current); |
| } |
| } |
| packageTags = pTags.toArray(new Taglet[] {}); |
| typeTags = tTags.toArray(new Taglet[] {}); |
| fieldTags = fTags.toArray(new Taglet[] {}); |
| constructorTags = cTags.toArray(new Taglet[] {}); |
| methodTags = mTags.toArray(new Taglet[] {}); |
| overviewTags = oTags.toArray(new Taglet[] {}); |
| inlineTags = iTags.toArray(new Taglet[] {}); |
| |
| //Init the serialized form tags |
| sTags.add(customTags.get("serialData")); |
| sTags.add(customTags.get("throws")); |
| if (!nosince) |
| sTags.add(customTags.get("since")); |
| sTags.add(customTags.get("see")); |
| serializedFormTags = sTags.toArray(new Taglet[] {}); |
| } |
| |
| /** |
| * Initialize standard Javadoc tags for ordering purposes. |
| */ |
| private void initStandardTaglets() { |
| if (javafx) { |
| initJavaFXTaglets(); |
| } |
| |
| Taglet temp; |
| addStandardTaglet(new ParamTaglet()); |
| addStandardTaglet(new ReturnTaglet()); |
| addStandardTaglet(new ThrowsTaglet()); |
| addStandardTaglet(new SimpleTaglet("exception", null, |
| SimpleTaglet.METHOD + SimpleTaglet.CONSTRUCTOR)); |
| addStandardTaglet(!nosince, new SimpleTaglet("since", message.getText("doclet.Since"), |
| SimpleTaglet.ALL)); |
| addStandardTaglet(showversion, new SimpleTaglet("version", message.getText("doclet.Version"), |
| SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)); |
| addStandardTaglet(showauthor, new SimpleTaglet("author", message.getText("doclet.Author"), |
| SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)); |
| addStandardTaglet(new SimpleTaglet("serialData", message.getText("doclet.SerialData"), |
| SimpleTaglet.EXCLUDED)); |
| customTags.put((temp = new SimpleTaglet("factory", message.getText("doclet.Factory"), |
| SimpleTaglet.METHOD)).getName(), temp); |
| addStandardTaglet(new SeeTaglet()); |
| //Standard inline tags |
| addStandardTaglet(new DocRootTaglet()); |
| addStandardTaglet(new InheritDocTaglet()); |
| addStandardTaglet(new ValueTaglet()); |
| addStandardTaglet(new LiteralTaglet()); |
| addStandardTaglet(new CodeTaglet()); |
| |
| // Keep track of the names of standard tags for error |
| // checking purposes. The following are not handled above. |
| // See, for example, com.sun.tools.javadoc.Comment |
| standardTags.add("deprecated"); |
| standardTags.add("link"); |
| standardTags.add("linkplain"); |
| standardTags.add("serial"); |
| standardTags.add("serialField"); |
| standardTags.add("Text"); |
| } |
| |
| /** |
| * Initialize JavaFX-related tags. |
| */ |
| private void initJavaFXTaglets() { |
| addStandardTaglet(new PropertyGetterTaglet()); |
| addStandardTaglet(new PropertySetterTaglet()); |
| addStandardTaglet(new SimpleTaglet("propertyDescription", |
| message.getText("doclet.PropertyDescription"), |
| SimpleTaglet.FIELD + SimpleTaglet.METHOD)); |
| addStandardTaglet(new SimpleTaglet("defaultValue", message.getText("doclet.DefaultValue"), |
| SimpleTaglet.FIELD + SimpleTaglet.METHOD)); |
| addStandardTaglet(new SimpleTaglet("treatAsPrivate", null, |
| SimpleTaglet.FIELD + SimpleTaglet.METHOD + SimpleTaglet.TYPE)); |
| } |
| |
| void addStandardTaglet(Taglet taglet) { |
| String name = taglet.getName(); |
| customTags.put(name, taglet); |
| standardTags.add(name); |
| } |
| |
| void addStandardTaglet(boolean enable, Taglet taglet) { |
| String name = taglet.getName(); |
| if (enable) |
| customTags.put(name, taglet); |
| standardTags.add(name); |
| } |
| |
| /** |
| * Initialize lowercase version of standard Javadoc tags. |
| */ |
| private void initStandardTagsLowercase() { |
| for (String standardTag : standardTags) { |
| standardTagsLowercase.add(StringUtils.toLowerCase(standardTag)); |
| } |
| } |
| |
| public boolean isKnownCustomTag(String tagName) { |
| return customTags.containsKey(tagName); |
| } |
| |
| /** |
| * Print a list of {@link Taglet}s that might conflict with |
| * standard tags in the future and a list of standard tags |
| * that have been overriden. |
| */ |
| public void printReport() { |
| printReportHelper("doclet.Notice_taglet_conflict_warn", potentiallyConflictingTags); |
| printReportHelper("doclet.Notice_taglet_overriden", overridenStandardTags); |
| printReportHelper("doclet.Notice_taglet_unseen", unseenCustomTags); |
| } |
| |
| private void printReportHelper(String noticeKey, Set<String> names) { |
| if (names.size() > 0) { |
| String[] namesArray = names.toArray(new String[] {}); |
| String result = " "; |
| for (int i = 0; i < namesArray.length; i++) { |
| result += "@" + namesArray[i]; |
| if (i + 1 < namesArray.length) { |
| result += ", "; |
| } |
| } |
| message.notice(noticeKey, result); |
| } |
| } |
| |
| /** |
| * Given the name of a tag, return the corresponding taglet. |
| * Return null if the tag is unknown. |
| * |
| * @param name the name of the taglet to retrieve. |
| * @return return the corresponding taglet. Return null if the tag is |
| * unknown. |
| */ |
| public Taglet getTaglet(String name) { |
| if (name.indexOf("@") == 0) { |
| return customTags.get(name.substring(1)); |
| } else { |
| return customTags.get(name); |
| } |
| |
| } |
| } |