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 seeLabel;
 159     public final Content serializedForm;
 160     public final Content servicesLabel;
 161     public final Content specifiedByLabel;
 162     public final Content subclassesLabel;
 163     public final Content subinterfacesLabel;
 164     public final Content summaryLabel;
 165     public final Content treeLabel;
 166     public final Content typeLabel;
 167     public final Content useLabel;
 168     public final Content valueLabel;
 169 
 170     private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels;
 171 
 172     private final Resources resources;
 173 
 174     /**
 175      * Creates a {@code Contents} object.
 176      *
 177      * @param configuration the configuration in which to find the
 178      * resources used to look up resource keys, and other details.
 179      */
 180     Contents(HtmlConfiguration configuration) {
 181         this.resources = configuration.getResources();
 182 
 183         allClassesLabel = getNonBreakContent("doclet.All_Classes");
 184         allImplementedInterfacesLabel = getContent("doclet.All_Implemented_Interfaces");
 185         allModulesLabel = getNonBreakContent("doclet.All_Modules");
 186         allPackagesLabel = getNonBreakContent("doclet.All_Packages");
 187         allSuperinterfacesLabel = getContent("doclet.All_Superinterfaces");
 188         also = getContent("doclet.also");
 189         annotationTypeOptionalMemberLabel = getContent("doclet.Annotation_Type_Optional_Member");
 190         annotationTypeRequiredMemberLabel = getContent("doclet.Annotation_Type_Required_Member");
 191         annotateTypeOptionalMemberSummaryLabel = getContent("doclet.Annotation_Type_Optional_Member_Summary");
 192         annotateTypeRequiredMemberSummaryLabel = getContent("doclet.Annotation_Type_Required_Member_Summary");
 193         annotationType = getContent("doclet.AnnotationType");
 194         annotationTypeDetailsLabel = getContent("doclet.Annotation_Type_Member_Detail");
 195         annotationTypeMemberDetail = getContent("doclet.Annotation_Type_Member_Detail");
 196         annotationTypes = getContent("doclet.AnnotationTypes");
 197         annotationtypes = getContent("doclet.annotationtypes");
 198         classLabel = getContent("doclet.Class");
 199         classes = getContent("doclet.Classes");
 200         constantFieldLabel = getContent("doclet.ConstantField");
 201         constantsSummaryTitle = getContent("doclet.Constants_Summary");
 202         constructorLabel = getContent("doclet.Constructor");
 203         constructorDetailsLabel = getContent("doclet.Constructor_Detail");
 204         constructorSummaryLabel = getContent("doclet.Constructor_Summary");
 205         constructors = getContent("doclet.Constructors");
 206         contentsHeading = getContent("doclet.Contents");
 207         defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME);
 208         default_ = getContent("doclet.Default");
 209         deprecatedAPI = getContent("doclet.Deprecated_API");
 210         deprecatedLabel = getContent("doclet.navDeprecated");
 211         deprecatedPhrase = getContent("doclet.Deprecated");
 212         deprecatedForRemovalPhrase = getContent("doclet.DeprecatedForRemoval");
 213         descfrmClassLabel = getContent("doclet.Description_From_Class");
 214         descfrmInterfaceLabel = getContent("doclet.Description_From_Interface");
 215         descriptionLabel = getContent("doclet.Description");
 216         detailLabel = getContent("doclet.Detail");
 217         enclosingClassLabel = getContent("doclet.Enclosing_Class");
 218         enclosingInterfaceLabel = getContent("doclet.Enclosing_Interface");
 219         enumConstantLabel = getContent("doclet.Enum_Constant");
 220         enumConstantDetailLabel = getContent("doclet.Enum_Constant_Detail");
 221         enumConstantSummary = getContent("doclet.Enum_Constant_Summary");
 222         enum_ = getContent("doclet.Enum");
 223         enums = getContent("doclet.Enums");
 224         error = getContent("doclet.Error");
 225         errors = getContent("doclet.Errors");
 226         exception = getContent("doclet.Exception");
 227         exceptions = getContent("doclet.Exceptions");
 228         exportedTo = getContent("doclet.ExportedTo");
 229         fieldDetailsLabel = getContent("doclet.Field_Detail");
 230         fieldSummaryLabel = getContent("doclet.Field_Summary");
 231         fieldLabel = getContent("doclet.Field");
 232         fields = getContent("doclet.Fields");
 233         framesLabel = getContent("doclet.Frames");
 234         fromLabel = getContent("doclet.From");
 235         functionalInterface = getContent("doclet.Functional_Interface");
 236         functionalInterfaceMessage = getContent("doclet.Functional_Interface_Message");
 237         helpLabel = getContent("doclet.Help");
 238         hierarchyForAllPackages = getContent("doclet.Hierarchy_For_All_Packages");
 239         implementation = getContent("doclet.Implementation");
 240         implementingClassesLabel = getContent("doclet.Implementing_Classes");
 241         inClass = getContent("doclet.in_class");
 242         inInterface = getContent("doclet.in_interface");
 243         indexLabel = getContent("doclet.Index");
 244         interfaceLabel = getContent("doclet.Interface");
 245         interfaces = getContent("doclet.Interfaces");
 246         methodDetailLabel = getContent("doclet.Method_Detail");
 247         methodSummary = getContent("doclet.Method_Summary");
 248         methodLabel = getContent("doclet.Method");
 249         methods = getContent("doclet.Methods");
 250         modifierLabel = getContent("doclet.Modifier");
 251         modifierAndTypeLabel = getContent("doclet.Modifier_and_Type");
 252         moduleLabel = getContent("doclet.Module");
 253         module_ = getContent("doclet.module");
 254         moduleSubNavLabel = getContent("doclet.Module_Sub_Nav");
 255         modulesLabel = getContent("doclet.Modules");
 256         navAnnotationTypeMember = getContent("doclet.navAnnotationTypeMember");
 257         navAnnotationTypeOptionalMember = getContent("doclet.navAnnotationTypeOptionalMember");
 258         navAnnotationTypeRequiredMember = getContent("doclet.navAnnotationTypeRequiredMember");
 259         navConstructor = getContent("doclet.navConstructor");
 260         navEnum = getContent("doclet.navEnum");
 261         navField = getContent("doclet.navField");
 262         navMethod = getContent("doclet.navMethod");
 263         navModuleDescription = getContent("doclet.navModuleDescription");
 264         navModules = getContent("doclet.navModules");
 265         navNested = getContent("doclet.navNested");
 266         navPackages = getContent("doclet.navPackages");
 267         navProperty = getContent("doclet.navProperty");
 268         navServices = getContent("doclet.navServices");
 269         nestedClassSummary = getContent("doclet.Nested_Class_Summary");
 270         newPage = new Comment(resources.getText("doclet.New_Page"));
 271         noFramesLabel = getNonBreakContent("doclet.No_Frames");
 272         noScriptMessage = getContent("doclet.No_Script_Message");
 273         openedTo = getContent("doclet.OpenedTo");
 274         openModuleLabel = getContent("doclet.Open_Module");
 275         overridesLabel = getContent("doclet.Overrides");
 276         overviewLabel = getContent("doclet.Overview");
 277         packageHierarchies = getContent("doclet.Package_Hierarchies");
 278         packageLabel = getContent("doclet.Package");
 279         package_ = getContent("doclet.package");
 280         packagesLabel = getContent("doclet.Packages");
 281         properties = getContent("doclet.Properties");
 282         propertyLabel = getContent("doclet.Property");
 283         propertyDetailsLabel = getContent("doclet.Property_Detail");
 284         propertySummaryLabel = getContent("doclet.Property_Summary");
 285         seeLabel = getContent("doclet.See");
 286         serializedForm = getContent("doclet.Serialized_Form");
 287         servicesLabel = getContent("doclet.Services");
 288         specifiedByLabel = getContent("doclet.Specified_By");
 289         subclassesLabel = getContent("doclet.Subclasses");
 290         subinterfacesLabel = getContent("doclet.Subinterfaces");
 291         summaryLabel = getContent("doclet.Summary");
 292         treeLabel = getContent("doclet.Tree");
 293         typeLabel = getContent("doclet.Type");
 294         useLabel = getContent("doclet.navClassUse");
 295         valueLabel = getContent("doclet.Value");
 296 
 297         navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class);
 298         navLinkLabels.put(VisibleMemberTable.Kind.INNER_CLASSES, getContent("doclet.navNested"));
 299         navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, getContent("doclet.navEnum"));
 300         navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField"));
 301         navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor"));
 302         navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod"));
 303     }
 304 
 305     /**
 306      * Gets a {@code Content} object, containing the string for
 307      * a given key in the doclet's resources.
 308      *
 309      * @param key the key for the desired string
 310      * @return a content tree for the string
 311      */
 312     public Content getContent(String key) {
 313         return new FixedStringContent(resources.getText(key));
 314     }
 315 
 316     /**
 317      * Gets a {@code Content} object, containing the string for
 318      * a given key in the doclet's resources, formatted with
 319      * given arguments.
 320      *
 321      * @param key the key for the desired string
 322      * @param o0  string or content argument to be formatted into the result
 323      * @return a content tree for the text
 324      */
 325     public Content getContent(String key, Object o0) {
 326         return getContent(key, o0, null, null);
 327     }
 328 
 329     /**
 330      * Gets a {@code Content} object, containing the string for
 331      * a given key in the doclet's resources, formatted with
 332      * given arguments.
 333 
 334      * @param key the key for the desired string
 335      * @param o0  string or content argument to be formatted into the result
 336      * @param o1  string or content argument to be formatted into the result
 337      * @return a content tree for the text
 338      */
 339     public Content getContent(String key, Object o0, Object o1) {
 340         return getContent(key, o0, o1, null);
 341     }
 342 
 343     /**
 344      * Gets a {@code Content} object, containing the string for
 345      * a given key in the doclet's resources, formatted with
 346      * given arguments.
 347      *
 348      * @param key the key for the desired string
 349      * @param o0  string or content argument to be formatted into the result
 350      * @param o1  string or content argument to be formatted into the result
 351      * @param o2  string or content argument to be formatted into the result
 352      * @return a content tree for the text
 353      */
 354     public Content getContent(String key, Object o0, Object o1, Object o2) {
 355         Content c = new ContentBuilder();
 356         Pattern p = Pattern.compile("\\{([012])\\}");
 357         String text = resources.getText(key); // TODO: cache
 358         Matcher m = p.matcher(text);
 359         int start = 0;
 360         while (m.find(start)) {
 361             c.add(text.substring(start, m.start()));
 362 
 363             Object o = null;
 364             switch (m.group(1).charAt(0)) {
 365                 case '0': o = o0; break;
 366                 case '1': o = o1; break;
 367                 case '2': o = o2; break;
 368             }
 369 
 370             if (o == null) {
 371                 c.add("{" + m.group(1) + "}");
 372             } else if (o instanceof String) {
 373                 c.add((String) o);
 374             } else if (o instanceof Content) {
 375                 c.add((Content) o);
 376             }
 377 
 378             start = m.end();
 379         }
 380 
 381         c.add(text.substring(start));
 382         return c;
 383     }
 384 
 385     /**
 386      * Gets a {@code Content} object, containing the string for
 387      * a given key in the doclet's resources, substituting
 388      * <code>&nbsp;</code> for any space characters found in
 389      * the named resource string.
 390      *
 391      * @param key the key for the desired string
 392      * @return a content tree for the string
 393      */
 394     private Content getNonBreakContent(String key) {
 395         String text = resources.getText(key); // TODO: cache
 396         Content c = new ContentBuilder();
 397         int start = 0;
 398         int p;
 399         while ((p = text.indexOf(" ", start)) != -1) {
 400             c.add(text.substring(start, p));
 401             c.add(Entity.NO_BREAK_SPACE);
 402             start = p + 1;
 403         }
 404         c.add(text.substring(start));
 405         return c; // TODO: should be made immutable
 406     }
 407 
 408     /**
 409      * Returns a content for a visible member kind.
 410      * @param kind the visible member table kind.
 411      * @return the string content
 412      */
 413     public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) {
 414         return Objects.requireNonNull(navLinkLabels.get(kind));
 415     }
 416 }