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>&nbsp;</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 }