You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/10/08 14:01:13 UTC

[1/2] incubator-juneau git commit: Start separating out HTMLDOC-related logic from rest-servlet API.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master 21a80b823 -> 926b7cf9a


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 861009f..5e030de 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -95,6 +95,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	private ConfigFile cf;
 	private Swagger swagger, fileSwagger;
 	private Map<String,Widget> widgets;
+	private HtmlDocContext hdc;
 
 	/**
 	 * Constructor.
@@ -167,7 +168,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	final void init(Method javaMethod, ObjectMap properties, Map<String,String> defHeader,
 			Map<String,String> defQuery, Map<String,String> defFormData, String defaultCharset,
 			SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser mUrlEncodingParser,
-			BeanContext beanContext, EncoderGroup encoders, Map<String,Widget> widgets) {
+			BeanContext beanContext, EncoderGroup encoders, Map<String,Widget> widgets, HtmlDocContext hdc) {
 		this.javaMethod = javaMethod;
 		this.properties = properties;
 		this.urlEncodingParser = mUrlEncodingParser;
@@ -195,6 +196,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		this.defaultCharset = defaultCharset;
 		this.defFormData = defFormData;
 		this.widgets = widgets;
+		this.hdc = hdc;
 
 		if (debug) {
 			String msg = ""
@@ -318,24 +320,24 @@ public final class RestRequest extends HttpServletRequestWrapper {
 				char c2 = StringUtils.charAt(name, 0);
 				if (c2 == 'a') {
 					if ("aside".equals(name))
-						return cm.htmlAside == null ? null : resolveVars(cm.htmlAside);
+						return resolveVars(hdc.aside);
 				} else if (c2 == 'f') {
 					if ("footer".equals(name))
-						return cm.htmlFooter == null ? null : resolveVars(cm.htmlFooter);
+						return resolveVars(hdc.footer);
 				} else if (c2 == 'h') {
 					if ("header".equals(name))
-						return cm.htmlHeader == null ? null : resolveVars(cm.htmlHeader);
+						return resolveVars(hdc.header);
 					if ("head.list".equals(name))
-						return resolveVars(cm.htmlHead);
+						return resolveVars(hdc.head);
 				} else if (c2 == 'n') {
 					if ("nav".equals(name))
-						return cm.htmlNav == null ? null : resolveVars(cm.htmlNav);
+						return resolveVars(hdc.nav);
 					if ("navlinks.list".equals(name)) {
-						if (cm.htmlNavLinks == null || cm.htmlNavLinks.length == 0)
+						if (hdc.navlinks == null || hdc.navlinks.length == 0)
 							return null;
 						try {
 							List<String> la = new ArrayList<String>();
-							for (String l : cm.htmlNavLinks) {
+							for (String l : hdc.navlinks) {
 								// Temporary backwards compatibility with JSON object format.
 								if (l.startsWith("{")) {
 									ObjectMap m = new ObjectMap(l);
@@ -351,14 +353,14 @@ public final class RestRequest extends HttpServletRequestWrapper {
 						}
 					}
 					if ("noResultsMessage".equals(name))
-						return cm.htmlNoResultsMessage == null ? null : resolveVars(cm.htmlNoResultsMessage);
+						return resolveVars(hdc.noResultsMessage);
 					if ("nowrap".equals(name))
-						return cm.htmlNoWrap;
+						return hdc.nowrap;
 				} else if (c2 == 's') {
 					if ("script.list".equals(name)) {
 						Set<String> l = new LinkedHashSet<String>();
-						if (cm.htmlScript != null)
-							l.add(resolveVars(cm.htmlScript));
+						if (hdc.script != null)
+							l.add(resolveVars(hdc.script));
 						for (Widget w : getWidgets().values()) {
 							String script;
 							try {
@@ -373,8 +375,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 					}
 					if ("style.list".equals(name)) {
 						Set<String> l = new LinkedHashSet<String>();
-						if (cm.htmlStyle != null)
-							l.add(resolveVars(cm.htmlStyle));
+						if (hdc.style != null)
+							l.add(resolveVars(hdc.style));
 						for (Widget w : getWidgets().values()) {
 							String style;
 							try {
@@ -391,12 +393,12 @@ public final class RestRequest extends HttpServletRequestWrapper {
 						String s = getStylesheet();
 						// Exclude absolute URIs to stylesheets for security reasons.
 						if (s == null || isAbsoluteUri(s))
-							s = cm.htmlStylesheet;
+							s = hdc.stylesheet;
 						return s == null ? null : resolveVars(s);
 					}
 				} else if (c2 == 't') {
 					if ("template".equals(name))
-						return cm.htmlTemplate;
+						return hdc.template;
 				}
 			}
 		} else if (c == 'P') {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
index fffd0c1..38e6b90 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -21,14 +21,11 @@ import javax.servlet.http.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
-import org.apache.juneau.html.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
-import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.utils.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -66,6 +63,7 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	private EncoderGroup encoders;
 	private ServletOutputStream os;
 	private PrintWriter w;
+	private HtmlDocBuilder htmlDocBuilder;
 
 	/**
 	 * Constructor.
@@ -180,6 +178,17 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	}
 
 	/**
+	 * Returns a programmatic interface for setting properties for the HTML doc view.
+	 *
+	 * @return A new programmatic interface for setting properties for the HTML doc view.
+	 */
+	public HtmlDocBuilder getHtmlDocBuilder() {
+		if (htmlDocBuilder == null)
+			htmlDocBuilder = new HtmlDocBuilder(properties);
+		return htmlDocBuilder;
+	}
+
+	/**
 	 * Add a serializer property to send to the serializers to override a default value.
 	 *
 	 * <p>
@@ -443,385 +452,6 @@ public final class RestResponse extends HttpServletResponseWrapper {
 			super.setHeader(name, value);
 	}
 
-	/**
-	 * Sets the HTML header section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The page header normally contains the title and description, but this value can be used to override the contents
-	 * to be whatever you want.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no header.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#header() @HtmlDoc.header()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML header section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlHeader(Object value) {
-		return setProperty(HtmlDocSerializerContext.HTMLDOC_header, value);
-	}
-
-	/**
-	 * Sets the links in the HTML nav section.
-	 *
-	 * <p>
-	 * The format of this value is a lax-JSON map of key/value pairs where the keys are the link text and the values are
-	 * relative (to the servlet) or absolute URLs.
-	 *
-	 * <p>
-	 * The page links are positioned immediately under the title and text.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This field can also use URIs of any support type in {@link UriResolver}.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#navlinks() @HtmlDoc.navlinks()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML nav section links links.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlNavLinks(String[] value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_navlinks, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML nav section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The nav section of the page contains the links.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * When a value is specified, the {@link #setHtmlNavLinks(String[])} value will be ignored.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#nav() @HtmlDoc.nav()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML nav section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlNav(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_nav, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML aside section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The aside section typically floats on the right side of the page.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#aside() @HtmlDoc.aside()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML aside section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to waste
-	 * 				string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlAside(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_aside, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML footer section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The footer section typically floats on the bottom of the page.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#footer() @HtmlDoc.footer()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML footer section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlFooter(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_footer, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML CSS style section contents.
-	 *
-	 * <p>
-	 * The format of this value is CSS.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#style() @HtmlDoc.style()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML CSS style section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlStyle(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_style, value);
-		return this;
-	}
-
-	/**
-	 * Sets the CSS URL in the HTML CSS style section.
-	 *
-	 * <p>
-	 * The format of this value is a comma-delimited list of URLs.
-	 *
-	 * <p>
-	 * Specifies the URL to the stylesheet to add as a link in the style tag in the header.
-	 *
-	 * <p>
-	 * The format of this value is CSS.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>) and can use URL protocols defined
-	 * by {@link UriResolver}.
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#stylesheet() @HtmlDoc.stylesheet()} annotation.
-	 *
-	 * @param value
-	 * 	The CSS URL in the HTML CSS style section.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlStylesheet(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_stylesheet, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML script section contents.
-	 *
-	 * <p>
-	 * The format of this value is Javascript.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#script() @HtmlDoc.script()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML script section contents.
-	 * 	Object will be converted to a string using {@link Object#toString()}.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlScript(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_script, value);
-		return this;
-	}
-
-	/**
-	 * Sets the HTML head section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation.
-	 *
-	 * @param value
-	 * 	The HTML head section contents.
-	 * 	<p>
-	 * 	<ul class='doctree'>
-	 * 		<li class='info'>
-	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
-	 * 				waste string concatenation cycles on non-HTML views.
-	 * 	</ul>
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlHead(Object...value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_head, value);
-		return this;
-	}
-
-	/**
-	 * Shorthand method for forcing the rendered HTML content to be no-wrap.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#nowrap() @HtmlDoc.nowrap()} annotation.
-	 *
-	 * @param value The new nowrap setting.
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlNoWrap(boolean value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_nowrap, value);
-		return this;
-	}
-
-	/**
-	 * Specifies the text to display when serializing an empty array or collection.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#noResultsMessage() @HtmlDoc.noResultsMessage()}
-	 * annotation.
-	 *
-	 * @param value The text to display when serializing an empty array or collection.
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlNoResultsMessage(Object value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_noResultsMessage, value);
-		return this;
-	}
-
-	/**
-	 * Specifies the template class to use for rendering the HTML page.
-	 *
-	 * <p>
-	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
-	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
-	 *
-	 * @param value The HTML page template to use to render the HTML page.
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlTemplate(Class<? extends HtmlDocTemplate> value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_template, value);
-		return this;
-	}
-
-	/**
-	 * Specifies the template class to use for rendering the HTML page.
-	 *
-	 * <p>
-	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
-	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
-	 *
-	 * @param value The HTML page template to use to render the HTML page.
-	 * @return This object (for method chaining).
-	 */
-	public RestResponse setHtmlTemplate(HtmlDocTemplate value) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_template, value);
-		return this;
-	}
 
 	@Override /* ServletResponse */
 	public void flushBuffer() throws IOException {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
index ef6d275..fe8622d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
@@ -108,7 +108,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlHeader(String)} and {@link RestResponse#setHtmlHeader(Object)} methods.
+	 * 		{@link HtmlDocConfig#header(Object)} and {@link HtmlDocBuilder#header(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -157,7 +157,7 @@ public @interface HtmlDoc {
 	 * 		This field can also use URIs of any support type in {@link UriResolver}.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlNavLinks(String[])} and {@link RestResponse#setHtmlNavLinks(String[])} methods.
+	 * 		{@link HtmlDocConfig#navlinks(Object[])} and {@link HtmlDocBuilder#navlinks(Object[])} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -207,7 +207,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlNav(String)} and {@link RestResponse#setHtmlNav(Object)} methods.
+	 * 		{@link HtmlDocConfig#nav(Object)} and {@link HtmlDocBuilder#nav(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -250,7 +250,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlAside(String)} and {@link RestResponse#setHtmlAside(Object)} methods.
+	 * 		{@link HtmlDocConfig#aside(Object)} and {@link HtmlDocBuilder#aside(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -293,7 +293,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlFooter(String)} and {@link RestResponse#setHtmlFooter(Object)} methods.
+	 * 		{@link HtmlDocConfig#footer(Object)} and {@link HtmlDocBuilder#footer(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -334,7 +334,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlStyle(String)} and {@link RestResponse#setHtmlStyle(Object)} methods.
+	 * 		{@link HtmlDocConfig#style(Object)} and {@link HtmlDocBuilder#style(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -375,7 +375,7 @@ public @interface HtmlDoc {
 	 * 		<br>See {@link RestContext#getVarResolver()} for the list of supported variables.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlStylesheet(String)}/{@link RestResponse#setHtmlStylesheet(Object)} methods.
+	 * 		{@link HtmlDocConfig#stylesheet(Object)}/{@link HtmlDocBuilder#stylesheet(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -413,7 +413,7 @@ public @interface HtmlDoc {
 	 * 		Multiple values are combined with newlines into a single string.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlScript(String)} and {@link RestResponse#setHtmlScript(Object)} methods.
+	 * 		{@link HtmlDocConfig#script(Object)} and {@link HtmlDocBuilder#script(Object)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -457,7 +457,7 @@ public @interface HtmlDoc {
 	 * 		The head content from the parent can be included by adding the literal <js>"INHERIT"</js> as a value.
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlHead(String[])} and {@link RestResponse#setHtmlHead(String[])} methods.
+	 * 		{@link HtmlDocConfig#head(Object[])} and {@link HtmlDocBuilder#head(Object[])} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>
@@ -491,7 +491,7 @@ public @interface HtmlDoc {
 	 * <ul class='spaced-list'>
 	 * 	<li>
 	 * 		The programmatic equivalent to this annotation are the
-	 * 		{@link RestConfig#setHtmlTemplate(Class)} and {@link RestResponse#setHtmlTemplate(Class)} methods.
+	 * 		{@link HtmlDocConfig#template(Class)} and {@link HtmlDocBuilder#template(Class)} methods.
 	 * 	<li>
 	 * 		On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class.
 	 * 	<li>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
index eed626a..6def29e 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
@@ -2974,12 +2974,6 @@
 				</td>
 			</tr>
 			<tr>
-				<td>{@link org.apache.juneau.rest.annotation.RestResource#favicon() favicon()}</td>
-				<td>
-					Favicon is searched for in child-to-parent order.
-				</td>
-			</tr>
-			<tr>
 				<td>{@link org.apache.juneau.rest.annotation.RestResource#staticFiles() staticFiles()}</td>
 				<td>
 					Static files on child are combined with those on parent class.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/UrlVar.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
index 365d48e..7e0b3af 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
@@ -31,7 +31,7 @@ import org.apache.juneau.svl.*;
  * See {@link UriResolver} for the kinds of URIs that can be resolved.
  * <ul>
  * 	<li>{@link HtmlDoc#widgets() @HtmlDoc.widgets()}
- * 	<li>{@link RestConfig#addHtmlWidget(Class)}
+ * 	<li>{@link HtmlDocConfig#widget(Class)}
  * </ul>
  *
  * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
index 2c3516c..0d5c241 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
@@ -30,7 +30,7 @@ import org.apache.juneau.svl.*;
  * They're registered via the following mechanisms:
  * <ul>
  * 	<li>{@link HtmlDoc#widgets() @HtmlDoc.widgets()}
- * 	<li>{@link RestConfig#addHtmlWidget(Class)}
+ * 	<li>{@link HtmlDocConfig#widget(Class)}
  * </ul>
  *
  * @see org.apache.juneau.svl

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/Widget.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/Widget.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/Widget.java
index e8a4812..7e6eb97 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/Widget.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/Widget.java
@@ -26,7 +26,7 @@ import org.apache.juneau.utils.*;
  * Widgets are associated with resources through the following
  * <ul>
  * 	<li>{@link HtmlDoc#widgets() @HtmlDoc.widgets}
- * 	<li>{@link RestConfig#addHtmlWidget(Class)}
+ * 	<li>{@link HtmlDocConfig#widget(Class)}
  * </ul>
  *
  * <p>


[2/2] incubator-juneau git commit: Start separating out HTMLDOC-related logic from rest-servlet API.

Posted by ja...@apache.org.
Start separating out HTMLDOC-related logic from rest-servlet API.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/926b7cf9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/926b7cf9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/926b7cf9

Branch: refs/heads/master
Commit: 926b7cf9a7ae0d544ebde7e32b6f2bd054bc8aeb
Parents: 21a80b8
Author: JamesBognar <ja...@apache.org>
Authored: Sun Oct 8 10:01:08 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Sun Oct 8 10:01:08 2017 -0400

----------------------------------------------------------------------
 .../juneau/html/HtmlDocSerializerContext.java   |  36 +-
 .../org/apache/juneau/internal/StringUtils.java |  17 +
 juneau-doc/src/main/javadoc/overview.html       |  43 +-
 .../java/org/apache/juneau/rest/CallMethod.java |  60 +--
 .../org/apache/juneau/rest/HtmlDocBuilder.java  | 408 +++++++++++++++++
 .../org/apache/juneau/rest/HtmlDocConfig.java   | 456 +++++++++++++++++++
 .../org/apache/juneau/rest/HtmlDocContext.java  | 171 +++++++
 .../java/org/apache/juneau/rest/RestConfig.java | 347 +-------------
 .../org/apache/juneau/rest/RestContext.java     | 217 +--------
 .../org/apache/juneau/rest/RestRequest.java     |  34 +-
 .../org/apache/juneau/rest/RestResponse.java    | 394 +---------------
 .../apache/juneau/rest/annotation/HtmlDoc.java  |  20 +-
 .../java/org/apache/juneau/rest/package.html    |   6 -
 .../org/apache/juneau/rest/vars/UrlVar.java     |   2 +-
 .../org/apache/juneau/rest/vars/WidgetVar.java  |   2 +-
 .../org/apache/juneau/rest/widget/Widget.java   |   2 +-
 16 files changed, 1161 insertions(+), 1054 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
index f017253..13c022a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
@@ -77,6 +77,8 @@ import org.apache.juneau.*;
  */
 public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 
+	static final String HTMLDOC = "HtmlDocSerializer.";
+
 	/**
 	 * <b>Configuration property:</b>  Header section contents.
 	 *
@@ -105,7 +107,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_header = "HtmlDocSerializer.header";
+	public static final String HTMLDOC_header = HTMLDOC + "header";
 
 	/**
 	 * <b>Configuration property:</b>  Page navigation links.
@@ -170,12 +172,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
 	 */
-	public static final String HTMLDOC_navlinks = "HtmlDocSerializer.navlinks.list";
+	public static final String HTMLDOC_navlinks = HTMLDOC + "navlinks.list";
 
 	/**
 	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_navlinks} property.
 	 */
-	public static final String HTMLDOC_navlinks_add = "HtmlDocSerializer.navlinks.list.add";
+	public static final String HTMLDOC_navlinks_add = HTMLDOC + "navlinks.list.add";
 
 	/**
 	 * <b>Configuration property:</b>  Nav section contents.
@@ -208,7 +210,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_nav = "HtmlDocSerializer.nav";
+	public static final String HTMLDOC_nav = HTMLDOC + "nav";
 
 	/**
 	 * <b>Configuration property:</b>  Aside section contents.
@@ -246,7 +248,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_aside = "HtmlDocSerializer.aside";
+	public static final String HTMLDOC_aside = HTMLDOC + "aside";
 
 	/**
 	 * <b>Configuration property:</b>  Footer section contents.
@@ -278,7 +280,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_footer = "HtmlDocSerializer.footer";
+	public static final String HTMLDOC_footer = HTMLDOC + "footer";
 
 	/**
 	 * <b>Configuration property:</b>  No-results message.
@@ -305,7 +307,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_noResultsMessage = "HtmlDocSerializer.noResultsMessage";
+	public static final String HTMLDOC_noResultsMessage = HTMLDOC + "noResultsMessage";
 
 	/**
 	 * <b>Configuration property:</b>  Prevent word wrap on page.
@@ -320,7 +322,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * Adds <js>"* {white-space:nowrap}"</js> to the CSS instructions on the page to prevent word wrapping.
 	 */
-	public static final String HTMLDOC_nowrap = "HtmlDocSerializer.nowrap";
+	public static final String HTMLDOC_nowrap = HTMLDOC + "nowrap";
 
 	/**
 	 * <b>Configuration property:</b>  Stylesheet import URLs.
@@ -341,12 +343,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_stylesheet = "HtmlDocSerializer.stylesheet";
+	public static final String HTMLDOC_stylesheet = HTMLDOC + "stylesheet";
 
 	/**
 	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_stylesheet} property.
 	 */
-	public static final String HTMLDOC_stylesheet_add = "HtmlDocSerializer.stylesheet.list.add";
+	public static final String HTMLDOC_stylesheet_add = HTMLDOC + "stylesheet.list.add";
 
 	/**
 	 * <b>Configuration property:</b>  CSS style code.
@@ -384,12 +386,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * 	)
 	 * </p>
 	 */
-	public static final String HTMLDOC_style = "HtmlDocSerializer.style.list";
+	public static final String HTMLDOC_style = HTMLDOC + "style.list";
 
 	/**
 	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_style} property.
 	 */
-	public static final String HTMLDOC_style_add = "HtmlDocSerializer.style.list.add";
+	public static final String HTMLDOC_style_add = HTMLDOC + "style.list.add";
 
 	/**
 	 * <b>Configuration property:</b>  Javascript code.
@@ -426,12 +428,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * 	)
 	 * </p>
 	 */
-	public static final String HTMLDOC_script = "HtmlDocSerializer.script.list";
+	public static final String HTMLDOC_script = HTMLDOC + "script.list";
 
 	/**
 	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_script} property.
 	 */
-	public static final String HTMLDOC_script_add = "HtmlDocSerializer.script.list.add";
+	public static final String HTMLDOC_script_add = HTMLDOC + "script.list.add";
 
 	/**
 	 * <b>Configuration property:</b>  Additional head section content.
@@ -468,12 +470,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * 	)
 	 * </p>
 	 */
-	public static final String HTMLDOC_head = "HtmlDocSerializer.head.list";
+	public static final String HTMLDOC_head = HTMLDOC + "head.list";
 
 	/**
 	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_head} property.
 	 */
-	public static final String HTMLDOC_links_add = "HtmlDocSerializer.head.list.add";
+	public static final String HTMLDOC_links_add = HTMLDOC + "head.list.add";
 
 	/**
 	 * <b>Configuration property:</b>  HTML document template.
@@ -501,7 +503,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * 	)
 	 * </p>
 	 */
-	public static final String HTMLDOC_template = "HtmlDocSerializer.template";
+	public static final String HTMLDOC_template = HTMLDOC + "template";
 
 
 	final String[] style, stylesheet, script, navlinks, head;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index 5abd77d..8ad75c8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -1181,6 +1181,23 @@ public final class StringUtils {
 	}
 
 	/**
+	 * Converts an array of objects to an array of strings.
+	 *
+	 * @param o The array of objects to convert to strings.
+	 * @return A new array of objects converted to strings.
+	 */
+	public static String[] toStrings(Object[] o) {
+		if (o == null)
+			return null;
+		if (o instanceof String[])
+			return (String[])o;
+		String[] s = new String[o.length];
+		for (int i = 0; i < o.length; i++)
+			s[i] = toString(o[i]);
+		return s;
+	}
+
+	/**
 	 * Converts a hexadecimal byte stream (e.g. "34A5BC") into a UTF-8 encoded string.
 	 *
 	 * @param hex The hexadecimal string.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-doc/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 351e1af..c1cdf86 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -7481,6 +7481,9 @@
 		<js>"&lt;link rel='icon' href='$U{servlet:/htdocs/juneau.png}'/&gt;"</js>
 	}
 				</p>
+			<li>
+				Removed several of the HTMLDOC-related methods from the <code>RestResponse/RestConfig/RestContext</code>
+				classes and moved it into the new {@link org.apache.juneau.rest.HtmlDocBuilder} class.
 		</ul>
 	</div>
 
@@ -8030,7 +8033,7 @@
 			<li>
 				Modifications to the following <ja>@HtmlDoc</ja> annotations:
 				<ul>
-					<li>{@link org.apache.juneau.rest.annotation.HtmlDoc#links() links()} - Now an array of strings instead of a JSON object.  Simplified syntax.
+					<li>{@link org.apache.juneau.rest.annotation.HtmlDoc#navlinks() navlinks()} - Now an array of strings instead of a JSON object.  Simplified syntax.
 						<br>For example:
 						<p class='bcode'>
 	<jc>// Old syntax</jc>
@@ -8513,17 +8516,17 @@
 					<li><code><del>setHtmlTitle(String)</del></code>
 					<li><code><del>setHtmlDescription(String)</del></code>
 					<li><code><del>setHtmlBranding(String)</del></code>
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlHeader(String) setHtmlHeader(String)}
+					<li><code><del>setHtmlHeader(String)</del></code>
 					<li><code><del>setHtmlLinks(String)</del></code>
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlNav(String) setHtmlNav(String)}
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlAside(String) setHtmlAside(String)}
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlFooter(String) setHtmlFooter(String)}
+					<li><code><del>setHtmlNav(String)</del></code>
+					<li><code><del>setHtmlAside(String)</del></code>
+					<li><code><del>setHtmlFooter(String)</del></code>
 					<li><code><del>setHtmlCss(String)</del></code>
 					<li><code><del>setHtmlCssUrl(String)</del></code>
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlNoWrap(boolean) setHtmlNoWrap(boolean)}
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlNoResultsMessage(String) setHtmlNoResultsMessage(String)}
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlTemplate(Class) setHtmlTemplate(Class)}
-					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlTemplate(HtmlDocTemplate) setHtmlTemplate(HtmlDocTemplate)}
+					<li><code><del>setHtmlNoWrap(boolean)</del></code>
+					<li><code><del>setHtmlNoResultsMessage(String)</del></code>
+					<li><code><del>setHtmlTemplate(Class)</del></code>
+					<li><code><del>setHtmlTemplate(HtmlDocTemplate)</del></code>
 					<li><code><del>addWidget(Class)</del></code>
 				</ul>
 			<li>
@@ -8532,17 +8535,17 @@
 					<li><code><del>setHtmlTitle(Object)</del></code>
 					<li><code><del>setHtmlDescription(Object)</del></code>
 					<li><code><del>setHtmlBranding(Object)</del></code>
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlHeader(Object) setHtmlHeader(Object)}
+					<li><code><del>setHtmlHeader(Object)</del></code>
 					<li><code><del>setHtmlLinks(Object)</del></code>
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlNav(Object) setHtmlNav(Object)}
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlAside(Object) setHtmlAside(Object)}
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlFooter(Object) setHtmlFooter(Object)}
+					<li><code><del>setHtmlNav(Object)</del></code>
+					<li><code><del>setHtmlAside(Object)</del></code>
+					<li><code><del>setHtmlFooter(Object)</del></code>
 					<li><code><del>setHtmlCss(Object)</del></code>
 					<li><code><del>setHtmlCssUrl(Object)</del></code>
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlNoWrap(boolean) setHtmlNoWrap(boolean)}
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlNoResultsMessage(Object) setHtmlNoResultsMessage(Object)}
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlTemplate(Class) setHtmlTemplate(Class)}
-					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlTemplate(HtmlDocTemplate) setHtmlTemplate(HtmlDocTemplate)}
+					<li><code><del>setHtmlNoWrap(boolean)</del></code>
+					<li><code><del>setHtmlNoResultsMessage(Object)</del></code>
+					<li><code><del>setHtmlTemplate(Class)</del></code>
+					<li><code><del>setHtmlTemplate(HtmlDocTemplate)</del></code>
 				</ul>
 			<li>
 				<code>&amp;plainText=true</code> parameter now works on byte-based serializers by converting the output to hex.
@@ -9733,7 +9736,7 @@
 			<li>New annotations on {@link org.apache.juneau.rest.annotation.RestResource}.
 				<ul>
 					<li><code><del>RestResource.stylesheet()</del></code>
-					<li>{@link org.apache.juneau.rest.annotation.RestResource#favicon()}
+					<li><code><del>RestResource.favicon()</del></code>
 					<li>{@link org.apache.juneau.rest.annotation.RestResource#staticFiles()}
 				</ul>
 			<li>Eliminated <code>org.apache.juneau.rest.jaxrs.JsonProvider</code> class.  
@@ -10248,7 +10251,7 @@
 		<h6 class='topic'>Core</h6>		
 		<ul class='spaced-list'>
 			<li>{@link org.apache.juneau.ClassMeta#newInstance()} method can now create new instances of arrays.
-			<li>Arguments passed to {@link org.apache.juneau.dto.Link} are now serialized using {@link org.apache.juneau.urlencoding.UrlEncodingSerializer}, so arbitrary POJOs can now be passed as arguments.
+			<li>Arguments passed to <code><del>Link</del></code> are now serialized using {@link org.apache.juneau.urlencoding.UrlEncodingSerializer}, so arbitrary POJOs can now be passed as arguments.
 			<li>New date filters:  <code>org.apache.juneau.transforms.Datefilter.ISO8601DTZP</code> and <code>org.apache.juneau.transforms.Datefilter.SimpleP</code>.
 			<li>New {@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_nowrap} setting for {@link org.apache.juneau.html.HtmlDocSerializer} class.  
 				Adds <js>"* {white-space:nowrap}"</js> to the style header to prevent word wrapping.
@@ -10469,7 +10472,7 @@
 				</ul>
 			<li>Code changes to facilitate breaking up bundles:
 				<ul>
-					<li><code>org.apache.juneau.rest.labels.Link</code> class moved to {@link org.apache.juneau.dto.Link}.
+					<li><code>org.apache.juneau.rest.labels.Link</code> class moved to <code><del>Link</del></code>.
 					<li>References to <code>org.apache.juneau.rest.RestException</code> in {@link org.apache.juneau.encoders.Encoder} class changed to <code>IOException</code>.
 				</ul>
 			<li>Changed configuration names for consistency with Jazz Framework.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
index 7f31520..55ec42c 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.internal.Utils.*;
-import static org.apache.juneau.rest.RestUtils.*;
 import static org.apache.juneau.rest.annotation.Inherit.*;
 
 import java.lang.annotation.*;
@@ -29,12 +28,9 @@ import javax.servlet.http.*;
 import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
-import org.apache.juneau.html.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.urlencoding.*;
@@ -67,11 +63,7 @@ class CallMethod implements Comparable<CallMethod>  {
 	private final Response[] responses;
 	private final RestContext context;
 	private final BeanContext beanContext;
-	final String htmlHeader, htmlNav, htmlAside, htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlNoResultsMessage;
-	final String[] htmlNavLinks, htmlHead;
-	final boolean htmlNoWrap;
-	final HtmlDocTemplate htmlTemplate;
-	private final Map<String,Widget> widgets;
+	private final HtmlDocContext htmlDocContext;
 
 	CallMethod(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 		Builder b = new Builder(servlet, method, context);
@@ -103,27 +95,11 @@ class CallMethod implements Comparable<CallMethod>  {
 		this.priority = b.priority;
 		this.parameters = b.parameters;
 		this.responses = b.responses;
-		this.htmlHeader = b.htmlHeader;
-		this.htmlNavLinks = b.htmlNavLinks;
-		this.htmlNav = b.htmlNav;
-		this.htmlAside = b.htmlAside;
-		this.htmlFooter = b.htmlFooter;
-		this.htmlStyle = b.htmlStyle;
-		this.htmlStylesheet = b.htmlStylesheet;
-		this.htmlScript = b.htmlScript;
-		this.htmlHead = b.htmlHead;
-		this.htmlNoWrap = b.htmlNoWrap;
-		this.htmlTemplate = b.htmlTemplate;
-		this.htmlNoResultsMessage = b.htmlNoResultsMessage;
-		this.widgets = Collections.unmodifiableMap(b.htmlWidgets);
+		this.htmlDocContext = new HtmlDocContext(method, context.getHtmlDocContext());
 	}
 
 	private static class Builder  {
-		private String httpMethod, defaultCharset, description, tags, summary, externalDocs, htmlNav, htmlAside,
-			htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlHeader, htmlNoResultsMessage;
-		private String[] htmlNavLinks, htmlHead;
-		private boolean htmlNoWrap;
-		private HtmlDocTemplate htmlTemplate;
+		private String httpMethod, defaultCharset, description, tags, summary, externalDocs;
 		private UrlPathPattern pathPattern;
 		private RestParam[] params;
 		private RestGuard[] guards;
@@ -141,7 +117,6 @@ class CallMethod implements Comparable<CallMethod>  {
 		private Integer priority;
 		private org.apache.juneau.rest.annotation.Parameter[] parameters;
 		private Response[] responses;
-		private Map<String,Widget> htmlWidgets;
 
 		private Builder(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 			String sig = method.getDeclaringClass().getName() + '.' + method.getName();
@@ -179,29 +154,6 @@ class CallMethod implements Comparable<CallMethod>  {
 				if (! m.paramFormat().isEmpty())
 					paramFormat = context.getVarResolver().resolve(m.paramFormat());
 
-				HtmlDoc hd = m.htmldoc();
-				htmlWidgets = new HashMap<String,Widget>(context.getHtmlWidgets());
-				for (Class<? extends Widget> wc : hd.widgets()) {
-					Widget w = ClassUtils.newInstance(Widget.class, wc);
-					htmlWidgets.put(w.getName(), w);
-				}
-
-				htmlHeader = resolveNewlineSeparatedAnnotation(hd.header(), context.getHtmlHeader());
-				htmlNav = resolveNewlineSeparatedAnnotation(hd.nav(), context.getHtmlNav());
-				htmlAside = resolveNewlineSeparatedAnnotation(hd.aside(), context.getHtmlAside());
-				htmlFooter = resolveNewlineSeparatedAnnotation(hd.footer(), context.getHtmlFooter());
-				htmlStyle = resolveNewlineSeparatedAnnotation(hd.style(), context.getHtmlStyle());
-				htmlScript = resolveNewlineSeparatedAnnotation(hd.script(), context.getHtmlScript());
-				htmlHead = resolveContent(hd.head(), context.getHtmlHead());
-				htmlNavLinks = resolveLinks(hd.navlinks(), context.getHtmlNavLinks());
-				htmlStylesheet = hd.stylesheet().isEmpty() ? context.getHtmlStylesheet() : hd.stylesheet();
-				htmlNoWrap = hd.nowrap() ? hd.nowrap() : context.getHtmlNoWrap();
-				htmlNoResultsMessage = hd.noResultsMessage().isEmpty() ? context.getHtmlNoResultsMessage() : hd.noResultsMessage();
-				htmlTemplate =
-					hd.template() == HtmlDocTemplate.class
-					? context.getHtmlTemplate()
-					: ClassUtils.newInstance(HtmlDocTemplate.class, hd.template());
-
 				List<Inherit> si = Arrays.asList(m.serializersInherit());
 				List<Inherit> pi = Arrays.asList(m.parsersInherit());
 
@@ -509,6 +461,10 @@ class CallMethod implements Comparable<CallMethod>  {
 		return null;
 	}
 
+	HtmlDocContext getHtmlDocContext() {
+		return htmlDocContext;
+	}
+
 	/**
 	 * Returns the localized Swagger tags for this Java method.
 	 */
@@ -795,7 +751,7 @@ class CallMethod implements Comparable<CallMethod>  {
 
 		ObjectMap requestProperties = createRequestProperties(properties, req);
 		req.init(method, requestProperties, defaultRequestHeaders, defaultQuery, defaultFormData, defaultCharset,
-			serializers, parsers, urlEncodingParser, beanContext, encoders, widgets);
+			serializers, parsers, urlEncodingParser, beanContext, encoders, htmlDocContext.widgets, htmlDocContext);
 		res.init(requestProperties, defaultCharset, serializers, urlEncodingSerializer, encoders);
 
 		// Class-level guards

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
new file mode 100644
index 0000000..99c6a3b
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
@@ -0,0 +1,408 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.html.HtmlDocSerializerContext.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Programmatic interface for setting properties used by the HtmlDoc serializer.
+ *
+ * <p>
+ * This class is instantiated by calling the {@link RestResponse#getHtmlDocBuilder()} method.
+ */
+public class HtmlDocBuilder {
+
+	private final ObjectMap properties;
+
+	HtmlDocBuilder(ObjectMap properties) {
+		this.properties = properties;
+	}
+
+	/**
+	 * Sets the HTML header section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The page header normally contains the title and description, but this value can be used to override the contents
+	 * to be whatever you want.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no header.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#header() @HtmlDoc.header()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML header section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder header(Object value) {
+		return set(HTMLDOC_header, value);
+	}
+
+	/**
+	 * Sets the links in the HTML nav section.
+	 *
+	 * <p>
+	 * The format of this value is a lax-JSON map of key/value pairs where the keys are the link text and the values are
+	 * relative (to the servlet) or absolute URLs.
+	 *
+	 * <p>
+	 * The page links are positioned immediately under the title and text.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This field can also use URIs of any support type in {@link UriResolver}.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#navlinks() @HtmlDoc.navlinks()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML nav section links links.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder navlinks(Object...value) {
+		return set(HTMLDOC_navlinks, value);
+	}
+
+	/**
+	 * Sets the HTML nav section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The nav section of the page contains the links.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * When a value is specified, the {@link #navlinks(Object[])} value will be ignored.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#nav() @HtmlDoc.nav()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML nav section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder nav(Object value) {
+		return set(HTMLDOC_nav, value);
+	}
+
+	/**
+	 * Sets the HTML aside section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The aside section typically floats on the right side of the page.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#aside() @HtmlDoc.aside()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML aside section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to waste
+	 * 				string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder aside(Object value) {
+		return set(HTMLDOC_aside, value);
+	}
+
+	/**
+	 * Sets the HTML footer section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The footer section typically floats on the bottom of the page.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#footer() @HtmlDoc.footer()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML footer section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder footer(Object value) {
+		return set(HTMLDOC_footer, value);
+	}
+
+	/**
+	 * Sets the HTML CSS style section contents.
+	 *
+	 * <p>
+	 * The format of this value is CSS.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#style() @HtmlDoc.style()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML CSS style section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder style(Object value) {
+		return set(HTMLDOC_style, value);
+	}
+
+	/**
+	 * Sets the CSS URL in the HTML CSS style section.
+	 *
+	 * <p>
+	 * The format of this value is a comma-delimited list of URLs.
+	 *
+	 * <p>
+	 * Specifies the URL to the stylesheet to add as a link in the style tag in the header.
+	 *
+	 * <p>
+	 * The format of this value is CSS.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>) and can use URL protocols defined
+	 * by {@link UriResolver}.
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#stylesheet() @HtmlDoc.stylesheet()} annotation.
+	 *
+	 * @param value
+	 * 	The CSS URL in the HTML CSS style section.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder stylesheet(Object value) {
+		return set(HTMLDOC_stylesheet, value);
+	}
+
+	/**
+	 * Sets the HTML script section contents.
+	 *
+	 * <p>
+	 * The format of this value is Javascript.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#script() @HtmlDoc.script()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML script section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder script(Object value) {
+		return set(HTMLDOC_script, value);
+	}
+
+	/**
+	 * Sets the HTML head section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML head section contents.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder head(Object...value) {
+		return set(HTMLDOC_head, value);
+	}
+
+	/**
+	 * Shorthand method for forcing the rendered HTML content to be no-wrap.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#nowrap() @HtmlDoc.nowrap()} annotation.
+	 *
+	 * @param value The new nowrap setting.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder nowrap(boolean value) {
+		return set(HTMLDOC_nowrap, value);
+	}
+
+	/**
+	 * Specifies the text to display when serializing an empty array or collection.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#noResultsMessage() @HtmlDoc.noResultsMessage()}
+	 * annotation.
+	 *
+	 * @param value The text to display when serializing an empty array or collection.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder noResultsMessage(Object value) {
+		return set(HTMLDOC_noResultsMessage, value);
+	}
+
+	/**
+	 * Specifies the template class to use for rendering the HTML page.
+	 *
+	 * <p>
+	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
+	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
+	 *
+	 * @param value The HTML page template to use to render the HTML page.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder template(Class<? extends HtmlDocTemplate> value) {
+		return set(HTMLDOC_template, value);
+	}
+
+	/**
+	 * Specifies the template class to use for rendering the HTML page.
+	 *
+	 * <p>
+	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
+	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
+	 *
+	 * @param value The HTML page template to use to render the HTML page.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocBuilder template(HtmlDocTemplate value) {
+		return set(HTMLDOC_template, value);
+	}
+
+	private HtmlDocBuilder set(String key, Object value) {
+		properties.put(key, value);
+		return this;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocConfig.java
new file mode 100644
index 0000000..0397198
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocConfig.java
@@ -0,0 +1,456 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.rest.RestUtils.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Programmatic interface for setting properties used by the HtmlDoc serializer.
+ */
+public class HtmlDocConfig {
+
+	String header, nav, aside, footer, style, stylesheet, script, noResultsMessage;
+	String[] navlinks, head;
+	boolean nowrap;
+	Object template = HtmlDocTemplateBasic.class;
+	List<Class<? extends Widget>> widgets = new ArrayList<Class<? extends Widget>>();
+
+	HtmlDocConfig process(HtmlDoc hd) {
+		for (Class<? extends Widget> cw : hd.widgets())
+			widget(cw);
+		header(resolveNewlineSeparatedAnnotation(hd.header(), header));
+		nav(resolveNewlineSeparatedAnnotation(hd.nav(), nav));
+		aside(resolveNewlineSeparatedAnnotation(hd.aside(), aside));
+		footer(resolveNewlineSeparatedAnnotation(hd.footer(), footer));
+		style(resolveNewlineSeparatedAnnotation(hd.style(), style));
+		script(resolveNewlineSeparatedAnnotation(hd.script(), script));
+		navlinks((Object[])resolveLinks(hd.navlinks(), navlinks));
+		head((Object[])resolveContent(hd.head(), head));
+
+		if (! hd.stylesheet().isEmpty())
+			stylesheet(hd.stylesheet());
+		if (! hd.noResultsMessage().isEmpty())
+			noResultsMessage(hd.noResultsMessage());
+		if (hd.nowrap())
+			nowrap(true);
+		if (hd.template() != HtmlDocTemplate.class)
+			template(hd.template());
+
+		return this;
+	}
+
+	/**
+	 * Sets the HTML header section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The page header normally contains the title and description, but this value can be used to override the contents
+	 * to be whatever you want.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no header.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#header() @HtmlDoc.header()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML header section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig header(Object value) {
+		header = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the links in the HTML nav section.
+	 *
+	 * <p>
+	 * The format of this value is a lax-JSON map of key/value pairs where the keys are the link text and the values are
+	 * relative (to the servlet) or absolute URLs.
+	 *
+	 * <p>
+	 * The page links are positioned immediately under the title and text.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This field can also use URIs of any support type in {@link UriResolver}.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#navlinks() @HtmlDoc.navlinks()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML nav section links links.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig navlinks(Object...value) {
+		navlinks = StringUtils.toStrings(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML nav section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The nav section of the page contains the links.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * When a value is specified, the {@link #navlinks(Object[])} value will be ignored.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#nav() @HtmlDoc.nav()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML nav section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig nav(Object value) {
+		this.nav = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML aside section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The aside section typically floats on the right side of the page.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#aside() @HtmlDoc.aside()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML aside section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to waste
+	 * 				string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig aside(Object value) {
+		this.aside = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML footer section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * The footer section typically floats on the bottom of the page.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#footer() @HtmlDoc.footer()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML footer section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig footer(Object value) {
+		this.footer = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML CSS style section contents.
+	 *
+	 * <p>
+	 * The format of this value is CSS.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#style() @HtmlDoc.style()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML CSS style section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig style(Object value) {
+		this.style = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the CSS URL in the HTML CSS style section.
+	 *
+	 * <p>
+	 * The format of this value is a comma-delimited list of URLs.
+	 *
+	 * <p>
+	 * Specifies the URL to the stylesheet to add as a link in the style tag in the header.
+	 *
+	 * <p>
+	 * The format of this value is CSS.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>) and can use URL protocols defined
+	 * by {@link UriResolver}.
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#stylesheet() @HtmlDoc.stylesheet()} annotation.
+	 *
+	 * @param value
+	 * 	The CSS URL in the HTML CSS style section.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig stylesheet(Object value) {
+		this.stylesheet = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML script section contents.
+	 *
+	 * <p>
+	 * The format of this value is Javascript.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#script() @HtmlDoc.script()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML script section contents.
+	 * 	Object will be converted to a string using {@link Object#toString()}.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig script(Object value) {
+		this.script = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Sets the HTML head section contents.
+	 *
+	 * <p>
+	 * The format of this value is HTML.
+	 *
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 *
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation.
+	 *
+	 * @param value
+	 * 	The HTML head section contents.
+	 * 	<p>
+	 * 	<ul class='doctree'>
+	 * 		<li class='info'>
+	 * 			<b>Tip:</b>  Use {@link StringMessage} to generate value with delayed serialization so as not to
+	 * 				waste string concatenation cycles on non-HTML views.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig head(Object...value) {
+		this.head = StringUtils.toStrings(value);
+		return this;
+	}
+
+	/**
+	 * Shorthand method for forcing the rendered HTML content to be no-wrap.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#nowrap() @HtmlDoc.nowrap()} annotation.
+	 *
+	 * @param value The new nowrap setting.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig nowrap(boolean value) {
+		this.nowrap = value;
+		return this;
+	}
+
+	/**
+	 * Specifies the text to display when serializing an empty array or collection.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#noResultsMessage() @HtmlDoc.noResultsMessage()}
+	 * annotation.
+	 *
+	 * @param value The text to display when serializing an empty array or collection.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig noResultsMessage(Object value) {
+		this.noResultsMessage = StringUtils.toString(value);
+		return this;
+	}
+
+	/**
+	 * Specifies the template class to use for rendering the HTML page.
+	 *
+	 * <p>
+	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
+	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
+	 *
+	 * @param value The HTML page template to use to render the HTML page.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig template(Class<? extends HtmlDocTemplate> value) {
+		this.template = value;
+		return this;
+	}
+
+	/**
+	 * Specifies the template class to use for rendering the HTML page.
+	 *
+	 * <p>
+	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
+	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
+	 *
+	 * @param value The HTML page template to use to render the HTML page.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig template(HtmlDocTemplate value) {
+		this.template = value;
+		return this;
+	}
+
+	/**
+	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
+	 * generate arbitrary replacement text.
+	 *
+	 * <p>
+	 * Widgets are inherited from parent to child, but can be overridden by reusing the widget name.
+	 *
+	 * @param value The widget class to add.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocConfig widget(Class<? extends Widget> value) {
+		this.widgets.add(value);
+		return this;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocContext.java
new file mode 100644
index 0000000..9f3809e
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocContext.java
@@ -0,0 +1,171 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.rest.RestUtils.*;
+
+import java.util.*;
+
+import org.apache.juneau.html.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
+
+/**
+ * Programmatic interface for set properties used by the HtmlDoc serializer.
+ */
+public final class HtmlDocContext {
+
+	final String header, nav, aside, style, stylesheet, script, footer, noResultsMessage;
+	final String[] navlinks, head;
+	final boolean nowrap;
+	final HtmlDocTemplate template;
+	final Map<String,Widget> widgets;
+
+	HtmlDocContext(Object resource, RestConfig config) throws RestServletException {
+		try {
+			Builder b = new Builder(resource, config);
+
+			this.header = b.header;
+			this.nav = b.nav;
+			this.aside = b.aside;
+			this.style = b.style;
+			this.stylesheet = b.stylesheet;
+			this.script = b.script;
+			this.footer = b.footer;
+			this.noResultsMessage = b.noResultsMessage;
+			this.navlinks = b.navlinks;
+			this.head = b.head;
+			this.nowrap = b.nowrap;
+			this.widgets = Collections.unmodifiableMap(b.widgets);
+			this.template = b.template;
+		} catch (RestServletException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestServletException("Exception occurred while initializing resource ''{0}''", resource.getClass().getSimpleName()).initCause(e);
+		}
+	}
+
+	HtmlDocContext(java.lang.reflect.Method method, HtmlDocContext pc) throws RestServletException {
+		try {
+			Builder b = new Builder(method, pc);
+			this.header = b.header;
+			this.nav = b.nav;
+			this.aside = b.aside;
+			this.style = b.style;
+			this.stylesheet = b.stylesheet;
+			this.script = b.script;
+			this.footer = b.footer;
+			this.noResultsMessage = b.noResultsMessage;
+			this.navlinks = b.navlinks;
+			this.head = b.head;
+			this.nowrap = b.nowrap;
+			this.widgets = Collections.unmodifiableMap(b.widgets);
+			this.template = b.template;
+		} catch (RestServletException e) {
+			throw e;
+		} catch (Exception e) {
+			String sig = method.getDeclaringClass().getName() + '.' + method.getName();
+			throw new RestServletException("Exception occurred while initializing method ''{0}''", sig).initCause(e);
+		}
+	}
+
+
+	static class Builder {
+
+		String header, nav, aside, style, stylesheet, script, footer, noResultsMessage;
+		String[] navlinks, head;
+		boolean nowrap;
+		HtmlDocTemplate template;
+		Map<String,Widget> widgets;
+
+
+		Builder(java.lang.reflect.Method method, HtmlDocContext pc) throws Exception {
+			String sig = method.getDeclaringClass().getName() + '.' + method.getName();
+
+			try {
+				RestMethod m = method.getAnnotation(RestMethod.class);
+				if (m == null)
+					throw new RestServletException("@RestMethod annotation not found on method ''{0}''", sig);
+
+					HtmlDoc hd = m.htmldoc();
+
+					widgets = new HashMap<String,Widget>(pc.widgets);
+					for (Class<? extends Widget> wc : hd.widgets()) {
+						Widget w = ClassUtils.newInstance(Widget.class, wc);
+						widgets.put(w.getName(), w);
+					}
+
+					header = resolveNewlineSeparatedAnnotation(hd.header(), pc.header);
+					nav = resolveNewlineSeparatedAnnotation(hd.nav(), pc.nav);
+					aside = resolveNewlineSeparatedAnnotation(hd.aside(), pc.aside);
+					footer = resolveNewlineSeparatedAnnotation(hd.footer(), pc.footer);
+					style = resolveNewlineSeparatedAnnotation(hd.style(), pc.style);
+					script = resolveNewlineSeparatedAnnotation(hd.script(), pc.script);
+					head = resolveContent(hd.head(), pc.head);
+					navlinks = resolveLinks(hd.navlinks(), pc.navlinks);
+					stylesheet = hd.stylesheet().isEmpty() ? pc.stylesheet : hd.stylesheet();
+					nowrap = hd.nowrap() ? hd.nowrap() : pc.nowrap;
+					noResultsMessage = hd.noResultsMessage().isEmpty() ? pc.noResultsMessage : hd.noResultsMessage();
+					template =
+						hd.template() == HtmlDocTemplate.class
+						? pc.template
+						: ClassUtils.newInstance(HtmlDocTemplate.class, hd.template());
+			} catch (RestServletException e) {
+				throw e;
+			} catch (Exception e) {
+				throw new RestServletException("Exception occurred while initializing method ''{0}''", sig).initCause(e);
+			}
+		}
+
+
+		Builder(Object resource, RestConfig sc) throws Exception {
+
+			HtmlDocConfig hdc = sc.htmlDocConfig;
+
+			this.widgets = new LinkedHashMap<String,Widget>();
+			for (Class<? extends Widget> wc : hdc.widgets) {
+				Widget w = resolve(resource, Widget.class, wc);
+				this.widgets.put(w.getName(), w);
+			}
+
+			header = hdc.header;
+			navlinks = hdc.navlinks;
+			nav = hdc.nav;
+			aside = hdc.aside;
+			style = hdc.style;
+			stylesheet = hdc.stylesheet;
+			script = hdc.script;
+			head = hdc.head;
+			footer = hdc.footer;
+			nowrap = hdc.nowrap;
+			noResultsMessage = hdc.noResultsMessage;
+			template = resolve(resource, HtmlDocTemplate.class, hdc.template);
+		}
+	}
+
+	//----------------------------------------------------------------------------------------------------
+	// Utility methods
+	//----------------------------------------------------------------------------------------------------
+
+	/**
+	 * Takes in an object of type T or a Class<T> and either casts or constructs a T.
+	 */
+	private static <T> T resolve(Object outer, Class<T> c, Object o, Object...cArgs) throws RestServletException {
+		try {
+			return ClassUtils.newInstanceFromOuter(outer, c, o, cArgs);
+		} catch (Exception e) {
+			throw new RestServletException("Exception occurred while constructing class ''{0}''", c).initCause(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
index d08bf42..ca8e558 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -15,7 +15,6 @@ package org.apache.juneau.rest;
 import static org.apache.juneau.internal.ArrayUtils.*;
 import static org.apache.juneau.internal.ReflectionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.rest.RestUtils.*;
 
 import java.lang.reflect.Method;
 import java.util.*;
@@ -27,7 +26,6 @@ import javax.servlet.http.*;
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.encoders.Encoder;
-import org.apache.juneau.html.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.internal.*;
@@ -35,7 +33,6 @@ import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.response.*;
 import org.apache.juneau.rest.vars.*;
-import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.svl.vars.*;
@@ -113,10 +110,10 @@ public class RestConfig implements ServletConfig {
 	List<MediaType> supportedContentTypes, supportedAcceptTypes;
 	List<Object> staticFiles;
 	RestContext parentContext;
-	String path, htmlHeader, htmlNav, htmlAside, htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlNoResultsMessage;
-	String[] htmlNavLinks, htmlHead;
+	String path;
 	String clientVersionHeader = "X-Client-Version";
 	String contextPath;
+	HtmlDocConfig htmlDocConfig = new HtmlDocConfig();
 
 	Object resourceResolver = RestResourceResolverSimple.class;
 	Object logger = RestLogger.Normal.class;
@@ -124,11 +121,7 @@ public class RestConfig implements ServletConfig {
 	Object infoProvider = RestInfoProvider.class;
 	Object allowHeaderParams, allowMethodParam, allowBodyParam, renderResponseStackTraces, useStackTraceHashes, defaultCharset, paramFormat;
 
-	boolean htmlNoWrap;
-	Object htmlTemplate = HtmlDocTemplateBasic.class;
-
 	Class<?> resourceClass;
-	List<Class<? extends Widget>> htmlWidgets = new ArrayList<Class<? extends Widget>>();
 
 	/**
 	 * Constructor for top-level servlets when using dependency injection.
@@ -252,26 +245,7 @@ public class RestConfig implements ServletConfig {
 				if (! r.paramFormat().isEmpty())
 					setParamFormat(vr.resolve(r.paramFormat()));
 
-				HtmlDoc hd = r.htmldoc();
-				for (Class<? extends Widget> cw : hd.widgets())
-					addHtmlWidget(cw);
-				setHtmlHeader(resolveNewlineSeparatedAnnotation(hd.header(), htmlHeader));
-				setHtmlNav(resolveNewlineSeparatedAnnotation(hd.nav(), htmlNav));
-				setHtmlAside(resolveNewlineSeparatedAnnotation(hd.aside(), htmlAside));
-				setHtmlFooter(resolveNewlineSeparatedAnnotation(hd.footer(), htmlFooter));
-				setHtmlStyle(resolveNewlineSeparatedAnnotation(hd.style(), htmlStyle));
-				setHtmlScript(resolveNewlineSeparatedAnnotation(hd.script(), htmlScript));
-				setHtmlNavLinks(resolveLinks(hd.navlinks(), htmlNavLinks));
-				setHtmlHead(resolveContent(hd.head(), htmlHead));
-
-				if (! hd.stylesheet().isEmpty())
-					setHtmlStylesheet(hd.stylesheet());
-				if (! hd.noResultsMessage().isEmpty())
-					setHtmlNoResultsMessage(hd.noResultsMessage());
-				if (hd.nowrap())
-					setHtmlNoWrap(true);
-				if (hd.template() != HtmlDocTemplate.class)
-					setHtmlTemplate(hd.template());
+				htmlDocConfig.process(r.htmldoc());
 			}
 
 			addResponseHandlers(
@@ -1202,319 +1176,12 @@ public class RestConfig implements ServletConfig {
 	}
 
 	/**
-	 * Sets the HTML header section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The page header normally contains the title and description, but this value can be used to override the contents
-	 * to be whatever you want.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no header.
+	 * Returns the configuration settings specific to the HTML doc view.
 	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#header() @HtmlDoc.header()} annotation.
-	 *
-	 * @param value The HTML header section contents.
-	 * @return This object (for method chaining).
+	 * @return The configuration settings specific to the HTML doc view.
 	 */
-	public RestConfig setHtmlHeader(String value) {
-		this.htmlHeader = value;
-		return this;
-	}
-
-	/**
-	 * Sets the links in the HTML nav section.
-	 *
-	 * <p>
-	 * The format of this value is a lax-JSON map of key/value pairs where the keys are the link text and the values are
-	 * relative (to the servlet) or absolute URLs.
-	 *
-	 * <p>
-	 * The page links are positioned immediately under the title and text.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This field can also use URIs of any support type in {@link UriResolver}.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#navlinks() @HtmlDoc.navlinks()} annotation.
-	 *
-	 * @param value The HTML nav section links links.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlNavLinks(String[] value) {
-		this.htmlNavLinks = value;
-		return this;
-	}
-
-	/**
-	 * Sets the HTML nav section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The nav section of the page contains the links.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * When a value is specified, the {@link #setHtmlNavLinks(String[])} value will be ignored.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#nav() @HtmlDoc.nav()} annotation.
-	 *
-	 * @param value The HTML nav section contents.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlNav(String value) {
-		this.htmlNav = value;
-		return this;
-	}
-
-	/**
-	 * Sets the HTML aside section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The aside section typically floats on the right side of the page.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#aside() @HtmlDoc.aside()} annotation.
-	 *
-	 * @param value The HTML aside section contents.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlAside(String value) {
-		this.htmlAside = value;
-		return this;
-	}
-
-	/**
-	 * Sets the HTML footer section contents.
-	 *
-	 * <p>
-	 * The format of this value is HTML.
-	 *
-	 * <p>
-	 * The footer section typically floats on the bottom of the page.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#footer() @HtmlDoc.footer()} annotation.
-	 *
-	 * @param value The HTML footer section contents.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlFooter(String value) {
-		this.htmlFooter = value;
-		return this;
-	}
-
-	/**
-	 * Sets the HTML CSS style section contents.
-	 *
-	 * <p>
-	 * The format of this value is CSS.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#style() @HtmlDoc.style()} annotation.
-	 *
-	 * @param value The HTML CSS style section contents.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlStyle(String value) {
-		this.htmlStyle = value;
-		return this;
-	}
-
-	/**
-	 * Sets the CSS URL in the HTML CSS style section.
-	 *
-	 * <p>
-	 * The format of this value is a URL.
-	 *
-	 * <p>
-	 * Specifies the URL to the stylesheet to add as a link in the style tag in the header.
-	 *
-	 * <p>
-	 * The format of this value is CSS.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>) and can use URL protocols defined
-	 * by {@link UriResolver}.
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#stylesheet() @HtmlDoc.stylesheet()} annotation.
-	 *
-	 * @param value The CSS URL in the HTML CSS style section.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlStylesheet(String value) {
-		this.htmlStylesheet = value;
-		return this;
-	}
-
-	/**
-	 * Sets the HTML script section contents.
-	 *
-	 * <p>
-	 * The format of this value is Javascript.
-	 *
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
-	 *
-	 * <p>
-	 * A value of <js>"NONE"</js> can be used to force no value.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#script() @HtmlDoc.script()} annotation.
-	 *
-	 * @param value The HTML script section contents.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlScript(String value) {
-		this.htmlScript = value;
-		return this;
-	}
-
-	/**
-	 * Adds to the HTML head section contents.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation.
-	 *
-	 * @param value The HTML head section content.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlHead(String...value) {
-		this.htmlHead = value;
-		return this;
-	}
-
-	/**
-	 * Shorthand method for forcing the rendered HTML content to be no-wrap.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#nowrap() @HtmlDoc.nowrap()} annotation.
-	 *
-	 * @param value The new nowrap setting.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlNoWrap(boolean value) {
-		this.htmlNoWrap = value;
-		return this;
-	}
-
-	/**
-	 * Specifies the text to display when serializing an empty array or collection.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#noResultsMessage() @HtmlDoc.noResultsMessage()}
-	 * annotation.
-	 *
-	 * @param value The text to display when serializing an empty array or collection.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlNoResultsMessage(String value) {
-		this.htmlNoResultsMessage = value;
-		return this;
-	}
-
-	/**
-	 * Specifies the template class to use for rendering the HTML page.
-	 *
-	 * <p>
-	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
-	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
-	 *
-	 * @param value The HTML page template to use to render the HTML page.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlTemplate(Class<? extends HtmlDocTemplate> value) {
-		this.htmlTemplate = value;
-		return this;
-	}
-
-	/**
-	 * Specifies the template class to use for rendering the HTML page.
-	 *
-	 * <p>
-	 * By default, uses {@link HtmlDocTemplateBasic} to render the contents, although you can provide your own custom
-	 * renderer or subclasses from the basic class to have full control over how the page is rendered.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
-	 *
-	 * @param value The HTML page template to use to render the HTML page.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig setHtmlTemplate(HtmlDocTemplate value) {
-		this.htmlTemplate = value;
-		return this;
-	}
-
-	/**
-	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
-	 * generate arbitrary replacement text.
-	 *
-	 * <p>
-	 * Widgets are inherited from parent to child, but can be overridden by reusing the widget name.
-	 *
-	 * @param value The widget class to add.
-	 * @return This object (for method chaining).
-	 */
-	public RestConfig addHtmlWidget(Class<? extends Widget> value) {
-		this.htmlWidgets.add(value);
-		return this;
+	public HtmlDocConfig getHtmlDocConfig() {
+		return htmlDocConfig;
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/926b7cf9/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index d113059..ef9200b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -33,7 +33,6 @@ import javax.servlet.http.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
-import org.apache.juneau.html.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.internal.*;
@@ -42,7 +41,6 @@ import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.annotation.Properties;
 import org.apache.juneau.rest.vars.*;
-import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.svl.vars.*;
@@ -69,21 +67,9 @@ public final class RestContext extends Context {
 		paramFormat,
 		clientVersionHeader,
 		fullPath,
-		contextPath,
-		htmlHeader,
-		htmlNav,
-		htmlAside,
-		htmlStyle,
-		htmlStylesheet,
-		htmlScript,
-		htmlFooter,
-		htmlNoResultsMessage;
-	private final String[]
-		htmlNavLinks,
-		htmlHead;
-	private final boolean htmlNoWrap;
-	private final HtmlDocTemplate htmlTemplate;
-	private final Map<String,Widget> htmlWidgets;
+		contextPath;
+
+	private final HtmlDocContext htmlDocContext;
 
 	private final Set<String> allowMethodParams;
 
@@ -204,20 +190,7 @@ public final class RestContext extends Context {
 			this.logger = b.logger;
 			this.fullPath = b.fullPath;
 			this.contextPath = nullIfEmpty(b.contextPath);
-
-			this.htmlWidgets = Collections.unmodifiableMap(b.htmlWidgets);
-			this.htmlHeader = b.htmlHeader;
-			this.htmlNavLinks = b.htmlNavLinks;
-			this.htmlNav = b.htmlNav;
-			this.htmlAside = b.htmlAside;
-			this.htmlStyle = b.htmlStyle;
-			this.htmlStylesheet = b.htmlStylesheet;
-			this.htmlScript = b.htmlScript;
-			this.htmlHead = b.htmlHead;
-			this.htmlFooter = b.htmlFooter;
-			this.htmlNoWrap = b.htmlNoWrap;
-			this.htmlNoResultsMessage = b.htmlNoResultsMessage;
-			this.htmlTemplate = b.htmlTemplate;
+			this.htmlDocContext = new HtmlDocContext(resource, config);
 
 			//----------------------------------------------------------------------------------------------------
 			// Initialize the child resources.
@@ -482,11 +455,7 @@ public final class RestContext extends Context {
 		UrlEncodingSerializer urlEncodingSerializer;
 		UrlEncodingParser urlEncodingParser;
 		EncoderGroup encoders;
-		String clientVersionHeader = "", defaultCharset, paramFormat, htmlHeader, htmlNav, htmlAside, htmlStyle,
-				htmlStylesheet, htmlScript, htmlFooter, htmlNoResultsMessage;
-		String[] htmlNavLinks, htmlHead;
-		boolean htmlNoWrap;
-		HtmlDocTemplate htmlTemplate;
+		String clientVersionHeader = "", defaultCharset, paramFormat;
 
 		List<MediaType> supportedContentTypes, supportedAcceptTypes;
 		Map<String,String> defaultRequestHeaders = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
@@ -502,7 +471,6 @@ public final class RestContext extends Context {
 		Set<String> allowMethodParams = new LinkedHashSet<String>();
 		RestLogger logger;
 		String fullPath;
-		Map<String,Widget> htmlWidgets;
 		Object resourceResolver;
 		String contextPath;
 
@@ -605,25 +573,6 @@ public final class RestContext extends Context {
 			logger = sc.logger == null ? new RestLogger.NoOp() : resolve(resource, RestLogger.class, sc.logger);
 
 			fullPath = (sc.parentContext == null ? "" : (sc.parentContext.fullPath + '/')) + sc.path;
-
-			this.htmlWidgets = new LinkedHashMap<String,Widget>();
-			for (Class<? extends Widget> wc : sc.htmlWidgets) {
-				Widget w = resolve(resource, Widget.class, wc);
-				this.htmlWidgets.put(w.getName(), w);
-			}
-
-			htmlHeader = sc.htmlHeader;
-			htmlNavLinks = sc.htmlNavLinks;
-			htmlNav = sc.htmlNav;
-			htmlAside = sc.htmlAside;
-			htmlStyle = sc.htmlStyle;
-			htmlStylesheet = sc.htmlStylesheet;
-			htmlScript = sc.htmlScript;
-			htmlHead = sc.htmlHead;
-			htmlFooter = sc.htmlFooter;
-			htmlNoWrap = sc.htmlNoWrap;
-			htmlNoResultsMessage = sc.htmlNoResultsMessage;
-			htmlTemplate = resolve(resource, HtmlDocTemplate.class, sc.htmlTemplate);
 		}
 	}
 
@@ -889,160 +838,12 @@ public final class RestContext extends Context {
 	}
 
 	/**
-	 * The HTML page header contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#header()} annotation or {@link RestConfig#setHtmlHeader(String)} method.
-	 *
-	 * @return The HTML page header contents.
-	 */
-	public String getHtmlHeader() {
-		return htmlHeader;
-	}
-
-	/**
-	 * The HTML page nav section links.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#navlinks()} annotation or {@link RestConfig#setHtmlNavLinks(String[])} method.
-	 *
-	 * @return The HTML page nav section links.
-	 */
-	public String[] getHtmlNavLinks() {
-		return htmlNavLinks;
-	}
-
-	/**
-	 * The HTML page nav section contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#nav()} annotation or {@link RestConfig#setHtmlNav(String)} method.
-	 *
-	 * @return The HTML page nav section contents.
-	 */
-	public String getHtmlNav() {
-		return htmlNav;
-	}
-
-	/**
-	 * The HTML page aside section contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#aside()} annotation or {@link RestConfig#setHtmlAside(String)} method.
-	 *
-	 * @return The HTML page aside section contents.
-	 */
-	public String getHtmlAside() {
-		return htmlAside;
-	}
-
-	/**
-	 * The HTML page footer section contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#footer()} annotation or {@link RestConfig#setHtmlFooter(String)} method.
-	 *
-	 * @return The HTML page footer section contents.
-	 */
-	public String getHtmlFooter() {
-		return htmlFooter;
-	}
-
-	/**
-	 * The HTML page stylesheet URL.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#stylesheet()} annotation or {@link RestConfig#setHtmlStylesheet(String)} method.
-	 *
-	 * @return The HTML page CSS URL.
-	 */
-	public String getHtmlStylesheet() {
-		return htmlStylesheet;
-	}
-
-	/**
-	 * The HTML page CSS contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#style()} annotation or {@link RestConfig#setHtmlStyle(String)} method.
-	 *
-	 * @return The HTML page CSS contents.
-	 */
-	public String getHtmlStyle() {
-		return htmlStyle;
-	}
-
-	/**
-	 * The HTML page Javascript contents.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#script()} annotation or {@link RestConfig#setHtmlScript(String)} method.
-	 *
-	 * @return The HTML page Javascript contents.
-	 */
-	public String getHtmlScript() {
-		return htmlScript;
-	}
-
-	/**
-	 * The HTML page head content.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#head()} annotation or {@link RestConfig#setHtmlHead(String[])} method.
-	 *
-	 * @return The HTML page head content.
-	 */
-	public String[] getHtmlHead() {
-		return htmlHead;
-	}
-
-	/**
-	 * The HTML page nowrap setting.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#nowrap()} annotation or {@link RestConfig#setHtmlNoWrap(boolean)} method.
-	 *
-	 * @return The HTML page nowrap setting.
-	 */
-	public boolean getHtmlNoWrap() {
-		return htmlNoWrap;
-	}
-
-	/**
-	 * The HTML page template.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#template()} annotation or {@link RestConfig#setHtmlTemplate(Class)} method.
-	 *
-	 * @return The HTML page template.
-	 */
-	public HtmlDocTemplate getHtmlTemplate() {
-		return htmlTemplate;
-	}
-
-	/**
-	 * The HTML page no-results message.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#noResultsMessage()} annotation or {@link RestConfig#setHtmlNoResultsMessage(String)}
-	 * method.
-	 *
-	 * @return The HTML page no-results message.
-	 */
-	public String getHtmlNoResultsMessage() {
-		return htmlNoResultsMessage;
-	}
-
-	/**
-	 * The widgets used for resolving <js>"$W{...}"<js> variables.
-	 *
-	 * <p>
-	 * Defined by the {@link HtmlDoc#widgets()} annotation or {@link RestConfig#addHtmlWidget(Class)} method.
+	 * Returns the context values for the HTML doc view.
 	 *
-	 * @return The var resolver widgets as a map with keys being the name returned by {@link Widget#getName()}.
+	 * @return The context values for the HTML doc view.
 	 */
-	public Map<String,Widget> getHtmlWidgets() {
-		return htmlWidgets;
+	public HtmlDocContext getHtmlDocContext() {
+		return htmlDocContext;
 	}
 
 	/**