001    /*
002     * Copyright 1998-2008 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    import com.sun.javadoc.*;
030    import java.io.*;
031    import java.util.*;
032    
033    /**
034     * Generate class usage information.
035     *
036     * @author Robert G. Field
037     */
038    public class ClassUseWriter extends SubWriterHolderWriter {
039    
040        final ClassDoc classdoc;
041        Set<PackageDoc> pkgToPackageAnnotations = null;
042        final Map<String,List<ProgramElementDoc>> pkgToClassTypeParameter;
043        final Map<String,List<ProgramElementDoc>> pkgToClassAnnotations;
044        final Map<String,List<ProgramElementDoc>> pkgToMethodTypeParameter;
045        final Map<String,List<ProgramElementDoc>> pkgToMethodArgTypeParameter;
046        final Map<String,List<ProgramElementDoc>> pkgToMethodReturnTypeParameter;
047        final Map<String,List<ProgramElementDoc>> pkgToMethodAnnotations;
048        final Map<String,List<ProgramElementDoc>> pkgToMethodParameterAnnotations;
049        final Map<String,List<ProgramElementDoc>> pkgToFieldTypeParameter;
050        final Map<String,List<ProgramElementDoc>> pkgToFieldAnnotations;
051        final Map<String,List<ProgramElementDoc>> pkgToSubclass;
052        final Map<String,List<ProgramElementDoc>> pkgToSubinterface;
053        final Map<String,List<ProgramElementDoc>> pkgToImplementingClass;
054        final Map<String,List<ProgramElementDoc>> pkgToField;
055        final Map<String,List<ProgramElementDoc>> pkgToMethodReturn;
056        final Map<String,List<ProgramElementDoc>> pkgToMethodArgs;
057        final Map<String,List<ProgramElementDoc>> pkgToMethodThrows;
058        final Map<String,List<ProgramElementDoc>> pkgToConstructorAnnotations;
059        final Map<String,List<ProgramElementDoc>> pkgToConstructorParameterAnnotations;
060        final Map<String,List<ProgramElementDoc>> pkgToConstructorArgs;
061        final Map<String,List<ProgramElementDoc>> pkgToConstructorArgTypeParameter;
062        final Map<String,List<ProgramElementDoc>> pkgToConstructorThrows;
063        final SortedSet<PackageDoc> pkgSet;
064        final MethodWriterImpl methodSubWriter;
065        final ConstructorWriterImpl constrSubWriter;
066        final FieldWriterImpl fieldSubWriter;
067        final NestedClassWriterImpl classSubWriter;
068    
069    
070        /**
071         * Constructor.
072         *
073         * @param filename the file to be generated.
074         * @throws IOException
075         * @throws DocletAbortException
076         */
077        public ClassUseWriter(ConfigurationImpl configuration,
078                              ClassUseMapper mapper, String path,
079                              String filename, String relpath,
080                              ClassDoc classdoc) throws IOException {
081            super(configuration, path, filename, relpath);
082            this.classdoc = classdoc;
083            if (mapper.classToPackageAnnotations.containsKey(classdoc.qualifiedName()))
084                    pkgToPackageAnnotations = new HashSet<PackageDoc>(mapper.classToPackageAnnotations.get(classdoc.qualifiedName()));
085            configuration.currentcd = classdoc;
086            this.pkgSet = new TreeSet<PackageDoc>();
087            this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam);
088            this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations);
089            this.pkgToMethodTypeParameter = pkgDivide(mapper.classToExecMemberDocTypeParam);
090            this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToExecMemberDocArgTypeParam);
091            this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldDocTypeParam);
092            this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToFieldDoc);
093            this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToExecMemberDocReturnTypeParam);
094            this.pkgToMethodAnnotations = pkgDivide(mapper.classToExecMemberDocAnnotations);
095            this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToExecMemberDocParamAnnotation);
096            this.pkgToSubclass = pkgDivide(mapper.classToSubclass);
097            this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface);
098            this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass);
099            this.pkgToField = pkgDivide(mapper.classToField);
100            this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn);
101            this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs);
102            this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows);
103            this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations);
104            this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation);
105            this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs);
106            this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorDocArgTypeParam);
107            this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows);
108            //tmp test
109            if (pkgSet.size() > 0 &&
110                mapper.classToPackage.containsKey(classdoc.qualifiedName()) &&
111                !pkgSet.equals(mapper.classToPackage.get(classdoc.qualifiedName()))) {
112                configuration.root.printWarning("Internal error: package sets don't match: " + pkgSet + " with: " +
113                                       mapper.classToPackage.get(classdoc.qualifiedName()));
114            }
115            methodSubWriter = new MethodWriterImpl(this);
116            constrSubWriter = new ConstructorWriterImpl(this);
117            fieldSubWriter = new FieldWriterImpl(this);
118            classSubWriter = new NestedClassWriterImpl(this);
119        }
120    
121        /**
122         * Write out class use pages.
123         * @throws DocletAbortException
124         */
125        public static void generate(ConfigurationImpl configuration,
126                                    ClassTree classtree)  {
127            ClassUseMapper mapper = new ClassUseMapper(configuration.root, classtree);
128            ClassDoc[] classes = configuration.root.classes();
129            for (int i = 0; i < classes.length; i++) {
130                ClassUseWriter.generate(configuration, mapper, classes[i]);
131            }
132            PackageDoc[] pkgs = configuration.packages;
133            for (int i = 0; i < pkgs.length; i++) {
134                PackageUseWriter.generate(configuration, mapper, pkgs[i]);
135            }
136        }
137    
138        private Map<String,List<ProgramElementDoc>> pkgDivide(Map<String,? extends List<? extends ProgramElementDoc>> classMap) {
139            Map<String,List<ProgramElementDoc>> map = new HashMap<String,List<ProgramElementDoc>>();
140            List<? extends ProgramElementDoc> list= classMap.get(classdoc.qualifiedName());
141            if (list != null) {
142                Collections.sort(list);
143                Iterator<? extends ProgramElementDoc> it = list.iterator();
144                while (it.hasNext()) {
145                    ProgramElementDoc doc = it.next();
146                    PackageDoc pkg = doc.containingPackage();
147                    pkgSet.add(pkg);
148                    List<ProgramElementDoc> inPkg = map.get(pkg.name());
149                    if (inPkg == null) {
150                        inPkg = new ArrayList<ProgramElementDoc>();
151                        map.put(pkg.name(), inPkg);
152                    }
153                    inPkg.add(doc);
154                }
155            }
156            return map;
157        }
158    
159        /**
160         * Generate a class page.
161         */
162        public static void generate(ConfigurationImpl configuration,
163                                    ClassUseMapper mapper, ClassDoc classdoc) {
164            ClassUseWriter clsgen;
165            String path = DirectoryManager.getDirectoryPath(classdoc.
166                                                                containingPackage());
167            if (path.length() > 0) {
168                path += File.separator;
169            }
170            path += "class-use";
171            String filename = classdoc.name() + ".html";
172            String pkgname = classdoc.containingPackage().name();
173            pkgname += (pkgname.length() > 0)? ".class-use": "class-use";
174            String relpath = DirectoryManager.getRelativePath(pkgname);
175            try {
176                clsgen = new ClassUseWriter(configuration,
177                                            mapper, path, filename,
178                                            relpath, classdoc);
179                clsgen.generateClassUseFile();
180                clsgen.close();
181            } catch (IOException exc) {
182                configuration.standardmessage.
183                    error("doclet.exception_encountered",
184                          exc.toString(), filename);
185                throw new DocletAbortException();
186            }
187        }
188    
189        /**
190         * Print the class use list.
191         */
192        protected void generateClassUseFile() throws IOException {
193    
194            printClassUseHeader();
195    
196            if (pkgSet.size() > 0) {
197                generateClassUse();
198            } else {
199                printText("doclet.ClassUse_No.usage.of.0",
200                          classdoc.qualifiedName());
201                p();
202            }
203    
204            printClassUseFooter();
205        }
206    
207        protected void generateClassUse() throws IOException {
208            if (configuration.packages.length > 1) {
209                generatePackageList();
210                generatePackageAnnotationList();
211            }
212            generateClassList();
213        }
214    
215        protected void generatePackageList() throws IOException {
216            tableIndexSummary();
217            tableHeaderStart("#CCCCFF");
218            printText("doclet.ClassUse_Packages.that.use.0",
219                getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc,
220                    false)));
221            tableHeaderEnd();
222    
223            for (Iterator<PackageDoc> it = pkgSet.iterator(); it.hasNext();) {
224                PackageDoc pkg = it.next();
225                generatePackageUse(pkg);
226            }
227            tableEnd();
228            space();
229            p();
230        }
231    
232        protected void generatePackageAnnotationList() throws IOException {
233            if ((! classdoc.isAnnotationType()) ||
234                   pkgToPackageAnnotations == null ||
235                   pkgToPackageAnnotations.size() == 0)
236                return;
237            tableIndexSummary();
238            tableHeaderStart("#CCCCFF");
239            printText("doclet.ClassUse_PackageAnnotation",
240                getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc,
241                    false)));
242            tableHeaderEnd();
243            for (Iterator<PackageDoc> it = pkgToPackageAnnotations.iterator(); it.hasNext();) {
244                PackageDoc pkg = it.next();
245                trBgcolorStyle("white", "TableRowColor");
246                summaryRow(0);
247                //Just want an anchor here.
248                printPackageLink(pkg, pkg.name(), true);
249                summaryRowEnd();
250                summaryRow(0);
251                printSummaryComment(pkg);
252                space();
253                summaryRowEnd();
254                trEnd();
255            }
256            tableEnd();
257            space();
258            p();
259        }
260    
261        protected void generateClassList() throws IOException {
262            for (Iterator<PackageDoc> it = pkgSet.iterator(); it.hasNext();) {
263                PackageDoc pkg = it.next();
264                anchor(pkg.name());
265                tableIndexSummary();
266                tableHeaderStart("#CCCCFF");
267                printText("doclet.ClassUse_Uses.of.0.in.1",
268                    getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER,
269                        classdoc, false)),
270                    getPackageLink(pkg, Util.getPackageName(pkg), false));
271                tableHeaderEnd();
272                tableEnd();
273                space();
274                p();
275                generateClassUse(pkg);
276            }
277        }
278    
279        /**
280         * Print the package use list.
281         */
282        protected void generatePackageUse(PackageDoc pkg) throws IOException {
283            trBgcolorStyle("white", "TableRowColor");
284            summaryRow(0);
285            //Just want an anchor here.
286            printHyperLink("", pkg.name(), Util.getPackageName(pkg), true);
287            summaryRowEnd();
288            summaryRow(0);
289            printSummaryComment(pkg);
290            space();
291            summaryRowEnd();
292            trEnd();
293        }
294    
295        /**
296         * Print the class use list.
297         */
298        protected void generateClassUse(PackageDoc pkg) throws IOException {
299            String classLink = getLink(new LinkInfoImpl(
300                LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false));
301            String pkgLink = getPackageLink(pkg, Util.getPackageName(pkg), false);
302            classSubWriter.printUseInfo(pkgToClassAnnotations.get(pkg.name()),
303                configuration.getText("doclet.ClassUse_Annotation", classLink,
304                pkgLink));
305    
306            classSubWriter.printUseInfo(pkgToClassTypeParameter.get(pkg.name()),
307                configuration.getText("doclet.ClassUse_TypeParameter", classLink,
308                pkgLink));
309            classSubWriter.printUseInfo(pkgToSubclass.get(pkg.name()),
310                configuration.getText("doclet.ClassUse_Subclass", classLink,
311                pkgLink));
312            classSubWriter.printUseInfo(pkgToSubinterface.get(pkg.name()),
313                                        configuration.getText("doclet.ClassUse_Subinterface",
314                                                classLink,
315                                                pkgLink));
316            classSubWriter.printUseInfo(pkgToImplementingClass.get(pkg.name()),
317                                        configuration.getText("doclet.ClassUse_ImplementingClass",
318                                                classLink,
319                                                pkgLink));
320            fieldSubWriter.printUseInfo(pkgToField.get(pkg.name()),
321                                        configuration.getText("doclet.ClassUse_Field",
322                                                classLink,
323                                                pkgLink));
324            fieldSubWriter.printUseInfo(pkgToFieldAnnotations.get(pkg.name()),
325                configuration.getText("doclet.ClassUse_FieldAnnotations",
326                classLink,
327                pkgLink));
328            fieldSubWriter.printUseInfo(pkgToFieldTypeParameter.get(pkg.name()),
329                configuration.getText("doclet.ClassUse_FieldTypeParameter",
330                classLink,
331                pkgLink));
332            methodSubWriter.printUseInfo(pkgToMethodAnnotations.get(pkg.name()),
333                configuration.getText("doclet.ClassUse_MethodAnnotations", classLink,
334                pkgLink));
335            methodSubWriter.printUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()),
336                configuration.getText("doclet.ClassUse_MethodParameterAnnotations", classLink,
337                pkgLink));
338            methodSubWriter.printUseInfo(pkgToMethodTypeParameter.get(pkg.name()),
339                configuration.getText("doclet.ClassUse_MethodTypeParameter", classLink,
340                pkgLink));
341            methodSubWriter.printUseInfo(pkgToMethodReturn.get(pkg.name()),
342                                         configuration.getText("doclet.ClassUse_MethodReturn",
343                                                 classLink,
344                                                 pkgLink));
345            methodSubWriter.printUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()),
346                configuration.getText("doclet.ClassUse_MethodReturnTypeParameter", classLink,
347                pkgLink));
348            methodSubWriter.printUseInfo(pkgToMethodArgs.get(pkg.name()),
349                                         configuration.getText("doclet.ClassUse_MethodArgs",
350                                                 classLink,
351                                                 pkgLink));
352            methodSubWriter.printUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()),
353                configuration.getText("doclet.ClassUse_MethodArgsTypeParameters",
354                classLink,
355                pkgLink));
356            methodSubWriter.printUseInfo(pkgToMethodThrows.get(pkg.name()),
357                                         configuration.getText("doclet.ClassUse_MethodThrows",
358                                                 classLink,
359                                                 pkgLink));
360            constrSubWriter.printUseInfo(pkgToConstructorAnnotations.get(pkg.name()),
361                configuration.getText("doclet.ClassUse_ConstructorAnnotations",
362                    classLink,
363                    pkgLink));
364            constrSubWriter.printUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()),
365                configuration.getText("doclet.ClassUse_ConstructorParameterAnnotations",
366                    classLink,
367                    pkgLink));
368            constrSubWriter.printUseInfo(pkgToConstructorArgs.get(pkg.name()),
369                                         configuration.getText("doclet.ClassUse_ConstructorArgs",
370                                                 classLink,
371                                                 pkgLink));
372            constrSubWriter.printUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()),
373                configuration.getText("doclet.ClassUse_ConstructorArgsTypeParameters",
374                classLink,
375                pkgLink));
376            constrSubWriter.printUseInfo(pkgToConstructorThrows.get(pkg.name()),
377                                         configuration.getText("doclet.ClassUse_ConstructorThrows",
378                                                 classLink,
379                                                 pkgLink));
380        }
381    
382        /**
383         * Print the header for the class use Listing.
384         */
385        protected void printClassUseHeader() {
386            String cltype = configuration.getText(classdoc.isInterface()?
387                                        "doclet.Interface":
388                                        "doclet.Class");
389            String clname = classdoc.qualifiedName();
390            printHtmlHeader(configuration.getText("doclet.Window_ClassUse_Header",
391                                cltype, clname), null, true);
392            printTop();
393            navLinks(true);
394            hr();
395            center();
396            h2();
397            strongText("doclet.ClassUse_Title", cltype, clname);
398            h2End();
399            centerEnd();
400        }
401    
402        /**
403         * Print the footer for the class use Listing.
404         */
405        protected void printClassUseFooter() {
406            hr();
407            navLinks(false);
408            printBottom();
409            printBodyHtmlEnd();
410        }
411    
412    
413        /**
414         * Print this package link
415         */
416        protected void navLinkPackage() {
417            navCellStart();
418            printHyperLink("../package-summary.html", "",
419                           configuration.getText("doclet.Package"), true, "NavBarFont1");
420            navCellEnd();
421        }
422    
423        /**
424         * Print class page indicator
425         */
426        protected void navLinkClass() {
427            navCellStart();
428            printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, "",
429                configuration.getText("doclet.Class"), true, "NavBarFont1"));
430            navCellEnd();
431        }
432    
433        /**
434         * Print class use link
435         */
436        protected void navLinkClassUse() {
437            navCellRevStart();
438            fontStyle("NavBarFont1Rev");
439            strongText("doclet.navClassUse");
440            fontEnd();
441            navCellEnd();
442        }
443    
444        protected void navLinkTree() {
445            navCellStart();
446            if (classdoc.containingPackage().isIncluded()) {
447                printHyperLink("../package-tree.html", "",
448                    configuration.getText("doclet.Tree"), true, "NavBarFont1");
449            } else {
450                printHyperLink(relativePath + "overview-tree.html", "",
451                    configuration.getText("doclet.Tree"), true, "NavBarFont1");
452            }
453            navCellEnd();
454        }
455    
456    }