URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [doclets/] [AbstractDoclet.java] - Rev 779
Compare with Previous | Blame | View Log
/* gnu.classpath.tools.doclets.AbstractDoclet Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath 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 for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ package gnu.classpath.tools.doclets; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.ConstructorDoc; import com.sun.javadoc.Doc; import com.sun.javadoc.Doclet; import com.sun.javadoc.ExecutableMemberDoc; import com.sun.javadoc.FieldDoc; import com.sun.javadoc.MethodDoc; import com.sun.javadoc.PackageDoc; import com.sun.javadoc.Parameter; import com.sun.javadoc.RootDoc; import com.sun.javadoc.Tag; import com.sun.javadoc.Type; import com.sun.tools.doclets.Taglet; import gnu.classpath.tools.taglets.GnuExtendedTaglet; import gnu.classpath.tools.taglets.AuthorTaglet; import gnu.classpath.tools.taglets.CodeTaglet; import gnu.classpath.tools.taglets.DeprecatedTaglet; import gnu.classpath.tools.taglets.GenericTaglet; import gnu.classpath.tools.taglets.SinceTaglet; import gnu.classpath.tools.taglets.ValueTaglet; import gnu.classpath.tools.taglets.VersionTaglet; import gnu.classpath.tools.taglets.TagletContext; import gnu.classpath.tools.IOToolkit; import gnu.classpath.tools.FileSystemClassLoader; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.SortedSet; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; /** * An abstract Doclet implementation with helpers for common tasks * performed by Doclets. */ public abstract class AbstractDoclet { /** * Mapping from tag type to Taglet for user Taglets specified on * the command line. */ protected Map tagletMap = new LinkedHashMap(); /** * Stores the package groups specified in the user * options. Contains objects of type PackageGroup. */ private List packageGroups = new LinkedList(); /** * The current classpath for loading taglet classes. */ private String tagletPath; /** * Keeps track of the tags mentioned by the user during option * processiong so that an error can be emitted if a tag is * mentioned more than once. */ private List mentionedTags = new LinkedList(); public static int optionLength(String option) { return instance.getOptionLength(option); } public static boolean validOptions(String[][] options) { return true; } private static AbstractDoclet instance; protected static void setInstance(AbstractDoclet instance) { AbstractDoclet.instance = instance; } protected abstract void run() throws DocletConfigurationException, IOException; public static boolean start(RootDoc rootDoc) { try { instance.startInstance(rootDoc); return true; } catch (DocletConfigurationException e) { instance.printError(e.getMessage()); return false; } catch (Exception e) { e.printStackTrace(); return false; } } protected RootDoc getRootDoc() { return this.rootDoc; } private RootDoc rootDoc; protected abstract InlineTagRenderer getInlineTagRenderer(); private void startInstance(RootDoc rootDoc) throws DocletConfigurationException, IOException { this.rootDoc = rootDoc; // Set the default Taglet order registerTaglet(new VersionTaglet()); registerTaglet(new AuthorTaglet()); registerTaglet(new SinceTaglet(getInlineTagRenderer())); registerTaglet(new StandardTaglet("serial")); registerTaglet(new StandardTaglet("deprecated")); registerTaglet(new StandardTaglet("see")); registerTaglet(new StandardTaglet("param")); registerTaglet(new StandardTaglet("return")); registerTaglet(new ValueTaglet()); registerTaglet(new CodeTaglet()); // Process command line options for (int i=0, ilim=rootDoc.options().length; i<ilim; ++i) { String[] optionArr = rootDoc.options()[i]; String _optionTag = optionArr[0]; DocletOption option = (DocletOption)nameToOptionMap.get(_optionTag.toLowerCase()); if (null != option) { option.set(optionArr); } } // Enable/disable standard taglets based on user input AuthorTaglet.setTagletEnabled(optionAuthor.getValue()); VersionTaglet.setTagletEnabled(optionVersion.getValue()); SinceTaglet.setTagletEnabled(!optionNoSince.getValue()); DeprecatedTaglet.setTagletEnabled(!optionNoDeprecated.getValue()); if (!getTargetDirectory().exists()) { if (!getTargetDirectory().mkdirs()) { throw new DocletConfigurationException("Cannot create target directory " + getTargetDirectory()); } } run(); } public File getTargetDirectory() { return optionTargetDirectory.getValue(); } private DocletOptionFile optionTargetDirectory = new DocletOptionFile("-d", new File(System.getProperty("user.dir"))); private DocletOptionFlag optionNoEmailWarn = new DocletOptionFlag("-noemailwarn"); private DocletOptionFlag optionAuthor = new DocletOptionFlag("-author"); private DocletOptionFlag optionVersion = new DocletOptionFlag("-version"); private DocletOptionFlag optionNoSince = new DocletOptionFlag("-nosince"); private DocletOptionFlag optionNoDeprecated = new DocletOptionFlag("-nodeprecated"); private DocletOptionGroup optionGroup = new DocletOptionGroup("-group"); private DocletOptionPackageWildcard optionNoQualifier = new DocletOptionPackageWildcard("-noqualifier", true); private DocletOptionFlag optionDocFilesSubDirs = new DocletOptionFlag("-docfilessubdirs"); private DocletOptionColonSeparated optionExcludeDocFilesSubDir = new DocletOptionColonSeparated("-excludedocfilessubdir"); private DocletOptionTagletPath optionTagletPath = new DocletOptionTagletPath("-tagletpath"); private DocletOptionTag optionTaglet = new DocletOptionTag("-taglet"); private DocletOptionTag optionTag = new DocletOptionTag("-tag"); private class DocletOptionTaglet extends DocletOption { DocletOptionTaglet(String optionName) { super(optionName); } public int getLength() { return 2; } public boolean set(String[] optionArr) { boolean tagletLoaded = false; String useTagletPath = AbstractDoclet.this.tagletPath; if (null == useTagletPath) { useTagletPath = System.getProperty("java.class.path"); } try { Class tagletClass; try { tagletClass = new FileSystemClassLoader(useTagletPath).loadClass(optionArr[1]); } catch (ClassNotFoundException e) { // If not found on specified tagletpath, try default classloader tagletClass = Class.forName(optionArr[1]); } Method registerTagletMethod = tagletClass.getDeclaredMethod("register", new Class[] { java.util.Map.class }); if (!registerTagletMethod.getReturnType().equals(Void.TYPE)) { printError("Taglet class '" + optionArr[1] + "' found, but register method doesn't return void."); } else if (registerTagletMethod.getExceptionTypes().length > 0) { printError("Taglet class '" + optionArr[1] + "' found, but register method contains throws clause."); } else if ((registerTagletMethod.getModifiers() & (Modifier.STATIC | Modifier.PUBLIC | Modifier.ABSTRACT)) != (Modifier.STATIC | Modifier.PUBLIC)) { printError("Taglet class '" + optionArr[1] + "' found, but register method isn't public static, or is abstract.."); } else { Map tempMap = new HashMap(); registerTagletMethod.invoke(null, new Object[] { tempMap }); tagletLoaded = true; String name = (String)tempMap.keySet().iterator().next(); Taglet taglet = (Taglet)tempMap.get(name); tagletMap.put(name, taglet); mentionedTags.add(taglet); } } catch (NoSuchMethodException e) { printError("Taglet class '" + optionArr[1] + "' found, but doesn't contain the register method."); } catch (SecurityException e) { printError("Taglet class '" + optionArr[1] + "' cannot be loaded: " + e.getMessage()); } catch (InvocationTargetException e) { printError("Taglet class '" + optionArr[1] + "' found, but register method throws exception: " + e.toString()); } catch (IllegalAccessException e) { printError("Taglet class '" + optionArr[1] + "' found, but there was a problem when accessing the register method: " + e.toString()); } catch (IllegalArgumentException e) { printError("Taglet class '" + optionArr[1] + "' found, but there was a problem when accessing the register method: " + e.toString()); } catch (ClassNotFoundException e) { printError("Taglet class '" + optionArr[1] + "' cannot be found."); } return tagletLoaded; } } private class DocletOptionGroup extends DocletOption { DocletOptionGroup(String optionName) { super(optionName); } public int getLength() { return 3; } public boolean set(String[] optionArr) { try { PackageMatcher packageMatcher = new PackageMatcher(); StringTokenizer tokenizer = new StringTokenizer(optionArr[2], ":"); while (tokenizer.hasMoreTokens()) { String packageWildcard = tokenizer.nextToken(); packageMatcher.addWildcard(packageWildcard); } SortedSet groupPackages = packageMatcher.filter(rootDoc.specifiedPackages()); packageGroups.add(new PackageGroup(optionArr[1], groupPackages)); return true; } catch (InvalidPackageWildcardException e) { return false; } } } private class DocletOptionTagletPath extends DocletOption { DocletOptionTagletPath(String optionName) { super(optionName); } public int getLength() { return 2; } public boolean set(String[] optionArr) { AbstractDoclet.this.tagletPath = optionArr[1]; return true; } } private class DocletOptionTag extends DocletOption { DocletOptionTag(String optionName) { super(optionName); } public int getLength() { return 2; } public boolean set(String[] optionArr) { String tagSpec = optionArr[1]; boolean validTagSpec = false; int ndx1 = tagSpec.indexOf(':'); if (ndx1 < 0) { Taglet taglet = (Taglet)tagletMap.get(tagSpec); if (null == taglet) { printError("There is no standard tag '" + tagSpec + "'."); } else { if (mentionedTags.contains(taglet)) { printError("Tag '" + tagSpec + "' has been added or moved before."); } else { mentionedTags.add(taglet); // re-append taglet tagletMap.remove(tagSpec); tagletMap.put(tagSpec, taglet); } } } else { int ndx2 = tagSpec.indexOf(':', ndx1 + 1); if (ndx2 > ndx1 && ndx2 < tagSpec.length() - 1) { String tagName = tagSpec.substring(0, ndx1); String tagHead = null; if (tagSpec.charAt(ndx2 + 1) == '\"') { if (tagSpec.charAt(tagSpec.length() - 1) == '\"') { tagHead = tagSpec.substring(ndx2 + 2, tagSpec.length() - 1); validTagSpec = true; } } else { tagHead = tagSpec.substring(ndx2 + 1); validTagSpec = true; } boolean tagScopeOverview = false; boolean tagScopePackages = false; boolean tagScopeTypes = false; boolean tagScopeConstructors = false; boolean tagScopeMethods = false; boolean tagScopeFields = false; boolean tagDisabled = false; tag_option_loop: for (int n=ndx1+1; n<ndx2; ++n) { switch (tagSpec.charAt(n)) { case 'X': tagDisabled = true; break; case 'a': tagScopeOverview = true; tagScopePackages = true; tagScopeTypes = true; tagScopeConstructors = true; tagScopeMethods = true; tagScopeFields = true; break; case 'o': tagScopeOverview = true; break; case 'p': tagScopePackages = true; break; case 't': tagScopeTypes = true; break; case 'c': tagScopeConstructors = true; break; case 'm': tagScopeMethods = true; break; case 'f': tagScopeFields = true; break; default: validTagSpec = false; break tag_option_loop; } } if (validTagSpec) { GenericTaglet taglet = new GenericTaglet(tagName, tagHead, tagScopeOverview, tagScopePackages, tagScopeTypes, tagScopeConstructors, tagScopeMethods, tagScopeFields); taglet.setTagletEnabled(!tagDisabled); taglet.register(tagletMap); mentionedTags.add(taglet); } } } if (!validTagSpec) { printError("Value for option -tag must be in format \"<tagname>:Xaoptcmf:<taghead>\"."); } return validTagSpec; } } private DocletOption[] commonOptions = { optionTargetDirectory, optionAuthor, optionVersion, optionNoSince, optionNoDeprecated, optionGroup, optionDocFilesSubDirs, optionExcludeDocFilesSubDir, optionTagletPath, optionTaglet, optionTag, }; private void registerOptions() { if (!optionsRegistered) { for (int i=0; i<commonOptions.length; ++i) { DocletOption option = commonOptions[i]; registerOption(option); } DocletOption[] docletOptions = getOptions(); for (int i=0; i<docletOptions.length; ++i) { DocletOption option = docletOptions[i]; registerOption(option); } optionsRegistered = true; } } protected abstract DocletOption[] getOptions(); private boolean optionsRegistered = false; private void registerOption(DocletOption option) { nameToOptionMap.put(option.getName(), option); } private Map nameToOptionMap = new HashMap(); private int getOptionLength(String optionName) { registerOptions(); DocletOption option = (DocletOption)nameToOptionMap.get(optionName.toLowerCase()); if (null != option) { return option.getLength(); } else { return -1; } } protected List getKnownDirectSubclasses(ClassDoc classDoc) { List result = new LinkedList(); if (!"java.lang.Object".equals(classDoc.qualifiedName())) { ClassDoc[] classes = rootDoc.classes(); for (int i=0; i<classes.length; ++i) { if (classDoc == classes[i].superclass()) { result.add(classes[i]); } } } return result; } protected static class IndexKey implements Comparable { private String name; private String lowerName; public IndexKey(String name) { this.name = name; this.lowerName = name.toLowerCase(); } public boolean equals(Object other) { return this.lowerName.equals(((IndexKey)other).lowerName); } public int hashCode() { return lowerName.hashCode(); } public int compareTo(Object other) { return lowerName.compareTo(((IndexKey)other).lowerName); } public String getName() { return name; } } private Map categorizedIndex; protected Map getCategorizedIndex() { if (null == categorizedIndex) { categorizedIndex = new LinkedHashMap(); Map indexMap = getIndexByName(); LinkedList keys = new LinkedList(); //indexMap.keySet().size()); keys.addAll(indexMap.keySet()); Collections.sort(keys); Iterator it = keys.iterator(); //indexMap.keySet().iterator(); char previousCategoryLetter = '\0'; Character keyLetter = null; while (it.hasNext()) { IndexKey key = (IndexKey)it.next(); char firstChar = Character.toUpperCase(key.getName().charAt(0)); if (firstChar != previousCategoryLetter) { keyLetter = new Character(firstChar); previousCategoryLetter = firstChar; categorizedIndex.put(keyLetter, new LinkedList()); } List letterList = (List)categorizedIndex.get(keyLetter); letterList.add(indexMap.get(key)); } } return categorizedIndex; } private Map indexByName; protected Map getIndexByName() { if (null == indexByName) { // Create index // Collect index indexByName = new HashMap(); //TreeMap(); // Add packages to index PackageDoc[] packages = rootDoc.specifiedPackages(); for (int i=0, ilim=packages.length; i<ilim; ++i) { PackageDoc c = packages[i]; if (c.name().length() > 0) { indexByName.put(new IndexKey(c.name()), c); } } // Add classes, fields and methods to index ClassDoc[] sumclasses = rootDoc.classes(); for (int i=0, ilim=sumclasses.length; i<ilim; ++i) { ClassDoc c = sumclasses[i]; if (null == c.containingClass()) { indexByName.put(new IndexKey(c.name() + " " + c.containingPackage().name()), c); } else { indexByName.put(new IndexKey(c.name().substring(c.containingClass().name().length() + 1) + " " + c.containingClass().name() + " " + c.containingPackage().name()), c); } FieldDoc[] fields = c.fields(); for (int j=0, jlim=fields.length; j<jlim; ++j) { indexByName.put(new IndexKey(fields[j].name() + " " + fields[j].containingClass().name() + " " + fields[j].containingPackage().name()), fields[j]); } MethodDoc[] methods = c.methods(); for (int j=0, jlim=methods.length; j<jlim; ++j) { MethodDoc method = methods[j]; indexByName.put(new IndexKey(method.name() + method.signature() + " " + method.containingClass().name() + " " + method.containingPackage().name()), method); } ConstructorDoc[] constructors = c.constructors(); for (int j=0, jlim=constructors.length; j<jlim; ++j) { ConstructorDoc constructor = constructors[j]; indexByName.put(new IndexKey(constructor.name() + constructor.signature() + " " + constructor.containingClass().name() + " " + constructor.containingPackage().name()), constructor); } } } return indexByName; } private void registerTaglet(Taglet taglet) { tagletMap.put(taglet.getName(), taglet); } protected void printTaglets(Tag[] tags, TagletContext context, TagletPrinter output, boolean inline) { for (Iterator it = tagletMap.keySet().iterator(); it.hasNext(); ) { String tagName = (String)it.next(); Object o = tagletMap.get(tagName); Taglet taglet = (Taglet)o; Doc doc = context.getDoc(); if (inline == taglet.isInlineTag() && ((doc == null && taglet.inOverview()) || (doc != null && ((doc.isConstructor() && taglet.inConstructor()) || (doc.isField() && taglet.inField()) || (doc.isMethod() && taglet.inMethod()) || (doc instanceof PackageDoc && taglet.inPackage()) || ((doc.isClass() || doc.isInterface()) && taglet.inType()))))) { List tagsOfThisType = new LinkedList(); for (int i=0; i<tags.length; ++i) { if (tags[i].name().substring(1).equals(tagName)) { tagsOfThisType.add(tags[i]); } } Tag[] tagletTags = (Tag[])tagsOfThisType.toArray(new Tag[tagsOfThisType.size()]); String tagletString; if (taglet instanceof StandardTaglet) { tagletString = renderTag(tagName, tagletTags, context); } else if (taglet instanceof GnuExtendedTaglet) { tagletString = ((GnuExtendedTaglet)taglet).toString(tagletTags, context); } else { tagletString = taglet.toString(tagletTags); } if (null != tagletString) { output.printTagletString(tagletString); } } } } protected void printInlineTaglet(Tag tag, TagletContext context, TagletPrinter output) { Taglet taglet = (Taglet)tagletMap.get(tag.name().substring(1)); if (null != taglet) { String tagletString; if (taglet instanceof GnuExtendedTaglet) { tagletString = ((GnuExtendedTaglet)taglet).toString(tag, context); } else { tagletString = taglet.toString(tag); } if (null != tagletString) { output.printTagletString(tagletString); } } else { printWarning("Unknown tag: " + tag.name()); } } protected void printMainTaglets(Tag[] tags, TagletContext context, TagletPrinter output) { printTaglets(tags, context, output, false); } /** * @param usedClassToPackagesMap ClassDoc to (PackageDoc to (UsageType to (Set of Doc))) */ private void addUsedBy(Map usedClassToPackagesMap, ClassDoc usedClass, UsageType usageType, Doc user, PackageDoc userPackage) { Map packageToUsageTypeMap = (Map)usedClassToPackagesMap.get(usedClass); if (null == packageToUsageTypeMap) { packageToUsageTypeMap = new HashMap(); usedClassToPackagesMap.put(usedClass, packageToUsageTypeMap); } Map usageTypeToUsersMap = (Map)packageToUsageTypeMap.get(userPackage); if (null == usageTypeToUsersMap) { usageTypeToUsersMap = new TreeMap(); packageToUsageTypeMap.put(userPackage, usageTypeToUsersMap); } Set userSet = (Set)usageTypeToUsersMap.get(usageType); if (null == userSet) { userSet = new TreeSet(); // FIXME: we need the collator from Main here usageTypeToUsersMap.put(usageType, userSet); } userSet.add(user); } /** * Create the cross reference database. */ private Map collectUsage() { Map _usedClassToPackagesMap = new HashMap(); ClassDoc[] classes = rootDoc.classes(); for (int i = 0, ilim = classes.length; i < ilim; ++ i) { ClassDoc clazz = classes[i]; if (clazz.isInterface()) { // classes implementing InterfaceRelation relation = (InterfaceRelation)getInterfaceRelations().get(clazz); Iterator it = relation.implementingClasses.iterator(); while (it.hasNext()) { ClassDoc implementor = (ClassDoc)it.next(); addUsedBy(_usedClassToPackagesMap, clazz, UsageType.CLASS_IMPLEMENTING, implementor, implementor.containingPackage()); } } else { // classes derived from for (ClassDoc superclass = clazz.superclass(); superclass != null; superclass = superclass.superclass()) { addUsedBy(_usedClassToPackagesMap, superclass, UsageType.CLASS_DERIVED_FROM, clazz, clazz.containingPackage()); } } FieldDoc[] fields = clazz.fields(); for (int j = 0, jlim = fields.length; j < jlim; ++ j) { FieldDoc field = fields[j]; // fields of type ClassDoc fieldType = field.type().asClassDoc(); if (null != fieldType) { addUsedBy(_usedClassToPackagesMap, fieldType, UsageType.FIELD_OF_TYPE, field, clazz.containingPackage()); } } MethodDoc[] methods = clazz.methods(); for (int j = 0, jlim = methods.length; j < jlim; ++ j) { MethodDoc method = methods[j]; // methods with return type ClassDoc returnType = method.returnType().asClassDoc(); if (null != returnType) { addUsedBy(_usedClassToPackagesMap, returnType, UsageType.METHOD_WITH_RETURN_TYPE, method, clazz.containingPackage()); } Parameter[] parameters = method.parameters(); for (int k=0; k<parameters.length; ++k) { // methods with parameter type Parameter parameter = parameters[k]; ClassDoc parameterType = parameter.type().asClassDoc(); if (null != parameterType) { addUsedBy(_usedClassToPackagesMap, parameterType, UsageType.METHOD_WITH_PARAMETER_TYPE, method, clazz.containingPackage()); } } // methods which throw ClassDoc[] thrownExceptions = method.thrownExceptions(); for (int k = 0, klim = thrownExceptions.length; k < klim; ++ k) { ClassDoc thrownException = thrownExceptions[k]; addUsedBy(_usedClassToPackagesMap, thrownException, UsageType.METHOD_WITH_THROWN_TYPE, method, clazz.containingPackage()); } } ConstructorDoc[] constructors = clazz.constructors(); for (int j = 0, jlim = constructors.length; j < jlim; ++ j) { ConstructorDoc constructor = constructors[j]; Parameter[] parameters = constructor.parameters(); for (int k = 0, klim = parameters.length; k < klim; ++ k) { // constructors with parameter type Parameter parameter = parameters[k]; ClassDoc parameterType = parameter.type().asClassDoc(); if (null != parameterType) { addUsedBy(_usedClassToPackagesMap, parameterType, UsageType.CONSTRUCTOR_WITH_PARAMETER_TYPE, constructor, clazz.containingPackage()); } } // constructors which throw ClassDoc[] thrownExceptions = constructor.thrownExceptions(); for (int k = 0, klim = thrownExceptions.length; k < klim; ++ k) { ClassDoc thrownException = thrownExceptions[k]; addUsedBy(_usedClassToPackagesMap, thrownException, UsageType.CONSTRUCTOR_WITH_THROWN_TYPE, constructor, clazz.containingPackage()); } } } return _usedClassToPackagesMap; } private Map usedClassToPackagesMap = null; protected Map getUsageOfClass(ClassDoc classDoc) { if (null == this.usedClassToPackagesMap) { this.usedClassToPackagesMap = collectUsage(); } return (Map)this.usedClassToPackagesMap.get(classDoc); } protected static class UsageType implements Comparable { public static final UsageType CLASS_DERIVED_FROM = new UsageType("class-derived-from"); public static final UsageType CLASS_IMPLEMENTING = new UsageType("class-implementing"); public static final UsageType FIELD_OF_TYPE = new UsageType("field-of-type"); public static final UsageType METHOD_WITH_RETURN_TYPE = new UsageType("method-with-return-type"); public static final UsageType METHOD_WITH_PARAMETER_TYPE = new UsageType("method-with-parameter-type"); public static final UsageType METHOD_WITH_THROWN_TYPE = new UsageType("method-with-thrown-type"); public static final UsageType CONSTRUCTOR_WITH_PARAMETER_TYPE = new UsageType("constructor-with-parameter-type"); public static final UsageType CONSTRUCTOR_WITH_THROWN_TYPE = new UsageType("constructor-with-thrown-type"); private String id; private UsageType(String id) { this.id = id; } public int compareTo(Object other) { return this.id.compareTo(((UsageType)other).id); } public String toString() { return "UsageType{id=" + id + "}"; } public String getId() { return id; } } private ResourceBundle resources; protected String getString(String key) { if (null == resources) { Locale currentLocale = Locale.getDefault(); resources = ResourceBundle.getBundle("htmldoclet.HtmlDoclet", currentLocale); } return resources.getString(key); } protected String format(String key, String value1) { return MessageFormat.format(getString(key), new Object[] { value1 }); } protected List getPackageGroups() { return packageGroups; } protected void copyDocFiles(File sourceDir, File targetDir) throws IOException { File sourceDocFiles = new File(sourceDir, "doc-files"); File targetDocFiles = new File(targetDir, "doc-files"); if (sourceDocFiles.exists()) { IOToolkit.copyDirectory(sourceDocFiles, targetDocFiles, optionDocFilesSubDirs.getValue(), optionExcludeDocFilesSubDir.getComponents()); } } private Set sourcePaths; /** * Try to determine the source directory for the given package by * looking at the path specified by -sourcepath, or the current * directory if -sourcepath hasn't been specified. * * @throws IOException if the source directory couldn't be * located. * * @return List of File */ protected List getPackageSourceDirs(PackageDoc packageDoc) throws IOException { if (null == sourcePaths) { for (int i=0; i<rootDoc.options().length; ++i) { if ("-sourcepath".equals(rootDoc.options()[i][0]) || "-s".equals(rootDoc.options()[i][0])) { sourcePaths = new LinkedHashSet(); String sourcepathString = rootDoc.options()[i][1]; StringTokenizer st = new StringTokenizer(sourcepathString, File.pathSeparator); while (st.hasMoreTokens()) { sourcePaths.add(new File(st.nextToken())); } } } if (null == sourcePaths) { sourcePaths = new LinkedHashSet(); sourcePaths.add(new File(System.getProperty("user.dir"))); } } String packageSubDir = packageDoc.name().replace('.', File.separatorChar); Iterator it = sourcePaths.iterator(); List result = new LinkedList(); while (it.hasNext()) { File pathComponent = (File)it.next(); File packageDir = new File(pathComponent, packageSubDir); if (packageDir.exists()) { result.add(packageDir); } } if (result.isEmpty()) { throw new IOException("Couldn't locate source directory for package " + packageDoc.name()); } else { return result; } } protected File getSourceFile(ClassDoc classDoc) throws IOException { List packageDirs = getPackageSourceDirs(classDoc.containingPackage()); Iterator it = packageDirs.iterator(); while (it.hasNext()) { File packageDir = (File)it.next(); File sourceFile = new File(packageDir, getOuterClassDoc(classDoc).name() + ".java"); if (sourceFile.exists()) { return sourceFile; } } throw new IOException("Couldn't locate source file for class " + classDoc.qualifiedTypeName()); } protected void printError(String error) { if (null != rootDoc) { rootDoc.printError(error); } else { System.err.println("ERROR: "+error); } } protected void printWarning(String warning) { if (null != rootDoc) { rootDoc.printWarning(warning); } else { System.err.println("WARNING: "+warning); } } protected void printNotice(String notice) { if (null != rootDoc) { rootDoc.printNotice(notice); } else { System.err.println(notice); } } protected static ClassDoc getOuterClassDoc(ClassDoc classDoc) { while (null != classDoc.containingClass()) { classDoc = classDoc.containingClass(); } return classDoc; } private SortedSet allPackages; protected Set getAllPackages() { if (null == this.allPackages) { allPackages = new TreeSet(); PackageDoc[] specifiedPackages = rootDoc.specifiedPackages(); for (int i=0; i<specifiedPackages.length; ++i) { allPackages.add(specifiedPackages[i]); } ClassDoc[] specifiedClasses = rootDoc.specifiedClasses(); for (int i=0; i<specifiedClasses.length; ++i) { allPackages.add(specifiedClasses[i].containingPackage()); } } return this.allPackages; } protected boolean omitPackageQualifier(PackageDoc packageDoc) { if (!optionNoQualifier.isSpecified()) { return false; } else { return optionNoQualifier.match(packageDoc); } } protected String possiblyQualifiedName(Type type) { if (null == type.asClassDoc() || !omitPackageQualifier(type.asClassDoc().containingPackage())) { return type.qualifiedTypeName(); } else { return type.typeName(); } } protected static class InterfaceRelation { public Set superInterfaces; public Set subInterfaces; public Set implementingClasses; public InterfaceRelation() { superInterfaces = new TreeSet(); subInterfaces = new TreeSet(); implementingClasses = new TreeSet(); } } private void addAllInterfaces(ClassDoc classDoc, Set allInterfaces) { ClassDoc[] interfaces = classDoc.interfaces(); for (int i=0; i<interfaces.length; ++i) { allInterfaces.add(interfaces[i]); addAllInterfaces(interfaces[i], allInterfaces); } } private Map allSubClasses; protected Map getAllSubClasses() { if (null == allSubClasses) { allSubClasses = new HashMap(); ClassDoc[] classDocs = getRootDoc().classes(); for (int i=0; i<classDocs.length; ++i) { if (!classDocs[i].isInterface()) { for (ClassDoc cd = classDocs[i].superclass(); null != cd; cd = cd.superclass()) { if (!cd.qualifiedTypeName().equals("java.lang.Object")) { List subClasses = (List)allSubClasses.get(cd); if (null == subClasses) { subClasses = new LinkedList(); allSubClasses.put(cd, subClasses); } subClasses.add(classDocs[i]); } } } } } return allSubClasses; } private Map interfaceRelations; private void addToInterfaces(ClassDoc classDoc, ClassDoc[] interfaces) { for (int i=0; i<interfaces.length; ++i) { InterfaceRelation interfaceRelation = (InterfaceRelation)interfaceRelations.get(interfaces[i]); if (null == interfaceRelation) { interfaceRelation = new InterfaceRelation(); interfaceRelations.put(interfaces[i], interfaceRelation); } interfaceRelation.implementingClasses.add(classDoc); addToInterfaces(classDoc, interfaces[i].interfaces()); } } protected Map getInterfaceRelations() { if (null == interfaceRelations) { interfaceRelations = new HashMap(); ClassDoc[] classDocs = getRootDoc().classes(); for (int i=0; i<classDocs.length; ++i) { if (classDocs[i].isInterface()) { InterfaceRelation relation = new InterfaceRelation(); addAllInterfaces(classDocs[i], relation.superInterfaces); interfaceRelations.put(classDocs[i], relation); } } Iterator it = interfaceRelations.keySet().iterator(); while (it.hasNext()) { ClassDoc interfaceDoc = (ClassDoc)it.next(); InterfaceRelation relation = (InterfaceRelation)interfaceRelations.get(interfaceDoc); Iterator superIt = relation.superInterfaces.iterator(); while (superIt.hasNext()) { ClassDoc superInterfaceDoc = (ClassDoc)superIt.next(); InterfaceRelation superRelation = (InterfaceRelation)interfaceRelations.get(superInterfaceDoc); if (null != superRelation) { superRelation.subInterfaces.add(interfaceDoc); } } } for (int i=0; i<classDocs.length; ++i) { if (!classDocs[i].isInterface()) { for (ClassDoc cd = classDocs[i]; null != cd; cd = cd.superclass()) { addToInterfaces(classDocs[i], cd.interfaces()); } } } } return interfaceRelations; } private Map sortedMethodMap = new HashMap(); protected MethodDoc[] getSortedMethods(ClassDoc classDoc) { MethodDoc[] result = (MethodDoc[])sortedMethodMap.get(classDoc); if (null == result) { MethodDoc[] methods = classDoc.methods(); result = (MethodDoc[])methods.clone(); Arrays.sort(result); return result; } return result; } private Map sortedConstructorMap = new HashMap(); protected ConstructorDoc[] getSortedConstructors(ClassDoc classDoc) { ConstructorDoc[] result = (ConstructorDoc[])sortedConstructorMap.get(classDoc); if (null == result) { ConstructorDoc[] constructors = classDoc.constructors(); result = (ConstructorDoc[])constructors.clone(); Arrays.sort(result); return result; } return result; } private Map sortedFieldMap = new HashMap(); protected FieldDoc[] getSortedFields(ClassDoc classDoc) { FieldDoc[] result = (FieldDoc[])sortedFieldMap.get(classDoc); if (null == result) { FieldDoc[] fields = classDoc.fields(); result = (FieldDoc[])fields.clone(); Arrays.sort(result); return result; } return result; } private Map sortedInnerClassMap = new HashMap(); protected ClassDoc[] getSortedInnerClasses(ClassDoc classDoc) { ClassDoc[] result = (ClassDoc[])sortedInnerClassMap.get(classDoc); if (null == result) { ClassDoc[] innerClasses = classDoc.innerClasses(); result = (ClassDoc[])innerClasses.clone(); Arrays.sort(result); return result; } return result; } protected abstract String renderTag(String tagName, Tag[] tags, TagletContext context); protected abstract String getDocletVersion(); protected SortedSet getThrownExceptions(ExecutableMemberDoc execMemberDoc) { SortedSet result = new TreeSet(); ClassDoc[] thrownExceptions = execMemberDoc.thrownExceptions(); for (int j=0; j<thrownExceptions.length; ++j) { result.add(thrownExceptions[j]); } return result; } protected boolean isUncheckedException(ClassDoc classDoc) { if (classDoc.isException()) { while (null != classDoc) { if (classDoc.qualifiedTypeName().equals("java.lang.RuntimeException")) { return true; } classDoc = classDoc.superclass(); } return false; } else { return false; } } protected FieldDoc findField(ClassDoc classDoc, String fieldName) { for (ClassDoc cd = classDoc; cd != null; cd = cd.superclass()) { FieldDoc[] fields = cd.fields(false); for (int i=0; i<fields.length; ++i) { if (fields[i].name().equals(fieldName)) { return fields[i]; } } } return null; } private Map implementedInterfacesCache = new HashMap(); protected Set getImplementedInterfaces(ClassDoc classDoc) { Set result = (Set)implementedInterfacesCache.get(classDoc); if (null == result) { result = new TreeSet(); for (ClassDoc cd = classDoc; cd != null; cd = cd.superclass()) { ClassDoc[] interfaces = cd.interfaces(); for (int i=0; i<interfaces.length; ++i) { result.add(interfaces[i]); InterfaceRelation relation = (InterfaceRelation)getInterfaceRelations().get(interfaces[i]); if (null != relation) { result.addAll(relation.superInterfaces); } } } implementedInterfacesCache.put(classDoc, result); } return result; } protected boolean isSinglePackage() { return getAllPackages().size() <= 1; } protected PackageDoc getSinglePackage() { return (PackageDoc)getAllPackages().iterator().next(); } }