Sun, 24 Feb 2013 11:36:58 -0800
7112427: The doclet needs to be able to generate JavaFX documentation.
Reviewed-by: jjg
Contributed-by: jan.valenta@oracle.com
1 /*
2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.doclets.internal.toolkit.util;
28 import java.util.*;
30 import com.sun.javadoc.*;
31 import com.sun.tools.doclets.internal.toolkit.*;
33 /**
34 * Build Class Hierarchy for all the Classes. This class builds the Class
35 * Tree and the Interface Tree separately.
36 *
37 * <p><b>This is NOT part of any supported API.
38 * If you write code that depends on this, you do so at your own risk.
39 * This code and its internal interfaces are subject to change or
40 * deletion without notice.</b>
41 *
42 * @see java.util.HashMap
43 * @see java.util.List
44 * @see com.sun.javadoc.Type
45 * @see com.sun.javadoc.ClassDoc
46 * @author Atul M Dambalkar
47 */
48 public class ClassTree {
50 /**
51 * List of baseclasses. Contains only java.lang.Object. Can be used to get
52 * the mapped listing of sub-classes.
53 */
54 private List<ClassDoc> baseclasses = new ArrayList<ClassDoc>();
56 /**
57 * Mapping for each Class with their SubClasses
58 */
59 private Map<ClassDoc,List<ClassDoc>> subclasses = new HashMap<ClassDoc,List<ClassDoc>>();
61 /**
62 * List of base-interfaces. Contains list of all the interfaces who do not
63 * have super-interfaces. Can be used to get the mapped listing of
64 * sub-interfaces.
65 */
66 private List<ClassDoc> baseinterfaces = new ArrayList<ClassDoc>();
68 /**
69 * Mapping for each Interface with their SubInterfaces
70 */
71 private Map<ClassDoc,List<ClassDoc>> subinterfaces = new HashMap<ClassDoc,List<ClassDoc>>();
73 private List<ClassDoc> baseEnums = new ArrayList<ClassDoc>();
74 private Map<ClassDoc,List<ClassDoc>> subEnums = new HashMap<ClassDoc,List<ClassDoc>>();
76 private List<ClassDoc> baseAnnotationTypes = new ArrayList<ClassDoc>();
77 private Map<ClassDoc,List<ClassDoc>> subAnnotationTypes = new HashMap<ClassDoc,List<ClassDoc>>();
79 /**
80 * Mapping for each Interface with classes who implement it.
81 */
82 private Map<ClassDoc,List<ClassDoc>> implementingclasses = new HashMap<ClassDoc,List<ClassDoc>>();
84 /**
85 * Constructor. Build the Tree using the Root of this Javadoc run.
86 *
87 * @param configuration the configuration of the doclet.
88 * @param noDeprecated Don't add deprecated classes in the class tree, if
89 * true.
90 */
91 public ClassTree(Configuration configuration, boolean noDeprecated) {
92 configuration.message.notice("doclet.Building_Tree");
93 buildTree(configuration.root.classes(), configuration);
94 }
96 /**
97 * Constructor. Build the Tree using the Root of this Javadoc run.
98 *
99 * @param root Root of the Document.
100 * @param configuration The curren configuration of the doclet.
101 */
102 public ClassTree(RootDoc root, Configuration configuration) {
103 buildTree(root.classes(), configuration);
104 }
106 /**
107 * Constructor. Build the tree for the given array of classes.
108 *
109 * @param classes Array of classes.
110 * @param configuration The curren configuration of the doclet.
111 */
112 public ClassTree(ClassDoc[] classes, Configuration configuration) {
113 buildTree(classes, configuration);
114 }
116 /**
117 * Generate mapping for the sub-classes for every class in this run.
118 * Return the sub-class list for java.lang.Object which will be having
119 * sub-class listing for itself and also for each sub-class itself will
120 * have their own sub-class lists.
121 *
122 * @param classes all the classes in this run.
123 * @param configuration the current configuration of the doclet.
124 */
125 private void buildTree(ClassDoc[] classes, Configuration configuration) {
126 for (int i = 0; i < classes.length; i++) {
127 // In the tree page (e.g overview-tree.html) do not include
128 // information of classes which are deprecated or are a part of a
129 // deprecated package.
130 if (configuration.nodeprecated &&
131 (Util.isDeprecated(classes[i]) ||
132 Util.isDeprecated(classes[i].containingPackage()))) {
133 continue;
134 }
136 if (configuration.javafx
137 && classes[i].tags("treatAsPrivate").length > 0) {
138 continue;
139 }
141 if (classes[i].isEnum()) {
142 processType(classes[i], configuration, baseEnums, subEnums);
143 } else if (classes[i].isClass()) {
144 processType(classes[i], configuration, baseclasses, subclasses);
145 } else if (classes[i].isInterface()) {
146 processInterface(classes[i]);
147 List<ClassDoc> list = implementingclasses.get(classes[i]);
148 if (list != null) {
149 Collections.sort(list);
150 }
151 } else if (classes[i].isAnnotationType()) {
152 processType(classes[i], configuration, baseAnnotationTypes,
153 subAnnotationTypes);
154 }
155 }
157 Collections.sort(baseinterfaces);
158 for (Iterator<List<ClassDoc>> it = subinterfaces.values().iterator(); it.hasNext(); ) {
159 Collections.sort(it.next());
160 }
161 for (Iterator<List<ClassDoc>> it = subclasses.values().iterator(); it.hasNext(); ) {
162 Collections.sort(it.next());
163 }
164 }
166 /**
167 * For the class passed map it to it's own sub-class listing.
168 * For the Class passed, get the super class,
169 * if superclass is non null, (it is not "java.lang.Object")
170 * get the "value" from the hashmap for this key Class
171 * if entry not found create one and get that.
172 * add this Class as a sub class in the list
173 * Recurse till hits java.lang.Object Null SuperClass.
174 *
175 * @param cd class for which sub-class mapping to be generated.
176 * @param configuration the current configurtation of the doclet.
177 */
178 private void processType(ClassDoc cd, Configuration configuration,
179 List<ClassDoc> bases, Map<ClassDoc,List<ClassDoc>> subs) {
180 ClassDoc superclass = Util.getFirstVisibleSuperClassCD(cd, configuration);
181 if (superclass != null) {
182 if (!add(subs, superclass, cd)) {
183 return;
184 } else {
185 processType(superclass, configuration, bases, subs);
186 }
187 } else { // cd is java.lang.Object, add it once to the list
188 if (!bases.contains(cd)) {
189 bases.add(cd);
190 }
191 }
192 List<Type> intfacs = Util.getAllInterfaces(cd, configuration);
193 for (Iterator<Type> iter = intfacs.iterator(); iter.hasNext();) {
194 add(implementingclasses, iter.next().asClassDoc(), cd);
195 }
196 }
198 /**
199 * For the interface passed get the interfaces which it extends, and then
200 * put this interface in the sub-interface list of those interfaces. Do it
201 * recursively. If a interface doesn't have super-interface just attach
202 * that interface in the list of all the baseinterfaces.
203 *
204 * @param cd Interface under consideration.
205 */
206 private void processInterface(ClassDoc cd) {
207 ClassDoc[] intfacs = cd.interfaces();
208 if (intfacs.length > 0) {
209 for (int i = 0; i < intfacs.length; i++) {
210 if (!add(subinterfaces, intfacs[i], cd)) {
211 return;
212 } else {
213 processInterface(intfacs[i]); // Recurse
214 }
215 }
216 } else {
217 // we need to add all the interfaces who do not have
218 // super-interfaces to baseinterfaces list to traverse them
219 if (!baseinterfaces.contains(cd)) {
220 baseinterfaces.add(cd);
221 }
222 }
223 }
225 /**
226 * Adjust the Class Tree. Add the class interface in to it's super-class'
227 * or super-interface's sub-interface list.
228 *
229 * @param map the entire map.
230 * @param superclass java.lang.Object or the super-interface.
231 * @param cd sub-interface to be mapped.
232 * @returns boolean true if class added, false if class already processed.
233 */
234 private boolean add(Map<ClassDoc,List<ClassDoc>> map, ClassDoc superclass, ClassDoc cd) {
235 List<ClassDoc> list = map.get(superclass);
236 if (list == null) {
237 list = new ArrayList<ClassDoc>();
238 map.put(superclass, list);
239 }
240 if (list.contains(cd)) {
241 return false;
242 } else {
243 list.add(cd);
244 }
245 return true;
246 }
248 /**
249 * From the map return the list of sub-classes or sub-interfaces. If list
250 * is null create a new one and return it.
251 *
252 * @param map The entire map.
253 * @param cd class for which the sub-class list is requested.
254 * @returns List Sub-Class list for the class passed.
255 */
256 private List<ClassDoc> get(Map<ClassDoc,List<ClassDoc>> map, ClassDoc cd) {
257 List<ClassDoc> list = map.get(cd);
258 if (list == null) {
259 return new ArrayList<ClassDoc>();
260 }
261 return list;
262 }
264 /**
265 * Return the sub-class list for the class passed.
266 *
267 * @param cd class whose sub-class list is required.
268 */
269 public List<ClassDoc> subclasses(ClassDoc cd) {
270 return get(subclasses, cd);
271 }
273 /**
274 * Return the sub-interface list for the interface passed.
275 *
276 * @param cd interface whose sub-interface list is required.
277 */
278 public List<ClassDoc> subinterfaces(ClassDoc cd) {
279 return get(subinterfaces, cd);
280 }
282 /**
283 * Return the list of classes which implement the interface passed.
284 *
285 * @param cd interface whose implementing-classes list is required.
286 */
287 public List<ClassDoc> implementingclasses(ClassDoc cd) {
288 List<ClassDoc> result = get(implementingclasses, cd);
289 List<ClassDoc> subinterfaces = allSubs(cd, false);
291 //If class x implements a subinterface of cd, then it follows
292 //that class x implements cd.
293 Iterator<ClassDoc> implementingClassesIter, subInterfacesIter = subinterfaces.listIterator();
294 ClassDoc c;
295 while(subInterfacesIter.hasNext()){
296 implementingClassesIter = implementingclasses(
297 subInterfacesIter.next()).listIterator();
298 while(implementingClassesIter.hasNext()){
299 c = implementingClassesIter.next();
300 if(! result.contains(c)){
301 result.add(c);
302 }
303 }
304 }
305 Collections.sort(result);
306 return result;
307 }
309 /**
310 * Return the sub-class/interface list for the class/interface passed.
311 *
312 * @param cd class/interface whose sub-class/interface list is required.
313 * @param isEnum true if the subclasses should be forced to come from the
314 * enum tree.
315 */
316 public List<ClassDoc> subs(ClassDoc cd, boolean isEnum) {
317 if (isEnum) {
318 return get(subEnums, cd);
319 } else if (cd.isAnnotationType()) {
320 return get(subAnnotationTypes, cd);
321 } else if (cd.isInterface()) {
322 return get(subinterfaces, cd);
323 } else if (cd.isClass()) {
324 return get(subclasses, cd);
325 } else {
326 return null;
327 }
329 }
331 /**
332 * Return a list of all direct or indirect, sub-classes and subinterfaces
333 * of the ClassDoc argument.
334 *
335 * @param cd ClassDoc whose sub-classes or sub-interfaces are requested.
336 * @param isEnum true if the subclasses should be forced to come from the
337 * enum tree.
338 */
339 public List<ClassDoc> allSubs(ClassDoc cd, boolean isEnum) {
340 List<ClassDoc> list = subs(cd, isEnum);
341 for (int i = 0; i < list.size(); i++) {
342 cd = list.get(i);
343 List<ClassDoc> tlist = subs(cd, isEnum);
344 for (int j = 0; j < tlist.size(); j++) {
345 ClassDoc tcd = tlist.get(j);
346 if (!list.contains(tcd)) {
347 list.add(tcd);
348 }
349 }
350 }
351 Collections.sort(list);
352 return list;
353 }
355 /**
356 * Return the base-classes list. This will have only one element namely
357 * thw classdoc for java.lang.Object, since this is the base class for all
358 * classes.
359 */
360 public List<ClassDoc> baseclasses() {
361 return baseclasses;
362 }
364 /**
365 * Return the list of base interfaces. This is the list of interfaces
366 * which do not have super-interface.
367 */
368 public List<ClassDoc> baseinterfaces() {
369 return baseinterfaces;
370 }
372 /**
373 * Return the list of base enums. This is the list of enums
374 * which do not have super-enums.
375 */
376 public List<ClassDoc> baseEnums() {
377 return baseEnums;
378 }
380 /**
381 * Return the list of base annotation types. This is the list of
382 * annotation types which do not have super-annotation types.
383 */
384 public List<ClassDoc> baseAnnotationTypes() {
385 return baseAnnotationTypes;
386 }
387 }