001/* 002 * Copyright (c) 1998, 2022, Oracle and/or its affiliates. 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. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package org.jdrupes.mdoclet.internal.doclets.toolkit.util; 027 028import java.util.*; 029import java.util.function.Predicate; 030 031import javax.lang.model.element.Element; 032import javax.lang.model.element.ModuleElement; 033import javax.lang.model.element.PackageElement; 034import javax.lang.model.element.RecordComponentElement; 035import javax.lang.model.element.TypeElement; 036 037import org.jdrupes.mdoclet.internal.doclets.toolkit.BaseConfiguration; 038 039/** 040 * Build list of all the summary packages, classes, constructors, fields and methods. 041 */ 042public class SummaryAPIListBuilder { 043 /** 044 * List of summary type Lists. 045 */ 046 private final Map<SummaryElementKind, SortedSet<Element>> summaryMap; 047 protected final BaseConfiguration configuration; 048 protected final Utils utils; 049 private final Predicate<Element> belongsToSummary; 050 051 public enum SummaryElementKind { 052 MODULE, 053 PACKAGE, 054 INTERFACE, 055 CLASS, 056 ENUM, 057 EXCEPTION_CLASS, // no ElementKind mapping 058 RECORD_CLASS, 059 ANNOTATION_TYPE, 060 FIELD, 061 METHOD, 062 CONSTRUCTOR, 063 ENUM_CONSTANT, 064 ANNOTATION_TYPE_MEMBER // no ElementKind mapping 065 }; 066 067 /** 068 * Constructor. 069 * 070 * @param configuration the current configuration of the doclet 071 */ 072 public SummaryAPIListBuilder(BaseConfiguration configuration, 073 Predicate<Element> belongsToSummary) { 074 this.configuration = configuration; 075 this.utils = configuration.utils; 076 this.belongsToSummary = belongsToSummary; 077 summaryMap = new EnumMap<>(SummaryElementKind.class); 078 for (SummaryElementKind kind : SummaryElementKind.values()) { 079 summaryMap.put(kind, createSummarySet()); 080 } 081 } 082 083 public boolean isEmpty() { 084 return summaryMap.values().stream().allMatch(Set::isEmpty); 085 } 086 087 /** 088 * Build the sorted list of all the summary APIs in this run. 089 * Build separate lists for summary modules, packages, classes, constructors, 090 * methods and fields. 091 */ 092 protected void buildSummaryAPIInfo() { 093 SortedSet<ModuleElement> modules = configuration.modules; 094 SortedSet<Element> mset = summaryMap.get(SummaryElementKind.MODULE); 095 for (Element me : modules) { 096 if (belongsToSummary.test(me)) { 097 mset.add(me); 098 handleElement(me); 099 } 100 } 101 SortedSet<PackageElement> packages = configuration.packages; 102 SortedSet<Element> pset = summaryMap.get(SummaryElementKind.PACKAGE); 103 for (Element pe : packages) { 104 if (belongsToSummary.test(pe)) { 105 pset.add(pe); 106 handleElement(pe); 107 } 108 } 109 for (TypeElement te : configuration.getIncludedTypeElements()) { 110 SortedSet<Element> eset; 111 if (belongsToSummary.test(te)) { 112 switch (te.getKind()) { 113 case ANNOTATION_TYPE -> { 114 eset = summaryMap.get(SummaryElementKind.ANNOTATION_TYPE); 115 eset.add(te); 116 } 117 case CLASS -> { 118 if (utils.isThrowable(te)) { 119 eset = summaryMap 120 .get(SummaryElementKind.EXCEPTION_CLASS); 121 } else { 122 eset = summaryMap.get(SummaryElementKind.CLASS); 123 } 124 eset.add(te); 125 } 126 case INTERFACE -> { 127 eset = summaryMap.get(SummaryElementKind.INTERFACE); 128 eset.add(te); 129 } 130 case ENUM -> { 131 eset = summaryMap.get(SummaryElementKind.ENUM); 132 eset.add(te); 133 } 134 case RECORD -> { 135 eset = summaryMap.get(SummaryElementKind.RECORD_CLASS); 136 eset.add(te); 137 } 138 } 139 handleElement(te); 140 } 141 composeSummaryList(summaryMap.get(SummaryElementKind.FIELD), 142 utils.getFields(te)); 143 composeSummaryList(summaryMap.get(SummaryElementKind.METHOD), 144 utils.getMethods(te)); 145 composeSummaryList(summaryMap.get(SummaryElementKind.CONSTRUCTOR), 146 utils.getConstructors(te)); 147 if (utils.isEnum(te)) { 148 composeSummaryList( 149 summaryMap.get(SummaryElementKind.ENUM_CONSTANT), 150 utils.getEnumConstants(te)); 151 } 152 if (utils.isRecord(te)) { 153 for (RecordComponentElement component : te 154 .getRecordComponents()) { 155 if (belongsToSummary.test(component)) { 156 throw new AssertionError( 157 "record components not supported in summary builders: " 158 + 159 "component: " + component.getSimpleName() + 160 " of record: " + te.getQualifiedName()); 161 } 162 } 163 } 164 if (utils.isAnnotationInterface(te)) { 165 composeSummaryList( 166 summaryMap.get(SummaryElementKind.ANNOTATION_TYPE_MEMBER), 167 utils.getAnnotationMembers(te)); 168 169 } 170 } 171 } 172 173 /** 174 * Add the members into a single list of summary members. 175 * 176 * @param sset set of summary elements 177 * @param members members to be added in the list 178 */ 179 private void composeSummaryList(SortedSet<Element> sset, 180 List<? extends Element> members) { 181 for (Element member : members) { 182 if (belongsToSummary.test(member)) { 183 sset.add(member); 184 handleElement(member); 185 } 186 } 187 } 188 189 /** 190 * Return the list of summary elements of a given type. 191 * 192 * @param kind the SummaryElementKind 193 * @return 194 */ 195 public SortedSet<Element> getSet(SummaryElementKind kind) { 196 return summaryMap.get(kind); 197 } 198 199 /** 200 * Return true if the list of a given type has size greater than 0. 201 * 202 * @param kind the type of list being checked. 203 */ 204 public boolean hasDocumentation(SummaryElementKind kind) { 205 return !summaryMap.get(kind).isEmpty(); 206 } 207 208 /** 209 * Additional extra processing of an included element. 210 * 211 * @param e element to process 212 */ 213 protected void handleElement(Element e) { 214 } 215 216 /** 217 * Create a summary set of elements. 218 * 219 * @return a summary set 220 */ 221 protected final SortedSet<Element> createSummarySet() { 222 return new TreeSet<>(utils.comparators.makeSummaryComparator()); 223 } 224}