001: /*
002: * Copyright 1998-2006 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.internal.toolkit.util;
027:
028: import com.sun.tools.doclets.internal.toolkit.*;
029: import com.sun.javadoc.*;
030: import java.util.*;
031:
032: /**
033: * Build the mapping of each Unicode character with it's member lists
034: * containing members names starting with it. Also build a list for all the
035: * Unicode characters which start a member name. Member name is
036: * classkind or field or method or constructor name.
037: *
038: * This code is not part of an API.
039: * It is implementation that is subject to change.
040: * Do not use it as an API
041: *
042: * @since 1.2
043: * @see java.lang.Character
044: * @author Atul M Dambalkar
045: */
046: public class IndexBuilder {
047:
048: /**
049: * Mapping of each Unicode Character with the member list containing
050: * members with names starting with it.
051: */
052: private Map indexmap = new HashMap();
053:
054: /**
055: * Don't generate deprecated information if true.
056: */
057: private boolean noDeprecated;
058:
059: /**
060: * Build this Index only for classes?
061: */
062: private boolean classesOnly;
063:
064: // make ProgramElementDoc[] when new toArray is available
065: protected final Object[] elements;
066:
067: /**
068: * A comparator used to sort classes and members.
069: * Note: Maybe this compare code belongs in the tool?
070: */
071: private class DocComparator implements Comparator {
072: public int compare(Object d1, Object d2) {
073: String doc1 = (((Doc) d1).name());
074: String doc2 = (((Doc) d2).name());
075: int compareResult;
076: if ((compareResult = doc1.compareToIgnoreCase(doc2)) != 0) {
077: return compareResult;
078: } else if (d1 instanceof ProgramElementDoc
079: && d2 instanceof ProgramElementDoc) {
080: doc1 = (((ProgramElementDoc) d1).qualifiedName());
081: doc2 = (((ProgramElementDoc) d2).qualifiedName());
082: return doc1.compareToIgnoreCase(doc2);
083: } else {
084: return 0;
085: }
086: }
087: }
088:
089: /**
090: * Constructor. Build the index map.
091: *
092: * @param configuration the current configuration of the doclet.
093: * @param noDeprecated true if -nodeprecated option is used,
094: * false otherwise.
095: */
096: public IndexBuilder(Configuration configuration,
097: boolean noDeprecated) {
098: this (configuration, noDeprecated, false);
099: }
100:
101: /**
102: * Constructor. Build the index map.
103: *
104: * @param configuration the current configuration of the doclet.
105: * @param noDeprecated true if -nodeprecated option is used,
106: * false otherwise.
107: * @param classesOnly Include only classes in index.
108: */
109: public IndexBuilder(Configuration configuration,
110: boolean noDeprecated, boolean classesOnly) {
111: if (classesOnly) {
112: configuration.message
113: .notice("doclet.Building_Index_For_All_Classes");
114: } else {
115: configuration.message.notice("doclet.Building_Index");
116: }
117: this .noDeprecated = noDeprecated;
118: this .classesOnly = classesOnly;
119: buildIndexMap(configuration.root);
120: Set set = indexmap.keySet();
121: elements = set.toArray();
122: Arrays.sort(elements);
123: }
124:
125: /**
126: * Sort the index map. Traverse the index map for all it's elements and
127: * sort each element which is a list.
128: */
129: protected void sortIndexMap() {
130: for (Iterator it = indexmap.values().iterator(); it.hasNext();) {
131: Collections.sort((List) it.next(), new DocComparator());
132: }
133: }
134:
135: /**
136: * Get all the members in all the Packages and all the Classes
137: * given on the command line. Form separate list of those members depending
138: * upon their names.
139: *
140: * @param root Root of the documemt.
141: */
142: protected void buildIndexMap(RootDoc root) {
143: PackageDoc[] packages = root.specifiedPackages();
144: ClassDoc[] classes = root.classes();
145: if (!classesOnly) {
146: if (packages.length == 0) {
147: Set set = new HashSet();
148: PackageDoc pd;
149: for (int i = 0; i < classes.length; i++) {
150: pd = classes[i].containingPackage();
151: if (pd != null && pd.name().length() > 0) {
152: set.add(pd);
153: }
154: }
155: adjustIndexMap((PackageDoc[]) set.toArray(packages));
156: } else {
157: adjustIndexMap(packages);
158: }
159: }
160: adjustIndexMap(classes);
161: if (!classesOnly) {
162: for (int i = 0; i < classes.length; i++) {
163: if (shouldAddToIndexMap(classes[i])) {
164: putMembersInIndexMap(classes[i]);
165: }
166: }
167: }
168: sortIndexMap();
169: }
170:
171: /**
172: * Put all the members(fields, methods and constructors) in the classdoc
173: * to the indexmap.
174: *
175: * @param classdoc ClassDoc whose members will be added to the indexmap.
176: */
177: protected void putMembersInIndexMap(ClassDoc classdoc) {
178: adjustIndexMap(classdoc.fields());
179: adjustIndexMap(classdoc.methods());
180: adjustIndexMap(classdoc.constructors());
181: }
182:
183: /**
184: * Adjust list of members according to their names. Check the first
185: * character in a member name, and then add the member to a list of members
186: * for that particular unicode character.
187: *
188: * @param elements Array of members.
189: */
190: protected void adjustIndexMap(Doc[] elements) {
191: for (int i = 0; i < elements.length; i++) {
192: if (shouldAddToIndexMap(elements[i])) {
193: String name = elements[i].name();
194: char ch = (name.length() == 0) ? '*' : Character
195: .toUpperCase(name.charAt(0));
196: Character unicode = new Character(ch);
197: List list = (List) indexmap.get(unicode);
198: if (list == null) {
199: list = new ArrayList();
200: indexmap.put(unicode, list);
201: }
202: list.add(elements[i]);
203: }
204: }
205: }
206:
207: /**
208: * Should this doc element be added to the index map?
209: */
210: protected boolean shouldAddToIndexMap(Doc element) {
211: return !(noDeprecated && element.tags("deprecated").length > 0);
212: }
213:
214: /**
215: * Return a map of all the individual member lists with Unicode character.
216: *
217: * @return Map index map.
218: */
219: public Map getIndexMap() {
220: return indexmap;
221: }
222:
223: /**
224: * Return the sorted list of members, for passed Unicode Character.
225: *
226: * @param index index Unicode character.
227: * @return List member list for specific Unicode character.
228: */
229: public List getMemberList(Character index) {
230: return (List) indexmap.get(index);
231: }
232:
233: /**
234: * Array of IndexMap keys, Unicode characters.
235: */
236: public Object[] elements() {
237: return elements;
238: }
239: }
|