--- old/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java Fri Jan 22 12:17:38 2016 +++ /dev/null Fri Jan 22 12:17:38 2016 @@ -1,549 +0,0 @@ -/* - * Copyright (c) 1998, 2015, 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.formats.html; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - -import com.sun.javadoc.*; -import com.sun.tools.doclets.formats.html.markup.*; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.tools.doclets.internal.toolkit.util.*; - -/** - * Generate class usage information. - * - *

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. - * - * @author Robert G. Field - * @author Bhavesh Patel (Modified) - */ -public class ClassUseWriter extends SubWriterHolderWriter { - - final ClassDoc classdoc; - Set pkgToPackageAnnotations = null; - final Map> pkgToClassTypeParameter; - final Map> pkgToClassAnnotations; - final Map> pkgToMethodTypeParameter; - final Map> pkgToMethodArgTypeParameter; - final Map> pkgToMethodReturnTypeParameter; - final Map> pkgToMethodAnnotations; - final Map> pkgToMethodParameterAnnotations; - final Map> pkgToFieldTypeParameter; - final Map> pkgToFieldAnnotations; - final Map> pkgToSubclass; - final Map> pkgToSubinterface; - final Map> pkgToImplementingClass; - final Map> pkgToField; - final Map> pkgToMethodReturn; - final Map> pkgToMethodArgs; - final Map> pkgToMethodThrows; - final Map> pkgToConstructorAnnotations; - final Map> pkgToConstructorParameterAnnotations; - final Map> pkgToConstructorArgs; - final Map> pkgToConstructorArgTypeParameter; - final Map> pkgToConstructorThrows; - final SortedSet pkgSet; - final MethodWriterImpl methodSubWriter; - final ConstructorWriterImpl constrSubWriter; - final FieldWriterImpl fieldSubWriter; - final NestedClassWriterImpl classSubWriter; - // Summary for various use tables. - final String classUseTableSummary; - final String subclassUseTableSummary; - final String subinterfaceUseTableSummary; - final String fieldUseTableSummary; - final String methodUseTableSummary; - final String constructorUseTableSummary; - - /** - * The HTML tree for main tag. - */ - protected HtmlTree mainTree = HtmlTree.MAIN(); - - /** - * Constructor. - * - * @param filename the file to be generated. - * @throws IOException - * @throws DocletAbortException - */ - public ClassUseWriter(ConfigurationImpl configuration, - ClassUseMapper mapper, DocPath filename, - ClassDoc classdoc) throws IOException { - super(configuration, filename); - this.classdoc = classdoc; - if (mapper.classToPackageAnnotations.containsKey(classdoc.qualifiedName())) - pkgToPackageAnnotations = new TreeSet<>(mapper.classToPackageAnnotations.get(classdoc.qualifiedName())); - configuration.currentcd = classdoc; - this.pkgSet = new TreeSet<>(); - this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam); - this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations); - this.pkgToMethodTypeParameter = pkgDivide(mapper.classToExecMemberDocTypeParam); - this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToExecMemberDocArgTypeParam); - this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldDocTypeParam); - this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToFieldDoc); - this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToExecMemberDocReturnTypeParam); - this.pkgToMethodAnnotations = pkgDivide(mapper.classToExecMemberDocAnnotations); - this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToExecMemberDocParamAnnotation); - this.pkgToSubclass = pkgDivide(mapper.classToSubclass); - this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface); - this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass); - this.pkgToField = pkgDivide(mapper.classToField); - this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn); - this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs); - this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows); - this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations); - this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation); - this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs); - this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorDocArgTypeParam); - this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows); - //tmp test - if (pkgSet.size() > 0 && - mapper.classToPackage.containsKey(classdoc.qualifiedName()) && - !pkgSet.equals(mapper.classToPackage.get(classdoc.qualifiedName()))) { - configuration.root.printWarning("Internal error: package sets don't match: " + pkgSet + " with: " + - mapper.classToPackage.get(classdoc.qualifiedName())); - } - methodSubWriter = new MethodWriterImpl(this); - constrSubWriter = new ConstructorWriterImpl(this); - fieldSubWriter = new FieldWriterImpl(this); - classSubWriter = new NestedClassWriterImpl(this); - classUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.classes")); - subclassUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.subclasses")); - subinterfaceUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.subinterfaces")); - fieldUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.fields")); - methodUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.methods")); - constructorUseTableSummary = configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.constructors")); - } - - /** - * Write out class use pages. - * @throws DocletAbortException - */ - public static void generate(ConfigurationImpl configuration, - ClassTree classtree) { - ClassUseMapper mapper = new ClassUseMapper(configuration, classtree); - for (ClassDoc aClass : configuration.root.classes()) { - // If -nodeprecated option is set and the containing package is marked - // as deprecated, do not generate the class-use page. We will still generate - // the class-use page if the class is marked as deprecated but the containing - // package is not since it could still be linked from that package-use page. - if (!(configuration.nodeprecated && - configuration.utils.isDeprecated(aClass.containingPackage()))) - ClassUseWriter.generate(configuration, mapper, aClass); - } - for (PackageDoc pkg : configuration.packages) { - // If -nodeprecated option is set and the package is marked - // as deprecated, do not generate the package-use page. - if (!(configuration.nodeprecated && configuration.utils.isDeprecated(pkg))) - PackageUseWriter.generate(configuration, mapper, pkg); - } - } - - private Map> pkgDivide(Map> classMap) { - Map> map = new HashMap<>(); - List list= classMap.get(classdoc.qualifiedName()); - if (list != null) { - Collections.sort(list, utils.makeComparatorForClassUse()); - for (ProgramElementDoc doc : list) { - PackageDoc pkg = doc.containingPackage(); - pkgSet.add(pkg); - List inPkg = map.get(pkg.name()); - if (inPkg == null) { - inPkg = new ArrayList<>(); - map.put(pkg.name(), inPkg); - } - inPkg.add(doc); - } - } - return map; - } - - /** - * Generate a class page. - */ - public static void generate(ConfigurationImpl configuration, - ClassUseMapper mapper, ClassDoc classdoc) { - ClassUseWriter clsgen; - DocPath path = DocPath.forPackage(classdoc) - .resolve(DocPaths.CLASS_USE) - .resolve(DocPath.forName(classdoc)); - try { - clsgen = new ClassUseWriter(configuration, - mapper, path, - classdoc); - clsgen.generateClassUseFile(); - clsgen.close(); - } catch (IOException exc) { - configuration.standardmessage. - error("doclet.exception_encountered", - exc.toString(), path.getPath()); - throw new DocletAbortException(exc); - } - } - - /** - * Generate the class use list. - */ - protected void generateClassUseFile() throws IOException { - HtmlTree body = getClassUseHeader(); - HtmlTree div = new HtmlTree(HtmlTag.DIV); - div.addStyle(HtmlStyle.classUseContainer); - if (pkgSet.size() > 0) { - addClassUse(div); - } else { - div.addContent(getResource("doclet.ClassUse_No.usage.of.0", - classdoc.qualifiedName())); - } - if (configuration.allowTag(HtmlTag.MAIN)) { - mainTree.addContent(div); - body.addContent(mainTree); - } else { - body.addContent(div); - } - HtmlTree htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) - ? HtmlTree.FOOTER() - : body; - addNavLinks(false, htmlTree); - addBottom(htmlTree); - if (configuration.allowTag(HtmlTag.FOOTER)) { - body.addContent(htmlTree); - } - printHtmlDocument(null, true, body); - } - - /** - * Add the class use documentation. - * - * @param contentTree the content tree to which the class use information will be added - */ - protected void addClassUse(Content contentTree) throws IOException { - HtmlTree ul = new HtmlTree(HtmlTag.UL); - ul.addStyle(HtmlStyle.blockList); - if (configuration.packages.size() > 1) { - addPackageList(ul); - addPackageAnnotationList(ul); - } - addClassList(ul); - contentTree.addContent(ul); - } - - /** - * Add the packages list that use the given class. - * - * @param contentTree the content tree to which the packages list will be added - */ - protected void addPackageList(Content contentTree) throws IOException { - Content caption = getTableCaption(configuration.getResource( - "doclet.ClassUse_Packages.that.use.0", - getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, classdoc)))); - Content table = (configuration.isOutputHtml5()) - ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) - : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); - table.addContent(getSummaryTableHeader(packageTableHeader, "col")); - Content tbody = new HtmlTree(HtmlTag.TBODY); - Iterator it = pkgSet.iterator(); - for (int i = 0; it.hasNext(); i++) { - PackageDoc pkg = it.next(); - HtmlTree tr = new HtmlTree(HtmlTag.TR); - if (i % 2 == 0) { - tr.addStyle(HtmlStyle.altColor); - } else { - tr.addStyle(HtmlStyle.rowColor); - } - addPackageUse(pkg, tr); - tbody.addContent(tr); - } - table.addContent(tbody); - Content li = HtmlTree.LI(HtmlStyle.blockList, table); - contentTree.addContent(li); - } - - /** - * Add the package annotation list. - * - * @param contentTree the content tree to which the package annotation list will be added - */ - protected void addPackageAnnotationList(Content contentTree) throws IOException { - if ((!classdoc.isAnnotationType()) || - pkgToPackageAnnotations == null || - pkgToPackageAnnotations.isEmpty()) { - return; - } - Content caption = getTableCaption(configuration.getResource( - "doclet.ClassUse_PackageAnnotation", - getLink(new LinkInfoImpl(configuration, - LinkInfoImpl.Kind.CLASS_USE_HEADER, classdoc)))); - Content table = (configuration.isOutputHtml5()) - ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) - : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); - table.addContent(getSummaryTableHeader(packageTableHeader, "col")); - Content tbody = new HtmlTree(HtmlTag.TBODY); - Iterator it = pkgToPackageAnnotations.iterator(); - for (int i = 0; it.hasNext(); i++) { - PackageDoc pkg = it.next(); - HtmlTree tr = new HtmlTree(HtmlTag.TR); - if (i % 2 == 0) { - tr.addStyle(HtmlStyle.altColor); - } else { - tr.addStyle(HtmlStyle.rowColor); - } - Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, - getPackageLink(pkg, new StringContent(pkg.name()))); - tr.addContent(tdFirst); - HtmlTree tdLast = new HtmlTree(HtmlTag.TD); - tdLast.addStyle(HtmlStyle.colLast); - addSummaryComment(pkg, tdLast); - tr.addContent(tdLast); - tbody.addContent(tr); - } - table.addContent(tbody); - Content li = HtmlTree.LI(HtmlStyle.blockList, table); - contentTree.addContent(li); - } - - /** - * Add the class list that use the given class. - * - * @param contentTree the content tree to which the class list will be added - */ - protected void addClassList(Content contentTree) throws IOException { - HtmlTree ul = new HtmlTree(HtmlTag.UL); - ul.addStyle(HtmlStyle.blockList); - for (PackageDoc pkg : pkgSet) { - Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg)); - HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION)) - ? HtmlTree.SECTION(markerAnchor) - : HtmlTree.LI(HtmlStyle.blockList, markerAnchor); - Content link = getResource("doclet.ClassUse_Uses.of.0.in.1", - getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, - classdoc)), - getPackageLink(pkg, utils.getPackageName(pkg))); - Content heading = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, link); - htmlTree.addContent(heading); - addClassUse(pkg, htmlTree); - if (configuration.allowTag(HtmlTag.SECTION)) { - ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); - } else { - ul.addContent(htmlTree); - } - } - Content li = HtmlTree.LI(HtmlStyle.blockList, ul); - contentTree.addContent(li); - } - - /** - * Add the package use information. - * - * @param pkg the package that uses the given class - * @param contentTree the content tree to which the package use information will be added - */ - protected void addPackageUse(PackageDoc pkg, Content contentTree) throws IOException { - Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, - getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg)))); - contentTree.addContent(tdFirst); - HtmlTree tdLast = new HtmlTree(HtmlTag.TD); - tdLast.addStyle(HtmlStyle.colLast); - addSummaryComment(pkg, tdLast); - contentTree.addContent(tdLast); - } - - /** - * Add the class use information. - * - * @param pkg the package that uses the given class - * @param contentTree the content tree to which the class use information will be added - */ - protected void addClassUse(PackageDoc pkg, Content contentTree) throws IOException { - Content classLink = getLink(new LinkInfoImpl(configuration, - LinkInfoImpl.Kind.CLASS_USE_HEADER, classdoc)); - Content pkgLink = getPackageLink(pkg, utils.getPackageName(pkg)); - classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_Annotation", classLink, - pkgLink), classUseTableSummary, contentTree); - classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_TypeParameter", classLink, - pkgLink), classUseTableSummary, contentTree); - classSubWriter.addUseInfo(pkgToSubclass.get(pkg.name()), - configuration.getResource("doclet.ClassUse_Subclass", classLink, - pkgLink), subclassUseTableSummary, contentTree); - classSubWriter.addUseInfo(pkgToSubinterface.get(pkg.name()), - configuration.getResource("doclet.ClassUse_Subinterface", classLink, - pkgLink), subinterfaceUseTableSummary, contentTree); - classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ImplementingClass", classLink, - pkgLink), classUseTableSummary, contentTree); - fieldSubWriter.addUseInfo(pkgToField.get(pkg.name()), - configuration.getResource("doclet.ClassUse_Field", classLink, - pkgLink), fieldUseTableSummary, contentTree); - fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_FieldAnnotations", classLink, - pkgLink), fieldUseTableSummary, contentTree); - fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_FieldTypeParameter", classLink, - pkgLink), fieldUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodAnnotations", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodParameterAnnotations", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodTypeParameter", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodReturn", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodReturnTypeParameter", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodArgs", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodArgsTypeParameters", classLink, - pkgLink), methodUseTableSummary, contentTree); - methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg.name()), - configuration.getResource("doclet.ClassUse_MethodThrows", classLink, - pkgLink), methodUseTableSummary, contentTree); - constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ConstructorAnnotations", classLink, - pkgLink), constructorUseTableSummary, contentTree); - constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ConstructorParameterAnnotations", classLink, - pkgLink), constructorUseTableSummary, contentTree); - constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ConstructorArgs", classLink, - pkgLink), constructorUseTableSummary, contentTree); - constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, - pkgLink), constructorUseTableSummary, contentTree); - constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg.name()), - configuration.getResource("doclet.ClassUse_ConstructorThrows", classLink, - pkgLink), constructorUseTableSummary, contentTree); - } - - /** - * Get the header for the class use Listing. - * - * @return a content tree representing the class use header - */ - protected HtmlTree getClassUseHeader() { - String cltype = configuration.getText(classdoc.isInterface()? - "doclet.Interface":"doclet.Class"); - String clname = classdoc.qualifiedName(); - String title = configuration.getText("doclet.Window_ClassUse_Header", - cltype, clname); - HtmlTree bodyTree = getBody(true, getWindowTitle(title)); - HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) - ? HtmlTree.HEADER() - : bodyTree; - addTop(htmlTree); - addNavLinks(true, htmlTree); - if (configuration.allowTag(HtmlTag.HEADER)) { - bodyTree.addContent(htmlTree); - } - ContentBuilder headContent = new ContentBuilder(); - headContent.addContent(getResource("doclet.ClassUse_Title", cltype)); - headContent.addContent(new HtmlTree(HtmlTag.BR)); - headContent.addContent(clname); - Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, - true, HtmlStyle.title, headContent); - Content div = HtmlTree.DIV(HtmlStyle.header, heading); - if (configuration.allowTag(HtmlTag.MAIN)) { - mainTree.addContent(div); - } else { - bodyTree.addContent(div); - } - return bodyTree; - } - - /** - * Get this package link. - * - * @return a content tree for the package link - */ - protected Content getNavLinkPackage() { - Content linkContent = - getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), packageLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get class page link. - * - * @return a content tree for the class page link - */ - protected Content getNavLinkClass() { - Content linkContent = getLink(new LinkInfoImpl( - configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, classdoc) - .label(configuration.getText("doclet.Class"))); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get the use link. - * - * @return a content tree for the use link - */ - protected Content getNavLinkClassUse() { - Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); - return li; - } - - /** - * Get the tree link. - * - * @return a content tree for the tree link - */ - protected Content getNavLinkTree() { - Content linkContent = classdoc.containingPackage().isIncluded() ? - getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), treeLabel) : - getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), treeLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } -} --- /dev/null Fri Jan 22 12:17:38 2016 +++ new/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java Fri Jan 22 12:17:38 2016 @@ -0,0 +1,554 @@ +/* + * Copyright (c) 1998, 2015, 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 jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Generate class usage information. + * + *

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. + * + * @author Robert G. Field + * @author Bhavesh Patel (Modified) + */ +public class ClassUseWriter extends SubWriterHolderWriter { + + final TypeElement typeElement; + Set pkgToPackageAnnotations = null; + final Map> pkgToClassTypeParameter; + final Map> pkgToClassAnnotations; + final Map> pkgToMethodTypeParameter; + final Map> pkgToMethodArgTypeParameter; + final Map> pkgToMethodReturnTypeParameter; + final Map> pkgToMethodAnnotations; + final Map> pkgToMethodParameterAnnotations; + final Map> pkgToFieldTypeParameter; + final Map> pkgToFieldAnnotations; + final Map> pkgToSubclass; + final Map> pkgToSubinterface; + final Map> pkgToImplementingClass; + final Map> pkgToField; + final Map> pkgToMethodReturn; + final Map> pkgToMethodArgs; + final Map> pkgToMethodThrows; + final Map> pkgToConstructorAnnotations; + final Map> pkgToConstructorParameterAnnotations; + final Map> pkgToConstructorArgs; + final Map> pkgToConstructorArgTypeParameter; + final Map> pkgToConstructorThrows; + final SortedSet pkgSet; + final MethodWriterImpl methodSubWriter; + final ConstructorWriterImpl constrSubWriter; + final FieldWriterImpl fieldSubWriter; + final NestedClassWriterImpl classSubWriter; + // Summary for various use tables. + final String classUseTableSummary; + final String subclassUseTableSummary; + final String subinterfaceUseTableSummary; + final String fieldUseTableSummary; + final String methodUseTableSummary; + final String constructorUseTableSummary; + + /** + * The HTML tree for main tag. + */ + protected HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * Constructor. + * + * @param filename the file to be generated. + * @throws IOException + * @throws DocletAbortException + */ + public ClassUseWriter(ConfigurationImpl configuration, + ClassUseMapper mapper, DocPath filename, + TypeElement typeElement) throws IOException { + super(configuration, filename); + this.typeElement = typeElement; + if (mapper.classToPackageAnnotations.containsKey(typeElement)) { + pkgToPackageAnnotations = new TreeSet<>(utils.makeClassUseComparator()); + pkgToPackageAnnotations.addAll(mapper.classToPackageAnnotations.get(typeElement)); + } + configuration.currentTypeElement = typeElement; + this.pkgSet = new TreeSet<>(utils.makePackageComparator()); + this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam); + this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations); + this.pkgToMethodTypeParameter = pkgDivide(mapper.classToMethodTypeParam); + this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToMethodArgTypeParam); + this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldTypeParam); + this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToField); + this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToMethodReturnTypeParam); + this.pkgToMethodAnnotations = pkgDivide(mapper.classToMethodAnnotations); + this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToMethodParamAnnotation); + this.pkgToSubclass = pkgDivide(mapper.classToSubclass); + this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface); + this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass); + this.pkgToField = pkgDivide(mapper.classToField); + this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn); + this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs); + this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows); + this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations); + this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation); + this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs); + this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorArgTypeParam); + this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows); + //tmp test + if (pkgSet.size() > 0 && + mapper.classToPackage.containsKey(this.typeElement) && + !pkgSet.equals(mapper.classToPackage.get(this.typeElement))) { + configuration.reporter.print(Diagnostic.Kind.WARNING, + "Internal error: package sets don't match: " + + pkgSet + " with: " + mapper.classToPackage.get(this.typeElement)); + } + methodSubWriter = new MethodWriterImpl(this); + constrSubWriter = new ConstructorWriterImpl(this); + fieldSubWriter = new FieldWriterImpl(this); + classSubWriter = new NestedClassWriterImpl(this); + classUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes")); + subclassUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subclasses")); + subinterfaceUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subinterfaces")); + fieldUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.fields")); + methodUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.methods")); + constructorUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.constructors")); + } + + /** + * Write out class use pages. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, ClassTree classtree) { + ClassUseMapper mapper = new ClassUseMapper(configuration, classtree); + for (TypeElement aClass : configuration.root.getIncludedClasses()) { + // If -nodeprecated option is set and the containing package is marked + // as deprecated, do not generate the class-use page. We will still generate + // the class-use page if the class is marked as deprecated but the containing + // package is not since it could still be linked from that package-use page. + if (!(configuration.nodeprecated && + configuration.utils.isDeprecated(configuration.utils.containingPackage(aClass)))) + ClassUseWriter.generate(configuration, mapper, aClass); + } + for (PackageElement pkg : configuration.packages) { + // If -nodeprecated option is set and the package is marked + // as deprecated, do not generate the package-use page. + if (!(configuration.nodeprecated && configuration.utils.isDeprecated(pkg))) + PackageUseWriter.generate(configuration, mapper, pkg); + } + } + + private Map> pkgDivide(Map> classMap) { + Map> map = new HashMap<>(); + List elements = (List) classMap.get(typeElement); + if (elements != null) { + Collections.sort(elements, utils.makeClassUseComparator()); + for (Element e : elements) { + PackageElement pkg = utils.containingPackage(e); + pkgSet.add(pkg); + List inPkg = map.get(pkg); + if (inPkg == null) { + inPkg = new ArrayList<>(); + map.put(pkg, inPkg); + } + inPkg.add(e); + } + } + return map; + } + + /** + * Generate a class page. + */ + public static void generate(ConfigurationImpl configuration, ClassUseMapper mapper, + TypeElement typeElement) { + ClassUseWriter clsgen; + DocPath path = DocPath.forPackage(configuration.utils, typeElement) + .resolve(DocPaths.CLASS_USE) + .resolve(DocPath.forName(configuration.utils, typeElement)); + try { + clsgen = new ClassUseWriter(configuration, mapper, path, typeElement); + clsgen.generateClassUseFile(); + clsgen.close(); + } catch (IOException exc) { + configuration.standardmessage. + error("doclet.exception_encountered", + exc.toString(), path.getPath()); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the class use elements. + */ + protected void generateClassUseFile() throws IOException { + HtmlTree body = getClassUseHeader(); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.classUseContainer); + if (pkgSet.size() > 0) { + addClassUse(div); + } else { + div.addContent(getResource("doclet.ClassUse_No.usage.of.0", + utils.getFullyQualifiedName(typeElement))); + } + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + body.addContent(mainTree); + } else { + body.addContent(div); + } + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the class use documentation. + * + * @param contentTree the content tree to which the class use information will be added + */ + protected void addClassUse(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + if (configuration.packages.size() > 1) { + addPackageList(ul); + addPackageAnnotationList(ul); + } + addClassList(ul); + contentTree.addContent(ul); + } + + /** + * Add the packages elements that use the given class. + * + * @param contentTree the content tree to which the packages elements will be added + */ + protected void addPackageList(Content contentTree) throws IOException { + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_Packages.that.use.0", + getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (PackageElement pkg : pkgSet) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + addPackageUse(pkg, tr); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); + } + + /** + * Add the package annotation elements. + * + * @param contentTree the content tree to which the package annotation elements will be added + */ + protected void addPackageAnnotationList(Content contentTree) throws IOException { + if (!utils.isAnnotationType(typeElement) || + pkgToPackageAnnotations == null || + pkgToPackageAnnotations.isEmpty()) { + return; + } + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_PackageAnnotation", + getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (PackageElement pkg : pkgToPackageAnnotations) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, getPackageLink(pkg)); + tr.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdLast); + tr.addContent(tdLast); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); + } + + /** + * Add the class elements that use the given class. + * + * @param contentTree the content tree to which the class elements will be added + */ + protected void addClassList(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + for (PackageElement pkg : pkgSet) { + Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(markerAnchor) + : HtmlTree.LI(HtmlStyle.blockList, markerAnchor); + Content link = getResource("doclet.ClassUse_Uses.of.0.in.1", + getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, + typeElement)), + getPackageLink(pkg, utils.getPackageName(pkg))); + Content heading = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, link); + htmlTree.addContent(heading); + addClassUse(pkg, htmlTree); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + Content li = HtmlTree.LI(HtmlStyle.blockList, ul); + contentTree.addContent(li); + } + + /** + * Add the package use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the package use information will be added + */ + protected void addPackageUse(PackageElement pkg, Content contentTree) throws IOException { + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg)))); + contentTree.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdLast); + contentTree.addContent(tdLast); + } + + /** + * Add the class use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the class use information will be added + */ + protected void addClassUse(PackageElement pkg, Content contentTree) throws IOException { + Content classLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)); + Content pkgLink = getPackageLink(pkg, utils.getPackageName(pkg)); + classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_Annotation", classLink, + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_TypeParameter", classLink, + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubclass.get(pkg), + configuration.getResource("doclet.ClassUse_Subclass", classLink, + pkgLink), subclassUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubinterface.get(pkg), + configuration.getResource("doclet.ClassUse_Subinterface", classLink, + pkgLink), subinterfaceUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg), + configuration.getResource("doclet.ClassUse_ImplementingClass", classLink, + pkgLink), classUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToField.get(pkg), + configuration.getResource("doclet.ClassUse_Field", classLink, + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_FieldAnnotations", classLink, + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_FieldTypeParameter", classLink, + pkgLink), fieldUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_MethodAnnotations", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_MethodParameterAnnotations", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodTypeParameter", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg), + configuration.getResource("doclet.ClassUse_MethodReturn", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodReturnTypeParameter", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg), + configuration.getResource("doclet.ClassUse_MethodArgs", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodArgsTypeParameters", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg), + configuration.getResource("doclet.ClassUse_MethodThrows", classLink, + pkgLink), methodUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorAnnotations", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorParameterAnnotations", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorArgs", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorThrows", classLink, + pkgLink), constructorUseTableSummary, contentTree); + } + + /** + * Get the header for the class use Listing. + * + * @return a content tree representing the class use header + */ + protected HtmlTree getClassUseHeader() { + String cltype = configuration.getText(utils.isInterface(typeElement) + ? "doclet.Interface" + : "doclet.Class"); + String clname = utils.getFullyQualifiedName(typeElement); + String title = configuration.getText("doclet.Window_ClassUse_Header", + cltype, clname); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + ContentBuilder headContent = new ContentBuilder(); + headContent.addContent(getResource("doclet.ClassUse_Title", cltype)); + headContent.addContent(new HtmlTree(HtmlTag.BR)); + headContent.addContent(clname); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, + true, HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + protected Content getNavLinkPackage() { + Content linkContent = + getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get class page link. + * + * @return a content tree for the class page link + */ + protected Content getNavLinkClass() { + Content linkContent = getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement) + .label(configuration.getText("doclet.Class"))); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the use link. + * + * @return a content tree for the use link + */ + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); + return li; + } + + /** + * Get the tree link. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content linkContent = utils.isEnclosingPackageIncluded(typeElement) + ? getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), treeLabel) + : getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), treeLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } +}