This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 3020119  Context API refactoring.
3020119 is described below

commit 3020119b91be0bb7707e78495245db572201bb22
Author: JamesBognar <[email protected]>
AuthorDate: Sun Sep 26 18:52:13 2021 -0400

    Context API refactoring.
---
 .../java/org/apache/juneau/BeanContextBuilder.java |  20 +
 .../java/org/apache/juneau/html/AsideFloat.java    |   2 +-
 .../org/apache/juneau/html/HtmlDocSerializer.java  | 514 +++------------------
 .../juneau/html/HtmlDocSerializerBuilder.java      | 332 ++++++++++---
 .../juneau/html/HtmlDocSerializerSession.java      | 101 ++--
 .../juneau/html/annotation/HtmlDocConfig.java      |  28 +-
 .../html/annotation/HtmlDocConfigAnnotation.java   |  87 +---
 7 files changed, 408 insertions(+), 676 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
index db0d4cc..192db38 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
@@ -1575,6 +1575,7 @@ public class BeanContextBuilder extends ContextBuilder {
         * @param values
         *      The values to add to this setting.
         * @return This object (for method chaining).
+        * @see #beanDictionary(Class...)
         */
        @FluentSetter
        public BeanContextBuilder beanDictionary(Collection<Class<?>> values) {
@@ -1585,7 +1586,11 @@ public class BeanContextBuilder extends ContextBuilder {
        /**
         * Returns the bean dictionary list.
         *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #beanDictionary(Class...)}.
+        *
         * @return The bean dictionary list.
+        * @see #beanDictionary(Class...)
         */
        public List<Class<?>> beanDictionary() {
                if (beanDictionary == null)
@@ -2473,6 +2478,7 @@ public class BeanContextBuilder extends ContextBuilder {
         * @param values
         *      The values to add to this setting.
         * @return This object (for method chaining).
+        * @see #notBeanClasses(Class...)
         */
        @FluentSetter
        public BeanContextBuilder notBeanClasses(Collection<Class<?>> values) {
@@ -2483,7 +2489,11 @@ public class BeanContextBuilder extends ContextBuilder {
        /**
         * Returns the list of not-bean classes.
         *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #notBeanClasses(Class...)}.
+        *
         * @return The list of not-bean classes.
+        * @see #notBeanClasses(Class...)
         */
        public Set<Class<?>> notBeanClasses() {
                if (notBeanClasses == null)
@@ -2538,6 +2548,7 @@ public class BeanContextBuilder extends ContextBuilder {
         * @param values
         *      The values to add to this setting.
         * @return This object (for method chaining).
+        * @see #notBeanPackages(String...)
         */
        @FluentSetter
        public BeanContextBuilder notBeanPackages(Collection<String> values) {
@@ -2548,7 +2559,11 @@ public class BeanContextBuilder extends ContextBuilder {
        /**
         * Returns the list of not-bean Java package names.
         *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #notBeanPackages(String...)}.
+        *
         * @return The list of not-bean Java package names.
+        * @see #notBeanPackages(String...)
         */
        public Set<String> notBeanPackages() {
                if (notBeanPackages == null)
@@ -2873,6 +2888,7 @@ public class BeanContextBuilder extends ContextBuilder {
         * @param values
         *      The values to add to this setting.
         * @return This object (for method chaining).
+        * @see #swaps(Class...)
         */
        @FluentSetter
        public BeanContextBuilder swaps(Collection<Class<?>> values) {
@@ -2883,7 +2899,11 @@ public class BeanContextBuilder extends ContextBuilder {
        /**
         * Returns the bean swaps list.
         *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #swaps(Class...)}.
+        *
         * @return The bean swaps list.
+        * @see #swaps(Class...)
         */
        public List<Class<?>> swaps() {
                if (swaps == null)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/AsideFloat.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/AsideFloat.java
index 32e1bd0..0f2b0bf 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/AsideFloat.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/AsideFloat.java
@@ -13,7 +13,7 @@
 package org.apache.juneau.html;
 
 /**
- * Identifies possible float values for {@link 
HtmlDocSerializer#HTMLDOC_asideFloat}.
+ * Identifies possible float values for {@link 
HtmlDocSerializerBuilder#asideFloat(AsideFloat)}.
  */
 public enum AsideFloat {
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index f628876..1ba71b1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -12,10 +12,14 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.html;
 
-import org.apache.juneau.*;
+import static java.util.Optional.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
+import static java.util.Collections.*;
+
+import java.util.*;
+
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -62,430 +66,25 @@ import org.apache.juneau.serializer.*;
 public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
        
//-------------------------------------------------------------------------------------------------------------------
-       // Configurable properties
-       
//-------------------------------------------------------------------------------------------------------------------
-
-       static final String PREFIX = "HtmlDocSerializer";
-
-       /**
-        * Configuration property:  Aside section contents.
-        *
-        * <p>
-        * Allows you to specify the contents of the aside section on the HTML 
page.
-        * The aside section floats on the right of the page for providing 
content supporting the serialized content of
-        * the page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_aside HTMLDOC_aside}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.aside.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.aside</c>
-        *      <li><b>Environment variable:</b>  <c>HTMLDOCSERIALIZER_ASIDE</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#aside()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#aside(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_aside = PREFIX + ".aside.ls";
-
-       /**
-        * Configuration property:  Float aside section contents.
-        *
-        * <p>
-        * Allows you to position the aside contents of the page around the 
main contents.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_asideFloat HTMLDOC_asideFloat}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.asideFloat.s"</js>
-        *      <li><b>Data type:</b>  {@link org.apache.juneau.html.AsideFloat}
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.asideFloat</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_ASIDEFLOAT</c>
-        *      <li><b>Default:</b>  {@link 
org.apache.juneau.html.AsideFloat#DEFAULT}
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#asideFloat()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#asideFloat(AsideFloat)}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_asideFloat = PREFIX + 
".asideFloat.s";
-
-       /**
-        * Configuration property:  Footer section contents.
-        *
-        * <p>
-        * Allows you to specify the contents of the footer section on the HTML 
page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_footer HTMLDOC_footer}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.footer.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.footer</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_FOOTER</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#footer()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#footer(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_footer = PREFIX + ".footer.ls";
-
-       /**
-        * Configuration property:  Additional head section content.
-        *
-        * <p>
-        * Adds the specified HTML content to the head section of the page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_head HTMLDOC_head}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.head.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.head</c>
-        *      <li><b>Environment variable:</b>  <c>HTMLDOCSERIALIZER_HEAD</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#head()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#head(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_head = PREFIX + ".head.ls";
-
-       /**
-        * Configuration property:  Header section contents.
-        *
-        * <p>
-        * Allows you to override the contents of the header section on the 
HTML page.
-        * The header section normally contains the title and description at 
the top of the page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_header HTMLDOC_header}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.header.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.header</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_HEADER</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#header()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#header(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_header = PREFIX + ".header.ls";
-
-       /**
-        * Configuration property:  Nav section contents.
-        *
-        * <p>
-        * Allows you to override the contents of the nav section on the HTML 
page.
-        * The nav section normally contains the page links at the top of the 
page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_nav HTMLDOC_nav}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.nav.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.nav</c>
-        *      <li><b>Environment variable:</b>  <c>HTMLDOCSERIALIZER_NAV</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#nav()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#nav(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_nav = PREFIX + ".nav.ls";
-
-       /**
-        * Configuration property:  Page navigation links.
-        *
-        * <p>
-        * Adds a list of hyperlinks immediately under the title and 
description but above the content of the page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_navlinks HTMLDOC_navlinks}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.navlinks.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.navlinks</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_NAVLINKS</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#navlinks()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#navlinks(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_navlinks = PREFIX + ".navlinks.ls";
-
-       /**
-        * Configuration property:  Add to the {@link #HTMLDOC_navlinks} 
property.
-        */
-       public static final String HTMLDOC_navlinks_add = PREFIX + 
".navlinks.ls/add";
-
-       /**
-        * Configuration property:  No-results message.
-        *
-        * <p>
-        * Allows you to specify the string message used when trying to 
serialize an empty array or empty list.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_noResultsMessage 
HTMLDOC_noResultsMessage}
-        *      <li><b>Name:</b>  
<js>"HtmlDocSerializer.noResultsMessage.s"</js>
-        *      <li><b>Data type:</b>  <c>String</c>
-        *      <li><b>System property:</b>  
<c>HtmlDocSerializer.noResultsMessage</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_NORESULTSMESSAGE</c>
-        *      <li><b>Default:</b>  <js>"&lt;p&gt;no results&lt;/p&gt;"</js>
-        *      <li><b>Session property:</b>  <jk>false</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#noResultsMessage()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#noResultsMessage(String)}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_noResultsMessage = PREFIX + 
".noResultsMessage.s";
-
-       /**
-        * Configuration property:  Prevent word wrap on page.
-        *
-        * <p>
-        * Adds <js>"* {white-space:nowrap}"</js> to the CSS instructions on 
the page to prevent word wrapping.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_nowrap HTMLDOC_nowrap}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.nowrap.b"</js>
-        *      <li><b>Data type:</b>  <jk>boolean</jk>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.nowrap</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_NOWRAP</c>
-        *      <li><b>Default:</b>  <jk>false</jk>
-        *      <li><b>Session property:</b>  <jk>false</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#nowrap()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#nowrap()}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_nowrap = PREFIX + ".nowrap.b";
-
-       /**
-        * Configuration property:  Javascript code.
-        *
-        * <p>
-        * Adds the specified Javascript code to the HTML page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_script HTMLDOC_script}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.script.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.script</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_SCRIPT</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#script()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#script(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_script = PREFIX + ".script.ls";
-
-       /**
-        * Configuration property:  Add to the {@link #HTMLDOC_script} property.
-        */
-       public static final String HTMLDOC_script_add = PREFIX + 
".script.ls/add";
-
-       /**
-        * Configuration property:  CSS style code.
-        *
-        * <p>
-        * Adds the specified CSS instructions to the HTML page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_style HTMLDOC_style}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.style.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.style</c>
-        *      <li><b>Environment variable:</b>  <c>HTMLDOCSERIALIZER_STYLE</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#style()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#style(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_style = PREFIX + ".style.ls";
-
-       /**
-        * Configuration property:  Add to the {@link #HTMLDOC_style} property.
-        */
-       public static final String HTMLDOC_style_add = PREFIX + ".style.ls/add";
-
-       /**
-        * Configuration property:  Stylesheet import URLs.
-        *
-        * <p>
-        * Adds a link to the specified stylesheet URL.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_stylesheet HTMLDOC_stylesheet}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.stylesheet.ls"</js>
-        *      <li><b>Data type:</b>  <c>List&lt;String&gt;</c>
-        *      <li><b>System property:</b>  <c>HtmlDocSerializer.stylesheet</c>
-        *      <li><b>Environment variable:</b>  
<c>HTMLDOCSERIALIZER_STYLESHEET</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>true</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#stylesheet()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#stylesheet(String[])}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_stylesheet = PREFIX + 
".stylesheet.ls";
-
-       /**
-        * Configuration property:  Add to the {@link #HTMLDOC_stylesheet} 
property.
-        */
-       public static final String HTMLDOC_stylesheet_add = PREFIX + 
".stylesheet.ls/add";
-
-       /**
-        * Configuration property:  HTML document template.
-        *
-        * <p>
-        * Specifies the template to use for serializing the page.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_template HTMLDOC_template}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.template.c"</js>
-        *      <li><b>Data type:</b>  <code>Class&lt;{@link 
org.apache.juneau.html.HtmlDocTemplate}&gt;</code>
-        *      <li><b>Default:</b>  {@link 
org.apache.juneau.html.BasicHtmlDocTemplate}
-        *      <li><b>Session property:</b>  <jk>false</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#template()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.html.HtmlDocSerializerBuilder#template(Class)}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_template = PREFIX + ".template.c";
-
-       /**
-        * Configuration property:  HTML Widgets.
-        *
-        * <p>
-        * Defines widgets that can be used in conjunction with string 
variables of the form <js>"$W{name}"</js>to quickly
-        * generate arbitrary replacement text.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.html.HtmlDocSerializer#HTMLDOC_widgets HTMLDOC_widgets}
-        *      <li><b>Name:</b>  <js>"HtmlDocSerializer.widgets.lo"</js>
-        *      <li><b>Data type:</b><c>List&lt;{@link 
org.apache.juneau.html.HtmlWidget}|Class&lt;{@link 
org.apache.juneau.html.HtmlWidget}&gt;&gt;</c>
-        *      <li><b>Default:</b>  empty list
-        *      <li><b>Session property:</b>  <jk>false</jk>
-        *      <li><b>Annotations:</b>
-        *              <ul>
-        *                      <li class='ja'>{@link HtmlDocConfig#widgets()}
-        *                      <li class='ja'>{@link 
org.apache.juneau.html.annotation.HtmlDocConfig#widgets()}
-        *              </ul>
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
HtmlDocSerializerBuilder#widgets(Class...)}
-        *                      <li class='jm'>{@link 
HtmlDocSerializerBuilder#widgets(HtmlWidget...)}
-        *              </ul>
-        * </ul>
-        */
-       public static final String HTMLDOC_widgets = PREFIX + ".widgets.lo";
-
-       
//-------------------------------------------------------------------------------------------------------------------
-       // Predefined instances
+       // Static
        
//-------------------------------------------------------------------------------------------------------------------
 
        /** Default serializer, all default settings. */
        public static final HtmlDocSerializer DEFAULT = new 
HtmlDocSerializer(create());
 
-
        
//-------------------------------------------------------------------------------------------------------------------
        // Instance
        
//-------------------------------------------------------------------------------------------------------------------
 
-       private final String[] style, stylesheet, script, navlinks, head, 
header, nav, aside, footer;
-       private final AsideFloat asideFloat;
-       private final String noResultsMessage;
-       private final boolean nowrap;
-       private final HtmlDocTemplate template;
-       private final HtmlWidgetMap widgets;
+       final String[] style, stylesheet, script, navlinks, head, header, nav, 
aside, footer;
+       final AsideFloat asideFloat;
+       final String noResultsMessage;
+       final boolean nowrap;
+       final Class<? extends HtmlDocTemplate> template;
+       final List<Class<? extends HtmlWidget>> widgets;
+
+       private final HtmlWidgetMap widgetMap;
+       private final HtmlDocTemplate templateBean;
 
        private volatile HtmlSchemaDocSerializer schemaSerializer;
 
@@ -496,23 +95,24 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
         */
        protected HtmlDocSerializer(HtmlDocSerializerBuilder builder) {
                super(builder);
-               ContextProperties cp = getContextProperties();
-               style = cp.getArray(HTMLDOC_style, String.class).orElse(new 
String[0]);
-               stylesheet = cp.getArray(HTMLDOC_stylesheet, 
String.class).orElse(new String[0]);
-               script = cp.getArray(HTMLDOC_script, String.class).orElse(new 
String[0]);
-               head = cp.getArray(HTMLDOC_head, String.class).orElse(new 
String[0]);
-               header = cp.getArray(HTMLDOC_header, String.class).orElse(new 
String[0]);
-               nav = cp.getArray(HTMLDOC_nav, String.class).orElse(new 
String[0]);
-               aside = cp.getArray(HTMLDOC_aside, String.class).orElse(new 
String[0]);
-               asideFloat = cp.get(HTMLDOC_asideFloat, 
AsideFloat.class).orElse(AsideFloat.RIGHT);
-               footer = cp.getArray(HTMLDOC_footer, String.class).orElse(new 
String[0]);
-               nowrap = cp.getBoolean(HTMLDOC_nowrap).orElse(false);
-               navlinks = cp.getArray(HTMLDOC_navlinks, 
String.class).orElse(new String[0]);
-               noResultsMessage = 
cp.getString(HTMLDOC_noResultsMessage).orElse("<p>no results</p>");
-               template = cp.getInstance(HTMLDOC_template, 
HtmlDocTemplate.class).orElseGet(BasicHtmlDocTemplate::new);
-
-               widgets = new HtmlWidgetMap();
-               widgets.append(cp.getInstanceArray(HTMLDOC_widgets, 
HtmlWidget.class).orElse(new HtmlWidget[0]));
+               style = ofNullable(builder.style).map(x -> 
toArray(x)).orElse(new String[0]);
+               stylesheet = ofNullable(builder.stylesheet).map(x -> 
toArray(x)).orElse(new String[0]);
+               script = ofNullable(builder.script).map(x -> 
toArray(x)).orElse(new String[0]);
+               head = ofNullable(builder.head).map(x -> toArray(x)).orElse(new 
String[0]);
+               header = ofNullable(builder.header).map(x -> 
toArray(x)).orElse(new String[0]);
+               nav = ofNullable(builder.nav).map(x -> toArray(x)).orElse(new 
String[0]);
+               aside = ofNullable(builder.aside).map(x -> 
toArray(x)).orElse(new String[0]);
+               footer = ofNullable(builder.footer).map(x -> 
toArray(x)).orElse(new String[0]);
+               navlinks = ofNullable(builder.navlinks).map(x -> 
toArray(x)).orElse(new String[0]);
+               asideFloat = builder.asideFloat;
+               noResultsMessage = builder.noResultsMessage;
+               nowrap = builder.nowrap;
+               template = builder.template;
+               widgets = builder.widgets == null ? emptyList() : new 
ArrayList<>(builder.widgets);
+
+               templateBean = newInstance(template);
+               widgetMap = new HtmlWidgetMap();
+               widgets.stream().map(x -> newInstance(x)).forEach(x -> 
widgetMap.append(x));
        }
 
        @Override /* Context */
@@ -560,7 +160,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Aside section contents.
         *
-        * @see #HTMLDOC_aside
+        * @see HtmlDocSerializerBuilder#aside(String...)
         * @return
         *      The overridden contents of the aside section on the HTML page.
         */
@@ -571,7 +171,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Float side section contents.
         *
-        * @see #HTMLDOC_asideFloat
+        * @see HtmlDocSerializerBuilder#asideFloat(AsideFloat)
         * @return
         *      How to float the aside contents on the page.
         */
@@ -582,7 +182,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Footer section contents.
         *
-        * @see #HTMLDOC_footer
+        * @see HtmlDocSerializerBuilder#footer(String...)
         * @return
         *      The overridden contents of the footer section on the HTML page.
         */
@@ -593,7 +193,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Additional head section content.
         *
-        * @see #HTMLDOC_head
+        * @see HtmlDocSerializerBuilder#head(String...)
         * @return
         *      HTML content to add to the head section of the HTML page.
         */
@@ -604,7 +204,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Header section contents.
         *
-        * @see #HTMLDOC_header
+        * @see HtmlDocSerializerBuilder#header(String...)
         * @return
         *      The overridden contents of the header section on the HTML page.
         */
@@ -615,7 +215,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Nav section contents.
         *
-        * @see #HTMLDOC_nav
+        * @see HtmlDocSerializerBuilder#nav(String...)
         * @return
         *      The overridden contents of the nav section on the HTML page.
         */
@@ -626,7 +226,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Page navigation links.
         *
-        * @see #HTMLDOC_navlinks
+        * @see HtmlDocSerializerBuilder#navlinks(String...)
         * @return
         *      Navigation links to add to the HTML page.
         */
@@ -637,7 +237,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * No-results message.
         *
-        * @see #HTMLDOC_noResultsMessage
+        * @see HtmlDocSerializerBuilder#noResultsMessage(String)
         * @return
         *      The message used when serializing an empty array or empty list.
         */
@@ -648,7 +248,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Prevent word wrap on page.
         *
-        * @see #HTMLDOC_nowrap
+        * @see HtmlDocSerializerBuilder#nowrap()
         * @return
         *      <jk>true</jk> if <js>"* {white-space:nowrap}"</js> shoudl be 
added to the CSS instructions on the page to prevent word wrapping.
         */
@@ -659,7 +259,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Javascript code.
         *
-        * @see #HTMLDOC_script
+        * @see HtmlDocSerializerBuilder#script(String...)
         * @return
         *      Arbitrary Javascript to add to the HTML page.
         */
@@ -670,7 +270,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * CSS style code.
         *
-        * @see #HTMLDOC_style
+        * @see HtmlDocSerializerBuilder#style(String...)
         * @return
         *      The CSS instructions to add to the HTML page.
         */
@@ -681,7 +281,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * Stylesheet import URLs.
         *
-        * @see #HTMLDOC_stylesheet
+        * @see HtmlDocSerializerBuilder#stylesheet(String...)
         * @return
         *      The link to the stylesheet of the HTML page.
         */
@@ -692,29 +292,41 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        /**
         * HTML document template.
         *
-        * @see #HTMLDOC_template
+        * @see HtmlDocSerializerBuilder#template(Class)
         * @return
         *      The template to use for serializing the page.
         */
        protected final HtmlDocTemplate getTemplate() {
-               return template;
+               return templateBean;
        }
 
        /**
         * HTML widgets.
         *
-        * @see #HTMLDOC_widgets
+        * @see HtmlDocSerializerBuilder#widgets(Class...)
         * @return
         *      Widgets defined on this serializers.
         */
        protected final HtmlWidgetMap getWidgets() {
-               return widgets;
+               return widgetMap;
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
        // Other methods
        
//-----------------------------------------------------------------------------------------------------------------
 
+       private String[] toArray(List<String> x) {
+               return x.toArray(new String[x.size()]);
+       }
+
+       private <T> T newInstance(Class<T> c) {
+               try {
+                       return c.newInstance();
+               } catch (Exception e) {
+                       throw runtimeException(e);
+               }
+       }
+
        @Override /* Context */
        public OMap toMap() {
                return super.toMap()
@@ -735,7 +347,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
                                        .a("nowrap", nowrap)
                                        .a("template", template)
                                        .a("noResultsMessage", noResultsMessage)
-                                       .a("widgets", widgets.keySet())
+                                       .a("widgets", widgets)
                        );
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
index db12942..8cfd10f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
@@ -12,12 +12,11 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.html;
 
-import static org.apache.juneau.html.HtmlDocSerializer.*;
-
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.nio.charset.*;
 import java.util.*;
+import java.util.regex.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.header.*;
@@ -32,6 +31,13 @@ import org.apache.juneau.xml.*;
 @FluentSetters
 public class HtmlDocSerializerBuilder extends HtmlStrippedDocSerializerBuilder 
{
 
+       List<String> aside, footer, head, header, nav, navlinks, script, style, 
stylesheet;
+       AsideFloat asideFloat;
+       String noResultsMessage;
+       boolean nowrap;
+       Class<? extends HtmlDocTemplate> template;
+       List<Class<? extends HtmlWidget>> widgets;
+
        /**
         * Constructor, default settings.
         */
@@ -40,6 +46,9 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
                produces("text/html");
                accept("text/html");
                type(HtmlDocSerializer.class);
+               asideFloat = AsideFloat.RIGHT;
+               noResultsMessage = "<p>no results</p>";
+               template = BasicHtmlDocTemplate.class;
        }
 
        /**
@@ -49,6 +58,20 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        protected HtmlDocSerializerBuilder(HtmlDocSerializer copyFrom) {
                super(copyFrom);
+               aside = copy(copyFrom.aside);
+               footer = copy(copyFrom.footer);
+               head = copy(copyFrom.head);
+               header = copy(copyFrom.header);
+               nav = copy(copyFrom.nav);
+               navlinks = copy(copyFrom.navlinks);
+               script = copy(copyFrom.script);
+               style = copy(copyFrom.style);
+               stylesheet = copy(copyFrom.stylesheet);
+               asideFloat = copyFrom.asideFloat;
+               noResultsMessage = copyFrom.noResultsMessage;
+               nowrap = copyFrom.nowrap;
+               template = copyFrom.template;
+               widgets = copy(copyFrom.widgets);
        }
 
        /**
@@ -58,6 +81,20 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        protected HtmlDocSerializerBuilder(HtmlDocSerializerBuilder copyFrom) {
                super(copyFrom);
+               aside = copy(copyFrom.aside);
+               footer = copy(copyFrom.footer);
+               head = copy(copyFrom.head);
+               header = copy(copyFrom.header);
+               nav = copy(copyFrom.nav);
+               navlinks = copy(copyFrom.navlinks);
+               script = copy(copyFrom.script);
+               style = copy(copyFrom.style);
+               stylesheet = copy(copyFrom.stylesheet);
+               asideFloat = copyFrom.asideFloat;
+               noResultsMessage = copyFrom.noResultsMessage;
+               nowrap = copyFrom.nowrap;
+               template = copyFrom.template;
+               widgets = copy(copyFrom.widgets);
        }
 
        @Override /* ContextBuilder */
@@ -124,11 +161,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder aside(String...value) {
-               set(HTMLDOC_aside, value);
+               aside = merge(aside, value);
                return this;
        }
 
        /**
+        * Returns the list of aside section contents.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #aside(String...)}.
+        *
+        * @return The list of aside section contents.
+        * @see #aside(String...)
+        */
+       public List<String> aside() {
+               if (aside == null)
+                       aside = new ArrayList<>();
+               return aside;
+       }
+
+       /**
         * Float aside section contents.
         *
         * <p>
@@ -158,7 +210,7 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder asideFloat(AsideFloat value) {
-               set(HTMLDOC_asideFloat, value);
+               asideFloat = value;
                return this;
        }
 
@@ -187,11 +239,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder footer(String...value) {
-               set(HTMLDOC_footer, value);
+               footer = merge(footer, value);
                return this;
        }
 
        /**
+        * Returns the list of footer section contents.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #footer(String...)}.
+        *
+        * @return The list of footer section contents.
+        * @see #footer(String...)
+        */
+       public List<String> footer() {
+               if (footer == null)
+                       footer = new ArrayList<>();
+               return footer;
+       }
+
+       /**
         * Additional head section content.
         *
         * <p>
@@ -213,11 +280,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder head(String...value) {
-               set(HTMLDOC_head, value);
+               head = merge(head, value);
                return this;
        }
 
        /**
+        * Returns the list of head section contents.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #head(String...)}.
+        *
+        * @return The list of head section contents.
+        * @see #head(String...)
+        */
+       public List<String> head() {
+               if (head == null)
+                       head = new ArrayList<>();
+               return head;
+       }
+
+       /**
         * Header section contents.
         *
         * <p>
@@ -240,11 +322,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder header(String...value) {
-               set(HTMLDOC_header, value);
+               header = merge(header, value);
                return this;
        }
 
        /**
+        * Returns the list of header section contents.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #header(String...)}.
+        *
+        * @return The list of header section contents.
+        * @see #header(String...)
+        */
+       public List<String> header() {
+               if (header == null)
+                       header = new ArrayList<>();
+               return header;
+       }
+
+       /**
         * Nav section contents.
         *
         * <p>
@@ -262,7 +359,7 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         * </p>
         *
         * <p>
-        * When this property is specified, the {@link 
HtmlDocSerializer#HTMLDOC_navlinks} property is ignored.
+        * When this property is specified, the {@link 
HtmlDocSerializerBuilder#navlinks(String...)} property is ignored.
         *
         * @param value
         *      The new value for this property.
@@ -270,11 +367,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder nav(String...value) {
-               set(HTMLDOC_nav, value);
+               nav = merge(nav, value);
                return this;
        }
 
        /**
+        * Returns the list of nav section contents.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #nav(String...)}.
+        *
+        * @return The list of nav section contents.
+        * @see #nav(String...)
+        */
+       public List<String> nav() {
+               if (nav == null)
+                       nav = new ArrayList<>();
+               return nav;
+       }
+
+       /**
         * Page navigation links.
         *
         * <p>
@@ -316,55 +428,24 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public HtmlDocSerializerBuilder navlinks_replace(String...value) {
-               set(HTMLDOC_navlinks, value);
+       public HtmlDocSerializerBuilder navlinks(String...value) {
+               navlinks = mergeNavLinks(navlinks, value);
                return this;
        }
 
        /**
-        * Add to the {@link HtmlDocSerializer#HTMLDOC_navlinks} property.
-        *
-        * <p>
-        * Adds a list of hyperlinks immediately under the title and 
description but above the content of the page.
-        *
-        * <p>
-        * This can be used to provide convenient hyperlinks when viewing the 
REST interface from a browser.
-        *
-        * <p>
-        * The value is an array of strings with two possible values:
-        * <ul>
-        *      <li>A key-value pair representing a hyperlink label and href:
-        *              <br><js>"google: http://google.com";</js>
-        *      <li>Arbitrary HTML.
-        * </ul>
+        * Returns the list of navlinks section contents.
         *
         * <p>
-        * Relative URLs are considered relative to the servlet path.
-        * For example, if the servlet path is 
<js>"http://localhost/myContext/myServlet";</js>, and the
-        * URL is <js>"foo"</js>, the link becomes 
<js>"http://localhost/myContext/myServlet/foo";</js>.
-        * Absolute (<js>"/myOtherContext/foo"</js>) and fully-qualified 
(<js>"http://localhost2/foo";</js>) URLs
-        * can also be used in addition to various other protocols specified by 
{@link UriResolver} such as
-        * <js>"servlet:/..."</js>.
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #navlinks(String...)}.
         *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      WriterSerializer <jv>serializer</jv> = HtmlDocSerializer
-        *              .<jsm>create</jsm>()
-        *              .navlinks(
-        *                      <js>"api: servlet:/api"</js>,
-        *                      <js>"doc: doc"</js>
-        *              )
-        *              .build();
-        * </p>
-        *
-        * @param value
-        *      The value to add to this property.
-        * @return This object (for method chaining).
+        * @return The list of navlinks section contents.
+        * @see #navlinks(String...)
         */
-       @FluentSetter
-       public HtmlDocSerializerBuilder navlinks(String...value) {
-               set(HTMLDOC_navlinks_add, value);
-               return this;
+       public List<String> navlinks() {
+               if (navlinks == null)
+                       navlinks = new ArrayList<>();
+               return navlinks;
        }
 
        /**
@@ -390,7 +471,7 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder noResultsMessage(String value) {
-               set(HTMLDOC_noResultsMessage, value);
+               noResultsMessage = value;
                return this;
        }
 
@@ -404,14 +485,24 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder nowrap() {
-               set(HTMLDOC_nowrap);
-               return this;
+               return nowrap(true);
        }
 
        /**
-        * Add to the {@link HtmlDocSerializer#HTMLDOC_script} property.
+        * Same as {@link #nowrap()} but allows you to explicitly specify the 
boolean value.
         *
-        * <p>
+        * @param value
+        *      The new value for this property.
+        * @return This object.
+        * @see #nowrap()
+        */
+       @FluentSetter
+       public HtmlDocSerializerBuilder nowrap(boolean value) {
+               nowrap = value;
+               return this;
+       }
+
+       /**
         * Adds the specified Javascript code to the HTML page.
         *
         * <p>
@@ -429,14 +520,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder script(String...value) {
-               set(HTMLDOC_script_add, value);
+               script = merge(script, value);
                return this;
        }
 
        /**
-        * Add to the {@link HtmlDocSerializer#HTMLDOC_style} property.
+        * Returns the list of page script contents.
         *
         * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #script(String...)}.
+        *
+        * @return The list of page script contents.
+        * @see #script(String...)
+        */
+       public List<String> script() {
+               if (script == null)
+                       script = new ArrayList<>();
+               return script;
+       }
+
+       /**
         * Adds the specified CSS instructions to the HTML page.
         *
         * <p class='bcode w800'>
@@ -455,15 +558,27 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder style(String...value) {
-               set(HTMLDOC_style_add, value);
+               style = merge(style, value);
                return this;
        }
 
        /**
-        * Add to the {@link HtmlDocSerializer#HTMLDOC_stylesheet} property.
+        * Returns the list of page style contents.
         *
         * <p>
-        * Adds a link to the specified stylesheet URL.
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #style(String...)}.
+        *
+        * @return The list of page style contents.
+        * @see #style(String...)
+        */
+       public List<String> style() {
+               if (style == null)
+                       style = new ArrayList<>();
+               return style;
+       }
+
+       /**
+        * Adds to the list of stylesheet URLs.
         *
         * <p>
         * Note that this stylesheet is controlled by the 
<code><ja>@Rest</ja>.stylesheet()</code> annotation.
@@ -474,11 +589,26 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         */
        @FluentSetter
        public HtmlDocSerializerBuilder stylesheet(String...value) {
-               set(HTMLDOC_stylesheet_add, value);
+               stylesheet = merge(stylesheet, value);
                return this;
        }
 
        /**
+        * Returns the list of stylesheet URLs.
+        *
+        * <p>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #stylesheet(String...)}.
+        *
+        * @return The list of stylesheet URLs.
+        * @see #stylesheet(String...)
+        */
+       public List<String> stylesheet() {
+               if (stylesheet == null)
+                       stylesheet = new ArrayList<>();
+               return stylesheet;
+       }
+
+       /**
         * HTML document template.
         *
         * <p>
@@ -501,8 +631,8 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public HtmlDocSerializerBuilder template(Class<?> value) {
-               set(HTMLDOC_template, value);
+       public HtmlDocSerializerBuilder template(Class<? extends 
HtmlDocTemplate> value) {
+               template = value;
                return this;
        }
 
@@ -550,7 +680,6 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
         *
         * <ul class='seealso'>
         *      <li class='link'>{@doc RestHtmlWidgets}
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
         * </ul>
         *
         * @param values The values to add to this setting.
@@ -559,25 +688,23 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
        @FluentSetter
        @SuppressWarnings("unchecked")
        public HtmlDocSerializerBuilder widgets(Class<? extends 
HtmlWidget>...values) {
-               return prependTo(HTMLDOC_widgets, values);
+               Collections.addAll(widgets(), values);
+               return this;
        }
 
        /**
-        * HTML Widgets.
+        * Returns the list of page widgets.
         *
         * <p>
-        * Same as {@link #widgets(Class...)} except input is pre-constructed 
instances.
-        *
-        * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
-        * </ul>
+        * Gives access to the inner list if you need to make more than simple 
additions via {@link #widgets(Class...)}.
         *
-        * @param values The values to add to this setting.
-        * @return This object (for method chaining).
+        * @return The list of page widgets.
+        * @see #widgets(Class...)
         */
-       @FluentSetter
-       public HtmlDocSerializerBuilder widgets(HtmlWidget...values) {
-               return prependTo(HTMLDOC_widgets, values);
+       public List<Class<? extends HtmlWidget>> widgets() {
+               if (widgets == null)
+                       widgets = new ArrayList<>();
+               return widgets;
        }
 
        // <FluentSetters>
@@ -1225,4 +1352,57 @@ public class HtmlDocSerializerBuilder extends 
HtmlStrippedDocSerializerBuilder {
        }
 
        // </FluentSetters>
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Helpers
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       private static <T> List<T> copy(List<T> s) {
+               return s == null || s.isEmpty() ? null : new ArrayList<>(s);
+       }
+
+       private static <T> List<T> copy(T[] s) {
+               return s.length == 0 ? null : new ArrayList<>(Arrays.asList(s));
+       }
+
+       private List<String> merge(List<String> old, String[] newValues) {
+               List<String> x = new ArrayList<>(newValues.length);
+               for (String s : newValues) {
+                       if ("NONE".equals(s)) {
+                               if (old != null)
+                                       old.clear();
+                       } else if ("INHERIT".equals(s)) {
+                               if (old != null)
+                                       x.addAll(old);
+                       } else {
+                               x.add(s);
+                       }
+               }
+               return x;
+       }
+
+       private List<String> mergeNavLinks(List<String> old, String[] 
newValues) {
+               List<String> x = new ArrayList<>(newValues.length);
+               for (String s : newValues) {
+                       if ("NONE".equals(s)) {
+                               if (old != null)
+                                       old.clear();
+                       } else if ("INHERIT".equals(s)) {
+                               if (old != null)
+                                       x.addAll(old);
+                       } else if (s.indexOf('[') != -1 && 
INDEXED_LINK_PATTERN.matcher(s).matches()) {
+                               Matcher lm = INDEXED_LINK_PATTERN.matcher(s);
+                               lm.matches();
+                               String key = lm.group(1);
+                               int index = Math.min(x.size(), 
Integer.parseInt(lm.group(2)));
+                               String remainder = lm.group(3);
+                               x.add(index, key.isEmpty() ? remainder : key + 
":" + remainder);
+                       } else {
+                               x.add(s);
+                       }
+               }
+               return x;
+       }
+
+       private static final Pattern INDEXED_LINK_PATTERN = 
Pattern.compile("(?s)(\\S*)\\[(\\d+)\\]\\:(.*)");
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 719202f..c02902d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -12,12 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.html;
 
-import static org.apache.juneau.html.HtmlDocSerializer.*;
-
 import java.io.IOException;
 import java.util.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
@@ -36,10 +33,6 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        private static final VarResolver DEFAULT_VR = 
VarResolver.create().defaultVars().vars(HtmlWidgetVar.class).build();
 
        private final HtmlDocSerializer ctx;
-       private final String[] navlinks, head, header, nav, aside, footer;
-       private final AsideFloat asideFloat;
-       private final Set<String> style, stylesheet, script;
-       private final boolean nowrap;
 
        /**
         * Create a new session using properties specified in the context.
@@ -53,24 +46,6 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        protected HtmlDocSerializerSession(HtmlDocSerializer ctx, 
SerializerSessionArgs args) {
                super(ctx, args);
                this.ctx = ctx;
-
-               SessionProperties sp = getSessionProperties();
-
-               header = sp.get(HTMLDOC_header, 
String[].class).orElse(ctx.getHeader());
-               nav = sp.get(HTMLDOC_nav, String[].class).orElse(ctx.getNav());
-               aside = sp.get(HTMLDOC_aside, 
String[].class).orElse(ctx.getAside());
-               asideFloat = sp.get(HTMLDOC_asideFloat, 
AsideFloat.class).orElse(ctx.getAsideFloat());
-               footer = sp.get(HTMLDOC_footer, 
String[].class).orElse(ctx.getFooter());
-               navlinks = sp.get(HTMLDOC_navlinks, 
String[].class).orElse(ctx.getNavlinks());
-
-               // These can contain dups after variable resolution, so de-dup 
them with hashsets.
-               style = ASet.of(sp.get(HTMLDOC_style, 
String[].class).orElse(ctx.getStyle()));
-               stylesheet = ASet.of(sp.get(HTMLDOC_stylesheet, 
String[].class).orElse(ctx.getStylesheet()));
-               script = ASet.of(sp.get(HTMLDOC_script, 
String[].class).orElse(ctx.getScript()));
-
-               head = sp.get(HTMLDOC_head, 
String[].class).orElse(ctx.getHead());
-               nowrap = sp.get(HTMLDOC_nowrap, 
boolean.class).orElse(ctx.isNowrap());
-
                addVarBean(HtmlWidgetMap.class, ctx.getWidgets());
        }
 
@@ -80,15 +55,15 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        }
 
        /**
-        * Returns the {@link HtmlDocSerializer#HTMLDOC_navlinks} setting value 
in this context.
+        * Returns the {@link HtmlDocSerializerBuilder#navlinks(String...)} 
setting value in this context.
         *
         * @return
-        *      The {@link HtmlDocSerializer#HTMLDOC_navlinks} setting value in 
this context.
+        *      The {@link HtmlDocSerializerBuilder#navlinks(String...)} 
setting value in this context.
         *      <jk>null</jk> if not specified.
         *      Never an empty map.
         */
        public final String[] getNavLinks() {
-               return navlinks;
+               return ctx.navlinks;
        }
 
        @Override /* Serializer */
@@ -123,84 +98,84 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        /**
         * Configuration property:  Aside section contents.
         *
-        * @see HtmlDocSerializer#HTMLDOC_aside
+        * @see HtmlDocSerializerBuilder#aside(String...)
         * @return
         *      The overridden contents of the aside section on the HTML page.
         */
        protected final String[] getAside() {
-               return aside;
+               return ctx.aside;
        }
 
        /**
         * Configuration property:  Aside section contents float.
         *
-        * @see HtmlDocSerializer#HTMLDOC_asideFloat
+        * @see HtmlDocSerializerBuilder#asideFloat(AsideFloat)
         * @return
         *      The location of where to place the aside section.
         */
        protected final AsideFloat getAsideFloat() {
-               return asideFloat;
+               return ctx.asideFloat;
        }
 
        /**
         * Configuration property:  Footer section contents.
         *
-        * @see HtmlDocSerializer#HTMLDOC_footer
+        * @see HtmlDocSerializerBuilder#footer(String...)
         * @return
         *      The overridden contents of the footer section on the HTML page.
         */
        protected final String[] getFooter() {
-               return footer;
+               return ctx.footer;
        }
 
        /**
         * Configuration property:  Additional head section content.
         *
-        * @see HtmlDocSerializer#HTMLDOC_head
+        * @see HtmlDocSerializerBuilder#head(String...)
         * @return
         *      HTML content to add to the head section of the HTML page.
         */
        protected final String[] getHead() {
-               return head;
+               return ctx.head;
        }
 
        /**
         * Configuration property:  Header section contents.
         *
-        * @see HtmlDocSerializer#HTMLDOC_header
+        * @see HtmlDocSerializerBuilder#header(String...)
         * @return
         *      The overridden contents of the header section on the HTML page.
         */
        protected final String[] getHeader() {
-               return header;
+               return ctx.header;
        }
 
        /**
         * Configuration property:  Nav section contents.
         *
-        * @see HtmlDocSerializer#HTMLDOC_nav
+        * @see HtmlDocSerializerBuilder#nav(String...)
         * @return
         *      The overridden contents of the nav section on the HTML page.
         */
        protected final String[] getNav() {
-               return nav;
+               return ctx.nav;
        }
 
        /**
         * Configuration property:  Page navigation links.
         *
-        * @see HtmlDocSerializer#HTMLDOC_navlinks
+        * @see HtmlDocSerializerBuilder#navlinks(String...)
         * @return
         *      Navigation links to add to the HTML page.
         */
        protected final String[] getNavlinks() {
-               return navlinks;
+               return ctx.navlinks;
        }
 
        /**
         * Configuration property:  No-results message.
         *
-        * @see HtmlDocSerializer#HTMLDOC_noResultsMessage
+        * @see HtmlDocSerializerBuilder#noResultsMessage(String)
         * @return
         *      The message used when serializing an empty array or empty list.
         */
@@ -211,51 +186,51 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        /**
         * Configuration property:  Prevent word wrap on page.
         *
-        * @see HtmlDocSerializer#HTMLDOC_nowrap
+        * @see HtmlDocSerializerBuilder#nowrap()
         * @return
-        *      <jk>true</jk> if <js>"* {white-space:nowrap}"</js> shoudl be 
added to the CSS instructions on the page to prevent word wrapping.
+        *      <jk>true</jk> if <js>"* {white-space:nowrap}"</js> should be 
added to the CSS instructions on the page to prevent word wrapping.
         */
        protected final boolean isNowrap() {
-               return nowrap;
+               return ctx.nowrap;
        }
 
        /**
         * Configuration property:  Javascript code.
         *
-        * @see HtmlDocSerializer#HTMLDOC_script
+        * @see HtmlDocSerializerBuilder#script(String...)
         * @return
         *      Arbitrary Javascript to add to the HTML page.
         */
-       protected final Set<String> getScript() {
-               return script;
+       protected final String[] getScript() {
+               return ctx.script;
        }
 
        /**
         * Configuration property:  CSS style code.
         *
-        * @see HtmlDocSerializer#HTMLDOC_style
+        * @see HtmlDocSerializerBuilder#style(String...)
         * @return
         *      The CSS instructions to add to the HTML page.
         */
-       protected final Set<String> getStyle() {
-               return style;
+       protected final String[] getStyle() {
+               return ctx.style;
        }
 
        /**
         * Configuration property:  Stylesheet import URLs.
         *
-        * @see HtmlDocSerializer#HTMLDOC_stylesheet
+        * @see HtmlDocSerializerBuilder#stylesheet(String...)
         * @return
         *      The link to the stylesheet of the HTML page.
         */
-       protected final Set<String> getStylesheet() {
-               return stylesheet;
+       protected final String[] getStylesheet() {
+               return ctx.stylesheet;
        }
 
        /**
         * Configuration property:  HTML document template.
         *
-        * @see HtmlDocSerializer#HTMLDOC_template
+        * @see HtmlDocSerializerBuilder#template(Class)
         * @return
         *      The template to use for serializing the page.
         */
@@ -264,9 +239,9 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
        }
 
        /**
-        * Configuration property:  Page navigation links.
+        * Configuration property:  Page widgets.
         *
-        * @see HtmlDocSerializer#HTMLDOC_navlinks
+        * @see HtmlDocSerializerBuilder#widgets(Class...)
         * @return
         *      Navigation links to add to the HTML page.
         */
@@ -286,15 +261,7 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
                                OMap
                                        .create()
                                        .filtered()
-                                       .a("aside", aside)
-                                       .a("head", head)
-                                       .a("header", header)
-                                       .a("footer", footer)
-                                       .a("nav", nav)
-                                       .a("navlinks", navlinks)
-                                       .a("script", script)
-                                       .a("style", style)
-                                       .a("stylesheet", stylesheet)
+                                       .a("ctx", ctx)
                                        .a("varResolver", getVarResolver())
                        );
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
index 779f139..a570942 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
@@ -32,7 +32,7 @@ import org.apache.juneau.svl.*;
 @Target({TYPE,METHOD})
 @Retention(RUNTIME)
 @Inherited
-@ContextApply(HtmlDocConfigAnnotation.Apply.class)
+@ContextApply(HtmlDocConfigAnnotation.ApplySerializer.class)
 public @interface HtmlDocConfig {
 
        /**
@@ -88,7 +88,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_aside}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#aside(String...)}
         * </ul>
         */
        String[] aside() default {};
@@ -137,7 +137,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_asideFloat}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#asideFloat(AsideFloat)}
         * </ul>
         */
        String asideFloat() default "DEFAULT";
@@ -177,7 +177,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_footer}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#footer(String...)}
         * </ul>
         */
        String[] footer() default {};
@@ -215,7 +215,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_head}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#head(String...)}
         * </ul>
         */
        String[] head() default {};
@@ -256,7 +256,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_header}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#header(String...)}
         * </ul>
         */
        String[] header() default {};
@@ -299,7 +299,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_nav}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#nav(String...)}
         * </ul>
         */
        String[] nav() default {};
@@ -361,7 +361,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_navlinks}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#navlinks(String...)}
         * </ul>
         */
        String[] navlinks() default {};
@@ -390,7 +390,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link 
HtmlDocSerializer#HTMLDOC_noResultsMessage}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#noResultsMessage(String)}
         * </ul>
         */
        String noResultsMessage() default "";
@@ -414,7 +414,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_nowrap}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#nowrap()}
         * </ul>
         */
        String nowrap() default "";
@@ -454,7 +454,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_script}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#script(String...)}
         * </ul>
         */
        String[] script() default {};
@@ -495,7 +495,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_style}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#style(String...)}
         * </ul>
         */
        String[] style() default {};
@@ -523,7 +523,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_stylesheet}
+        *      <li class='jm'>{@link 
HtmlDocSerializerBuilder#stylesheet(String...)}
         * </ul>
         */
        String[] stylesheet() default {};
@@ -554,7 +554,7 @@ public @interface HtmlDocConfig {
         * </ul>
         *
         * <ul class='seealso'>
-        *      <li class='jf'>{@link HtmlDocSerializer#HTMLDOC_template}
+        *      <li class='jm'>{@link HtmlDocSerializerBuilder#template(Class)}
         * </ul>
         */
        Class<? extends HtmlDocTemplate> template() default 
HtmlDocTemplate.Null.class;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
index 9a31360..2031325 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigAnnotation.java
@@ -12,14 +12,7 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.html.annotation;
 
-import static org.apache.juneau.html.HtmlDocSerializer.*;
-import static org.apache.juneau.internal.StringUtils.*;
-import static java.util.Arrays.*;
-
-import java.util.regex.*;
-
 import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.html.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.svl.*;
@@ -30,78 +23,38 @@ import org.apache.juneau.svl.*;
 public class HtmlDocConfigAnnotation {
 
        /**
-        * Applies {@link HtmlDocConfig} annotations to a {@link 
ContextPropertiesBuilder}.
+        * Applies {@link HtmlDocConfig} annotations to a {@link 
HtmlDocSerializerBuilder}.
         */
-       public static class Apply extends 
AnnotationApplier<HtmlDocConfig,ContextPropertiesBuilder> {
+       public static class ApplySerializer extends 
AnnotationApplier<HtmlDocConfig,HtmlDocSerializerBuilder> {
 
                /**
                 * Constructor.
                 *
                 * @param vr The resolver for resolving values in annotations.
                 */
-               public Apply(VarResolverSession vr) {
-                       super(HtmlDocConfig.class, 
ContextPropertiesBuilder.class, vr);
+               public ApplySerializer(VarResolverSession vr) {
+                       super(HtmlDocConfig.class, 
HtmlDocSerializerBuilder.class, vr);
                }
 
+               @SuppressWarnings("unchecked")
                @Override
-               public void apply(AnnotationInfo<HtmlDocConfig> ai, 
ContextPropertiesBuilder b) {
+               public void apply(AnnotationInfo<HtmlDocConfig> ai, 
HtmlDocSerializerBuilder b) {
                        HtmlDocConfig a = ai.getAnnotation();
 
-                       b.setIf(a.aside().length > 0, HTMLDOC_aside, 
resolveList(a.aside(), b.peek(String[].class, HTMLDOC_aside)));
-                       b.setIf(! "DEFAULT".equalsIgnoreCase(a.asideFloat()), 
HTMLDOC_asideFloat, a.asideFloat().toUpperCase());
-                       b.setIf(a.footer().length > 0, HTMLDOC_footer, 
resolveList(a.footer(), b.peek(String[].class, HTMLDOC_footer)));
-                       b.setIf(a.head().length > 0, HTMLDOC_head, 
resolveList(a.head(), b.peek(String[].class, HTMLDOC_head)));
-                       b.setIf(a.header().length > 0, HTMLDOC_header, 
resolveList(a.header(), b.peek(String[].class, HTMLDOC_header)));
-                       b.setIf(a.nav().length > 0, HTMLDOC_nav, 
resolveList(a.nav(), b.peek(String[].class, HTMLDOC_nav)));
-                       b.setIf(a.navlinks().length > 0, HTMLDOC_navlinks, 
resolveLinks(a.navlinks(), b.peek(String[].class, HTMLDOC_navlinks)));
-                       string(a.noResultsMessage()).ifPresent(x -> 
b.set(HTMLDOC_noResultsMessage, x));
-                       bool(a.nowrap()).ifPresent(x -> b.set(HTMLDOC_nowrap, 
x));
-                       b.setIf(a.script().length > 0, HTMLDOC_script, 
resolveList(a.script(), b.peek(String[].class, HTMLDOC_script)));
-                       b.setIf(a.style().length > 0, HTMLDOC_style, 
resolveList(a.style(), b.peek(String[].class, HTMLDOC_style)));
-                       b.setIf(a.stylesheet().length > 0, HTMLDOC_stylesheet, 
resolveList(a.stylesheet(), b.peek(String[].class, HTMLDOC_stylesheet)));
-                       b.setIf(a.template() != HtmlDocTemplate.Null.class, 
HTMLDOC_template, a.template());
-                       asList(a.widgets()).stream().forEach(x -> 
b.prependTo(HTMLDOC_widgets, x));
-               }
-
-               private static final Pattern INDEXED_LINK_PATTERN = 
Pattern.compile("(?s)(\\S*)\\[(\\d+)\\]\\:(.*)");
-
-               private String[] resolveLinks(Object[] value, String[] prev) {
-                       AList<String> list = AList.create();
-                       for (Object v : value) {
-                               String s = string(stringify(v)).orElse(null);
-                               if (s == null)
-                                       return new String[0];
-                               if ("INHERIT".equals(s)) {
-                                       if (prev != null)
-                                               list.a(prev);
-                               } else if (s.indexOf('[') != -1 && 
INDEXED_LINK_PATTERN.matcher(s).matches()) {
-                                       Matcher lm = 
INDEXED_LINK_PATTERN.matcher(s);
-                                       lm.matches();
-                                       String key = lm.group(1);
-                                       int index = Math.min(list.size(), 
Integer.parseInt(lm.group(2)));
-                                       String remainder = lm.group(3);
-                                       list.add(index, key.isEmpty() ? 
remainder : key + ":" + remainder);
-                               } else {
-                                       list.add(s);
-                               }
-                       }
-                       return list.asArrayOf(String.class);
-               }
-
-               private String[] resolveList(Object[] value, String[] prev) {
-                       ASet<String> set = ASet.of();
-                       for (Object v : value) {
-                               String s = string(stringify(v)).orElse(null);
-                               if ("INHERIT".equals(s)) {
-                                       if (prev != null)
-                                               set.a(prev);
-                               } else if ("NONE".equals(s)) {
-                                       return new String[0];
-                               } else {
-                                       set.add(s);
-                               }
-                       }
-                       return set.asArrayOf(String.class);
+                       strings(a.aside()).ifPresent(x -> b.aside(x));
+                       strings(a.footer()).ifPresent(x -> b.footer(x));
+                       strings(a.head()).ifPresent(x -> b.head(x));
+                       strings(a.header()).ifPresent(x -> b.header(x));
+                       strings(a.nav()).ifPresent(x -> b.nav(x));
+                       strings(a.navlinks()).ifPresent(x -> b.navlinks(x));
+                       strings(a.script()).ifPresent(x -> b.script(x));
+                       strings(a.style()).ifPresent(x -> b.style(x));
+                       strings(a.stylesheet()).ifPresent(x -> b.stylesheet(x));
+                       string(a.asideFloat()).filter(x -> ! 
"DEFAULT".equalsIgnoreCase(x)).map(AsideFloat::valueOf).ifPresent(x -> 
b.asideFloat(x));
+                       string(a.noResultsMessage()).ifPresent(x -> 
b.noResultsMessage(x));
+                       bool(a.nowrap()).ifPresent(x -> b.nowrap(x));
+                       type(a.template()).ifPresent(x -> b.template(x));
+                       classes(a.widgets()).ifPresent(x -> b.widgets((Class<? 
extends HtmlWidget>[]) x));
                }
        }
 }
\ No newline at end of file

Reply via email to