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