| /* |
| * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.tools.doclets.internal.toolkit.util; |
| |
| import java.util.*; |
| |
| import com.sun.javadoc.*; |
| import com.sun.tools.doclets.internal.toolkit.*; |
| |
| /** |
| * Build Class Hierarchy for all the Classes. This class builds the Class |
| * Tree and the Interface Tree separately. |
| * |
| * <p><b>This is NOT part of any supported API. |
| * If you write code that depends on this, you do so at your own risk. |
| * This code and its internal interfaces are subject to change or |
| * deletion without notice.</b> |
| * |
| * @see java.util.HashMap |
| * @see java.util.List |
| * @see com.sun.javadoc.Type |
| * @see com.sun.javadoc.ClassDoc |
| * @author Atul M Dambalkar |
| */ |
| public class ClassTree { |
| |
| /** |
| * List of baseclasses. Contains only java.lang.Object. Can be used to get |
| * the mapped listing of sub-classes. |
| */ |
| private List<ClassDoc> baseclasses = new ArrayList<>(); |
| |
| /** |
| * Mapping for each Class with their SubClasses |
| */ |
| private Map<ClassDoc,List<ClassDoc>> subclasses = new HashMap<>(); |
| |
| /** |
| * List of base-interfaces. Contains list of all the interfaces who do not |
| * have super-interfaces. Can be used to get the mapped listing of |
| * sub-interfaces. |
| */ |
| private List<ClassDoc> baseinterfaces = new ArrayList<>(); |
| |
| /** |
| * Mapping for each Interface with their SubInterfaces |
| */ |
| private Map<ClassDoc,List<ClassDoc>> subinterfaces = new HashMap<>(); |
| |
| private List<ClassDoc> baseEnums = new ArrayList<>(); |
| private Map<ClassDoc,List<ClassDoc>> subEnums = new HashMap<>(); |
| |
| private List<ClassDoc> baseAnnotationTypes = new ArrayList<>(); |
| private Map<ClassDoc,List<ClassDoc>> subAnnotationTypes = new HashMap<>(); |
| |
| /** |
| * Mapping for each Interface with classes who implement it. |
| */ |
| private Map<ClassDoc,List<ClassDoc>> implementingclasses = new HashMap<>(); |
| |
| /** |
| * Constructor. Build the Tree using the Root of this Javadoc run. |
| * |
| * @param configuration the configuration of the doclet. |
| * @param noDeprecated Don't add deprecated classes in the class tree, if |
| * true. |
| */ |
| public ClassTree(Configuration configuration, boolean noDeprecated) { |
| configuration.message.notice("doclet.Building_Tree"); |
| buildTree(configuration.root.classes(), configuration); |
| } |
| |
| /** |
| * Constructor. Build the Tree using the Root of this Javadoc run. |
| * |
| * @param root Root of the Document. |
| * @param configuration The curren configuration of the doclet. |
| */ |
| public ClassTree(RootDoc root, Configuration configuration) { |
| buildTree(root.classes(), configuration); |
| } |
| |
| /** |
| * Constructor. Build the tree for the given array of classes. |
| * |
| * @param classes Array of classes. |
| * @param configuration The curren configuration of the doclet. |
| */ |
| public ClassTree(ClassDoc[] classes, Configuration configuration) { |
| buildTree(classes, configuration); |
| } |
| |
| /** |
| * Generate mapping for the sub-classes for every class in this run. |
| * Return the sub-class list for java.lang.Object which will be having |
| * sub-class listing for itself and also for each sub-class itself will |
| * have their own sub-class lists. |
| * |
| * @param classes all the classes in this run. |
| * @param configuration the current configuration of the doclet. |
| */ |
| private void buildTree(ClassDoc[] classes, Configuration configuration) { |
| for (ClassDoc aClass : classes) { |
| // In the tree page (e.g overview-tree.html) do not include |
| // information of classes which are deprecated or are a part of a |
| // deprecated package. |
| if (configuration.nodeprecated && |
| (Util.isDeprecated(aClass) || |
| Util.isDeprecated(aClass.containingPackage()))) { |
| continue; |
| } |
| |
| if (configuration.javafx |
| && aClass.tags("treatAsPrivate").length > 0) { |
| continue; |
| } |
| |
| if (aClass.isEnum()) { |
| processType(aClass, configuration, baseEnums, subEnums); |
| } else if (aClass.isClass()) { |
| processType(aClass, configuration, baseclasses, subclasses); |
| } else if (aClass.isInterface()) { |
| processInterface(aClass); |
| List<ClassDoc> list = implementingclasses.get(aClass); |
| if (list != null) { |
| Collections.sort(list); |
| } |
| } else if (aClass.isAnnotationType()) { |
| processType(aClass, configuration, baseAnnotationTypes, |
| subAnnotationTypes); |
| } |
| } |
| |
| Collections.sort(baseinterfaces); |
| for (List<ClassDoc> docs : subinterfaces.values()) { |
| Collections.sort(docs); |
| } |
| for (List<ClassDoc> docs : subclasses.values()) { |
| Collections.sort(docs); |
| } |
| } |
| |
| /** |
| * For the class passed map it to it's own sub-class listing. |
| * For the Class passed, get the super class, |
| * if superclass is non null, (it is not "java.lang.Object") |
| * get the "value" from the hashmap for this key Class |
| * if entry not found create one and get that. |
| * add this Class as a sub class in the list |
| * Recurse till hits java.lang.Object Null SuperClass. |
| * |
| * @param cd class for which sub-class mapping to be generated. |
| * @param configuration the current configurtation of the doclet. |
| */ |
| private void processType(ClassDoc cd, Configuration configuration, |
| List<ClassDoc> bases, Map<ClassDoc,List<ClassDoc>> subs) { |
| ClassDoc superclass = Util.getFirstVisibleSuperClassCD(cd, configuration); |
| if (superclass != null) { |
| if (!add(subs, superclass, cd)) { |
| return; |
| } else { |
| processType(superclass, configuration, bases, subs); |
| } |
| } else { // cd is java.lang.Object, add it once to the list |
| if (!bases.contains(cd)) { |
| bases.add(cd); |
| } |
| } |
| List<Type> intfacs = Util.getAllInterfaces(cd, configuration); |
| for (Type intfac : intfacs) { |
| add(implementingclasses, intfac.asClassDoc(), cd); |
| } |
| } |
| |
| /** |
| * For the interface passed get the interfaces which it extends, and then |
| * put this interface in the sub-interface list of those interfaces. Do it |
| * recursively. If a interface doesn't have super-interface just attach |
| * that interface in the list of all the baseinterfaces. |
| * |
| * @param cd Interface under consideration. |
| */ |
| private void processInterface(ClassDoc cd) { |
| ClassDoc[] intfacs = cd.interfaces(); |
| if (intfacs.length > 0) { |
| for (ClassDoc intfac : intfacs) { |
| if (!add(subinterfaces, intfac, cd)) { |
| return; |
| } else { |
| processInterface(intfac); // Recurse |
| } |
| } |
| } else { |
| // we need to add all the interfaces who do not have |
| // super-interfaces to baseinterfaces list to traverse them |
| if (!baseinterfaces.contains(cd)) { |
| baseinterfaces.add(cd); |
| } |
| } |
| } |
| |
| /** |
| * Adjust the Class Tree. Add the class interface in to it's super-class' |
| * or super-interface's sub-interface list. |
| * |
| * @param map the entire map. |
| * @param superclass java.lang.Object or the super-interface. |
| * @param cd sub-interface to be mapped. |
| * @returns boolean true if class added, false if class already processed. |
| */ |
| private boolean add(Map<ClassDoc,List<ClassDoc>> map, ClassDoc superclass, ClassDoc cd) { |
| List<ClassDoc> list = map.get(superclass); |
| if (list == null) { |
| list = new ArrayList<>(); |
| map.put(superclass, list); |
| } |
| if (list.contains(cd)) { |
| return false; |
| } else { |
| list.add(cd); |
| } |
| return true; |
| } |
| |
| /** |
| * From the map return the list of sub-classes or sub-interfaces. If list |
| * is null create a new one and return it. |
| * |
| * @param map The entire map. |
| * @param cd class for which the sub-class list is requested. |
| * @returns List Sub-Class list for the class passed. |
| */ |
| private List<ClassDoc> get(Map<ClassDoc,List<ClassDoc>> map, ClassDoc cd) { |
| List<ClassDoc> list = map.get(cd); |
| if (list == null) { |
| return new ArrayList<>(); |
| } |
| return list; |
| } |
| |
| /** |
| * Return the sub-class list for the class passed. |
| * |
| * @param cd class whose sub-class list is required. |
| */ |
| public List<ClassDoc> subclasses(ClassDoc cd) { |
| return get(subclasses, cd); |
| } |
| |
| /** |
| * Return the sub-interface list for the interface passed. |
| * |
| * @param cd interface whose sub-interface list is required. |
| */ |
| public List<ClassDoc> subinterfaces(ClassDoc cd) { |
| return get(subinterfaces, cd); |
| } |
| |
| /** |
| * Return the list of classes which implement the interface passed. |
| * |
| * @param cd interface whose implementing-classes list is required. |
| */ |
| public List<ClassDoc> implementingclasses(ClassDoc cd) { |
| List<ClassDoc> result = get(implementingclasses, cd); |
| List<ClassDoc> subinterfaces = allSubs(cd, false); |
| |
| //If class x implements a subinterface of cd, then it follows |
| //that class x implements cd. |
| Iterator<ClassDoc> implementingClassesIter, subInterfacesIter = subinterfaces.listIterator(); |
| ClassDoc c; |
| while(subInterfacesIter.hasNext()){ |
| implementingClassesIter = implementingclasses( |
| subInterfacesIter.next()).listIterator(); |
| while(implementingClassesIter.hasNext()){ |
| c = implementingClassesIter.next(); |
| if(! result.contains(c)){ |
| result.add(c); |
| } |
| } |
| } |
| Collections.sort(result); |
| return result; |
| } |
| |
| /** |
| * Return the sub-class/interface list for the class/interface passed. |
| * |
| * @param cd class/interface whose sub-class/interface list is required. |
| * @param isEnum true if the subclasses should be forced to come from the |
| * enum tree. |
| */ |
| public List<ClassDoc> subs(ClassDoc cd, boolean isEnum) { |
| if (isEnum) { |
| return get(subEnums, cd); |
| } else if (cd.isAnnotationType()) { |
| return get(subAnnotationTypes, cd); |
| } else if (cd.isInterface()) { |
| return get(subinterfaces, cd); |
| } else if (cd.isClass()) { |
| return get(subclasses, cd); |
| } else { |
| return null; |
| } |
| |
| } |
| |
| /** |
| * Return a list of all direct or indirect, sub-classes and subinterfaces |
| * of the ClassDoc argument. |
| * |
| * @param cd ClassDoc whose sub-classes or sub-interfaces are requested. |
| * @param isEnum true if the subclasses should be forced to come from the |
| * enum tree. |
| */ |
| public List<ClassDoc> allSubs(ClassDoc cd, boolean isEnum) { |
| List<ClassDoc> list = subs(cd, isEnum); |
| for (int i = 0; i < list.size(); i++) { |
| cd = list.get(i); |
| List<ClassDoc> tlist = subs(cd, isEnum); |
| for (ClassDoc tcd : tlist) { |
| if (!list.contains(tcd)) { |
| list.add(tcd); |
| } |
| } |
| } |
| Collections.sort(list); |
| return list; |
| } |
| |
| /** |
| * Return the base-classes list. This will have only one element namely |
| * thw classdoc for java.lang.Object, since this is the base class for all |
| * classes. |
| */ |
| public List<ClassDoc> baseclasses() { |
| return baseclasses; |
| } |
| |
| /** |
| * Return the list of base interfaces. This is the list of interfaces |
| * which do not have super-interface. |
| */ |
| public List<ClassDoc> baseinterfaces() { |
| return baseinterfaces; |
| } |
| |
| /** |
| * Return the list of base enums. This is the list of enums |
| * which do not have super-enums. |
| */ |
| public List<ClassDoc> baseEnums() { |
| return baseEnums; |
| } |
| |
| /** |
| * Return the list of base annotation types. This is the list of |
| * annotation types which do not have super-annotation types. |
| */ |
| public List<ClassDoc> baseAnnotationTypes() { |
| return baseAnnotationTypes; |
| } |
| } |