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.formats.html; 27 28 import java.util.EnumMap; 29 import java.util.Objects; 30 import java.util.regex.Matcher; 31 import java.util.regex.Pattern; 32 33 import jdk.javadoc.internal.doclets.formats.html.markup.Comment; 34 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 35 import jdk.javadoc.internal.doclets.formats.html.markup.Entity; 36 import jdk.javadoc.internal.doclets.formats.html.markup.FixedStringContent; 37 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 38 import jdk.javadoc.internal.doclets.toolkit.Content; 39 import jdk.javadoc.internal.doclets.toolkit.Resources; 40 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; 41 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; 42 43 44 /** 45 * Constants and factory methods for common fragments of content 46 * used by HtmlDoclet. The string content of these fragments is 47 * generally obtained from the {@link Resources resources} found 48 * in the doclet's configuration. 49 * 50 * @implNote 51 * Many constants are made available in this class, so that they are 52 * only created once per doclet-instance, instead of once per generated page. 53 */ 54 public class Contents { 55 56 public final Content allClassesLabel; 57 public final Content allImplementedInterfacesLabel; 58 public final Content allModulesLabel; 59 public final Content allPackagesLabel; 60 public final Content allSuperinterfacesLabel; 61 public final Content also; 62 public final Content annotationTypeOptionalMemberLabel; 63 public final Content annotationTypeRequiredMemberLabel; 64 public final Content annotateTypeOptionalMemberSummaryLabel; 65 public final Content annotateTypeRequiredMemberSummaryLabel; 66 public final Content annotationType; 67 public final Content annotationTypeDetailsLabel; 68 public final Content annotationTypeMemberDetail; 69 public final Content annotationtypes; 70 public final Content annotationTypes; 71 public final Content classLabel; 72 public final Content classes; 73 public final Content constantFieldLabel; 74 public final Content constantsSummaryTitle; 75 public final Content constructorLabel; 76 public final Content constructorDetailsLabel; 77 public final Content constructorSummaryLabel; 78 public final Content constructors; 79 public final Content contentsHeading; 80 public final Content defaultPackageLabel; 81 public final Content default_; 82 public final Content deprecatedAPI; 83 public final Content deprecatedLabel; 84 public final Content deprecatedPhrase; 85 public final Content deprecatedForRemovalPhrase; 86 public final Content descfrmClassLabel; 87 public final Content descfrmInterfaceLabel; 88 public final Content descriptionLabel; 89 public final Content detailLabel; 90 public final Content enclosingClassLabel; 91 public final Content enclosingInterfaceLabel; 92 public final Content enumConstantLabel; 93 public final Content enumConstantDetailLabel; 94 public final Content enumConstantSummary; 95 public final Content enum_; 96 public final Content enums; 97 public final Content error; 98 public final Content errors; 99 public final Content exception; 100 public final Content exceptions; 101 public final Content exportedTo; 102 public final Content fieldLabel; 103 public final Content fieldDetailsLabel; 104 public final Content fieldSummaryLabel; 105 public final Content fields; 106 public final Content framesLabel; 107 public final Content fromLabel; 108 public final Content functionalInterface; 109 public final Content functionalInterfaceMessage; 110 public final Content helpLabel; 111 public final Content hierarchyForAllPackages; 112 public final Content implementation; 113 public final Content implementingClassesLabel; 114 public final Content inClass; 115 public final Content inInterface; 116 public final Content indexLabel; 117 public final Content interfaceLabel; 118 public final Content interfaces; 119 public final Content methodDetailLabel; 120 public final Content methodLabel; 121 public final Content methodSummary; 122 public final Content methods; 123 public final Content modifierAndTypeLabel; 124 public final Content modifierLabel; 125 public final Content moduleLabel; 126 public final Content module_; 127 public final Content moduleSubNavLabel; 128 public final Content modulesLabel; 129 public final Content navAnnotationTypeMember; 130 public final Content navAnnotationTypeOptionalMember; 131 public final Content navAnnotationTypeRequiredMember; 132 public final Content navConstructor; 133 public final Content navEnum; 134 public final Content navField; 135 public final Content navMethod; 136 public final Content navModuleDescription; 137 public final Content navModules; 138 public final Content navNested; 139 public final Content navPackages; 140 public final Content navProperty; 141 public final Content navServices; 142 public final Content nestedClassSummary; 143 public final Content newPage; 144 public final Content noFramesLabel; 145 public final Content noScriptMessage; 146 public final Content openModuleLabel; 147 public final Content openedTo; 148 public final Content overridesLabel; 149 public final Content overviewLabel; 150 public final Content packageHierarchies; 151 public final Content packageLabel; 152 public final Content package_; 153 public final Content packagesLabel; 154 public final Content properties; 155 public final Content propertyLabel; 156 public final Content propertyDetailsLabel; 157 public final Content propertySummaryLabel; 158 public final Content record; 159 public final Content seeLabel; 160 public final Content serializedForm; 161 public final Content servicesLabel; 162 public final Content specifiedByLabel; 163 public final Content subclassesLabel; 164 public final Content subinterfacesLabel; 165 public final Content summaryLabel; 166 public final Content treeLabel; 167 public final Content typeLabel; 168 public final Content useLabel; 169 public final Content valueLabel; 170 171 private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels; 172 173 private final Resources resources; 174 175 /** 176 * Creates a {@code Contents} object. 177 * 178 * @param configuration the configuration in which to find the 179 * resources used to look up resource keys, and other details. 180 */ 181 Contents(HtmlConfiguration configuration) { 182 this.resources = configuration.getResources(); 183 184 allClassesLabel = getNonBreakContent("doclet.All_Classes"); 185 allImplementedInterfacesLabel = getContent("doclet.All_Implemented_Interfaces"); 186 allModulesLabel = getNonBreakContent("doclet.All_Modules"); 187 allPackagesLabel = getNonBreakContent("doclet.All_Packages"); 188 allSuperinterfacesLabel = getContent("doclet.All_Superinterfaces"); 189 also = getContent("doclet.also"); 190 annotationTypeOptionalMemberLabel = getContent("doclet.Annotation_Type_Optional_Member"); 191 annotationTypeRequiredMemberLabel = getContent("doclet.Annotation_Type_Required_Member"); 192 annotateTypeOptionalMemberSummaryLabel = getContent("doclet.Annotation_Type_Optional_Member_Summary"); 193 annotateTypeRequiredMemberSummaryLabel = getContent("doclet.Annotation_Type_Required_Member_Summary"); 194 annotationType = getContent("doclet.AnnotationType"); 195 annotationTypeDetailsLabel = getContent("doclet.Annotation_Type_Member_Detail"); 196 annotationTypeMemberDetail = getContent("doclet.Annotation_Type_Member_Detail"); 197 annotationTypes = getContent("doclet.AnnotationTypes"); 198 annotationtypes = getContent("doclet.annotationtypes"); 199 classLabel = getContent("doclet.Class"); 200 classes = getContent("doclet.Classes"); 201 constantFieldLabel = getContent("doclet.ConstantField"); 202 constantsSummaryTitle = getContent("doclet.Constants_Summary"); 203 constructorLabel = getContent("doclet.Constructor"); 204 constructorDetailsLabel = getContent("doclet.Constructor_Detail"); 205 constructorSummaryLabel = getContent("doclet.Constructor_Summary"); 206 constructors = getContent("doclet.Constructors"); 207 contentsHeading = getContent("doclet.Contents"); 208 defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME); 209 default_ = getContent("doclet.Default"); 210 deprecatedAPI = getContent("doclet.Deprecated_API"); 211 deprecatedLabel = getContent("doclet.navDeprecated"); 212 deprecatedPhrase = getContent("doclet.Deprecated"); 213 deprecatedForRemovalPhrase = getContent("doclet.DeprecatedForRemoval"); 214 descfrmClassLabel = getContent("doclet.Description_From_Class"); 215 descfrmInterfaceLabel = getContent("doclet.Description_From_Interface"); 216 descriptionLabel = getContent("doclet.Description"); 217 detailLabel = getContent("doclet.Detail"); 218 enclosingClassLabel = getContent("doclet.Enclosing_Class"); 219 enclosingInterfaceLabel = getContent("doclet.Enclosing_Interface"); 220 enumConstantLabel = getContent("doclet.Enum_Constant"); 221 enumConstantDetailLabel = getContent("doclet.Enum_Constant_Detail"); 222 enumConstantSummary = getContent("doclet.Enum_Constant_Summary"); 223 enum_ = getContent("doclet.Enum"); 224 enums = getContent("doclet.Enums"); 225 error = getContent("doclet.Error"); 226 errors = getContent("doclet.Errors"); 227 exception = getContent("doclet.Exception"); 228 exceptions = getContent("doclet.Exceptions"); 229 exportedTo = getContent("doclet.ExportedTo"); 230 fieldDetailsLabel = getContent("doclet.Field_Detail"); 231 fieldSummaryLabel = getContent("doclet.Field_Summary"); 232 fieldLabel = getContent("doclet.Field"); 233 fields = getContent("doclet.Fields"); 234 framesLabel = getContent("doclet.Frames"); 235 fromLabel = getContent("doclet.From"); 236 functionalInterface = getContent("doclet.Functional_Interface"); 237 functionalInterfaceMessage = getContent("doclet.Functional_Interface_Message"); 238 helpLabel = getContent("doclet.Help"); 239 hierarchyForAllPackages = getContent("doclet.Hierarchy_For_All_Packages"); 240 implementation = getContent("doclet.Implementation"); 241 implementingClassesLabel = getContent("doclet.Implementing_Classes"); 242 inClass = getContent("doclet.in_class"); 243 inInterface = getContent("doclet.in_interface"); 244 indexLabel = getContent("doclet.Index"); 245 interfaceLabel = getContent("doclet.Interface"); 246 interfaces = getContent("doclet.Interfaces"); 247 methodDetailLabel = getContent("doclet.Method_Detail"); 248 methodSummary = getContent("doclet.Method_Summary"); 249 methodLabel = getContent("doclet.Method"); 250 methods = getContent("doclet.Methods"); 251 modifierLabel = getContent("doclet.Modifier"); 252 modifierAndTypeLabel = getContent("doclet.Modifier_and_Type"); 253 moduleLabel = getContent("doclet.Module"); 254 module_ = getContent("doclet.module"); 255 moduleSubNavLabel = getContent("doclet.Module_Sub_Nav"); 256 modulesLabel = getContent("doclet.Modules"); 257 navAnnotationTypeMember = getContent("doclet.navAnnotationTypeMember"); 258 navAnnotationTypeOptionalMember = getContent("doclet.navAnnotationTypeOptionalMember"); 259 navAnnotationTypeRequiredMember = getContent("doclet.navAnnotationTypeRequiredMember"); 260 navConstructor = getContent("doclet.navConstructor"); 261 navEnum = getContent("doclet.navEnum"); 262 navField = getContent("doclet.navField"); 263 navMethod = getContent("doclet.navMethod"); 264 navModuleDescription = getContent("doclet.navModuleDescription"); 265 navModules = getContent("doclet.navModules"); 266 navNested = getContent("doclet.navNested"); 267 navPackages = getContent("doclet.navPackages"); 268 navProperty = getContent("doclet.navProperty"); 269 navServices = getContent("doclet.navServices"); 270 nestedClassSummary = getContent("doclet.Nested_Class_Summary"); 271 newPage = new Comment(resources.getText("doclet.New_Page")); 272 noFramesLabel = getNonBreakContent("doclet.No_Frames"); 273 noScriptMessage = getContent("doclet.No_Script_Message"); 274 openedTo = getContent("doclet.OpenedTo"); 275 openModuleLabel = getContent("doclet.Open_Module"); 276 overridesLabel = getContent("doclet.Overrides"); 277 overviewLabel = getContent("doclet.Overview"); 278 packageHierarchies = getContent("doclet.Package_Hierarchies"); 279 packageLabel = getContent("doclet.Package"); 280 package_ = getContent("doclet.package"); 281 packagesLabel = getContent("doclet.Packages"); 282 properties = getContent("doclet.Properties"); 283 propertyLabel = getContent("doclet.Property"); 284 propertyDetailsLabel = getContent("doclet.Property_Detail"); 285 propertySummaryLabel = getContent("doclet.Property_Summary"); 286 record = getContent("doclet.Record"); 287 seeLabel = getContent("doclet.See"); 288 serializedForm = getContent("doclet.Serialized_Form"); 289 servicesLabel = getContent("doclet.Services"); 290 specifiedByLabel = getContent("doclet.Specified_By"); 291 subclassesLabel = getContent("doclet.Subclasses"); 292 subinterfacesLabel = getContent("doclet.Subinterfaces"); 293 summaryLabel = getContent("doclet.Summary"); 294 treeLabel = getContent("doclet.Tree"); 295 typeLabel = getContent("doclet.Type"); 296 useLabel = getContent("doclet.navClassUse"); 297 valueLabel = getContent("doclet.Value"); 298 299 navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class); 300 navLinkLabels.put(VisibleMemberTable.Kind.INNER_CLASSES, getContent("doclet.navNested")); 301 navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, getContent("doclet.navEnum")); 302 navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField")); 303 navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor")); 304 navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod")); 305 } 306 307 /** 308 * Gets a {@code Content} object, containing the string for 309 * a given key in the doclet's resources. 310 * 311 * @param key the key for the desired string 312 * @return a content tree for the string 313 */ 314 public Content getContent(String key) { 315 return new FixedStringContent(resources.getText(key)); 316 } 317 318 /** 319 * Gets a {@code Content} object, containing the string for 320 * a given key in the doclet's resources, formatted with 321 * given arguments. 322 * 323 * @param key the key for the desired string 324 * @param o0 string or content argument to be formatted into the result 325 * @return a content tree for the text 326 */ 327 public Content getContent(String key, Object o0) { 328 return getContent(key, o0, null, null); 329 } 330 331 /** 332 * Gets a {@code Content} object, containing the string for 333 * a given key in the doclet's resources, formatted with 334 * given arguments. 335 336 * @param key the key for the desired string 337 * @param o0 string or content argument to be formatted into the result 338 * @param o1 string or content argument to be formatted into the result 339 * @return a content tree for the text 340 */ 341 public Content getContent(String key, Object o0, Object o1) { 342 return getContent(key, o0, o1, null); 343 } 344 345 /** 346 * Gets a {@code Content} object, containing the string for 347 * a given key in the doclet's resources, formatted with 348 * given arguments. 349 * 350 * @param key the key for the desired string 351 * @param o0 string or content argument to be formatted into the result 352 * @param o1 string or content argument to be formatted into the result 353 * @param o2 string or content argument to be formatted into the result 354 * @return a content tree for the text 355 */ 356 public Content getContent(String key, Object o0, Object o1, Object o2) { 357 Content c = new ContentBuilder(); 358 Pattern p = Pattern.compile("\\{([012])\\}"); 359 String text = resources.getText(key); // TODO: cache 360 Matcher m = p.matcher(text); 361 int start = 0; 362 while (m.find(start)) { 363 c.add(text.substring(start, m.start())); 364 365 Object o = null; 366 switch (m.group(1).charAt(0)) { 367 case '0': o = o0; break; 368 case '1': o = o1; break; 369 case '2': o = o2; break; 370 } 371 372 if (o == null) { 373 c.add("{" + m.group(1) + "}"); 374 } else if (o instanceof String) { 375 c.add((String) o); 376 } else if (o instanceof Content) { 377 c.add((Content) o); 378 } 379 380 start = m.end(); 381 } 382 383 c.add(text.substring(start)); 384 return c; 385 } 386 387 /** 388 * Gets a {@code Content} object, containing the string for 389 * a given key in the doclet's resources, substituting 390 * <code> </code> for any space characters found in 391 * the named resource string. 392 * 393 * @param key the key for the desired string 394 * @return a content tree for the string 395 */ 396 private Content getNonBreakContent(String key) { 397 String text = resources.getText(key); // TODO: cache 398 Content c = new ContentBuilder(); 399 int start = 0; 400 int p; 401 while ((p = text.indexOf(" ", start)) != -1) { 402 c.add(text.substring(start, p)); 403 c.add(Entity.NO_BREAK_SPACE); 404 start = p + 1; 405 } 406 c.add(text.substring(start)); 407 return c; // TODO: should be made immutable 408 } 409 410 /** 411 * Returns a content for a visible member kind. 412 * @param kind the visible member table kind. 413 * @return the string content 414 */ 415 public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) { 416 return Objects.requireNonNull(navLinkLabels.get(kind)); 417 } 418 }