001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.html;
014
015import org.apache.juneau.*;
016import org.apache.juneau.serializer.*;
017
018/**
019 * Serializes POJOs to HTTP responses as HTML documents.
020 *
021 * <h5 class='topic'>Media types</h5>
022 *
023 * Handles <code>Accept</code> types:  <code><b>text/html</b></code>
024 * <p>
025 * Produces <code>Content-Type</code> types:  <code><b>text/html</b></code>
026 *
027 * <h5 class='topic'>Description</h5>
028 *
029 * Same as {@link HtmlSerializer}, except wraps the response in <code><xt>&lt;html&gt;</code>,
030 * <code><xt>&lt;head&gt;</code>, and <code><xt>&lt;body&gt;</code> tags so that it can be rendered in a browser.
031 *
032 * <p>
033 * Configurable properties are typically specified via <ja>@RestResource(properties)</ja> and <ja>@RestMethod(properties)</ja>
034 * annotations, although they can also be set programmatically via the <code>RestResponse.setProperty()</code> method.
035 *
036 * <h5 class='section'>Example:</h5>
037 * <p class='bcode w800'>
038 *    <ja>@RestResource</ja>(
039 *       messages=<js>"nls/AddressBookResource"</js>,
040 *       properties={
041 *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_title</jsf>, value=<js>"$L{title}"</js>),
042 *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_description</jsf>, value=<js>"$L{description}"</js>),
043 *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_navlinks</jsf>, value=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>)
044 *       }
045 *    )
046 *    <jk>public class</jk> AddressBookResource <jk>extends</jk> BasicRestServletJena {
047 * </p>
048 *
049 * <p>
050 * Note that shortcut annotations are also provided for these particular settings:
051 * <p class='bcode w800'>
052 *    <ja>@RestResource</ja>(
053 *       messages=<js>"nls/AddressBookResource"</js>,
054 *       title=<js>"$L{title}"</js>,
055 *       description=<js>"$L{description}"</js>,
056 *       htmldoc=<ja>@HtmlDoc</ja>(
057 *          navlinks={
058 *             <js>"options: ?method=OPTIONS"</js>,
059 *             <js>"doc: doc"</js>
060 *          }
061 *       )
062 *    )
063 * </p>
064 *
065 * <p>
066 * The <code>$L{...}</code> variable represent localized strings pulled from the resource bundle identified by the
067 * <code>messages</code> annotation.
068 * <br>These variables are replaced at runtime based on the HTTP request locale.
069 * <br>Several built-in runtime variable types are defined, and the API can be extended to include user-defined variables.
070 */
071public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
072
073   //-------------------------------------------------------------------------------------------------------------------
074   // Configurable properties
075   //-------------------------------------------------------------------------------------------------------------------
076
077   private static final String PREFIX = "HtmlDocSerializer.";
078
079   /**
080    * Configuration property:  Aside section contents.
081    *
082    * <h5 class='section'>Property:</h5>
083    * <ul>
084    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.aside.ls"</js>
085    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
086    *    <li><b>Default:</b>  empty list
087    *    <li><b>Session property:</b>  <jk>true</jk>
088    * </ul>
089    *
090    * <h5 class='section'>Description:</h5>
091    * <p>
092    * Allows you to specify the contents of the aside section on the HTML page.
093    * The aside section floats on the right of the page for providing content supporting the serialized content of
094    * the page.
095    *
096    * <p>
097    * By default, the aside section is empty.
098    *
099    * <h5 class='section'>Example:</h5>
100    * <p class='bcode w800'>
101    *    <ja>@RestResource</ja>(
102    *       htmldoc=<ja>@HtmlDoc</ja>(
103    *          aside={
104    *             <js>"&lt;ul&gt;"</js>,
105    *             <js>" &lt;li&gt;Item 1"</js>,
106    *             <js>" &lt;li&gt;Item 2"</js>,
107    *             <js>" &lt;li&gt;Item 3"</js>,
108    *             <js>"&lt;/ul&gt;"</js>
109    *          }
110    *       )
111    *    )
112    * </p>
113    */
114   public static final String HTMLDOC_aside = PREFIX + "aside.ls";
115
116   /**
117    * Configuration property:  Footer section contents.
118    *
119    * <h5 class='section'>Property:</h5>
120    * <ul>
121    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.footer.ls"</js>
122    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
123    *    <li><b>Default:</b>  empty list
124    *    <li><b>Session property:</b>  <jk>true</jk>
125    * </ul>
126    *
127    * <h5 class='section'>Description:</h5>
128    * <p>
129    * Allows you to specify the contents of the footer section on the HTML page.
130    *
131    * <p>
132    * By default, the footer section is empty.
133    *
134    * <h5 class='section'>Example:</h5>
135    * <p class='bcode w800'>
136    *    <ja>@RestResource</ja>(
137    *       htmldoc=<ja>@HtmlDoc</ja>(
138    *          footer={
139    *             <js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
140    *          }
141    *       )
142    *    )
143    * </p>
144    */
145   public static final String HTMLDOC_footer = PREFIX + "footer.ls";
146
147   /**
148    * Configuration property:  Additional head section content.
149    *
150    * <h5 class='section'>Property:</h5>
151    * <ul>
152    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.head.ls"</js>
153    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
154    *    <li><b>Default:</b>  empty list
155    *    <li><b>Session property:</b>  <jk>true</jk>
156    * </ul>
157    *
158    * <h5 class='section'>Description:</h5>
159    * <p>
160    * Adds the specified HTML content to the head section of the page.
161    *
162    * <h5 class='section'>Example:</h5>
163    * <p class='bcode w800'>
164    *    <ja>@RestResource</ja>(
165    *       properties={
166    *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_links</jsf>,
167    *             value=<js>"['&lt;link rel=\"icon\" href=\"htdocs/mypageicon.ico\"&gt;']"</js>)
168    *       }
169    *    )
170    * </p>
171    *
172    * <p>
173    * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
174    * <p class='bcode w800'>
175    *    <ja>@RestResource</ja>(
176    *       htmldoc=@HtmlDoc(
177    *          head={
178    *             <js>"&lt;link rel='icon' href='$U{servlet:/htdocs/mypageicon.ico}'&gt;"</js>
179    *          }
180    *       )
181    *    )
182    * </p>
183    */
184   public static final String HTMLDOC_head = PREFIX + "head.ls";
185
186   /**
187    * Configuration property:  Header section contents.
188    *
189    * <h5 class='section'>Property:</h5>
190    * <ul>
191    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.ls"</js>
192    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
193    *    <li><b>Default:</b>  empty list
194    *    <li><b>Session property:</b>  <jk>true</jk>
195    * </ul>
196    *
197    * <h5 class='section'>Description:</h5>
198    * <p>
199    * Allows you to override the contents of the header section on the HTML page.
200    * The header section normally contains the title and description at the top of the page.
201    *
202    * <h5 class='section'>Example:</h5>
203    * <p class='bcode w800'>
204    *    <ja>@RestResource</ja>(
205    *       htmldoc=<ja>@HtmlDoc</ja>(
206    *          header={
207    *             <js>"&lt;h1&gt;My own header&lt;/h1&gt;"</js>
208    *          }
209    *       )
210    *    )
211    * </p>
212    */
213   public static final String HTMLDOC_header = PREFIX + "header.ls";
214
215   /**
216    * Configuration property:  Nav section contents.
217    *
218    * <h5 class='section'>Property:</h5>
219    * <ul>
220    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.nav.ls"</js>
221    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
222    *    <li><b>Default:</b>  empty list
223    *    <li><b>Session property:</b>  <jk>true</jk>
224    * </ul>
225    *
226    * <h5 class='section'>Description:</h5>
227    * <p>
228    * Allows you to override the contents of the nav section on the HTML page.
229    * The nav section normally contains the page links at the top of the page.
230    *
231    * <h5 class='section'>Example:</h5>
232    * <p class='bcode w800'>
233    *    <ja>@RestResource</ja>(
234    *       htmldoc=<ja>@HtmlDoc</ja>(
235    *          nav={
236    *             <js>"&lt;p class='special-navigation'&gt;This is my special navigation content&lt;/p&gt;"</js>
237    *          }
238    *       )
239    *    )
240    * </p>
241    *
242    * <p>
243    * When this property is specified, the {@link #HTMLDOC_navlinks} property is ignored.
244    */
245   public static final String HTMLDOC_nav = PREFIX + "nav.ls";
246
247   /**
248    * Configuration property:  Page navigation links.
249    *
250    * <h5 class='section'>Property:</h5>
251    * <ul>
252    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.navlinks.ls"</js>
253    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
254    *    <li><b>Default:</b>  empty list
255    *    <li><b>Session property:</b>  <jk>true</jk>
256    * </ul>
257    *
258    * <h5 class='section'>Description:</h5>
259    * <p>
260    * Adds a list of hyperlinks immediately under the title and description but above the content of the page.
261    *
262    * <p>
263    * This can be used to provide convenient hyperlinks when viewing the REST interface from a browser.
264    *
265    * <p>
266    * The value is an array of strings with two possible values:
267    * <ul>
268    *    <li>A key-value pair representing a hyperlink label and href:
269    *       <br><js>"google: http://google.com"</js>
270    *    <li>Arbitrary HTML.
271    * </ul>
272    *
273    * <p>
274    * Relative URLs are considered relative to the servlet path.
275    * For example, if the servlet path is <js>"http://localhost/myContext/myServlet"</js>, and the
276    * URL is <js>"foo"</js>, the link becomes <js>"http://localhost/myContext/myServlet/foo"</js>.
277    * Absolute (<js>"/myOtherContext/foo"</js>) and fully-qualified (<js>"http://localhost2/foo"</js>) URLs
278    * can also be used in addition to various other protocols specified by {@link UriResolver} such as
279    * <js>"servlet:/..."</js>.
280    *
281    * <h5 class='section'>Example:</h5>
282    * <p>
283    * The <code>AddressBookResource</code> sample class uses this property...
284    * <p class='bcode w800'>
285    *    <ja>@RestResource</ja>(
286    *       properties={
287    *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_navlinks</jsf>,
288    *             value=<js>"['options: ?method=OPTIONS', 'doc: doc']"</js>)
289    *       }
290    *    )
291    *    <jk>public class</jk> AddressBookResource <jk>extends</jk> BasicRestServletJena {
292    * </p>
293    *
294    * <p>
295    * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
296    * <p class='bcode w800'>
297    *    <ja>@RestResource</ja>(
298    *       htmldoc=@HtmlDoc(
299    *          navlinks={
300    *             <js>"options: ?method=OPTIONS"</js>,
301    *             <js>"doc: doc"</js>
302    *          }
303    *       )
304    *    )
305    *    <jk>public class</jk> AddressBookResource <jk>extends</jk> BasicRestServletJena {
306    * </p>
307    */
308   public static final String HTMLDOC_navlinks = PREFIX + "navlinks.ls";
309
310   /**
311    * Configuration property:  Add to the {@link #HTMLDOC_navlinks} property.
312    */
313   public static final String HTMLDOC_navlinks_add = PREFIX + "navlinks.ls/add";
314
315   /**
316    * Configuration property:  No-results message.
317    *
318    * <h5 class='section'>Property:</h5>
319    * <ul>
320    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.noResultsMessage.s"</js>
321    *    <li><b>Data type:</b>  <code>String</code>
322    *    <li><b>Default:</b>  <js>"&lt;p&gt;no results&lt;/p&gt;"</js>
323    *    <li><b>Session property:</b>  <jk>false</jk>
324    * </ul>
325    *
326    * <h5 class='section'>Description:</h5>
327    * <p>
328    * Allows you to specify the string message used when trying to serialize an empty array or empty list.
329    *
330    * <h5 class='section'>Example:</h5>
331    * <p class='bcode w800'>
332    *    <ja>@RestResource</ja>(
333    *       htmldoc=<ja>@HtmlDoc</ja>(
334    *          noResultsMessage=<js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
335    *       )
336    *    )
337    * </p>
338    *
339    * <p>
340    * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
341    */
342   public static final String HTMLDOC_noResultsMessage = PREFIX + "noResultsMessage.s";
343
344   /**
345    * Configuration property:  Prevent word wrap on page.
346    *
347    * <h5 class='section'>Property:</h5>
348    * <ul>
349    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.nowrap.b"</js>
350    *    <li><b>Data type:</b>  <code>Boolean</code>
351    *    <li><b>Default:</b>  <jk>false</jk>
352    *    <li><b>Session property:</b>  <jk>false</jk>
353    * </ul>
354    *
355    * <h5 class='section'>Description:</h5>
356    * <p>
357    * Adds <js>"* {white-space:nowrap}"</js> to the CSS instructions on the page to prevent word wrapping.
358    */
359   public static final String HTMLDOC_nowrap = PREFIX + "nowrap.b";
360
361   /**
362    * Configuration property:  Javascript code.
363    *
364    * <h5 class='section'>Property:</h5>
365    * <ul>
366    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.script.ls"</js>
367    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
368    *    <li><b>Default:</b>  empty list
369    *    <li><b>Session property:</b>  <jk>true</jk>
370    * </ul>
371    *
372    * <h5 class='section'>Description:</h5>
373    * <p>
374    * Adds the specified Javascript code to the HTML page.
375    *
376    * <h5 class='section'>Example:</h5>
377    * <p class='bcode w800'>
378    *    <ja>@RestResource</ja>(
379    *       properties={
380    *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_script</jsf>,
381    *             value=<js>"alert('hello!');"</js>)
382    *       }
383    *    )
384    * </p>
385    *
386    * <p>
387    * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
388    * <p class='bcode w800'>
389    *    <ja>@RestResource</ja>(
390    *       htmldoc=@HtmlDoc(
391    *          script={
392    *             <js>"alert('hello!');"</js>
393    *          }
394    *       )
395    *    )
396    * </p>
397    */
398   public static final String HTMLDOC_script = PREFIX + "script.ls";
399
400   /**
401    * Configuration property:  Add to the {@link #HTMLDOC_script} property.
402    */
403   public static final String HTMLDOC_script_add = PREFIX + "script.ls/add";
404
405   /**
406    * Configuration property:  CSS style code.
407    *
408    * <h5 class='section'>Property:</h5>
409    * <ul>
410    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.style.ls"</js>
411    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
412    *    <li><b>Default:</b>  empty list
413    *    <li><b>Session property:</b>  <jk>true</jk>
414    * </ul>
415    *
416    * <h5 class='section'>Description:</h5>
417    * <p>
418    * Adds the specified CSS instructions to the HTML page.
419    *
420    * <h5 class='section'>Example:</h5>
421    * <p class='bcode w800'>
422    *    <ja>@RestResource</ja>(
423    *       properties={
424    *          <ja>@Property</ja>(name=HtmlDocSerializer.<jsf>HTMLDOC_style</jsf>,
425    *             value=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>)
426    *       }
427    *    )
428    * </p>
429    *
430    * <p>
431    * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
432    * <p class='bcode w800'>
433    *    <ja>@RestResource</ja>(
434    *       htmldoc=@HtmlDoc(
435    *          style={
436    *             <js>"h3 { color: red; }"</js>,
437    *             <js>"h5 { font-weight: bold; }"</js>
438    *          }
439    *       )
440    *    )
441    * </p>
442    */
443   public static final String HTMLDOC_style = PREFIX + "style.ls";
444
445   /**
446    * Configuration property:  Add to the {@link #HTMLDOC_style} property.
447    */
448   public static final String HTMLDOC_style_add = PREFIX + "style.ls/add";
449
450   /**
451    * Configuration property:  Stylesheet import URLs.
452    *
453    * <h5 class='section'>Property:</h5>
454    * <ul>
455    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.stylesheet.ls"</js>
456    *    <li><b>Data type:</b>  <code>List&lt;String&gt;</code>
457    *    <li><b>Default:</b>  empty list
458    *    <li><b>Session property:</b>  <jk>true</jk>
459    * </ul>
460    *
461    * <h5 class='section'>Description:</h5>
462    * <p>
463    * Adds a link to the specified stylesheet URL.
464    *
465    * <p>
466    * Note that this stylesheet is controlled by the <code><ja>@RestResource</ja>.stylesheet()</code> annotation.
467    */
468   public static final String HTMLDOC_stylesheet = PREFIX + "stylesheet.ls";
469
470   /**
471    * Configuration property:  Add to the {@link #HTMLDOC_stylesheet} property.
472    */
473   public static final String HTMLDOC_stylesheet_add = PREFIX + "stylesheet.ls/add";
474
475   /**
476    * Configuration property:  HTML document template.
477    *
478    * <h5 class='section'>Property:</h5>
479    * <ul>
480    *    <li><b>Name:</b>  <js>"HtmlDocSerializer.template.c"</js>
481    *    <li><b>Data type:</b>  <code>Class&lt;? <jk>extends</jk> HtmlDocTemplate&gt;</code>
482    *    <li><b>Default:</b>  <code>HtmlDocTemplateBasic.<jk>class</jk></code>
483    *    <li><b>Session property:</b>  <jk>false</jk>
484    * </ul>
485    *
486    * <h5 class='section'>Description:</h5>
487    * <p>
488    * Specifies the template to use for serializing the page.
489    *
490    * <p>
491    * By default, the {@link BasicHtmlDocTemplate} class is used to construct the contents of the HTML page, but
492    * can be overridden with your own custom implementation class.
493    *
494    * <h5 class='section'>Example:</h5>
495    * <p class='bcode w800'>
496    *    <ja>@RestResource</ja>(
497    *       htmldoc=@HtmlDoc(
498    *          template=MySpecialDocTemplate.<jk>class</jk>
499    *       )
500    *    )
501    * </p>
502    */
503   public static final String HTMLDOC_template = PREFIX + "template.c";
504
505
506   //-------------------------------------------------------------------------------------------------------------------
507   // Predefined instances
508   //-------------------------------------------------------------------------------------------------------------------
509
510   /** Default serializer, all default settings. */
511   public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(PropertyStore.DEFAULT);
512
513
514   //-------------------------------------------------------------------------------------------------------------------
515   // Instance
516   //-------------------------------------------------------------------------------------------------------------------
517
518   private final String[] style, stylesheet, script, navlinks, head, header, nav, aside, footer;
519   private final String noResultsMessage;
520   private final boolean nowrap;
521   private final HtmlDocTemplate template;
522
523   private volatile HtmlSchemaDocSerializer schemaSerializer;
524
525   /**
526    * Constructor.
527    *
528    * @param ps The property store containing all the settings for this object.
529    */
530   public HtmlDocSerializer(PropertyStore ps) {
531      this(ps, "text/html", (String)null);
532   }
533
534   /**
535    * Constructor.
536    *
537    * @param ps
538    *    The property store containing all the settings for this object.
539    * @param produces
540    *    The media type that this serializer produces.
541    * @param accept
542    *    The accept media types that the serializer can handle.
543    *    <p>
544    *    Can contain meta-characters per the <code>media-type</code> specification of
545    *    {@doc RFC2616.section14.1}
546    *    <p>
547    *    If empty, then assumes the only media type supported is <code>produces</code>.
548    *    <p>
549    *    For example, if this serializer produces <js>"application/json"</js> but should handle media types of
550    *    <js>"application/json"</js> and <js>"text/json"</js>, then the arguments should be:
551    *    <p class='bcode w800'>
552    *    <jk>super</jk>(ps, <js>"application/json"</js>, <js>"application/json",text/json"</js>);
553    *    </p>
554    *    <br>...or...
555    *    <p class='bcode w800'>
556    *    <jk>super</jk>(ps, <js>"application/json"</js>, <js>"*&#8203;/json"</js>);
557    *    </p>
558    * <p>
559    * The accept value can also contain q-values.
560    */
561   public HtmlDocSerializer(PropertyStore ps, String produces, String accept) {
562      super(ps, produces, accept);
563      style = getArrayProperty(HTMLDOC_style, String.class);
564      stylesheet = getArrayProperty(HTMLDOC_stylesheet, String.class);
565      script = getArrayProperty(HTMLDOC_script, String.class);
566      head = getArrayProperty(HTMLDOC_head, String.class);
567      header = getArrayProperty(HTMLDOC_header, String.class);
568      nav = getArrayProperty(HTMLDOC_nav, String.class);
569      aside = getArrayProperty(HTMLDOC_aside, String.class);
570      footer = getArrayProperty(HTMLDOC_footer, String.class);
571      nowrap = getBooleanProperty(HTMLDOC_nowrap, false);
572      navlinks = getArrayProperty(HTMLDOC_navlinks, String.class);
573      noResultsMessage = getStringProperty(HTMLDOC_noResultsMessage, "<p>no results</p>");
574      template = getInstanceProperty(HTMLDOC_template, HtmlDocTemplate.class, BasicHtmlDocTemplate.class);
575   }
576
577   @Override /* Serializer */
578   public HtmlDocSerializerSession createSession(SerializerSessionArgs args) {
579      return new HtmlDocSerializerSession(this, args);
580   }
581
582   @Override /* XmlSerializer */
583   public HtmlSerializer getSchemaSerializer() {
584      if (schemaSerializer == null)
585         schemaSerializer = builder().build(HtmlSchemaDocSerializer.class);
586      return schemaSerializer;
587   }
588
589
590   //-----------------------------------------------------------------------------------------------------------------
591   // Properties
592   //-----------------------------------------------------------------------------------------------------------------
593
594   /**
595    * Configuration property:  CSS style code.
596    *
597    * @see #HTMLDOC_style
598    * @return
599    *    The CSS instructions to add to the HTML page.
600    */
601   protected final String[] getStyle() {
602      return style;
603   }
604
605   /**
606    * Configuration property:  Stylesheet import URLs.
607    *
608    * @see #HTMLDOC_stylesheet
609    * @return
610    *    The link to the stylesheet of the HTML page.
611    */
612   protected final String[] getStylesheet() {
613      return stylesheet;
614   }
615
616   /**
617    * Configuration property:  Javascript code.
618    *
619    * @see #HTMLDOC_script
620    * @return
621    *    Arbitrary Javascript to add to the HTML page.
622    */
623   protected final String[] getScript() {
624      return script;
625   }
626
627   /**
628    * Configuration property:  Page navigation links.
629    *
630    * @see #HTMLDOC_navlinks
631    * @return
632    *    Navigation links to add to the HTML page.
633    */
634   protected final String[] getNavlinks() {
635      return navlinks;
636   }
637
638   /**
639    * Configuration property:  Additional head section content.
640    *
641    * @see #HTMLDOC_head
642    * @return
643    *    HTML content to add to the head section of the HTML page.
644    */
645   protected final String[] getHead() {
646      return head;
647   }
648
649   /**
650    * Configuration property:  Header section contents.
651    *
652    * @see #HTMLDOC_header
653    * @return
654    *    The overridden contents of the header section on the HTML page.
655    */
656   protected final String[] getHeader() {
657      return header;
658   }
659
660   /**
661    * Configuration property:  Nav section contents.
662    *
663    * @see #HTMLDOC_nav
664    * @return
665    *    The overridden contents of the nav section on the HTML page.
666    */
667   protected final String[] getNav() {
668      return nav;
669   }
670
671   /**
672    * Configuration property:  Aside section contents.
673    *
674    * @see #HTMLDOC_aside
675    * @return
676    *    The overridden contents of the aside section on the HTML page.
677    */
678   protected final String[] getAside() {
679      return aside;
680   }
681
682   /**
683    * Configuration property:  Footer section contents.
684    *
685    * @see #HTMLDOC_footer
686    * @return
687    *    The overridden contents of the footer section on the HTML page.
688    */
689   protected final String[] getFooter() {
690      return footer;
691   }
692
693   /**
694    * Configuration property:  No-results message.
695    *
696    * @see #HTMLDOC_noResultsMessage
697    * @return
698    *    The message used when serializing an empty array or empty list.
699    */
700   protected final String getNoResultsMessage() {
701      return noResultsMessage;
702   }
703
704   /**
705    * Configuration property:  Prevent word wrap on page.
706    *
707    * @see #HTMLDOC_nowrap
708    * @return
709    *    <jk>true</jk> if <js>"* {white-space:nowrap}"</js> shoudl be added to the CSS instructions on the page to prevent word wrapping.
710    */
711   protected final boolean isNowrap() {
712      return nowrap;
713   }
714
715   /**
716    * Configuration property:  HTML document template.
717    *
718    * @see #HTMLDOC_template
719    * @return
720    *    The template to use for serializing the page.
721    */
722   protected final HtmlDocTemplate getTemplate() {
723      return template;
724   }
725
726   @Override /* Context */
727   public ObjectMap asMap() {
728      return super.asMap()
729         .append("HtmlDocSerializer", new ObjectMap()
730            .append("header", header)
731            .append("nav", nav)
732            .append("navlinks", navlinks)
733            .append("aside", aside)
734            .append("footer", footer)
735            .append("style", style)
736            .append("head", head)
737            .append("stylesheet", stylesheet)
738            .append("nowrap", nowrap)
739            .append("template", template)
740            .append("noResultsMessage", noResultsMessage)
741         );
742   }
743}