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.formats.html; 027 028import java.util.Collection; 029import java.util.EnumMap; 030import java.util.Objects; 031import java.util.regex.Matcher; 032import java.util.regex.Pattern; 033 034import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.ContentBuilder; 035import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.Entity; 036import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.Text; 037import org.jdrupes.mdoclet.internal.doclets.toolkit.Content; 038import org.jdrupes.mdoclet.internal.doclets.toolkit.Resources; 039import org.jdrupes.mdoclet.internal.doclets.toolkit.util.VisibleMemberTable; 040 041/** 042 * Constants and factory methods for common fragments of content 043 * used by HtmlDoclet. The string content of these fragments is 044 * generally obtained from the {@link Resources resources} found 045 * in the doclet's configuration. 046 * 047 * @implNote 048 * Many constants are made available in this class, so that they are 049 * only created once per doclet-instance, instead of once per generated page. 050 */ 051public class Contents { 052 053 public final Content allClassesAndInterfacesLabel; 054 public final Content allImplementedInterfacesLabel; 055 public final Content allModulesLabel; 056 public final Content allPackagesLabel; 057 public final Content allSuperinterfacesLabel; 058 public final Content also; 059 public final Content annotationTypeOptionalMemberLabel; 060 public final Content annotationTypeRequiredMemberLabel; 061 public final Content annotateTypeOptionalMemberSummaryLabel; 062 public final Content annotateTypeRequiredMemberSummaryLabel; 063 public final Content annotationType; 064 public final Content annotationTypeDetailsLabel; 065 public final Content annotationTypeMemberDetail; 066 public final Content annotationtypes; 067 public final Content annotationTypes; 068 public final Content classLabel; 069 public final Content classes; 070 public final Content constantFieldLabel; 071 public final Content constantsSummaryTitle; 072 public final Content constructorLabel; 073 public final Content constructorDetailsLabel; 074 public final Content constructorSummaryLabel; 075 public final Content constructors; 076 public final Content contentsHeading; 077 public final Content defaultPackageLabel; 078 public final Content default_; 079 public final Content deprecatedAPI; 080 public final Content deprecatedLabel; 081 public final Content deprecatedPhrase; 082 public final Content deprecatedForRemovalPhrase; 083 public final Content descriptionFromClassLabel; 084 public final Content descriptionFromInterfaceLabel; 085 public final Content descriptionLabel; 086 public final Content detailLabel; 087 public final Content enclosingClassLabel; 088 public final Content enclosingInterfaceLabel; 089 public final Content enumConstantLabel; 090 public final Content enumConstantDetailLabel; 091 public final Content enumConstantSummary; 092 public final Content enum_; 093 public final Content enums; 094 public final Content exceptionClass; 095 public final Content exceptionClasses; 096 public final Content exportedTo; 097 public final Content externalSpecifications; 098 public final Content fieldLabel; 099 public final Content fieldDetailsLabel; 100 public final Content fieldSummaryLabel; 101 public final Content fields; 102 public final Content fromLabel; 103 public final Content functionalInterface; 104 public final Content functionalInterfaceMessage; 105 public final Content helpLabel; 106 public final Content helpSubNavLabel; 107 public final Content hierarchyForAllPackages; 108 public final Content implementation; 109 public final Content implementingClassesLabel; 110 public final Content inClass; 111 public final Content inInterface; 112 public final Content indexLabel; 113 public final Content interfaceLabel; 114 public final Content interfaces; 115 public final Content methodDetailLabel; 116 public final Content methodLabel; 117 public final Content methodSummary; 118 public final Content methods; 119 public final Content modifierAndTypeLabel; 120 public final Content modifierLabel; 121 public final Content moduleLabel; 122 public final Content module_; 123 public final Content moduleSubNavLabel; 124 public final Content modulesLabel; 125 public final Content navAnnotationTypeMember; 126 public final Content navAnnotationTypeOptionalMember; 127 public final Content navAnnotationTypeRequiredMember; 128 public final Content navClassesAndInterfaces; 129 public final Content navConstructor; 130 public final Content navDescription; 131 public final Content navEnum; 132 public final Content navField; 133 public final Content navHelpNavigation; 134 public final Content navHelpPages; 135 public final Content navMethod; 136 public final Content navModules; 137 public final Content navNested; 138 public final Content navPackages; 139 public final Content navProperty; 140 public final Content navServices; 141 public final Content nestedClassSummary; 142 public final Content newAPI; 143 public final Content newLabel; 144 public final Content noScriptMessage; 145 public final Content openModuleLabel; 146 public final Content openedTo; 147 public final Content overridesLabel; 148 public final Content overviewLabel; 149 public final Content packageHierarchies; 150 public final Content packageLabel; 151 public final Content package_; 152 public final Content packagesLabel; 153 public final Content packageSubNavLabel; 154 public final Content packageSummaryLabel; 155 public final Content parameters; 156 public final Content previewAPI; 157 public final Content previewLabel; 158 public final Content previewMark; 159 public final Content previewPhrase; 160 public final Content properties; 161 public final Content propertyLabel; 162 public final Content propertyDetailsLabel; 163 public final Content propertySummaryLabel; 164 public final Content records; 165 public final Content recordComponents; 166 public final Content referencedIn; 167 public final Content relatedPackages; 168 public final Content returns; 169 public final Content seeAlso; 170 public final Content serializedForm; 171 public final Content servicesLabel; 172 public final Content specificationLabel; 173 public final Content specifiedByLabel; 174 public final Content subclassesLabel; 175 public final Content subinterfacesLabel; 176 public final Content summaryLabel; 177 public final Content systemPropertiesLabel; 178 public final Content systemPropertiesSummaryLabel; 179 public final Content throws_; 180 public final Content treeLabel; 181 public final Content typeLabel; 182 public final Content typeParameters; 183 public final Content useLabel; 184 public final Content valueLabel; 185 186 private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels; 187 188 private final Resources resources; 189 190 /** 191 * Creates a {@code Contents} object. 192 * 193 * @param configuration the configuration in which to find the 194 * resources used to look up resource keys, and other details. 195 */ 196 Contents(HtmlConfiguration configuration) { 197 this.resources = configuration.getDocResources(); 198 199 this.allClassesAndInterfacesLabel 200 = getContent("doclet.All_Classes_And_Interfaces"); 201 allImplementedInterfacesLabel 202 = getContent("doclet.All_Implemented_Interfaces"); 203 allModulesLabel = getNonBreakResource("doclet.All_Modules"); 204 allPackagesLabel = getNonBreakResource("doclet.All_Packages"); 205 allSuperinterfacesLabel = getContent("doclet.All_Superinterfaces"); 206 also = getContent("doclet.also"); 207 annotationTypeOptionalMemberLabel 208 = getContent("doclet.Annotation_Type_Optional_Member"); 209 annotationTypeRequiredMemberLabel 210 = getContent("doclet.Annotation_Type_Required_Member"); 211 annotateTypeOptionalMemberSummaryLabel 212 = getContent("doclet.Annotation_Type_Optional_Member_Summary"); 213 annotateTypeRequiredMemberSummaryLabel 214 = getContent("doclet.Annotation_Type_Required_Member_Summary"); 215 annotationType = getContent("doclet.AnnotationType"); 216 annotationTypeDetailsLabel 217 = getContent("doclet.Annotation_Type_Member_Detail"); 218 annotationTypeMemberDetail 219 = getContent("doclet.Annotation_Type_Member_Detail"); 220 annotationTypes = getContent("doclet.AnnotationTypes"); 221 annotationtypes = getContent("doclet.annotationtypes"); 222 classLabel = getContent("doclet.Class"); 223 classes = getContent("doclet.Classes"); 224 constantFieldLabel = getContent("doclet.ConstantField"); 225 constantsSummaryTitle = getContent("doclet.Constants_Summary"); 226 constructorLabel = getContent("doclet.Constructor"); 227 constructorDetailsLabel = getContent("doclet.Constructor_Detail"); 228 constructorSummaryLabel = getContent("doclet.Constructor_Summary"); 229 constructors = getContent("doclet.Constructors"); 230 contentsHeading = getContent("doclet.Contents"); 231 defaultPackageLabel = getContent("doclet.Unnamed_Package"); 232 default_ = getContent("doclet.Default"); 233 deprecatedAPI = getContent("doclet.Deprecated_API"); 234 deprecatedLabel = getContent("doclet.navDeprecated"); 235 deprecatedPhrase = getContent("doclet.Deprecated"); 236 deprecatedForRemovalPhrase = getContent("doclet.DeprecatedForRemoval"); 237 descriptionFromClassLabel = getContent("doclet.Description_From_Class"); 238 descriptionFromInterfaceLabel 239 = getContent("doclet.Description_From_Interface"); 240 descriptionLabel = getContent("doclet.Description"); 241 detailLabel = getContent("doclet.Detail"); 242 enclosingClassLabel = getContent("doclet.Enclosing_Class"); 243 enclosingInterfaceLabel = getContent("doclet.Enclosing_Interface"); 244 enumConstantLabel = getContent("doclet.Enum_Constant"); 245 enumConstantDetailLabel = getContent("doclet.Enum_Constant_Detail"); 246 enumConstantSummary = getContent("doclet.Enum_Constant_Summary"); 247 enum_ = getContent("doclet.Enum"); 248 enums = getContent("doclet.Enums"); 249 exceptionClass = getContent("doclet.ExceptionClass"); 250 exceptionClasses = getContent("doclet.ExceptionClasses"); 251 exportedTo = getContent("doclet.ExportedTo"); 252 externalSpecifications = getContent("doclet.External_Specifications"); 253 fieldDetailsLabel = getContent("doclet.Field_Detail"); 254 fieldSummaryLabel = getContent("doclet.Field_Summary"); 255 fieldLabel = getContent("doclet.Field"); 256 fields = getContent("doclet.Fields"); 257 fromLabel = getContent("doclet.From"); 258 functionalInterface = getContent("doclet.Functional_Interface"); 259 functionalInterfaceMessage 260 = getContent("doclet.Functional_Interface_Message"); 261 helpLabel = getContent("doclet.Help"); 262 helpSubNavLabel = getContent("doclet.Help_Sub_Nav"); 263 hierarchyForAllPackages 264 = getContent("doclet.Hierarchy_For_All_Packages"); 265 implementation = getContent("doclet.Implementation"); 266 implementingClassesLabel = getContent("doclet.Implementing_Classes"); 267 inClass = getContent("doclet.in_class"); 268 inInterface = getContent("doclet.in_interface"); 269 indexLabel = getContent("doclet.Index"); 270 interfaceLabel = getContent("doclet.Interface"); 271 interfaces = getContent("doclet.Interfaces"); 272 methodDetailLabel = getContent("doclet.Method_Detail"); 273 methodSummary = getContent("doclet.Method_Summary"); 274 methodLabel = getContent("doclet.Method"); 275 methods = getContent("doclet.Methods"); 276 modifierLabel = getContent("doclet.Modifier"); 277 modifierAndTypeLabel = getContent("doclet.Modifier_and_Type"); 278 moduleLabel = getContent("doclet.Module"); 279 module_ = getContent("doclet.module"); 280 moduleSubNavLabel = getContent("doclet.Module_Sub_Nav"); 281 modulesLabel = getContent("doclet.Modules"); 282 navAnnotationTypeMember = getContent("doclet.navAnnotationTypeMember"); 283 navAnnotationTypeOptionalMember 284 = getContent("doclet.navAnnotationTypeOptionalMember"); 285 navAnnotationTypeRequiredMember 286 = getContent("doclet.navAnnotationTypeRequiredMember"); 287 navClassesAndInterfaces = getContent("doclet.navClassesAndInterfaces"); 288 navConstructor = getContent("doclet.navConstructor"); 289 navEnum = getContent("doclet.navEnum"); 290 navField = getContent("doclet.navField"); 291 navHelpNavigation = getContent("doclet.navNavigation"); 292 navHelpPages = getContent("doclet.navPages"); 293 navMethod = getContent("doclet.navMethod"); 294 navDescription = getContent("doclet.navDescription"); 295 navModules = getContent("doclet.navModules"); 296 navNested = getContent("doclet.navNested"); 297 navPackages = getContent("doclet.navPackages"); 298 navProperty = getContent("doclet.navProperty"); 299 navServices = getContent("doclet.navServices"); 300 nestedClassSummary = getContent("doclet.Nested_Class_Summary"); 301 newAPI = getContent("doclet.New_API"); 302 newLabel = getContent("doclet.New_Label"); 303 noScriptMessage = getContent("doclet.No_Script_Message"); 304 openedTo = getContent("doclet.OpenedTo"); 305 openModuleLabel = getContent("doclet.Open_Module"); 306 overridesLabel = getContent("doclet.Overrides"); 307 overviewLabel = getContent("doclet.Overview"); 308 packageHierarchies = getContent("doclet.Package_Hierarchies"); 309 packageLabel = getContent("doclet.Package"); 310 package_ = getContent("doclet.package"); 311 packagesLabel = getContent("doclet.Packages"); 312 packageSubNavLabel = getContent("doclet.Package_Sub_Nav"); 313 this.packageSummaryLabel = getContent("doclet.Package_Summary"); 314 parameters = getContent("doclet.Parameters"); 315 previewAPI = getContent("doclet.Preview_API"); 316 previewLabel = getContent("doclet.Preview_Label"); 317 previewMark = getContent("doclet.Preview_Mark"); 318 previewPhrase = getContent("doclet.Preview"); 319 properties = getContent("doclet.Properties"); 320 propertyLabel = getContent("doclet.Property"); 321 propertyDetailsLabel = getContent("doclet.Property_Detail"); 322 propertySummaryLabel = getContent("doclet.Property_Summary"); 323 records = getContent("doclet.RecordClasses"); 324 recordComponents = getContent("doclet.RecordComponents"); 325 referencedIn = getContent("doclet.ReferencedIn"); 326 relatedPackages = getContent("doclet.Related_Packages"); 327 returns = getContent("doclet.Returns"); 328 seeAlso = getContent("doclet.See_Also"); 329 serializedForm = getContent("doclet.Serialized_Form"); 330 servicesLabel = getContent("doclet.Services"); 331 specificationLabel = getContent("doclet.Specification"); 332 specifiedByLabel = getContent("doclet.Specified_By"); 333 subclassesLabel = getContent("doclet.Subclasses"); 334 subinterfacesLabel = getContent("doclet.Subinterfaces"); 335 summaryLabel = getContent("doclet.Summary"); 336 systemPropertiesLabel = getContent("doclet.systemProperties"); 337 systemPropertiesSummaryLabel 338 = getContent("doclet.systemPropertiesSummary"); 339 throws_ = getContent("doclet.Throws"); 340 treeLabel = getContent("doclet.Tree"); 341 typeLabel = getContent("doclet.Type"); 342 typeParameters = getContent("doclet.TypeParameters"); 343 useLabel = getContent("doclet.navClassUse"); 344 valueLabel = getContent("doclet.Value"); 345 346 navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class); 347 navLinkLabels.put(VisibleMemberTable.Kind.NESTED_CLASSES, 348 getContent("doclet.navNested")); 349 navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, 350 getContent("doclet.navEnum")); 351 navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, 352 getContent("doclet.navField")); 353 navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, 354 getContent("doclet.navConstructor")); 355 navLinkLabels.put(VisibleMemberTable.Kind.METHODS, 356 getContent("doclet.navMethod")); 357 navLinkLabels.put( 358 VisibleMemberTable.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, 359 getContent("doclet.navAnnotationTypeOptionalMember")); 360 navLinkLabels.put( 361 VisibleMemberTable.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, 362 getContent("doclet.navAnnotationTypeRequiredMember")); 363 } 364 365 /** 366 * Gets a {@code Content} object, containing the string for 367 * a given key in the doclet's resources. 368 * 369 * @param key the key for the desired string 370 * @return the string 371 */ 372 public Content getContent(String key) { 373 return Text.of(resources.getText(key)); 374 } 375 376 /** 377 * Gets a {@code Content} object, containing the string for 378 * a given key in the doclet's resources, formatted with 379 * given arguments. 380 * 381 * @param key the key for the desired string 382 * @param o0 string or content argument to be formatted into the result 383 * @return the string 384 */ 385 public Content getContent(String key, Object o0) { 386 return getContent(key, o0, null, null); 387 } 388 389 /** 390 * Gets a {@code Content} object, containing the string for 391 * a given key in the doclet's resources, formatted with 392 * given arguments. 393 394 * @param key the key for the desired string 395 * @param o0 string or content argument to be formatted into the result 396 * @param o1 string or content argument to be formatted into the result 397 * @return the string 398 */ 399 public Content getContent(String key, Object o0, Object o1) { 400 return getContent(key, o0, o1, null); 401 } 402 403 /** 404 * Gets a {@code Content} object, containing the string for 405 * a given key in the doclet's resources, formatted with 406 * given arguments. 407 * 408 * @param key the key for the desired string 409 * @param o0 string or content argument to be formatted into the result 410 * @param o1 string or content argument to be formatted into the result 411 * @param o2 string or content argument to be formatted into the result 412 * @return the string 413 */ 414 public Content getContent(String key, Object o0, Object o1, Object o2) { 415 Content c = new ContentBuilder(); 416 Pattern p = Pattern.compile("\\{([012])\\}"); 417 String text = resources.getText(key); // TODO: cache 418 Matcher m = p.matcher(text); 419 int start = 0; 420 while (m.find(start)) { 421 c.add(text.substring(start, m.start())); 422 423 Object o = null; 424 switch (m.group(1).charAt(0)) { 425 case '0': 426 o = o0; 427 break; 428 case '1': 429 o = o1; 430 break; 431 case '2': 432 o = o2; 433 break; 434 } 435 436 if (o == null) { 437 c.add("{" + m.group(1) + "}"); 438 } else if (o instanceof String str) { 439 c.add(str); 440 } else if (o instanceof Content con) { 441 c.add(con); 442 } 443 444 start = m.end(); 445 } 446 447 c.add(text.substring(start)); 448 return c; 449 } 450 451 /** 452 * Returns content composed of items joined together with the specified separator. 453 * 454 * @param separator the separator 455 * @param items the items 456 * @return the composition 457 */ 458 public Content join(Content separator, Collection<Content> items) { 459 Content result = new ContentBuilder(); 460 boolean first = true; 461 for (Content c : items) { 462 if (first) { 463 first = false; 464 } else { 465 result.add(separator); 466 } 467 result.add(c); 468 } 469 return result; 470 } 471 472 /** 473 * Gets a {@code Content} object, containing the string for 474 * a given key in the doclet's resources, substituting 475 * <code> </code> for any space characters found in 476 * the named resource string. 477 * 478 * @param key the key for the desired string 479 * @return the string 480 */ 481 private Content getNonBreakResource(String key) { 482 return getNonBreakString(resources.getText(key)); 483 } 484 485 /** 486 * Gets a {@code Content} object for a string, substituting 487 * <code> </code> for any space characters found in 488 * the named resource string. 489 * 490 * @param text the string 491 * @return the string content 492 */ 493 public Content getNonBreakString(String text) { 494 Content c = new ContentBuilder(); 495 int start = 0; 496 int p; 497 while ((p = text.indexOf(" ", start)) != -1) { 498 c.add(text.substring(start, p)); 499 c.add(Entity.NO_BREAK_SPACE); 500 start = p + 1; 501 } 502 c.add(text.substring(start)); 503 return c; // TODO: should be made immutable 504 } 505 506 /** 507 * {@return a label that describes the VisibleMemberTable kind} 508 * 509 * @param kind the visible member table kind. 510 */ 511 public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) { 512 return Objects.requireNonNull(navLinkLabels.get(kind)); 513 } 514}