1 /* 2 * Copyright (c) 1998, 2019, 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 */ 25 26 package jdk.javadoc.internal.doclets.toolkit.util; 27 28 import java.util.*; 29 30 import javax.lang.model.element.Element; 31 import javax.lang.model.element.ModuleElement; 32 import javax.lang.model.element.PackageElement; 33 import javax.lang.model.element.TypeElement; 34 35 import jdk.javadoc.doclet.DocletEnvironment; 36 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; 37 import jdk.javadoc.internal.doclets.toolkit.Messages; 38 39 import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; 40 41 /** 42 * Build the mapping of each Unicode character with it's member lists 43 * containing members names starting with it. Also build a list for all the 44 * Unicode characters which start a member name. Member name is 45 * classkind or field or method or constructor name. 46 * 47 * <p><b>This is NOT part of any supported API. 48 * If you write code that depends on this, you do so at your own risk. 49 * This code and its internal interfaces are subject to change or 50 * deletion without notice.</b> 51 * 52 * @see java.lang.Character 53 */ 54 public class IndexBuilder { 55 56 /** 57 * Mapping of each Unicode Character with the member list containing 58 * members with names starting with it. 59 */ 60 private final Map<Character, SortedSet<Element>> indexmap; 61 62 /** 63 * Don't generate deprecated information if true. 64 */ 65 private boolean noDeprecated; 66 67 /** 68 * Build this Index only for classes? 69 */ 70 private boolean classesOnly; 71 72 /** 73 * Indicates javafx mode. 74 */ 75 private boolean javafx; 76 77 private final BaseConfiguration configuration; 78 private final Utils utils; 79 private final Comparator<Element> comparator; 80 81 /** 82 * Constructor. Build the index map. 83 * 84 * @param configuration the current configuration of the doclet. 85 * @param noDeprecated true if -nodeprecated option is used, 86 * false otherwise. 87 */ 88 public IndexBuilder(BaseConfiguration configuration, boolean noDeprecated) { 89 this(configuration, noDeprecated, false); 90 } 91 92 /** 93 * Constructor. Build the index map. 94 * 95 * @param configuration the current configuration of the doclet. 96 * @param noDeprecated true if -nodeprecated option is used, 97 * false otherwise. 98 * @param classesOnly Include only classes in index. 99 */ 100 public IndexBuilder(BaseConfiguration configuration, boolean noDeprecated, 101 boolean classesOnly) { 102 this.configuration = configuration; 103 this.utils = configuration.utils; 104 105 Messages messages = configuration.getMessages(); 106 if (classesOnly) { 107 messages.notice("doclet.Building_Index_For_All_Classes"); 108 } else { 109 messages.notice("doclet.Building_Index"); 110 } 111 112 this.noDeprecated = noDeprecated; 113 this.classesOnly = classesOnly; 114 this.javafx = configuration.javafx; 115 this.indexmap = new TreeMap<>(); 116 comparator = classesOnly 117 ? utils.makeAllClassesComparator() 118 : utils.makeIndexUseComparator(); 119 buildIndexMap(configuration.docEnv); 120 } 121 122 /** 123 * Get all the members in all the Packages and all the Classes 124 * given on the command line. Form separate list of those members depending 125 * upon their names. 126 * 127 * @param docEnv the doclet environment 128 */ 129 protected void buildIndexMap(DocletEnvironment docEnv) { 130 Set<PackageElement> packages = configuration.getSpecifiedPackageElements(); 131 Set<TypeElement> classes = configuration.getIncludedTypeElements(); 132 if (!classesOnly) { 133 if (packages.isEmpty()) { 134 Set<PackageElement> set = new HashSet<>(); 135 for (TypeElement aClass : classes) { 136 PackageElement pkg = utils.containingPackage(aClass); 137 if (pkg != null && !pkg.isUnnamed()) { 138 set.add(pkg); 139 } 140 } 141 adjustIndexMap(set); 142 } else { 143 adjustIndexMap(packages); 144 } 145 } 146 adjustIndexMap(classes); 147 if (!classesOnly) { 148 for (TypeElement aClass : classes) { 149 if (shouldAddToIndexMap(aClass)) { 150 putMembersInIndexMap(aClass); 151 } 152 } 153 if (configuration.showModules) { 154 addModulesToIndexMap(); 155 } 156 } 157 } 158 159 /** 160 * Put all the members(fields, methods and constructors) in the te 161 * to the indexmap. 162 * 163 * @param te TypeElement whose members will be added to the indexmap. 164 */ 165 protected void putMembersInIndexMap(TypeElement te) { 166 VisibleMemberTable vmt = configuration.getVisibleMemberTable(te); 167 adjustIndexMap(vmt.getMembers(ANNOTATION_TYPE_FIELDS)); 168 adjustIndexMap(vmt.getMembers(FIELDS)); 169 adjustIndexMap(vmt.getMembers(METHODS)); 170 adjustIndexMap(vmt.getMembers(CONSTRUCTORS)); 171 adjustIndexMap(vmt.getMembers(ENUM_CONSTANTS)); 172 } 173 174 175 /** 176 * Adjust list of members according to their names. Check the first 177 * character in a member name, and then add the member to a list of members 178 * for that particular unicode character. 179 * 180 * @param elements Array of members. 181 */ 182 protected void adjustIndexMap(Iterable<? extends Element> elements) { 183 for (Element element : elements) { 184 if (shouldAddToIndexMap(element)) { 185 String name = utils.isPackage(element) 186 ? utils.getPackageName((PackageElement)element) 187 : utils.getSimpleName(element); 188 char ch = (name.length() == 0) ? 189 '*' : 190 Character.toUpperCase(name.charAt(0)); 191 Character unicode = ch; 192 SortedSet<Element> list = indexmap.computeIfAbsent(unicode, 193 c -> new TreeSet<>(comparator)); 194 list.add(element); 195 } 196 } 197 } 198 199 /** 200 * Add all the modules to index map. 201 */ 202 protected void addModulesToIndexMap() { 203 for (ModuleElement mdle : configuration.modules) { 204 String mdleName = mdle.getQualifiedName().toString(); 205 char ch = (mdleName.length() == 0) 206 ? '*' 207 : Character.toUpperCase(mdleName.charAt(0)); 208 Character unicode = ch; 209 SortedSet<Element> list = indexmap.computeIfAbsent(unicode, 210 c -> new TreeSet<>(comparator)); 211 list.add(mdle); 212 } 213 } 214 215 /** 216 * Should this element be added to the index map? 217 */ 218 protected boolean shouldAddToIndexMap(Element element) { 219 if (utils.hasHiddenTag(element)) { 220 return false; 221 } 222 223 if (utils.isPackage(element)) 224 // Do not add to index map if -nodeprecated option is set and the 225 // package is marked as deprecated. 226 return !(noDeprecated && configuration.utils.isDeprecated(element)); 227 else 228 // Do not add to index map if -nodeprecated option is set and if the 229 // element is marked as deprecated or the containing package is marked as 230 // deprecated. 231 return !(noDeprecated && 232 (configuration.utils.isDeprecated(element) || 233 configuration.utils.isDeprecated(utils.containingPackage(element)))); 234 } 235 236 /** 237 * Return a map of all the individual member lists with Unicode character. 238 * 239 * @return Map index map. 240 */ 241 public Map<Character, SortedSet<Element>> getIndexMap() { 242 return indexmap; 243 } 244 245 /** 246 * Return the sorted list of members, for passed Unicode Character. 247 * 248 * @param index index Unicode character. 249 * @return List member list for specific Unicode character. 250 */ 251 public List<? extends Element> getMemberList(Character index) { 252 SortedSet<Element> set = indexmap.get(index); 253 if (set == null) 254 return null; 255 List<Element> out = new ArrayList<>(); 256 out.addAll(set); 257 return out; 258 } 259 260 /** 261 * Array of IndexMap keys, Unicode characters. 262 */ 263 public List<Character> index() { 264 return new ArrayList<>(indexmap.keySet()); 265 } 266 }