001    /*
002     * Copyright 1998-2004 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.doclets.formats.html;
027    
028    import com.sun.tools.doclets.internal.toolkit.util.*;
029    
030    import com.sun.javadoc.*;
031    import java.io.*;
032    import java.util.*;
033    
034    /**
035     * Abstract class to print the class hierarchy page for all the Classes. This
036     * is sub-classed by {@link PackageTreeWriter} and {@link TreeWriter} to
037     * generate the Package Tree and global Tree(for all the classes and packages)
038     * pages.
039     *
040     * @author Atul M Dambalkar
041     */
042    public abstract class AbstractTreeWriter extends HtmlDocletWriter {
043    
044        /**
045         * The class and interface tree built by using {@link ClassTree}
046         */
047        protected final ClassTree classtree;
048    
049        /**
050         * Constructor initilises classtree variable. This constructor will be used
051         * while generating global tree file "overview-tree.html".
052         *
053         * @param filename   File to be generated.
054         * @param classtree  Tree built by {@link ClassTree}.
055         * @throws IOException
056         * @throws DocletAbortException
057         */
058        protected AbstractTreeWriter(ConfigurationImpl configuration,
059                                     String filename, ClassTree classtree)
060                                     throws IOException {
061            super(configuration, filename);
062            this.classtree = classtree;
063        }
064    
065        /**
066         * Create appropriate directory for the package and also initilise the
067         * relative path from this generated file to the current or
068         * the destination directory. This constructor will be used while
069         * generating "package tree" file.
070         *
071         * @param path Directories in this path will be created if they are not
072         * already there.
073         * @param filename Name of the package tree file to be generated.
074         * @param classtree The tree built using {@link ClassTree}.
075         * for the package pkg.
076         * @param pkg PackageDoc for which tree file will be generated.
077         * @throws IOException
078         * @throws DocletAbortException
079         */
080        protected AbstractTreeWriter(ConfigurationImpl configuration,
081                                     String path, String filename,
082                                     ClassTree classtree, PackageDoc pkg)
083                                     throws IOException {
084            super(configuration,
085                  path, filename, DirectoryManager.getRelativePath(pkg.name()));
086            this.classtree = classtree;
087        }
088    
089        /**
090         * Generate each level of the class tree. For each sub-class or
091         * sub-interface indents the next level information.
092         * Recurses itself to generate subclasses info.
093         * To iterate is human, to recurse is divine - L. Peter Deutsch.
094         *
095         * @param parent the superclass or superinterface of the list.
096         * @param list list of the sub-classes at this level.
097         * @param isEnum true if we are generating a tree for enums.
098         */
099        protected void generateLevelInfo(ClassDoc parent, List<ClassDoc> list,
100                boolean isEnum) {
101            if (list.size() > 0) {
102                ul();
103                for (int i = 0; i < list.size(); i++) {
104                    ClassDoc local = list.get(i);
105                    printPartialInfo(local);
106                    printExtendsImplements(parent, local);
107                    generateLevelInfo(local, classtree.subs(local, isEnum),
108                        isEnum);   // Recurse
109                }
110                ulEnd();
111            }
112        }
113    
114        /**
115         * Generate the heading for the tree depending upon tree type if it's a
116         * Class Tree or Interface tree and also print the tree.
117         *
118         * @param list List of classes which are at the most base level, all the
119         * other classes in this run will derive from these classes.
120         * @param heading Heading for the tree.
121         */
122        protected void generateTree(List<ClassDoc> list, String heading) {
123            if (list.size() > 0) {
124                ClassDoc firstClassDoc = list.get(0);
125                printTreeHeading(heading);
126                generateLevelInfo(!firstClassDoc.isInterface()? firstClassDoc : null,
127                    list,
128                    list == classtree.baseEnums());
129            }
130        }
131    
132        /**
133         * Print the information regarding the classes which this class extends or
134         * implements.
135         *
136         * @param cd The classdoc under consideration.
137         */
138        protected void printExtendsImplements(ClassDoc parent, ClassDoc cd) {
139            ClassDoc[] interfaces = cd.interfaces();
140            if (interfaces.length > (cd.isInterface()? 1 : 0)) {
141                Arrays.sort(interfaces);
142                int counter = 0;
143                for (int i = 0; i < interfaces.length; i++) {
144                    if (parent != interfaces[i]) {
145                        if (! (interfaces[i].isPublic() ||
146                                Util.isLinkable(interfaces[i], configuration()))) {
147                            continue;
148                        }
149                        if (counter == 0) {
150                            if (cd.isInterface()) {
151                                print(" (" + configuration.getText("doclet.also") + " extends ");
152                            } else {
153                                print(" (implements ");
154                            }
155                        } else {
156                            print(", ");
157                        }
158                        printPreQualifiedClassLink(LinkInfoImpl.CONTEXT_TREE,
159                            interfaces[i]);
160                        counter++;
161                    }
162                }
163                if (counter > 0) {
164                    println(")");
165                }
166            }
167        }
168    
169        /**
170         * Print information about the class kind, if it's a "class" or "interface".
171         *
172         * @param cd classdoc.
173         */
174        protected void printPartialInfo(ClassDoc cd) {
175            li("circle");
176            printPreQualifiedStrongClassLink(LinkInfoImpl.CONTEXT_TREE, cd);
177        }
178    
179        /**
180         * Print the heading for the tree.
181         *
182         * @param heading Heading for the tree.
183         */
184        protected void printTreeHeading(String heading) {
185            h2();
186            println(configuration.getText(heading));
187            h2End();
188        }
189    
190        /**
191         * Highlight "Tree" word in the navigation bar, since this is the tree page.
192         */
193        protected void navLinkTree() {
194            navCellRevStart();
195            fontStyle("NavBarFont1Rev");
196            strongText("doclet.Tree");
197            fontEnd();
198            navCellEnd();
199        }
200    }