0N/A/*
797N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.tools.doclets.internal.toolkit.builders;
0N/A
765N/Aimport java.io.*;
765N/Aimport java.util.*;
765N/Aimport com.sun.javadoc.*;
0N/Aimport com.sun.tools.doclets.internal.toolkit.util.*;
0N/Aimport com.sun.tools.doclets.internal.toolkit.*;
0N/A
0N/A/**
0N/A * Builds the Constants Summary Page.
0N/A *
0N/A * This code is not part of an API.
0N/A * It is implementation that is subject to change.
0N/A * Do not use it as an API
0N/A *
0N/A * @author Jamie Ho
765N/A * @author Bhavesh Patel (Modified)
0N/A * @since 1.5
0N/A */
0N/Apublic class ConstantsSummaryBuilder extends AbstractBuilder {
0N/A
0N/A /**
0N/A * The root element of the constant summary XML is {@value}.
0N/A */
0N/A public static final String ROOT = "ConstantSummary";
0N/A
0N/A /**
0N/A * The maximum number of package directories shown in the constant
0N/A * value index.
0N/A */
0N/A public static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2;
0N/A
0N/A /**
0N/A * The writer used to write the results.
0N/A */
0N/A protected ConstantsSummaryWriter writer;
0N/A
0N/A /**
0N/A * The set of ClassDocs that have constant fields.
0N/A */
73N/A protected Set<ClassDoc> classDocsWithConstFields;
0N/A
0N/A /**
0N/A * The set of printed package headers.
0N/A */
73N/A protected Set<String> printedPackageHeaders;
0N/A
0N/A /**
0N/A * The current package being documented.
0N/A */
0N/A private PackageDoc currentPackage;
0N/A
0N/A /**
0N/A * The current class being documented.
0N/A */
0N/A private ClassDoc currentClass;
0N/A
0N/A /**
765N/A * The content tree for the constant summary documentation.
765N/A */
765N/A private Content contentTree;
765N/A
765N/A /**
0N/A * Construct a new ConstantsSummaryBuilder.
0N/A *
0N/A * @param configuration the current configuration of the
0N/A * doclet.
0N/A */
0N/A private ConstantsSummaryBuilder(Configuration configuration) {
0N/A super(configuration);
0N/A }
0N/A
0N/A /**
0N/A * Construct a ConstantsSummaryBuilder.
0N/A *
0N/A * @param configuration the configuration used in this run
0N/A * of the doclet.
0N/A * @param writer the writer for the summary.
0N/A */
0N/A public static ConstantsSummaryBuilder getInstance(
0N/A Configuration configuration, ConstantsSummaryWriter writer) {
0N/A ConstantsSummaryBuilder builder = new ConstantsSummaryBuilder(
0N/A configuration);
0N/A builder.writer = writer;
73N/A builder.classDocsWithConstFields = new HashSet<ClassDoc>();
0N/A return builder;
0N/A }
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A public void build() throws IOException {
0N/A if (writer == null) {
0N/A //Doclet does not support this output.
0N/A return;
0N/A }
765N/A build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree);
0N/A }
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A public String getName() {
0N/A return ROOT;
0N/A }
0N/A
0N/A /**
0N/A * Build the constant summary.
0N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param contentTree the content tree to which the documentation will be added
0N/A */
765N/A public void buildConstantSummary(XMLNode node, Content contentTree) throws Exception {
765N/A contentTree = writer.getHeader();
765N/A buildChildren(node, contentTree);
765N/A writer.addFooter(contentTree);
765N/A writer.printDocument(contentTree);
0N/A writer.close();
0N/A }
0N/A
0N/A /**
765N/A * Build the list of packages.
765N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param contentTree the content tree to which the content list will be added
0N/A */
765N/A public void buildContents(XMLNode node, Content contentTree) {
765N/A Content contentListTree = writer.getContentsHeader();
0N/A PackageDoc[] packages = configuration.packages;
73N/A printedPackageHeaders = new HashSet<String>();
0N/A for (int i = 0; i < packages.length; i++) {
0N/A if (hasConstantField(packages[i]) && ! hasPrintedPackageIndex(packages[i].name())) {
765N/A writer.addLinkToPackageContent(packages[i],
0N/A parsePackageName(packages[i].name()),
765N/A printedPackageHeaders, contentListTree);
0N/A }
0N/A }
765N/A contentTree.addContent(writer.getContentsList(contentListTree));
0N/A }
0N/A
0N/A /**
0N/A * Build the summary for each documented package.
0N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param contentTree the tree to which the summaries will be added
0N/A */
765N/A public void buildConstantSummaries(XMLNode node, Content contentTree) {
0N/A PackageDoc[] packages = configuration.packages;
73N/A printedPackageHeaders = new HashSet<String>();
765N/A Content summariesTree = writer.getConstantSummaries();
0N/A for (int i = 0; i < packages.length; i++) {
0N/A if (hasConstantField(packages[i])) {
0N/A currentPackage = packages[i];
0N/A //Build the documentation for the current package.
765N/A buildChildren(node, summariesTree);
0N/A }
0N/A }
765N/A contentTree.addContent(summariesTree);
0N/A }
0N/A
0N/A /**
765N/A * Build the header for the given package.
0N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param summariesTree the tree to which the package header will be added
0N/A */
765N/A public void buildPackageHeader(XMLNode node, Content summariesTree) {
765N/A String parsedPackageName = parsePackageName(currentPackage.name());
765N/A if (! printedPackageHeaders.contains(parsedPackageName)) {
765N/A writer.addPackageName(currentPackage,
765N/A parsePackageName(currentPackage.name()), summariesTree);
765N/A printedPackageHeaders.add(parsedPackageName);
765N/A }
0N/A }
0N/A
0N/A /**
0N/A * Build the summary for the current class.
0N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param summariesTree the tree to which the class constant summary will be added
0N/A */
765N/A public void buildClassConstantSummary(XMLNode node, Content summariesTree) {
0N/A ClassDoc[] classes = currentPackage.name().length() > 0 ?
0N/A currentPackage.allClasses() :
0N/A configuration.classDocCatalog.allClasses(
0N/A DocletConstants.DEFAULT_PACKAGE_NAME);
0N/A Arrays.sort(classes);
765N/A Content classConstantTree = writer.getClassConstantHeader();
0N/A for (int i = 0; i < classes.length; i++) {
0N/A if (! classDocsWithConstFields.contains(classes[i]) ||
0N/A ! classes[i].isIncluded()) {
0N/A continue;
0N/A }
0N/A currentClass = classes[i];
0N/A //Build the documentation for the current class.
765N/A buildChildren(node, classConstantTree);
0N/A }
765N/A summariesTree.addContent(classConstantTree);
0N/A }
0N/A
0N/A /**
765N/A * Build the summary of constant members in the class.
765N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param classConstantTree the tree to which the constant members table
765N/A * will be added
0N/A */
765N/A public void buildConstantMembers(XMLNode node, Content classConstantTree) {
765N/A new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree);
0N/A }
0N/A
0N/A /**
0N/A * Return true if the given package has constant fields to document.
0N/A *
0N/A * @param pkg the package being checked.
0N/A * @return true if the given package has constant fields to document.
0N/A */
0N/A private boolean hasConstantField(PackageDoc pkg) {
0N/A ClassDoc[] classes;
0N/A if (pkg.name().length() > 0) {
0N/A classes = pkg.allClasses();
0N/A } else {
0N/A classes = configuration.classDocCatalog.allClasses(
0N/A DocletConstants.DEFAULT_PACKAGE_NAME);
0N/A }
0N/A boolean found = false;
0N/A for (int j = 0; j < classes.length; j++){
0N/A if (classes[j].isIncluded() && hasConstantField(classes[j])) {
0N/A found = true;
0N/A }
0N/A }
0N/A return found;
0N/A }
0N/A
0N/A /**
0N/A * Return true if the given class has constant fields to document.
0N/A *
0N/A * @param classDoc the class being checked.
0N/A * @return true if the given package has constant fields to document.
0N/A */
0N/A private boolean hasConstantField (ClassDoc classDoc) {
0N/A VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(classDoc,
0N/A VisibleMemberMap.FIELDS, configuration.nodeprecated);
183N/A List<?> fields = visibleMemberMapFields.getLeafClassMembers(configuration);
183N/A for (Iterator<?> iter = fields.iterator(); iter.hasNext(); ) {
0N/A FieldDoc field = (FieldDoc) iter.next();
0N/A if (field.constantValueExpression() != null) {
0N/A classDocsWithConstFields.add(classDoc);
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Return true if the given package name has been printed. Also
0N/A * return true if the root of this package has been printed.
0N/A *
0N/A * @param pkgname the name of the package to check.
0N/A */
0N/A private boolean hasPrintedPackageIndex(String pkgname) {
73N/A String[] list = printedPackageHeaders.toArray(new String[] {});
0N/A for (int i = 0; i < list.length; i++) {
0N/A if (pkgname.startsWith(list[i])) {
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Print the table of constants.
0N/A *
0N/A * @author Jamie Ho
0N/A * @since 1.4
0N/A */
0N/A private class ConstantFieldBuilder {
0N/A
0N/A /**
0N/A * The map used to get the visible variables.
0N/A */
0N/A protected VisibleMemberMap visibleMemberMapFields = null;
0N/A
0N/A /**
0N/A * The map used to get the visible variables.
0N/A */
0N/A protected VisibleMemberMap visibleMemberMapEnumConst = null;
0N/A
0N/A /**
0N/A * The classdoc that we are examining constants for.
0N/A */
0N/A protected ClassDoc classdoc;
0N/A
0N/A /**
0N/A * Construct a ConstantFieldSubWriter.
0N/A * @param classdoc the classdoc that we are examining constants for.
0N/A */
0N/A public ConstantFieldBuilder(ClassDoc classdoc) {
0N/A this.classdoc = classdoc;
0N/A visibleMemberMapFields = new VisibleMemberMap(classdoc,
0N/A VisibleMemberMap.FIELDS, configuration.nodeprecated);
0N/A visibleMemberMapEnumConst = new VisibleMemberMap(classdoc,
0N/A VisibleMemberMap.ENUM_CONSTANTS, configuration.nodeprecated);
0N/A }
0N/A
0N/A /**
0N/A * Builds the table of constants for a given class.
765N/A *
765N/A * @param node the XML element that specifies which components to document
765N/A * @param classConstantTree the tree to which the class constants table
765N/A * will be added
0N/A */
765N/A protected void buildMembersSummary(XMLNode node, Content classConstantTree) {
73N/A List<FieldDoc> members = new ArrayList<FieldDoc>(members());
0N/A if (members.size() > 0) {
0N/A Collections.sort(members);
765N/A writer.addConstantMembers(classdoc, members, classConstantTree);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return the list of visible constant fields for the given classdoc.
0N/A * @param cd the classdoc to examine.
0N/A * @return the list of visible constant fields for the given classdoc.
0N/A */
73N/A protected List<FieldDoc> members() {
73N/A List<ProgramElementDoc> l = visibleMemberMapFields.getLeafClassMembers(configuration);
0N/A l.addAll(visibleMemberMapEnumConst.getLeafClassMembers(configuration));
73N/A Iterator<ProgramElementDoc> iter;
0N/A
0N/A if(l != null){
0N/A iter = l.iterator();
0N/A } else {
0N/A return null;
0N/A }
73N/A List<FieldDoc> inclList = new LinkedList<FieldDoc>();
0N/A FieldDoc member;
0N/A while(iter.hasNext()){
0N/A member = (FieldDoc)iter.next();
0N/A if(member.constantValue() != null){
0N/A inclList.add(member);
0N/A }
0N/A }
0N/A return inclList;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Parse the package name. We only want to display package name up to
0N/A * 2 levels.
0N/A */
0N/A private String parsePackageName(String pkgname) {
0N/A int index = -1;
0N/A for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) {
0N/A index = pkgname.indexOf(".", index + 1);
0N/A }
0N/A if (index != -1) {
0N/A pkgname = pkgname.substring(0, index);
0N/A }
0N/A return pkgname;
0N/A }
0N/A}