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/06/07 00:27:44 UTC

[1/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master 3bdc0d85a -> f4812b7ce


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/vars/UrlVar.java b/juneau-rest/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
new file mode 100644
index 0000000..8e0ddc8
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/vars/UrlVar.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * 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.vars;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * Resolver for resolving URL variables <js>"$U{name}"</js>.
+ * <p>
+ * The advantage of using this variable is that you can resolve URLs with special protocols such as <js>"servlet:/xxx"</js>.
+ * <p>
+ * See {@link UriResolver} for the kinds of URIs that can be resolved.
+ * <ul>
+ * 	<li>{@link RestResource#widgets() @RestResource.widgets()}
+ * 	<li>{@link RestMethod#widgets() @RestMethod.widgets()}
+ * 	<li>{@link RestConfig#addWidget(Class)}
+ * </ul>
+ * <p>
+ * Uses the URI resolver returned by {@link RestRequest#getUriResolver(UriResolution, UriRelativity)} with resolution
+ * 	{@link UriResolution#ROOT_RELATIVE} and relativity {@link UriRelativity#RESOURCE}.
+ *
+ * @see org.apache.juneau.svl
+ */
+public class UrlVar extends SimpleVar {
+
+	/**
+	 * The name of the session or context object that identifies the {@link RestRequest} object.
+	 */
+	public static final String SESSION_req = "req";
+
+	/** The name of this variable. */
+	public static final String NAME = "U";
+
+	/**
+	 * Constructor.
+	 */
+	public UrlVar() {
+		super(NAME);
+	}
+
+	@Override /* Parameter */
+	public String resolve(VarResolverSession session, String key) {
+		RestRequest req = session.getSessionObject(RestRequest.class, SESSION_req);
+		return req.getUriResolver(UriResolution.ROOT_RELATIVE, UriRelativity.RESOURCE).resolve(key);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java b/juneau-rest/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
new file mode 100644
index 0000000..3c73f8d
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/vars/WidgetVar.java
@@ -0,0 +1,63 @@
+// ***************************************************************************************************************************
+// * 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.vars;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * Resolver for resolving widget variables <js>"$W{name}"</js>.
+ * <p>
+ * Widgets are simple class that produce some sort of string based on a passed-in HTTP request.
+ * <p>
+ * They're registered via the following mechanisms:
+ * <ul>
+ * 	<li>{@link RestResource#widgets() @RestResource.widgets()}
+ * 	<li>{@link RestMethod#widgets() @RestMethod.widgets()}
+ * 	<li>{@link RestConfig#addWidget(Class)}
+ * </ul>
+ *
+ * @see org.apache.juneau.svl
+ */
+public class WidgetVar extends SimpleVar {
+
+	/**
+	 * The name of the session or context object that identifies the {@link RestRequest} object.
+	 */
+	public static final String SESSION_req = "req";
+
+	/** The name of this variable. */
+	public static final String NAME = "W";
+
+	/**
+	 * Constructor.
+	 */
+	public WidgetVar() {
+		super(NAME);
+	}
+
+	@Override /* Parameter */
+	public String resolve(VarResolverSession session, String key) {
+		RestRequest req = session.getSessionObject(RestRequest.class, SESSION_req);
+		Widget w = req.getWidgets().get(key);
+		if (w == null)
+			return "unknown-widget-"+key;
+		try {
+			return w.resolve(req);
+		} catch (Exception e) {
+			return "widget-error-"+e.getLocalizedMessage();
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/widget/ContentTypeLinksWidget.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/widget/ContentTypeLinksWidget.java b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/ContentTypeLinksWidget.java
new file mode 100644
index 0000000..23aabb5
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/ContentTypeLinksWidget.java
@@ -0,0 +1,48 @@
+// ***************************************************************************************************************************
+// * 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.widget;
+
+import static org.apache.juneau.dto.html5.HtmlBuilder.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.html5.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.rest.*;
+
+/**
+ * Widget that returns back a list of hyperlinks for rendering the contents of a page in a variety of content types.
+ * <p>
+ * The variable it resolves is <js>"$W{contentTypeLinks}"</js>.
+ */
+public class ContentTypeLinksWidget extends Widget {
+
+	@Override /* Widget */
+	public String getName() {
+		return "contentTypeLinks";
+	}
+
+	@Override /* Widget */
+	public String resolve(RestRequest req) throws Exception {
+		UriResolver uriResolver = req.getUriResolver(UriResolution.ROOT_RELATIVE, UriRelativity.RESOURCE);
+		P p = p();
+		List<MediaType> l = new ArrayList<MediaType>(req.getSerializerGroup().getSupportedMediaTypes());
+		Collections.sort(l);
+		for (MediaType mt : l)
+			p.child(a()._class("link").href(uriResolver.resolve("request:/?plainText=true&Accept="+mt)).child(mt)).child(br());
+		return HtmlSerializer.DEFAULT_SQ.serialize(p);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/widget/PoweredByJuneauWidget.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/widget/PoweredByJuneauWidget.java b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/PoweredByJuneauWidget.java
new file mode 100644
index 0000000..4878f26
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/PoweredByJuneauWidget.java
@@ -0,0 +1,35 @@
+// ***************************************************************************************************************************
+// * 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.widget;
+
+import org.apache.juneau.rest.*;
+
+/**
+ * Widget that places a powered-by-Juneau message on the page.
+ * <p>
+ * The variable it resolves is <js>"$W{poweredByJuneau}"</js>.
+ */
+public class PoweredByJuneauWidget extends Widget {
+
+	@Override /* Widget */
+	public String getName() {
+		return "poweredByJuneau";
+	}
+
+	@Override /* Widget */
+	public String resolve(RestRequest req) throws Exception {
+		return "<a href='http://juneau.apache.org'><img style='float:right;padding-right:20px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALoAAAA8CAYAAADR56A0AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAAtf0lEQVR4Ae19CWBVxdn2nDnn3C0JhCVAQoCELUAEFFDrHurSWvfa8NW27opL2BW1VuW6UDeUHXGpS93+j1hbterXVsvl629Ra8SAYQ1JgLATyHZzl7PM97xz7wk3GwQl/l/97+jNzJl5Z3vnmXfeeWfOgbGkS3IgyYEkB5IcSHIgyYEkB5IcSHIgyYEkB5IcSHLg+8IB4S/QqC+h53PPalo+ZHPjoiF76p8ecgXFiRVMJT/p/v05IBhT
 6Of0JDHsxP1v8JsbeDwb88Wz4/UJt5QYweVDL3Hp7F2NM2YbCjPCjDVG2A96z97yGYFdmcSs41lvsqzvjgMEaIBHOL75PrvYFmy362JW8t21ovM1SanbefKjUwqAXAHIG5bnnq2p4l0Fkz1sCENYwvJ6VE8kKmaglKsC6w9LgaOXmqT438YBAnnwTZYV9bEZBjWOs19CbFVZ77E/h0Lsww8YWzcpLsgSpXzi5Pgu+3RcJTqpK4o/YIZeyB3ELF7q1pXuYVNEIdBN22Iel+C8KSRKu91RfiJ10pEG32WHk3V9cw4441X7OhuMVdrPVTbG7WZjSbSHo4xpUEg5BpvrrCYSZvOCUfaOKlhoaz3bOeEWJudDYu1OeYlxXRU+bkAXfsYVP7P96GeRf1hJ74HsxJBhWUwo+xTOegHVmg6gY7Zv+qKu/wkTMSGw7ilgEvqbdP8uHCjzM9egIeyVFB/7OYHbwAjT2oxxjI0lgK5ypmAiWBj9ehvjC+D/Ael/t8NsbyjCtrp9bFyTwT7PuIrt+q76ffyAXgidu5hZe+8e/kqqxq8xe5rClW5vF7bic6ksw7SZ4cZcb6hnn3ebteXU76qDyXq+FQcIH6J2GesRFSxf0KrsZZdCchdZNhIAaAK4VEKJMgZ4WSGEm5DgB/B1SHoVPwA/qGlsL7IOhuRfH42yt6t3s0eGTWORb9XKTmQ+Ljq6o7LsmpZ3awpTr2kIW4wf4PvR71qNK4MaIsIWpoJlTWXhoL2B2rUSag5J9Q7aKBkcT0sMd0CejO4KDtBSWwwBZlpsTrqP/SJiMxUbzp4RSHK5DhOwAWRyjt8cjkl4CX6TQI8ESPoUYbPBKM/2etgoTIQePbqz5UjaSfm60sWb+c2rEIWFKunl228ceYId4UvrGwWzoopthpT1wZ3qqIZdnEX2ciVazxUjBP4Yyt+otoKEKv1+v9MOJR521JkWIJ86dao7gTahhGSwKzgA5osz85mbAZyhMMsIN
 rIe4RATFuSvBRFlQeu2AHrHt/FsI176lBansaNMQZxiIF+4CRs2g/HGIGEB2LdZz65oe+syv5VEl5uJ4mJpIhQGf8nNFW4Z0FEU9gV3sUyPqugRy7YUjSkujWmNhr3f5Yu+H2tEACuYXPRETU1N6pQpM3/FuYgCyC9Mnz49D2viXk3TjKBhDHlm4cK1U6fO+CnoOWg/hV8tBFZGhUy4SdeVHMjys6adj7AixctywO3RALXUyWFliWksJKJIspNIcn4UTIhzpL2kiYs0TnszwVIwGXpR+yWWpEdPx985kvQblVwyebycKOWT8u9LY9qExibBwmHlIGbvPtXgeU1NwrYiimpGuOnDGREmw2s9/FW1MVUHcgIdIwm9ePHielXlXwO7a6khQqhZ0OcuDxv2FVDtMikOoB5gc7UO4K+JP5OXdF3MAT+MDP3vYztqG9mDAhKafs0S25HoJNXjP0hvktTNNETbQupDqgvQgE4gzcvDMaB3cTfYN5boKwsKtAnPBYwtl4zNZ1H7wYOGJTwuqCeWWIVdyg+gyzEb0xaz2VY15jpQa4e5oiyMdUhKcxksKysjOcBs2xYWp1yOU6oVm1jG3RQD+S1UYQP3zIsflKCk60oOkISl8smSRr4VYmuwzdoC0TvMEszGuMbkN0n2BOlNtI60dyS9I+1b+9DdOTa12TJPF//5xkAvCASkymJHxDKYVbiJdS1k2hsAS1cKVzMRthQVu09VRNM11VUbtRZkvbB+G21CSad3+lVcXCwZ6XLxDU1N7pgaJIyv9+zZUwcaKysrq7ektdkqcLS3YWgeJ2/S7zoOALtS6JTdzlItL8uGyDlQW8sKU73sMaihP4yGmS4gdhzwtgB3XE8glaU5XU6b+DOajXgFVhuGjemAruvF4ZLj1R+O6Ezoi/E44i8pMdaOGze5R7rybKNiGjAfwUzOXua6faWqKWkC0llRmYlDIz3K7B31XB059tW1wQ5s59QOyVhSZfAj0U
 5xxCe7HX28mT5GVxhnbXutL6ZImHNj5bdH4cStgGGAwpMwwZy4zvjxtvIAK6B2sQIWoL50WCcSVWpVZ+sRrBDtKibLhRQKVAfVifrUApZBdR3RFbPixLqojZTH8VvnVb64hHm9A9n5IJig62yYprFzDINN2edmf+1jsbmwi3cDw3+KQtJkKVQYlYYf+U6YwE8uUUdvDsMS49GZAon+2vr17OaCl1kEWY/al1iJx/73mCW6HwsTgfyL4eN7G7V87iHwPrWbquME9FOAvJ9X1dKCEcvkqsJ1TdGp/1jqJo8tXhskdUdRDkvzhOY6jGcE8hVkyYltcgWUeGg8io14TmpOfAWQDMEf4im82IY4obw2Qap7YqDduiVtvKzYitJcbptiWkT4wYs5BQVciZWLvIEW6QJ1Mqx8rQcQz8c0kZR4/5z+Oj7qa14ZW1R85Adkl87xW1MLrT/rAX3xYazHo7FXYobJBEyDT/WLsJV41GBZOQ2z2CWBjM5IcDuiBs8UTx79HPA7cU4eSjGpI4xl9erHvPBxE6rrnGzLsRTvAKZkyCmLUxV1SiM3DFe6pWGWP6do9rWqqnigrtiQ5hxW13rB+EN575c+1YEkb1O1M4hfDR4xXBXCM7py01onLpHYiSvLyE+N+qwxmA1YQixbZ7okM3DirAhN4YoVivRM3UCTEwnSTINOI/th11zW0FH5kagixm0vW+/EHaZqGSIp6wCQVoKRuXn5QuHZAIKiCXvHhspNZY7EpnQnTOV+NXj4BK6oobFbN3zdstS2T7R6ug4EJ2B3UnNixcbNfsAIP3v9oJGZQrWGoCfY2pGL9TsWjv2N8QD6I3jw1rW/WEdCBCbabEXRx0Bp2L5o0aI29VP7KPdX17LTcSHvRTwNR5yNFZsD7HTEb0NwwSoIR5TxX7OkxnNzOFGiy1KR5uRBVpSPU0a2ob6JnTfiia49JT0mib4CgzsxUGyW5J46BvrElHphWSk42Y80sFV6N2u
 gT+geSHNYSRUsSiyCWy7rYFv/wdbzxndXlJK6o4MnJqFpMvFte/5mMyXry6FDs5Ty8v3Ii63t4aWbMVJXii2RZoz0MvUTFRVCSyL2x50u0cyx3649GKxbmzvivjGVG5cQnxPb4YTXDhzdw7KMT3HqF92Yl5ejbNrU4KQ5JTr+SoaViRWbZfn5Ljtk3YtJPK0bV3tQuhxIzPGRuSMOlDI2/4+VGx8jkDsCYn1+vq42WR/BtLQJ5Kd0VIc/DmheV5euq/o/DWb/CfRX/HLoUN1fXh4xuPhlT64/GYKS50alKKeNs9F3H5C5xxIHCv3+/n7Gotzmgy1NAOhqOjK0AToVAh6JNSYb6uJsGC0ZkN4cUp1BeDH5bKM6YjjREpgRklKdMlJs/OfENUtzoksAPyzRDMtdHx5l3ZFrV0e8QNq3dscE9ELoiVQj+vkQpDlrxJXEJlhLWJivxTXcm0i02ELTiOscsrOXRz+jlkefH/JRSR0NdHyJ77jRBQUqlnqz97Z9P8XgDVTBqaCpX48MTzCoCEhr1lEBclmOZamWD7BrsK1XFVv5HVjZQyjCImUbTIetVgEAxZQBumsxwJ4LsN+BJBoK2ZdAvE7Bo1encjWVIpui9lXwnkOdsj0INzsC+USoDKW5eXl2k/WXDE0btM80/1ZnWW9gtCsUgZ0KFyNgbL4uW9PnXpGbV1hoaOfmBwIHqZCQxyNcTUFaXTqldqTQ4QJEKJrcgh7qHBYPlCfs2SHG1yi2lQrLlOQP9Z0SyVbdaAhNV0X9KL/fZH4/ljRlP6jKsO+R7aEyEh0YI/kC3fkzHBI9h0pzMAzZXo1l40T0T5g74yCFR0N9IXu6EtvVoHUO4FFYM5iJy/g5z83heDxlwTxMR6PJhCxPzOF3ies00GNSLGB+nnPaOS5FXAZgGbCu6E22GUBrB6UI1QvgwwIlqExawd0HIqZpc/4YtXx/4OibJgfItrDvhsK2CqDZBubcCc4/SZMEPgkJ
 ORAON6Cc2LQRwMB/BRCvcuJb+a8CmL/P0lyz1gwe+XelYsP7cQlrTUS5RIuC7wwK+4+QznR9/k5EPde6TlQM7ATMNTkjcpD+Jar17THNH51YufGveE50ATwsXzs47/reqv7iQWZ8vCM7+/QB1dWhfXV1PBtoOR6OLHxo91/GVKxfd9TyAHJyC5Yt2HDnnXdunzdvXpOM6ODPhDfZRiTdSslf/JRl1nOWC3lSq5tYRjHIcpaBUTT9aFDak9rNcURHNHAO6MkHr+nCFzSrmOXlQT865G85vrFc3/5vpzm+isWkKUyo92qYxhG0J2RjLgplDW6y3BSKCxNMc1q91DTsZGota+7J5Z9XxEBV3EIitW466bHIZ63LzRuTrqrjDlrmZQDWpj6qfs26nLxLWdWmdwIMEhZAS8xr4JRJHtUJJYXiK3NyPFVVOSYrwEMAv5wqbWJVVbjBxYqqo8YvUMBdiH1/FVYHTF5VSufBo87N4HxAjR29EjPV3ZO7/vH1kLwzTti66ROnzvgkkxITaH8tnau+OtM6/cRtG1cLrFYlDQ3K+JLBMr1kfAWvKCmxx1Rseqk0d0QvwPG3+3n3XBzorh9pmkqDAsgcgyNiFNwmD0VgASEVhG0ZOtRdXY4tQgE9tXQFEDLOfoJSAHIcwB/VyeKJasLbbDe83V9eyDLCXpYGkCq4s4ItSRzARBn/EaAlqBN90JGT8U6Y8qL5LjAHvM2WBH75t0v+dAroznL9z0GnnQ514oIGyzJTVJLmFh3H98WSnxa0SZrLhQwaBAvVWuYHCrPnU6sJVEdrfWFBAYRlgAZ06iHLCnUTkb/mAqBQNyrBoVnI/05BfLK1Lgv1YtrRrGMsJyfHzK3CZAjQE1wVw0qAjeOm4oZ1uSM+BlPPLu07JmXsXpg6CyBzAhBGwp6+37J3j6nc/C/Kgjpx+sqnIfgJPZNzAI+V4VKoJGfsNIzHxgDkBDBIfpz3kYu/XFNChiY59EzzqYt4r
 fXSmJ1l8kS3plcvy3WwMziLlXi0v4pNt0sYW1Nebk5i5VZzv4+cMcayI9OI349hKf36ZmRpXshzUxtfq9hht2lAqySIolr4dAuDNESoINI54CcSyQH4rcP07PxoZQCzBlDmOSjVT4EucJ0C+v64rRYnQDN06OZhBfd4sMSjuavR5v+IkNUbfSVRjpCFvofAgnCDSJMAOFoHkAdWx4AJ0HQLWcqNmOMLcyurpLkJuuTC7qq2YG3O8BFK1eaNiRaM9vhBkrV1PNmRyWEmUKJH0y1Yz1iQ6iwdOjTbbSuXhG12tySSf5RnIHPvQ3umDCsP7Kc6nUkGYXbzflzQEJq5lEiHlpeTvt3GEStkv8rKaOtSg7DcTHtxRwLtkGmUqWT8eE2kpYkAPSS4Pvv3cz/ymlEdN4UswgyKaOtwxV+OYUZOjr4yJwdkh10BgsWBgHAsPodT2i8rIZ09O57pfXpmLXFr7PRItOduN7dOx7YC+wWfC4YIdAZyDT3h+EGgwQxDbUTP0IJm8NMkoOeY9I6noRZqZaylMNShVJv1T6y7K8JHBTpZWiZBLft77sQ8HNNfUYfNp0fR3E3CKsOge1O4lgU9HWobzkEhVl2KosJCEMTgPD6xMhCm/InLZnudcDaEYVO9LlXlSliIZQ5d0NRehYlwAbhVhLipGawALAo4yUf1CWwgkiBBG0dh4uzMry472DxhLP1WQqpuiN85hUFWveBlyn1NlnYz4n6bn5+vKgAdrQQ2i07ENY1/ji0vr3bA6+Rr7aPiZkAjTbYhvhkl+UcTgMXNnhRs15VVle0fkTuCMseg0YpKsxS5UpB6xqqqWqXGHikvtaXdxFaRRLt46FBXZnf9fiGsq5tMW8V+eHgwCustt1FOHMzYhtHeF9f4ZMMwRvApDXEO+KHAU6Np30xSnx5iE4Pi5CNuj8SAXlnAPBjW+MrYqlHH4fGoQM8owLXyAGoS/AafqmtBG4e/CvdAUViJnp8blaYNEl
 aC1DYeFWIHbNqPTKgoWedMkiO1Uw4CJCvRwGpwR6NtfTymctMWxHNMAH46rBVrB494GXy65f/m5d175qZAgx9pRyozMQ2ynJNE+3pQ3sTeqjpyn20soPRCCPj4vqAIL8m8nr9zYw3tJQqgZimVG7atHTzyQwzOdJD+dlRZmZTaPM3u5xM8BZtWufmj9kHdwlB17IgxlBobZsa6YzPaxLQQokZis/oYbHeu9nKTuQh8pA241wORiMlPq3wLR4YP3A+6Y21uXiUsgB5c84bJJ+bIKoOFNgUHkP9SKjet8IMP+B2xrdRGau9bmWnXQ/f/TZOBdRvjSiAGQoFfB8QkqSkMyY4TJSnB4+CmnkpgoyHQd+JpcnjlRMBKgDjKi3wQA9RIrBB9N3dnGbmM7Yg3/7h7RwS67DhAuCL7NC/u3E8KIgIHY55G296FA48mt8JGhoQJlRxiGB3EWUIUEn0A3oTOIkqAqRMuZg9flzvyfABxYI1lTqFM5bAXh6qrKWgKmy/P0Ph1LGr+HM/PzwHAaEmmRJ24DIc9qQRCawlJIMcBzZmQRx/stUxY4sxHiZ4GdF3uqCt7qEo6LqRJNSS7ulpFvSqDnRr9WZah6u+RTg6gvEt5jKhwqzDxoMYGev4mbn84zFP0VOJTFmA0A3IC++NYe5zyiO/0P6ESARO0EHWxPYhDQ74FoGArDp5IfIL/oI47JFG+NMyU3yNqxShZlJPavk+5nx0/vHfE8t0bgzi0JnRXghKKdAzQMZA7KkuM/aTKEOBj80imwT4Zk/IoNJ5GGMGqIHsmJw92czR5dMX0uhSrLzj8/wbogbiVo7uefp7GeE5EmNE07nIFRXQlVIAJ0FJoMCDIYUSMrdIuSB7Y51yvEytjmjGFOnaO/owBn7nPMjePrdz4HlEPA9icXGOr1n8G68Un4BNJ2OdJt6YNMqkwNje1Bhuma4XNBs0NSCeThgQ/mkSj4uvDtUyAPIhxOH9M5dZ9dNCTD1X
 EZtYdhyzlE9pUUl2JdY6u2PhnlLcF40wbYQl0bht1YdxkQuEZRC9XOhno/J/u3btbVpOVhlfTPsdh0mmF+fk+tg9o5niNOMG50yO8MTU17D0UzsQqtw2JbYSSC5Ie5o+fjKnauIrUqoPe+hZSPweZaPPLKjt9rwY50uoMS/9PVah32nRUhLMSgBlgJzATkEka06whP6ajU7O5VGGcyUBgJsGHaSYnSuxZliF1eaKjpsZouKa4okY0k7FDVFSXuDbMS6yleRMqtCtpW40lRq237SgXagV2nIWNWHawZEIHJ1kgTJzCkV393R9UrILq4Qf2/C0Yn1g2hcFV0nms0kF5uQDlhQhDTRn5AeSUh6YP0aBaTHqB/S8b7FN55tpBI04jYGYPrYbkBSfBPewNiLgGNBuQhW43StFCw4O4CGzdq02X/cKEzZsPOCAnM6au8FOgau2GCoE6FQ/GE13ElCPRKOQlo164nDOsdMjIE+i4fnP15j0jcvNI6pyCHytggSP2j2jIxScltUn2CT4Bx/SjndhwNuK5rdsbi8KJbYOi0hvIkskt6NA3LAe40Q1HVqQWic5DB3q7k9zavwVXJZ458eL9qmp+Dib0xXsCgyzo45wAD3MDMYYAK39gc0yy0zMBn7pH4LVwbIgn/GfBKNQ8KUjwyDJitHKiQHnB+LmFcGFDekj2E/1y+NS6ed/4uUOgE2NpE7kyvzC1sTF6bhCg9nCXGrbNVVgVc6Rkt6ImRgwHLDH9PAKM4IRoEbWmmMXumR+xZXEdV+H8hm5AdL1trQYvwB9BOqx0UPzREOKg8jnYdBlQfRsSpAQmAhUnoynoRdiynsVq8JTM1MEf0sn3lWXISYDtxK14n5UB6P/C+q9SnTSKNDNwLkAyjOhW+xR+UYOwb0J4BqlBpUz5Yy9Vm7YmZ9iJStWWrxzTawdVxgcutgchmvhmlNY/aLFyRPmD8Oe0Glxnb+F1hbSIBRWiVTrlJWer8o4+I1s+
 9gvtTryO8sZKaPFXQnWRpVSrIuUQ1IthhmVvsZjWC1cjeuIFSTnbCOwEcMgFCCKAPP5MTSSQq7jwBDXzK0sxKnFX4AKd8xSyVNAnISzS+yEZ1fgKALWG1iU1bJlS3W3RmuP40CHQi+N3SWqDYoKL69mmbZqGIGsQ/4wp+q9CgB5dOIecR3NImpNd3fjg/O0rP+6kNJcmRXlfpMm6FSBfh5PNi4/Ut7W5Iz/CFYurP8/Jv2tYedkeoqUDIxJ2mGz0QoY8OEk0+QEwSkZBgbIKm0bsGbAWB0RZdn7PiGJOxtWz/0adl1G+jhxs6rhUJiYjz0NkrYEZbXmU82mQpHOR56L9KA+soJUpNoHiBdHMpCCBrHTwiCvdhlg9YsemXWRebIVG4QcNfi0cnlEECiUkIYNTXgsiPMCcLemYPBSKh1sTdf6ZmMkm17A/5ffyTAUwdcOIPut2a1OjltUTI041SslNVzykdKcNqpTsJKzpAgh20Kb5dtjUA0z1pGFCQLG1h0NW/TcUNEwY938I5JFoIuaAGxzrkmFEJNApqvPN7TyllCrtkWcweomfkMHPwquf2ERoWshWygF01cVdA8K0KknNTIPWpepQY/C6qDab8nRSmstNmN0kLu+n6b0xyRdS3kqcbJLkRW/lj8IrEUdpELWL+2o6dBPzGvmMP82b0TiD6rp3B5gJ0LEfSeGJ0On9eA4UFMg6Ld36xSDNpWJU5epDhz4d1QmQLxygubzIcyXVOXrblg2Nlv3YQJf7JziAuoPKp7roliFZbehHYcQRaERp7shrhmiutwxdmUz5u9XVyTZQGj1/G0cFOHb0qpx/6STVqe72fqBFlZ1yynO73gvVB8U1jaZ1TkTxrIxaHl/EdLGI6WEIQ1h7EHbLH4UpLmzowlJSlEjUszoSdb3BuO8RZvv8QqT8JGL63q9vSLsvGPEtCZmuF5ui+irLTkGLcMiqdOMmXrS07NSC4jPPXP7q6af4qZVShQTFZ
 NjzXxk7tr/z3KketEPUrkSPMaUAEiqAOcxPJRMigd3gBsSXcjIsMIgn26iCbaCwuqluXm+FZl+0/YP1z4LRk0qKpTmunfqaox6Mm+VgXCraZdqGoUTfosRXqqqifgCnmRABUVUln6O9Uj/YfTC4ByLlNgDzKQIZSXRoGqCSq25ithZh6hNtYuORRTtNo8anmn+mZ6wA0WGtgOfUaSjGW9Wmshj5SWV6nuix+fs1THon99dc8wDkHmMrN9zX2tpDdKWDR87ow9X5FdHoeq9mPk1xYQ8ss7ADQk6jyM456jzxOpGabLmk/GCDfIDi6RS5Izu6k0/yoFU/nbQEX7br/oo3tlDcA0NvvFoILQPbMzAQphc4qZc36+uQ6JDkKocNzuBBw448rDLtNGiD3aJ4KdTN1f1CmJnQMQujll62uz71Nt2zp1em4p2Kr0Wkm5axC6qp6tE8P8Ew9sZblyf/5xnn6pMU5QFUZRV4T7/Zq6q3Lsg+5Ro8f0X1w9GAd5p/lKE9oEs1lTG/KMx+2tugbBjugsocsk2888m3oYZfkb4OQQupKdQeqluvtZqWX1L1wXw/NqC3lPiPCnLnLvfXucPH9lS1sw9Y5nMTKirkDUeSvtSwRIc6BUnKCYGAATXg2YGaa449eMRlrGLj25pqai6YokntS8zTOhyIW5DWwIzZX9NG7DLNuWRloXITJkBztoQ66YrvC5maPrU0d9RZYyvX/4OIRg/K/PG6bXvfyNa03wD0N4MZLwN3a+MFjIY8/2WWqmXvtoyVbpc9adjm8npKoxUHVwCowXqc9ohe0LYVL7qGl+9bjBVUB7obRLv1KbgLtBno80EVazEZZMF0Xo34EA7EFJwVYOTi43vEamXJ+IOTUO9AjWuGYRs4OcKmkVQNUldkTVjTIZNoO4PQXsMyX6rwVn6UG8r7MU47sclW3j2g1D3g01m9z9T5jK8/jG+x2W6U/ZtCqMewuklNbt74gqUVDSw8zue628
 P5jRec/OPe57kb54Ya3deHoqz/8OujLy179twFt+//+JWjtrwdghbMi6eLxwbf3f2eisfrTk/bnl5rpmb1QKeEFVxtCt4/lWuesMBipOAlOUj1Q2bo/su2vfMI5Z2DyeGPF3IkL+CoRYJfW0eKj1CfIXq6fNRRPjrIoTTw+OUdRvReDPL1eHzbwAvUdWgHVgZpfRiP4/T2yoCFRObnQlwHaQ7FMXYS6pTbXp79cVs9NrzL9zNjKrhwLej+IVUTTDqEJ5H+jUn2azdT7vJiW0WCGuDEwLPVu8zoLBx+YZsQs7xMZLFJjLbXQrHvlC3eG9JswyWaABppVZFiFuWhkxFcfMMEYLcAGDHbZGtFVO54MUpY7HwaPv8JyxQaQ1SttgmIaetEAfOrpqhvaIqYt2PhDHNVfQiqbD22xrmQ7ui2SCNG4t46i0SNRx+q+P3CmdmF3miKFy+6mwvKQ9vmvlwVkOMSK56W3tjKGxsk+b4w4hBbEqCVicL3Lz/pwjehks226rr/3TXAqBj2w4Pbh12874Q0s/+zb20/L+1nb3y0FBxoLovyH83JSloTPTnkzj6Gxn/hsi0cCSr/1QdW3pTo/rkYxMt9XM8P2RFs9a1AGq+f9bl+kqubEaqfUblwE9IhLY6sQiTWRW/JWFy1R1d+7cz0xOQOw5uGD+8dtm2PPIaHRF5bXd1Pc7trYRtv31QXLwnMVUqzh2fZHjs6Di9zdFhBOwmlQ4b0saKaNg4bSkpGWQQY4rYcs7Kc/H5QozJhTbC4oVXTxtUphmhBJyca4hTQ9tVchpkHc6dD05FPedHmTLw5FaIy8SwlMr1ZZXaPpHPLY9icTAOOS3EC8IOQvl7olyExZus4mF+P/sphQmYKcqzS9J9s+/QBd/xI1YQbGkw/tOIBSPj+Fiy8OsYQpwvVRrT+dN+Qin3GjtzMuVsH7WTxfK3KPOKj0z8QKUtGX3Gp0JWfXPfXQI/U7gcLt3x2woF/TB2q4Lb
 Qr4u+fPf5BNojlkmJbYDuL/Br/oDfnJt3zw3Y/D0OGYWNItvT06xf5MZxuIHTdCxWb9Qo6WtgV73RxcyDs7YsuOWoNR2BILHBhXhflEhXrFiBY7PYpMErYPJ9Udw5oe/AOIBhRIt3SFtIJ6IlGtq8wFFRBAIFtDyR1o8JUpaRIRLLdOpOjKMC4KggKkfW6bSN2v3hhRe6Pg+dahHPKN1xlEYXtv58ySUWtYfaRWkUdmjI76hOop8zZw51QtZLtIjT/HPmxM7cKeK7cYkYkW0pyrpntq5rj5vCsF0Q8zDN2hYPXYd7XjjHUEfP3zHvJTStmWffpJnEPxQgHs+7NO3cxxqKPZ7wBXV7fFtWzen1Qc8+yqWKyR+65as3X0HZxNcWPO1UfSSVHcJH8u7ZtDj/EfHbvLtee3j4PW/MGzlHPDz87kOP5N0dXDTifvHksDvkZo7o/Sw2kE7eY/YBzNZ5aLA7E+fQHI2e0v1gDDHRyUN+fEefGEXhljQxhjbTtFfXF+Mn607ZiekOmCmzE08vfTcXFg847XBoEukTaVukY8I6dTo0tO/wx9tLL5o78fBb9CkhvtNB6NXem7MfefvWgXPFbQMfFrdmz1l5e/bsH9/c/94Tiwb8+sOpA2ZfByxonS7wyITKCvyDEa/NvvCMBwZc98K8c69a+ugpV/3wydE/f2zRib/a+fgJhecfOfvh1DYNItXDP97v85f4m2DKx6tUfJ6pqF/CajojjI97QMKkQ8rvabDCryiKS5rn0HkVnWshWQ9X0XFo+vQ7ToZ2naNz8fF8RZFL/ZQpMwoAvQxscAIYUKlezJgx4zQcgebiasQGxK2ZOnXWSZjEo1ByxOt1/aW2ttZKSUnJQlo5Pm03YcmS+V8gTyaAQ5J072233dbD5UoZjvBnyKOUQbpPyxzwIyTjPVHlM/SpnFo5derMcyBG+qLuyoULF/6LaPEDjmRAoL3no709bUOUUF0E4L59s85jmuZtqlc/
 nvDiEw0zZ870TrOsbKRvmTJlSpZte+1ly57cU1Q0M1/4tBrE75ky5Y4R+MjkRoT5wYN1F2Dpgk3U3oR2fEVlIt5C+8dFo/ouoi8qKuqFC6OwjQo3Ph3yNeLW3jZz5mDNNA/48ZUz9EedkjXwPNixfbBwfDwRcaDRimprT520YMHqW++8sw/uZPFlTz5JZw/NfaJ+ddI5E0RoWeNn41bfRRqujwkRXRptiNzv8vTOc7nM57GkjTMNc8liNqfF6tbJOtojE7F/TODDT/z5N449tD0lT7eiuPShZkY1+xWFpdz/yMgbUhsiZsmhHmW7n4u9AN9eOVLst00Is26/GfEA3rbhZ9ZawSq87ezRVM8AOhdTOU7nFb0fPg/XDbklELFz7vTSgQGQkqyoaNZw/CMYV+NO2NagyyUnCb6v+DNUgJd9xAZYnK6+4Ya70qhx0HrPxgHNFrwfSrt1fHREK8e4DcTGqOmJJ55oMNPTVbxoewFeAKZPMMy8ffbsfjBWnGXbrlSi13XvOBxR/Bx1kz1eZGTkZNiKyMOb7e/jdxnejO8Wl6bnWFzssCzd0Z0RHVtpALzusAqOx86uFMfjdVRuv379rwZu8AUbc2dqqnEDxQWDHEqyei6FOXedqGlWPoVRz1lqxHiY+o+N3ESK27WroSfyn4QvDX+q2fyMounTTyX1iurEBLyS69YZRJeRkXEI9yBwZZ71jzS4KylOM+0zbV3vR+G+mdnX4ISRjCE7cKZ3fXyymDh8vKdo2qxzNcvqy0MGhINUldqsJBTfjiNw4yf7L8azydqlmQun4yvgc0zhNUKW+vym6gOz36h77JClaXeaImVwxFYWBHWxpp2yvnVUTY1dLCy3it1ikcH0BsP0ro2aGjRp7fV0t+/D7LqxMBZI50zKFnW22+kIgGcpyo/daurlOP38G75dMYFMDFAOD4aE8aml2FOsTZ5r7t34aA0kOZUhpV6Lkjt4wEDLSbF06dObcc5ejMP3s
 b5IpAeRg6U5SxY+XUyfYYDBYLs3LUJSG/G2C/ddxkFa+eiZwI3Y9TjyKaXnF/EMC9eOzIN1l4P2TR61zsJVAXPx4ie3Tp48GVJOjAMeS2tqaq8gel3HlSrG3LbNx0OCN+CrYMEHH3wQAhVXUi3WX1XxeXu4GChjfKMPnqKONFhVx+FePq0UOANkPZcsWfDhMkh/YLMJH0cdiGM1WBno9RusOdyGtaRZf6wClz45eLD2Ntx7raP0bt1gpmFi69KlT22zbe2PquAnUfy0abMuhsCsgIQeQtKYeIaJUobLRutfxKpBNOBPBLdxItRGwDF9yYIFH9JKBp429O07aCCBHTPtDyhjELdEATpXQ/lo/0F+By4RJILMf4T1n2Uvu3Bw/7Hva1xdgA/jvtFohS/asiulaDWbL69qNBrGww1R4+KXd957x//Z4Zeb9Q7K/8bRi/e8tD8UdT0AU+MjTYZ3Y9hyPxwxPFbQ0j/DbeRRhnD9bDKb3KHJtg3QZ8J2bkat8fhg4tPoUBEOh0qhwmzEl6BPwgnWiIc2zj1tzobfLgXAbQI5+cfSekdCzpo1awCYiPkjUnGl+TQqA4O0adq0mddOmTEDkoxnQ0TJAwLcTTxoWeHXn3lmfoUcQNBiuU8D3qTEpryqKkj9uGDpwoV/xgnSqdiNSkB4PClnA8CYo6IaE4nUF6z4eHETVxdtBV/rwC2C+CbVhZ0fAM6rTVWVJ7EEMLSXiqd/vgF7cXv7koXz3zAMg1QDgFmpRnsnAZjnYmLpUHe2L1u2rBGb9RTZB1sZa5piB+VHe3tjLXofq1Ad6i6gOJRNZ13DMUHG4IMShfh0wT8oHm40zN9YvXhQj5hnUwQuFaVRnylMDsCF2inoM9rQesQepx1Qu7xLlsyrzM3N9WGKuRcvXvAi2nMOssh3S51vXcpC2v6JTwKhXJy1+D/MrDOfvzxr8RKos89z7h0Mf+72netueG/PXatK2C0k+8gpf9x3T2nxvt
 mrY49d93d+9fyDT21/pqTedv3TtLwVUebNDJuuD3CldJ0pug3oMdiLG5DtC902QO9eXR95suz+/3ri6/s34Oporya3eB1qyqthRat5tPze/RLcBX7S7ZVjBTmxgMQm+Y2NjXsgEb24PlWKwXiT4hYvng9bL/8a3x7BXdbwC/jKrpRYQhjvEICIBqCUE8s21I9CoZAEEcU3NTUB6NrjFMYp3tJQg/tTCkPt2bBo0YKnF8+f/xHMA8v37dvngSpQZxjqK0sWLnwXatJKgMWFXxhS9K/InaFERTfKS85pbzAYbBDCjfbh8wDPPScHedGi+Suw0uwEDe/do/tzlEZO4+IVnM33wpn4h8uWzacJiK/Lhj+KRGqCWLFe49x+iuKeeuqpGkzuv0PNGoB/FeK9pfPnl91+++2pmLQvLVr09Af4LYUk/4JoPapaoSn2SgqTg3r1sWF0q6Yw8Q9HrTsxcdSePdOfpzifzxfC1dm/UNg2tSmos5TCDv8onOguznhi2BX9F1x8ab/5F12WtfhN7AeuwLngLvj4mEPT1U2N+374h51F95Uw2fcWkh/l0HNiXGLRxz2Mj+nsCZr8o1BUWx8Wnn11wr40YvHle+26fYnGlCNW7BDOzH906KwTHvY7xP58gCGmpnRlh1qUDfC1mYjx9rSgc9pIfmIeZ/WgeKgwbZY10CZuxjssk/InuCPRUVqL9MQ2JJRBwRZ0FJHY9ljbpH7cmrZ1HW3KSawzscz26qTCf9Tt6Z5XZC1+52f9l/4T/tsXZS74UUGGv3m1JJq4a1OXk/Bd+7f28+fclPXg+Tf1md73G7XNH5PWbEb+o1dNG/2YvNnnxB3vzpAa4qgiTtk0MPG4ZqYmDpxDF49rpqF4Z1DjvkxLzNte2Mnj5Ke6E+Oc+shPzO/Et9cHpJHdvkU5iXkTy3fyJ8Yl0iaEceOiGfhOW5r775RDdTttc/LG/eZ4J93xT4O6Wpi1cOD4LL/vjN4xA0Asjeo
 7XKdD/z3xYx2bcsLj/uknzJWzxR+T5N+T/iW70QkOdDgpOpH3uyT5du2cMubJ3NvGzLuXWpwE+Xc5bsm6uooD7erAdcKcEBRmGVVaVjjq282armp5stwkB46BA4mbseZsO82a4bbBX6GI4mL6gnLSJTnwPeNAfv7t/U7Iu+k38W4lpfn3bHz/f+1OG9XFNqLj8KWtLTGG0MlY0iU58O/PgTZAxqufJ2mm8mWsayuO6dTz358dyR58XznQBui4H7G7bOvv5GkeTLJJ/fz7OvLJfiU5kORAkgNJDiQ5kORAkgNJDiQ5kORAkgNJDiQ5kORA13LgfwDH2sLXsLj6ewAAAABJRU5ErkJggg=='></a>";
+	}
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/widget/Widget.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/widget/Widget.java b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/Widget.java
new file mode 100644
index 0000000..ec52998
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/widget/Widget.java
@@ -0,0 +1,44 @@
+// ***************************************************************************************************************************
+// * 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.widget;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Defines an interface for defining resolvers for <js>"$W{...}"</js> string variables.
+ * <p>
+ * Widgets are associated with resources through the following
+ * <ul>
+ * 	<li>{@link RestResource#widgets() @RestResource.widgets}
+ * 	<li>{@link RestMethod#widgets() @RestMethod.widgets}
+ * 	<li>{@link RestConfig#addWidget(Class)}
+ * </ul>
+ */
+public abstract class Widget {
+
+	/**
+	 * The widget key (i.e. The contents of the <js>"$W{...}"</js> variable).
+	 * @return The widget key.
+	 * 	Must not be <jk>null</jk>.
+	 */
+	public abstract String getName();
+
+	/**
+	 * Resolves the value for the variable.
+	 * @param req The HTTP request object.
+	 * @return The resolved value.
+	 * @throws Exception
+	 */
+	public abstract String resolve(RestRequest req) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/resources/org/apache/juneau/rest/styles/devops.css
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/resources/org/apache/juneau/rest/styles/devops.css b/juneau-rest/src/main/resources/org/apache/juneau/rest/styles/devops.css
index c0c45b7..4f43617 100644
--- a/juneau-rest/src/main/resources/org/apache/juneau/rest/styles/devops.css
+++ b/juneau-rest/src/main/resources/org/apache/juneau/rest/styles/devops.css
@@ -11,84 +11,85 @@
  * specific language governing permissions and limitations under the License.                                              *
  ***************************************************************************************************************************/
  
+/**********************************************************************************************************************/
+/**  Sections                                                                                                        **/
+/**********************************************************************************************************************/
 html {
-	height: 100%;
 }
-
 body {
-	background-color: rgb(59,75,84);
+	background-color: #3B4B54;
 	margin: 0px;
-	font-family: sans-serif;
-	font-size: 12px;
-	color: #26343F;
-	height: 100%;
+	font-size: 11pt;
+	font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
+	color: #B3B3B3;
+	height: 100%;	
+}
+header * {
+    font-size:11pt;
+	color: #B3B3B3;
+	background-color: #26343F;
+}
+nav {
+	margin: 10px 20px 10px 20px;
+	color: #94A3AB;
+}
+section {
+	display: table;
+	width: 100%;
+}
+article {
+	display: table-cell;
+}
+aside {
+	display: table-cell;
+	vertical-align: top;
+	padding: 20px 20px;
+}
+footer { 
+	padding: 10px;
+	width: 100%;
+	bottom: 0;
+	position: fixed;
+	background-color: #26343F;
 }
 
-/************************************************************************************/
-/**  Title/description section                                                     **/
-/************************************************************************************/
+/**********************************************************************************************************************/
+/**  Page elements                                                                                                   **/
+/**********************************************************************************************************************/
+
+/* Hyperlinks */
+.link {
+	font-size:10pt;
+	color: #94A3AB;
+	text-decoration: none;
+	margin: 0px 15px;
+	text-transform: uppercase;
+}
+.link:active, .link:hover {
+	color: white;
+	text-decoration: underline;
+}
+
+/* Title */
 h3.title {
-    font-size:12pt;
 	color: white;
 	margin: 0px;
 	padding: 10px 20px;
 	text-decoration: none;
 	font-weight: normal;
-	background-color: rgb(38,52,63);
 	border-bottom: 2px solid #34534B;
-	font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
 }
 
+/* Description */
 h5.description {
-    font-size:11pt;
 	color: #B3B3B3;
 	margin: 0;
 	padding: 10px 20px;
 	text-decoration: none;
 	font-weight: normal;
-	background-color: rgb(38,52,63);
 	border-bottom: 2px solid #34534B;
-	font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
 }
 
-
-
-/************************************************************************************/
-/**  Links section                                                                 **/
-/************************************************************************************/
-p.links {
-	margin-left: 20px;
-	margin-bottom: 0;
-	text-align: left;
-	color: #94A3AB;
-	text-transform: uppercase;
-}
-
-p.links a {
-	font-size:12px;
-	color: #94A3AB;
-	text-decoration: none;
-	margin-left: 15px;
-	margin-right: 15px;
-}
-
-p.links a:active, p.links a:hover {
-	font-size:12px;
-	color: white;
-	text-decoration: underline;
-}
-
-/* Use this to place links in description section aligned on the left.
-p.links {
-	margin-right: 20px;
-	margin-top: -30px;
-	text-align: right;
-	color: #94A3AB;
-	text-transform: uppercase;
-}
-*/
-
-
 /************************************************************************************/
 /**  Data section                                                                  **/
 /************************************************************************************/
@@ -105,15 +106,18 @@ div.data {
 	display: inline-block;
 	overflow-x: auto;
 	box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+	font-family: sans-serif;
+	color:#26343F;
+}
+div.data * {
+	font-size: 9pt;
+	color: #26343F;
 }
-
 div.data td {
 	vertical-align: top;
 	border-bottom:1px solid #d9dcde;
 	border-right:1px solid #d9dcde;
 	padding:0.2em 0.5em;
-	color:#26343F;
-	font-size:12px;
 }
 
 
@@ -125,38 +129,29 @@ table {
 	border: none;
 }
 
-p {
-	font-family: sans-serif;
-	font-size: 12px;
-}
-
-a {
+div.data a {
 	color: #116998;
 	text-decoration: none;
 }
 
-a:hover {
-	color: #26343F;
+div.data a:hover {
 	text-decoration: underline;
 }
 
-th, .header {
-	border-top:1px solid #d9dcde;
+div.data th, .header {
+	border-top:1px solid #D9DCDE;
 	padding: 4px 8px;
 	font-weight: bold;
 	text-align:center;
-	background-color: rgb(244,246,249);
-	font-family: sans-serif;
-	font-size: 12px;
-	color: #26343f;
+	background-color: #F4F6F9;
 }
 
 button {
 	border-left:1px solid #A1AFAC;
 	border-top:1px solid #A1AFAC;
 	color: white;
-	font-size: 12px;
-	background: #00b299;
+	font-size: 9pt;
+	background: #00B299;
     font-weight: bold;
     padding: 5px 20px;	
 	border-radius: 5px;
@@ -169,12 +164,12 @@ button:hover {
 	background-color: #66D1C2;
 }
 
-ul {
+div.data ul {
 	margin:0px;
 	padding-left:20px;
 }
 
-textarea, pre { 
+div.data textarea, pre { 
 	-moz-tab-size:3; 
 	-o-tab-size:3; 
 	-webkit-tab-size:3; 
@@ -195,8 +190,4 @@ iframe.output {
     overflow: hidden;
     width:100%;
 	min-height:400px;
-}
-
-input {
-}
-
+}
\ No newline at end of file



[3/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html
deleted file mode 100644
index 90441cf..0000000
--- a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-/***************************************************************************************************************************
- * 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.
- *
- ***************************************************************************************************************************/
- -->
-<html>
-<head>
-	<style type='text/css'>
-		@import '$R{servletURI}/style.css';
-	</style>
-	<script>
-		// Quick and dirty function to allow tabs in textarea.
-		function checkTab(e) {
-		    if (e.keyCode == 9) {
-			    var t = e.target;
-			    var ss = t.selectionStart, se = t.selectionEnd;
-	            t.value = t.value.slice(0,ss).concat('\t').concat(t.value.slice(ss,t.value.length));
-		        e.preventDefault();
-		    }
-		}	
-		// Load results from IFrame into this document.
-		function loadResults(buff) {
-			var doc = buff.contentDocument || buff.contentWindow.document;
-			var buffBody = doc.getElementById('data');
-			if (buffBody != null) {
-				document.getElementById('results').innerHTML = buffBody.innerHTML;
-			}
-		}
-	</script>
-</head>
-<body>
-	<h3 class='title'>Code Formatter</h3>
-	<div class='data'>
-		<form id='form' action='codeFormatter' method='POST' target='buff'>
-			<table>
-				<tr>
-					<th>Language: </th>
-					<td>
-						<select name='lang'>
-							<option value='java'>Java</option>
-							<option value='xml'>XML</option>
-						</select>
-					</td>
-					<td><button type='submit'>Submit</button><button type='reset'>Reset</button></td>
-				</tr>		
-				<tr>
-					<td colspan='3'><textarea name='code' style='min-width:800px;min-height:400px;font-family:Courier;font-size:9pt;' onkeydown='checkTab(event)'></textarea></td>
-				</tr>
-			</table>
-		</form>
-		<div id='results' class='monospace'>
-		</div>
-	</div>
-	<iframe name='buff' style='display:none' onload="parent.loadResults(this)"></iframe>
-</body>
-</html>
-

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
index 80a4aa9..81307c1 100644
--- a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
+++ b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootResourcesTest.java
@@ -41,13 +41,13 @@ public class RootResourcesTest extends RestTestcase {
 		ResourceDescription[] x = r.getResponse(ResourceDescription[].class);
 		assertEquals("helloWorld", x[0].getName().getName());
 		assertEquals(path + "/helloWorld", x[0].getName().getHref());
-		assertEquals("Hello World sample resource", x[0].getDescription());
+		assertEquals("Hello World", x[0].getDescription());
 
 		r = jsonClient.doOptions("");
 		ObjectMap x2 = r.getResponse(ObjectMap.class);
 		String s = x2.getObjectMap("info").getString("description");
 		if (debug) System.err.println(s);
-		assertTrue(s, s.startsWith("This is an example"));
+		assertTrue(s, s.startsWith("Example of a router resource page"));
 	}
 
 	//====================================================================================================
@@ -60,13 +60,13 @@ public class RootResourcesTest extends RestTestcase {
 		ResourceDescription[] x = r.getResponse(ResourceDescription[].class);
 		assertEquals("helloWorld", x[0].getName().getName());
 		assertEquals(path + "/helloWorld", x[0].getName().getHref());
-		assertEquals("Hello World sample resource", x[0].getDescription());
+		assertEquals("Hello World", x[0].getDescription());
 
 		r = jsonClient.doOptions("");
 		ObjectMap x2 = r.getResponse(ObjectMap.class);
 		String s = x2.getObjectMap("info").getString("description");
 		if (debug) System.err.println(s);
-		assertTrue(s, s.startsWith("This is an example"));
+		assertTrue(s, s.startsWith("Example of a router resource page"));
 		
 		client.closeQuietly();
 	}
@@ -81,13 +81,13 @@ public class RootResourcesTest extends RestTestcase {
 		ResourceDescription[] x = r.getResponse(ResourceDescription[].class);
 		assertEquals("helloWorld", x[0].getName().getName());
 		assertTrue(x[0].getName().getHref().endsWith("/helloWorld"));
-		assertEquals("Hello World sample resource", x[0].getDescription());
+		assertEquals("Hello World", x[0].getDescription());
 
 		r = jsonClient.doOptions("").accept("text/json");
 		ObjectMap x2 = r.getResponse(ObjectMap.class);
 		String s = x2.getObjectMap("info").getString("description");
 		if (debug) System.err.println(s);
-		assertTrue(s, s.startsWith("This is an example"));
+		assertTrue(s, s.startsWith("Example of a router resource page"));
 		
 		client.closeQuietly();
 	}
@@ -127,6 +127,6 @@ public class RootResourcesTest extends RestTestcase {
 		RestCall r = jsonClient.doOptions("");
 		Swagger o = r.getResponse(Swagger.class);
 		if (debug) System.err.println(o);
-		assertEquals("This is an example of a router resource that is used to access other resources.", o.getInfo().getDescription());
+		assertEquals("Example of a router resource page.", o.getInfo().getDescription());
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java
index 0e32ebe..eaeb701 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java
@@ -37,7 +37,9 @@ import org.apache.juneau.svl.vars.*;
  */
 @SuppressWarnings("serial")
 @RestResource(
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS'}"
+	),
 	config="$S{juneau.configFile}",
 	stylesheet="$C{REST/stylesheet,styles/juneau.css}"
 )

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java
index 8c66669..e48ccb5 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java
@@ -38,7 +38,9 @@ import org.apache.juneau.svl.vars.*;
  */
 @SuppressWarnings("serial")
 @RestResource(
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS'}"
+	),
 	config="$S{juneau.configFile}",
 	stylesheet="$C{REST/stylesheet,styles/juneau.css}"
 )

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceJena.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceJena.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceJena.java
index 4d971c9..efe3cd5 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceJena.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceJena.java
@@ -20,7 +20,9 @@ import org.apache.juneau.rest.jena.*;
  */
 @SuppressWarnings("serial")
 @RestResource(
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS'}"
+	),
 	config="$S{juneau.configFile}",
 	stylesheet="$C{REST/stylesheet,styles/juneau.css}"
 )

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
index 2b2c99c..b8d542a 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java
@@ -33,7 +33,9 @@ import org.apache.juneau.rest.annotation.Body;
 	path="/config",
 	title="Configuration",
 	description="Contents of configuration file.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',edit:'servlet:/edit'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',edit:'servlet:/edit'}"
+	)
 )
 public class ConfigResource extends Resource {
 	private static final long serialVersionUID = 1L;
@@ -81,9 +83,11 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="GET", path="/{section}",
 		description="Show config file section.",
-		parameters={
-			@Parameter(in="path", name="section", description="Section name.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="section", description="Section name.")
+			}
+		)
 	)
 	public ObjectMap getConfigSection(@Path("section") String section) throws Exception {
 		return getSection(section);
@@ -99,10 +103,12 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="GET", path="/{section}/{key}",
 		description="Show config file entry.",
-		parameters={
-			@Parameter(in="path", name="section", description="Section name."),
-			@Parameter(in="path", name="key", description="Entry name.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="section", description="Section name."),
+				@Parameter(in="path", name="key", description="Entry name.")
+			}
+		)
 	)
 	public String getConfigEntry(@Path("section") String section, @Path("key") String key) throws Exception {
 		return getSection(section).getString(key);
@@ -117,9 +123,11 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="POST", path="/",
 		description="Sets contents of config file from a FORM post.",
-		parameters={
-			@Parameter(in="formData", name="contents", description="New contents in INI file format.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="formData", name="contents", description="New contents in INI file format.")
+			}
+		)
 	)
 	public ConfigFile setConfigContentsFormPost(@FormData("contents") String contents) throws Exception {
 		return setConfigContents(new StringReader(contents));
@@ -134,9 +142,11 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="PUT", path="/",
 		description="Sets contents of config file.",
-		parameters={
-			@Parameter(in="body", description="New contents in INI file format.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="body", description="New contents in INI file format.")
+			}
+		)
 	)
 	public ConfigFile setConfigContents(@Body Reader contents) throws Exception {
 		ConfigFile cf2 = new ConfigFileBuilder().build(contents);
@@ -153,10 +163,12 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="PUT", path="/{section}",
 		description="Add or overwrite a config file section.",
-		parameters={
-			@Parameter(in="path", name="section", description="Section name."),
-			@Parameter(in="body", description="New contents for section as a simple map with string keys and values.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="section", description="Section name."),
+				@Parameter(in="body", description="New contents for section as a simple map with string keys and values.")
+			}
+		)
 	)
 	public ObjectMap setConfigSection(@Path("section") String section, @Body Map<String,String> contents) throws Exception {
 		getConfigContents().setSection(section, contents);
@@ -174,11 +186,13 @@ public class ConfigResource extends Resource {
 	 */
 	@RestMethod(name="PUT", path="/{section}/{key}",
 		description="Add or overwrite a config file entry.",
-		parameters={
-			@Parameter(in="path", name="section", description="Section name."),
-			@Parameter(in="path", name="key", description="Entry name."),
-			@Parameter(in="body", description="New value as a string.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="section", description="Section name."),
+				@Parameter(in="path", name="key", description="Entry name."),
+				@Parameter(in="body", description="New value as a string.")
+			}
+		)
 	)
 	public String setConfigSection(@Path("section") String section, @Path("key") String key, @Body String value) throws Exception {
 		getConfigContents().put(section, key, value, false);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index 8f67665..060a7e6 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -57,7 +57,9 @@ import org.apache.juneau.utils.*;
 	title="File System Explorer",
 	description="Contents of $R{attribute.path}",
 	messages="nls/DirectoryResource",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS'}"
+	),
 	properties={
 		@Property(name=HTML_uriAnchorText, value=PROPERTY_NAME),
 		@Property(name=REST_allowMethodParam, value="*"),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
index 865c35c..52d4783 100755
--- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
@@ -87,7 +87,13 @@ public class LogsResource extends Resource {
 	 * @return The log file.
 	 * @throws Exception
 	 */
-	@RestMethod(name="GET", path="/*", responses={@Response(200),@Response(404)})
+	@RestMethod(
+		name="GET", 
+		path="/*", 
+		swagger=@MethodSwagger(
+			responses={@Response(200),@Response(404)}
+		)
+	)	
 	public Object getFileOrDirectory(RestRequest req, RestResponse res, @Properties ObjectMap properties, @PathRemainder String path) throws Exception {
 
 		File f = getFile(path);
@@ -101,12 +107,12 @@ public class LogsResource extends Resource {
 					l.add(new FileResource(fc, fUrl));
 				}
 			}
-			res.setPageText(new StringMessage("Contents of {0}", f.getAbsolutePath()));
-			properties.put(HTMLDOC_text, "Contents of " + f.getAbsolutePath());
+			res.setHtmlDescription(new StringMessage("Contents of {0}", f.getAbsolutePath()));
+			properties.put(HTMLDOC_description, "Contents of " + f.getAbsolutePath());
 			return l;
 		}
 
-		res.setPageText(new StringMessage("File details on {0}", f.getAbsolutePath()));
+		res.setHtmlDescription(new StringMessage("File details on {0}", f.getAbsolutePath()));
 		return new FileResource(f, new URL(req.getTrimmedRequestURL().toString()));
 	}
 
@@ -125,7 +131,13 @@ public class LogsResource extends Resource {
 	 * @param severity Optional severity filter.  Only show log entries with the specified severity.  Example: "&amp;severity=(ERROR,WARN)".
 	 * @throws Exception
 	 */
-	@RestMethod(name="VIEW", path="/*", responses={@Response(200),@Response(404)})
+	@RestMethod(
+		name="VIEW", 
+		path="/*",
+		swagger=@MethodSwagger(
+			responses={@Response(200),@Response(404)}
+		)
+	)
 	@SuppressWarnings("nls")
 	public void viewFile(RestRequest req, RestResponse res, @PathRemainder String path, @Properties ObjectMap properties, @Query("highlight") boolean highlight, @Query("start") String start, @Query("end") String end, @Query("thread") String thread, @Query("loggers") String[] loggers, @Query("severity") String[] severity) throws Exception {
 
@@ -198,7 +210,14 @@ public class LogsResource extends Resource {
 	 * @return The parsed contents of the log file.
 	 * @throws Exception
 	 */
-	@RestMethod(name="PARSE", path="/*", converters=Queryable.class, responses={@Response(200),@Response(404)})
+	@RestMethod(
+		name="PARSE", 
+		path="/*", 
+		converters=Queryable.class, 
+		swagger=@MethodSwagger(
+			responses={@Response(200),@Response(404)}
+		)
+	)
 	public LogParser viewParsedEntries(RestRequest req, @PathRemainder String path, @Query("start") String start, @Query("end") String end, @Query("thread") String thread, @Query("loggers") String[] loggers, @Query("severity") String[] severity) throws Exception {
 
 		File f = getFile(path);
@@ -218,7 +237,13 @@ public class LogsResource extends Resource {
 	 * @return The contents of the log file.
 	 * @throws Exception
 	 */
-	@RestMethod(name="DOWNLOAD", path="/*", responses={@Response(200),@Response(404)})
+	@RestMethod(
+		name="DOWNLOAD", 
+		path="/*", 
+		swagger=@MethodSwagger(
+			responses={@Response(200),@Response(404)}
+		)
+	)
 	public Object downloadFile(RestResponse res, @PathRemainder String path) throws Exception {
 
 		File f = getFile(path);
@@ -238,7 +263,13 @@ public class LogsResource extends Resource {
 	 * @return A redirect object to the root.
 	 * @throws Exception
 	 */
-	@RestMethod(name="DELETE", path="/*", responses={@Response(200),@Response(404)})
+	@RestMethod(
+		name="DELETE", 
+		path="/*",
+		swagger=@MethodSwagger(
+			responses={@Response(200),@Response(404)}
+		)
+	)
 	public Object deleteFile(@PathRemainder String path) throws Exception {
 
 		File f = getFile(path);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
----------------------------------------------------------------------
diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
index 90f2cf8..7f70117 100644
--- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
+++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
@@ -1944,12 +1944,11 @@ public final class RestCall {
 	/**
 	 * Sets <code>Debug: value</code> header on this request.
 	 *
-	 * @param value The debug value.
 	 * @return This object (for method chaining).
 	 * @throws RestCallException
 	 */
-	public RestCall debug(boolean value) throws RestCallException {
-		header("Debug", value);
+	public RestCall debug() throws RestCallException {
+		header("Debug", true);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index 5dc2ac6..23b31bf 100644
--- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -1481,10 +1481,10 @@ public class RestClientBuilder extends CoreObjectBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public RestClientBuilder debug(boolean value) {
-		super.debug(value);
-		this.debug = value;
-		header("Debug", value);
+	public RestClientBuilder debug() {
+		super.debug();
+		this.debug = true;
+		header("Debug", true);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/package.html
----------------------------------------------------------------------
diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/package.html b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/package.html
index 0f685ef..0696559 100644
--- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/package.html
+++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/package.html
@@ -632,7 +632,7 @@
 	<h3 class='topic' onclick='toggle(this)'>1.5 - Debugging</h3>
 	<div class='topic'>
 		<p>
-			Use the {@link org.apache.juneau.rest.client.RestClientBuilder#debug(boolean)} method to enable logging for HTTP requests
+			Use the {@link org.apache.juneau.rest.client.RestClientBuilder#debug()} method to enable logging for HTTP requests
 			made from the client.
 		</p>
 		<p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HtmlPropertiesResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HtmlPropertiesResource.java b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HtmlPropertiesResource.java
index 648008c..e75ea5a 100644
--- a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HtmlPropertiesResource.java
+++ b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/HtmlPropertiesResource.java
@@ -39,9 +39,11 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 
 	@RestResource(
 		path="/Normal",
-		pageTitle="Normal-title",
-		pageText="Normal-text",
-		pageLinks="{link:'Normal-links'}"
+		htmldoc=@HtmlDoc(
+			title="Normal-title",
+			description="Normal-text",
+			links="{link:'Normal-links'}"
+		)
 	)
 	public static class Normal extends RestServletDefault {
 
@@ -56,7 +58,14 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		// Values pulled from @RestResource(pageX), overridden by @RestMethod(pageX) annotations.
 		//----------------------------------------------------------------------------------------------------
-		@RestMethod(path="/test2", pageTitle="Normal.test2-title", pageText="Normal.test2-text", pageLinks="{link:'Normal.test2-links'}")
+		@RestMethod(
+			path="/test2",
+			htmldoc=@HtmlDoc(
+				title="Normal.test2-title",
+				description="Normal.test2-text",
+				links="{link:'Normal.test2-links'}"
+			)
+		)
 		public String test2() {
 			return "OK";
 		}
@@ -66,9 +75,9 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		@RestMethod(path="/test3")
 		public String test3(RestResponse res) {
-			res.setPageTitle("Normal.test3-title");
-			res.setPageText("Normal.test3-text");
-			res.setPageLinks("{link:'Normal.test3-links'}");
+			res.setHtmlTitle("Normal.test3-title");
+			res.setHtmlDescription("Normal.test3-text");
+			res.setHtmlLinks("{link:'Normal.test3-links'}");
 			return "OK";
 		}
 
@@ -78,7 +87,7 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		@RestMethod(path="/test4")
 		public String test4(RestResponse res) {
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_title, "Normal.test4-title");
-			res.setProperty(HtmlDocSerializerContext.HTMLDOC_text, "Normal.test4-text");
+			res.setProperty(HtmlDocSerializerContext.HTMLDOC_description, "Normal.test4-text");
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_links, "{link:'Normal.test4-links'}");
 			return "OK";
 		}
@@ -91,9 +100,9 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 
 		@Override
 		public void init(RestConfig config) throws Exception {
-			config.setPageTitle("NormalInit-title");
-			config.setPageText("NormalInit-text");
-			config.setPageLinks("{link:'NormalInit-links'}");
+			config.setHtmlTitle("NormalInit-title");
+			config.setHtmlDescription("NormalInit-text");
+			config.setHtmlLinks("{link:'NormalInit-links'}");
 			super.init(config);
 		}
 
@@ -108,7 +117,14 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		// Values pulled from RestConfig.setX() methods, overridden by @RestMethod(pageX) annotations.
 		//----------------------------------------------------------------------------------------------------
-		@RestMethod(path="/test2", pageTitle="NormalInit.test2-title", pageText="NormalInit.test2-text", pageLinks="{link:'NormalInit.test2-links'}")
+		@RestMethod(
+			path="/test2",
+			htmldoc=@HtmlDoc(
+				title="NormalInit.test2-title",
+				description="NormalInit.test2-text",
+				links="{link:'NormalInit.test2-links'}"
+			)
+		)
 		public String test2() {
 			return "OK";
 		}
@@ -118,9 +134,9 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		@RestMethod(path="/test3")
 		public String test3(RestResponse res) {
-			res.setPageTitle("NormalInit.test3-title");
-			res.setPageText("NormalInit.test3-text");
-			res.setPageLinks("{link:'NormalInit.test3-links'}");
+			res.setHtmlTitle("NormalInit.test3-title");
+			res.setHtmlDescription("NormalInit.test3-text");
+			res.setHtmlLinks("{link:'NormalInit.test3-links'}");
 			return "OK";
 		}
 
@@ -130,7 +146,7 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		@RestMethod(path="/test4")
 		public String test4(RestResponse res) {
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_title, "NormalInit.test4-title");
-			res.setProperty(HtmlDocSerializerContext.HTMLDOC_text, "NormalInit.test4-text");
+			res.setProperty(HtmlDocSerializerContext.HTMLDOC_description, "NormalInit.test4-text");
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_links, "{link:'NormalInit.test4-links'}");
 			return "OK";
 		}
@@ -164,8 +180,8 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		@RestMethod(path="/test3")
 		public String test3(RestResponse res) {
-			res.setPageTitle("NormalDefaulting.test3-title");
-			res.setPageText("NormalDefaulting.test3-text");
+			res.setHtmlTitle("NormalDefaulting.test3-title");
+			res.setHtmlDescription("NormalDefaulting.test3-text");
 			return "OK";
 		}
 
@@ -175,7 +191,7 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		@RestMethod(path="/test4")
 		public String test4(RestResponse res) {
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_title, "NormalDefaulting.test4-title");
-			res.setProperty(HtmlDocSerializerContext.HTMLDOC_text, "NormalDefaulting.test4-text");
+			res.setProperty(HtmlDocSerializerContext.HTMLDOC_description, "NormalDefaulting.test4-text");
 			return "OK";
 		}
 	}
@@ -199,7 +215,14 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		// Values pulled from parent @RestResource(path/title), overridden by @RestMethod(pageX) annotations.
 		//----------------------------------------------------------------------------------------------------
 		@Override
-		@RestMethod(path="/test2", pageTitle="NormalSubclassed1.test2-title", pageText="NormalSubclassed1.test2-text", pageLinks="{link:'NormalSubclassed1.test2-links'}")
+		@RestMethod(
+			path="/test2",
+			htmldoc=@HtmlDoc(
+				title="NormalSubclassed1.test2-title",
+				description="NormalSubclassed1.test2-text",
+				links="{link:'NormalSubclassed1.test2-links'}"
+			)
+		)
 		public String test2() {
 			return "OK";
 		}
@@ -207,9 +230,11 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 
 	@RestResource(
 		path="/NormalSubclassed2",
-		pageTitle="NormalSubclassed2-title",
-		pageText="NormalSubclassed2-text",
-		pageLinks="{link:'NormalSubclassed2-links'}"
+		htmldoc=@HtmlDoc(
+			title="NormalSubclassed2-title",
+			description="NormalSubclassed2-text",
+			links="{link:'NormalSubclassed2-links'}"
+		)
 	)
 	public static class NormalSubclassed2 extends Normal {
 
@@ -226,7 +251,14 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		// Values pulled from parent @RestResource(path/title), overridden by @RestMethod(pageX).
 		//----------------------------------------------------------------------------------------------------
 		@Override
-		@RestMethod(path="/test2", pageTitle="NormalSubclassed2.test2-title", pageText="NormalSubclassed2.test2-text", pageLinks="{link:'NormalSubclassed2.test2-links'}")
+		@RestMethod(
+			path="/test2",
+			htmldoc=@HtmlDoc(
+				title="NormalSubclassed2.test2-title",
+				description="NormalSubclassed2.test2-text",
+				links="{link:'NormalSubclassed2.test2-links'}"
+			)
+		)
 		public String test2() {
 			return "OK";
 		}
@@ -235,9 +267,11 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 	@RestResource(
 		path="/LocalizedExplicit",
 		messages="HtmlPropertiesResource",
-		pageTitle="$L{pageTitle}",
-		pageText="$L{pageText}",
-		pageLinks="$L{pageLinks}"
+		htmldoc=@HtmlDoc(
+			title="$L{pageTitle}",
+			description="$L{pageText}",
+			links="$L{pageLinks}"
+		)
 	)
 	public static class LocalizedExplicit extends RestServletDefault {
 
@@ -252,7 +286,12 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		// Values pulled from @RestResource(pageX) with $L variables, overridden by @RestMethod(pageX) with $L variables.
 		//----------------------------------------------------------------------------------------------------
-		@RestMethod(path="/test2", pageTitle="$L{test2.pageTitle}", pageText="$L{test2.pageText}", pageLinks="$L{test2.pageLinks}")
+		@RestMethod(
+			path="/test2",
+			htmldoc=@HtmlDoc(
+				title="$L{test2.pageTitle}", description="$L{test2.pageText}", links="$L{test2.pageLinks}"
+			)
+		)
 		public String test2() {
 			return "OK";
 		}
@@ -262,9 +301,9 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		//----------------------------------------------------------------------------------------------------
 		@RestMethod(path="/test3")
 		public String test3(RestResponse res) {
-			res.setPageTitle("$L{test3.pageTitle}");
-			res.setPageText("$L{test3.pageText}");
-			res.setPageLinks("$L{test3.pageLinks}");
+			res.setHtmlTitle("$L{test3.pageTitle}");
+			res.setHtmlDescription("$L{test3.pageText}");
+			res.setHtmlLinks("$L{test3.pageLinks}");
 			return "OK";
 		}
 
@@ -274,7 +313,7 @@ public class HtmlPropertiesResource extends RestServletGroupDefault {
 		@RestMethod(path="/test4")
 		public String test4(RestResponse res) {
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_title, "$L{test4.pageTitle}");
-			res.setProperty(HtmlDocSerializerContext.HTMLDOC_text, "$L{test4.pageText}");
+			res.setProperty(HtmlDocSerializerContext.HTMLDOC_description, "$L{test4.pageText}");
 			res.setProperty(HtmlDocSerializerContext.HTMLDOC_links, "$L{test4.pageLinks}");
 			return "OK";
 		}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/NlsResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/NlsResource.java b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/NlsResource.java
index d9ce1e7..0048e8e 100644
--- a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/NlsResource.java
+++ b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/NlsResource.java
@@ -48,24 +48,26 @@ public class NlsResource extends RestServletGroupDefault {
 		@RestMethod(
 			name="POST", path="/{a}",
 			description="Test1.c",
-			parameters={
-				@Parameter(in="path", name="a", description="Test1.d"),
-				@Parameter(in="query", name="b", description="Test1.e"),
-				@Parameter(in="body", description="Test1.f"),
-				@Parameter(in="header", name="D", description="Test1.g"),
-				@Parameter(in="path", name="a2", description="Test1.h"),
-				@Parameter(in="query", name="b2", description="Test1.i"),
-				@Parameter(in="header", name="D2", description="Test1.j"),
-			},
-			responses={
-				@Response(200),
-				@Response(value=201,
-					description="Test1.l",
-					headers={
-						@Parameter(in="foo", name="bar", description="Test1.m"),
-					}
-				)
-			}
+			swagger=@MethodSwagger(
+				parameters={
+					@Parameter(in="path", name="a", description="Test1.d"),
+					@Parameter(in="query", name="b", description="Test1.e"),
+					@Parameter(in="body", description="Test1.f"),
+					@Parameter(in="header", name="D", description="Test1.g"),
+					@Parameter(in="path", name="a2", description="Test1.h"),
+					@Parameter(in="query", name="b2", description="Test1.i"),
+					@Parameter(in="header", name="D2", description="Test1.j"),
+				},
+				responses={
+					@Response(200),
+					@Response(value=201,
+						description="Test1.l",
+						headers={
+							@Parameter(in="foo", name="bar", description="Test1.m"),
+						}
+					)
+				}
+			)
 		)
 		public String test1(@Path("a") String a, @Query("b") String b, @Body String c, @Header("D") String d,
 				@Path("e") String e, @Query("f") String f, @Header("g") String g) {
@@ -166,24 +168,26 @@ public class NlsResource extends RestServletGroupDefault {
 		@RestMethod(
 			name="POST", path="/{a}",
 			description="$L{foo}",
-			parameters={
-				@Parameter(in="path", name="a", description="$L{foo}"),
-				@Parameter(in="query", name="b", description="$L{foo}"),
-				@Parameter(in="body", description="$L{foo}"),
-				@Parameter(in="header", name="D", description="$L{foo}"),
-				@Parameter(in="path", name="a2", description="$L{foo}"),
-				@Parameter(in="query", name="b2", description="$L{foo}"),
-				@Parameter(in="header", name="D2", description="$L{foo}")
-			},
-			responses={
-				@Response(200),
-				@Response(value=201,
-					description="$L{foo}",
-					headers={
-						@Parameter(in="foo", name="bar", description="$L{foo}"),
-					}
-				)
-			}
+			swagger=@MethodSwagger(
+				parameters={
+					@Parameter(in="path", name="a", description="$L{foo}"),
+					@Parameter(in="query", name="b", description="$L{foo}"),
+					@Parameter(in="body", description="$L{foo}"),
+					@Parameter(in="header", name="D", description="$L{foo}"),
+					@Parameter(in="path", name="a2", description="$L{foo}"),
+					@Parameter(in="query", name="b2", description="$L{foo}"),
+					@Parameter(in="header", name="D2", description="$L{foo}")
+				},
+				responses={
+					@Response(200),
+					@Response(value=201,
+						description="$L{foo}",
+						headers={
+							@Parameter(in="foo", name="bar", description="$L{foo}"),
+						}
+					)
+				}
+			)
 		)
 		public String test6(@Path("a") String a, @Query("b") String b, @Body String c, @Header("D") String d,
 				@Path("e") String e, @Query("f") String f, @Header("g") String g) {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HtmlPropertiesTest.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HtmlPropertiesTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HtmlPropertiesTest.java
index c3e3cf0..acf2b8c 100644
--- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HtmlPropertiesTest.java
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/HtmlPropertiesTest.java
@@ -258,28 +258,4 @@ public class HtmlPropertiesTest extends RestTestcase {
 		assertTrue(s.contains("LocalizedExplicit.test4.nls.pageText"));
 		assertTrue(s.contains("LocalizedExplicit.test4.nls.pageLinks"));
 	}
-
-	//----------------------------------------------------------------------------------------------------
-	// Values pulled from resource bundle.
-	//----------------------------------------------------------------------------------------------------
-	@Test
-	public void testLocalizedImplicitTest1() throws Exception {
-		RestClient client = TestMicroservice.DEFAULT_CLIENT;
-		String s = client.doGet("/testHtmlProperties/LocalizedImplicit/test1").accept("text/html").getResponseAsString();
-		assertTrue(s.contains("LocalizedImplicit.nls.pageTitle"));
-		assertTrue(s.contains("LocalizedImplicit.nls.pageText"));
-		assertTrue(s.contains("LocalizedImplicit.nls.pageLinks"));
-	}
-
-	//----------------------------------------------------------------------------------------------------
-	// Values pulled from resource bundle, overridden by values in resource bundle at method level.
-	//----------------------------------------------------------------------------------------------------
-	@Test
-	public void testLocalizedImplicitTest2() throws Exception {
-		RestClient client = TestMicroservice.DEFAULT_CLIENT;
-		String s = client.doGet("/testHtmlProperties/LocalizedImplicit/test2").accept("text/html").getResponseAsString();
-		assertTrue(s.contains("LocalizedImplicit.test2.nls.pageTitle"));
-		assertTrue(s.contains("LocalizedImplicit.test2.nls.pageText"));
-		assertTrue(s.contains("LocalizedImplicit.test2.nls.pageLinks"));
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/RestTestcase.java
----------------------------------------------------------------------
diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/RestTestcase.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/RestTestcase.java
index 521c965..983180e 100644
--- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/RestTestcase.java
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/RestTestcase.java
@@ -55,7 +55,7 @@ public class RestTestcase {
 	 */
 	protected RestClient getDebugClient(String label, Serializer serializer, Parser parser) {
 		if (! clients.containsKey(label))
-			clients.put(label, TestMicroservice.client(serializer, parser).debug(true).build());
+			clients.put(label, TestMicroservice.client(serializer, parser).debug().build());
 		return clients.get(label);
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
index efb827c..69d6814 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -14,6 +14,7 @@ package org.apache.juneau.rest;
 
 import static javax.servlet.http.HttpServletResponse.*;
 import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
+import static org.apache.juneau.html.HtmlDocSerializerContext.*;
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.Utils.*;
 import static org.apache.juneau.rest.RestContext.*;
@@ -29,9 +30,11 @@ 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.*;
@@ -63,7 +66,11 @@ class CallMethod implements Comparable<CallMethod>  {
 	private final org.apache.juneau.rest.annotation.Parameter[] parameters;
 	private final Response[] responses;
 	private final RestContext context;
-	private final String pageTitle, pageText, pageLinks;
+	private final String htmlTitle, htmlDescription, htmlHeader, htmlLinks, htmlNav, htmlAside, htmlFooter, htmlCss,
+		htmlCssUrl, htmlNoResultsMessage;
+	private final boolean htmlNoWrap;
+	private final HtmlDocTemplate htmlTemplate;
+	private final Map<String,Widget> widgets;
 
 	CallMethod(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 		Builder b = new Builder(servlet, method, context);
@@ -94,13 +101,26 @@ class CallMethod implements Comparable<CallMethod>  {
 		this.priority = b.priority;
 		this.parameters = b.parameters;
 		this.responses = b.responses;
-		this.pageTitle = b.pageTitle;
-		this.pageText = b.pageText;
-		this.pageLinks = b.pageLinks;
+		this.htmlTitle = b.htmlTitle;
+		this.htmlDescription = b.htmlDescription;
+		this.htmlHeader = b.htmlHeader;
+		this.htmlLinks = b.htmlLinks;
+		this.htmlNav = b.htmlNav;
+		this.htmlAside = b.htmlAside;
+		this.htmlFooter = b.htmlFooter;
+		this.htmlCss = b.htmlCss;
+		this.htmlCssUrl = b.htmlCssUrl;
+		this.htmlNoWrap = b.htmlNoWrap;
+		this.htmlTemplate = b.htmlTemplate;
+		this.htmlNoResultsMessage = b.htmlNoResultsMessage;
+		this.widgets = Collections.unmodifiableMap(b.widgets);
 	}
 
 	private static class Builder  {
-		private String httpMethod, defaultCharset, description, tags, summary, externalDocs, pageTitle, pageText, pageLinks;
+		private String httpMethod, defaultCharset, description, tags, summary, externalDocs, htmlTitle, htmlDescription,
+			htmlLinks, htmlNav, htmlAside, htmlFooter, htmlCssUrl, htmlCss, htmlHeader, htmlNoResultsMessage;
+		private boolean htmlNoWrap;
+		private HtmlDocTemplate htmlTemplate;
 		private UrlPathPattern pathPattern;
 		private RestParam[] params;
 		private RestGuard[] guards;
@@ -117,6 +137,7 @@ class CallMethod implements Comparable<CallMethod>  {
 		private Integer priority;
 		private org.apache.juneau.rest.annotation.Parameter[] parameters;
 		private Response[] responses;
+		private Map<String,Widget> widgets;
 
 		private Builder(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
 			try {
@@ -127,25 +148,41 @@ class CallMethod implements Comparable<CallMethod>  {
 
 				if (! m.description().isEmpty())
 					description = m.description();
-				if (! m.tags().isEmpty())
-					tags = m.tags();
+				MethodSwagger sm = m.swagger();
+				if (! sm.tags().isEmpty())
+					tags = sm.tags();
 				if (! m.summary().isEmpty())
 					summary = m.summary();
-				if (! m.externalDocs().isEmpty())
-					externalDocs = m.externalDocs();
-				deprecated = m.deprecated();
-				parameters = m.parameters();
-				responses = m.responses();
+				if (! sm.externalDocs().isEmpty())
+					externalDocs = sm.externalDocs();
+				deprecated = sm.deprecated();
+				parameters = sm.parameters();
+				responses = sm.responses();
 				serializers = context.getSerializers();
 				parsers = context.getParsers();
 				urlEncodingSerializer = context.getUrlEncodingSerializer();
 				urlEncodingParser = context.getUrlEncodingParser();
 				encoders = context.getEncoders();
 				properties = context.getProperties();
+				widgets = new HashMap<String,Widget>(context.getWidgets());
+				for (Class<? extends Widget> wc : m.widgets()) {
+					Widget w = ClassUtils.newInstance(Widget.class, wc);
+					widgets.put(w.getName(), w);
+				}
 
-				pageTitle = m.pageTitle().isEmpty() ? context.getPageTitle() : m.pageTitle();
-				pageText = m.pageText().isEmpty() ? context.getPageText() : m.pageText();
-				pageLinks = m.pageLinks().isEmpty() ? context.getPageLinks() : m.pageLinks();
+				HtmlDoc hd = m.htmldoc();
+				htmlTitle = hd.title().isEmpty() ? context.getHtmlTitle() : hd.title();
+				htmlDescription = hd.description().isEmpty() ? context.getHtmlDescription() : hd.description();
+				htmlHeader = hd.header().isEmpty() ? context.getHtmlHeader() : hd.header();
+				htmlLinks = hd.links().isEmpty() ? context.getHtmlLinks() : hd.links();
+				htmlNav = hd.nav().isEmpty() ? context.getHtmlNav() : hd.nav();
+				htmlAside = hd.aside().isEmpty() ? context.getHtmlAside() : hd.aside();
+				htmlFooter = hd.footer().isEmpty() ? context.getHtmlFooter() : hd.footer();
+				htmlCss = hd.css().isEmpty() ? context.getHtmlCss() : hd.css();
+				htmlCssUrl = hd.cssUrl().isEmpty() ? context.getHtmlCssUrl() : hd.cssUrl();
+				htmlNoWrap = hd.nowrap() ? hd.nowrap() : context.getHtmlNoWrap();
+				htmlNoResultsMessage = hd.noResultsMessage().isEmpty() ? context.getHtmlNoResultsMessage() : hd.header();
+				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());
@@ -700,7 +737,8 @@ class CallMethod implements Comparable<CallMethod>  {
 		req.getPathMatch().setRemainder(remainder);
 
 		ObjectMap requestProperties = createRequestProperties(properties, req);
-		req.init(method, requestProperties, defaultRequestHeaders, defaultQuery, defaultFormData, defaultCharset, serializers, parsers, urlEncodingParser, encoders, pageTitle, pageText, pageLinks);
+		req.init(method, requestProperties, defaultRequestHeaders, defaultQuery, defaultFormData, defaultCharset,
+			serializers, parsers, urlEncodingParser, encoders, widgets);
 		res.init(requestProperties, defaultCharset, serializers, urlEncodingSerializer, encoders);
 
 		// Class-level guards
@@ -820,12 +858,41 @@ class CallMethod implements Comparable<CallMethod>  {
 						return req.getMethodSummary();
 					if (k.equals(REST_methodDescription))
 						return req.getMethodDescription();
-					if (k.equals(HtmlDocSerializerContext.HTMLDOC_title))
-						return req.getPageTitle();
-					if (k.equals(HtmlDocSerializerContext.HTMLDOC_text))
-						return req.getPageText();
-					if (k.equals(HtmlDocSerializerContext.HTMLDOC_links))
-						return req.getPageLinks();
+					if (k.equals(HTMLDOC_title)) {
+						String s = htmlTitle;
+						if (! StringUtils.isEmpty(s))
+							return req.resolveVars(s);
+						return req.getServletTitle();
+					}
+					if (k.equals(HTMLDOC_description)) {
+						String s = htmlDescription;
+						if (! StringUtils.isEmpty(s))
+							return req.resolveVars(s);
+						s = req.getMethodSummary();
+						if (StringUtils.isEmpty(s))
+							s = req.getServletDescription();
+						return s;
+					}
+					if (k.equals(HTMLDOC_header))
+						return htmlHeader == null ? null : req.resolveVars(htmlHeader);
+					if (k.equals(HTMLDOC_links))
+						return htmlLinks == null ? null : req.resolveVars(htmlLinks);
+					if (k.equals(HTMLDOC_nav))
+						return htmlNav == null ? null : req.resolveVars(htmlNav);
+					if (k.equals(HTMLDOC_aside))
+						return htmlAside == null ? null : req.resolveVars(htmlAside);
+					if (k.equals(HTMLDOC_footer))
+						return htmlFooter == null ? null : req.resolveVars(htmlFooter);
+					if (k.equals(HTMLDOC_css))
+						return htmlCss == null ? null : req.resolveVars(htmlCss);
+					if (k.equals(HTMLDOC_cssUrl))
+						return htmlCssUrl == null ? null : req.resolveVars(htmlCssUrl);
+					if (k.equals(HTMLDOC_template))
+						return htmlTemplate;
+					if (k.equals(HTMLDOC_nowrap))
+						return htmlNoWrap;
+					if (k.equals(HTMLDOC_noResultsMessage))
+						return htmlNoResultsMessage == null ? null : req.resolveVars(htmlNoResultsMessage);
 					o = req.getPathMatch().get(k);
 					if (o == null)
 						o = req.getHeader(k);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
index 8d35327..234cabf 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -26,6 +26,7 @@ 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.*;
@@ -33,6 +34,7 @@ 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.*;
@@ -105,7 +107,8 @@ public class RestConfig implements ServletConfig {
 	Object favIcon;
 	List<Object> staticFiles;
 	RestContext parentContext;
-	String path, pageTitle, pageText, pageLinks;
+	String path, htmlTitle, htmlDescription, htmlLinks, htmlHeader, htmlNav, htmlAside, htmlFooter, htmlCss, htmlCssUrl,
+		htmlNoResultsMessage;
 	String clientVersionHeader = "X-Client-Version";
 
 	Object resourceResolver = RestResourceResolver.class;
@@ -113,6 +116,12 @@ public class RestConfig implements ServletConfig {
 	Object callHandler = RestCallHandler.class;
 	Object infoProvider = RestInfoProvider.class;
 
+	boolean htmlNoWrap;
+	Object htmlTemplate = HtmlDocTemplateBasic.class;
+
+	Class<?> resourceClass;
+	Map<String,Widget> widgets = new HashMap<String,Widget>();
+
 	/**
 	 * Constructor.
 	 * @param config The servlet config passed into the servlet by the servlet container.
@@ -121,6 +130,7 @@ public class RestConfig implements ServletConfig {
 	 */
 	RestConfig(ServletConfig config, Class<?> resourceClass, RestContext parentContext) throws ServletException {
 		this.inner = config;
+		this.resourceClass = resourceClass;
 		this.parentContext = parentContext;
 		try {
 
@@ -193,12 +203,7 @@ public class RestConfig implements ServletConfig {
 					setPath(r.path());
 				if (! r.clientVersionHeader().isEmpty())
 					setClientVersionHeader(r.clientVersionHeader());
-				if (! r.pageTitle().isEmpty())
-					setPageTitle(r.pageTitle());
-				if (! r.pageText().isEmpty())
-					setPageText(r.pageText());
-				if (! r.pageLinks().isEmpty())
-					setPageLinks(r.pageLinks());
+
 				if (r.resourceResolver() != RestResourceResolver.class)
 					setResourceResolver(r.resourceResolver());
 				if (r.logger() != RestLogger.Normal.class)
@@ -207,6 +212,35 @@ public class RestConfig implements ServletConfig {
 					setCallHandler(r.callHandler());
 				if (r.infoProvider() != RestInfoProvider.class)
 					setInfoProvider(r.infoProvider());
+
+				for (Class<? extends Widget> cw : r.widgets())
+					addWidget(cw);
+
+				HtmlDoc hd = r.htmldoc();
+				if (! hd.title().isEmpty())
+					setHtmlTitle(hd.title());
+				if (! hd.description().isEmpty())
+					setHtmlDescription(hd.description());
+				if (! hd.header().isEmpty())
+					setHtmlHeader(hd.header());
+				if (! hd.links().isEmpty())
+					setHtmlLinks(hd.links());
+				if (! hd.nav().isEmpty())
+					setHtmlNav(hd.nav());
+				if (! hd.aside().isEmpty())
+					setHtmlAside(hd.aside());
+				if (! hd.footer().isEmpty())
+					setHtmlFooter(hd.footer());
+				if (! hd.css().isEmpty())
+					setHtmlCss(hd.css());
+				if (! hd.cssUrl().isEmpty())
+					setHtmlCssUrl(hd.cssUrl());
+				if (! hd.noResultsMessage().isEmpty())
+					setHtmlNoResultsMessage(hd.noResultsMessage());
+				if (hd.nowrap())
+					setHtmlNoWrap(true);
+				if (hd.template() != HtmlDocTemplate.class)
+					setHtmlTemplate(hd.template());
 			}
 
 			addResponseHandlers(
@@ -254,7 +288,9 @@ public class RestConfig implements ServletConfig {
 	 * 	<li>{@link RequestVar}
 	 * 	<li>{@link SerializedRequestAttrVar}
 	 * 	<li>{@link ServletInitParamVar}
+	 * 	<li>{@link UrlVar}
 	 * 	<li>{@link UrlEncodeVar}
+	 * 	<li>{@link WidgetVar}
 	 * </ul>
 	 *
 	 * @param vars The {@link Var} classes to add to this config.
@@ -1016,41 +1052,313 @@ public class RestConfig implements ServletConfig {
 	}
 
 	/**
-	 * Sets the page title to use on HTML views of pages.
+	 * Sets the HTML page title.
+	 * <p>
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h3&gt; <xa>class</xa>=<xs>'title'</xs>&gt;</xt></code> element and then added
+	 * 	to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageTitle</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageTitle</code> resource bundle value.
+	 * 	<li><code><ja>@RestResource</ja>(title)</code> annotation.
+	 * 	<li><code>{servletClass}.title</code> resource bundle value.
+	 * 	<li><code>info/title</code> entry in swagger file.
+	 * <ol>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * <ul class='doctree'>
+	 * 	<li class='info'>
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(title)</code> annotation to specify the
+	 * 		page title.
+	 * 		However, this annotation is provided in cases where you want the page title to be different that the one
+	 * 		shown in the swagger document.
+	 * </ul>
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#title() @HtmlDoc.title()} annotation.
+	 *
+	 * @param value The HTML page title.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig setHtmlTitle(String value) {
+		this.htmlTitle = value;
+		return this;
+	}
+
+	/**
+	 * Sets the HTML page description.
+	 * <p>
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h5&gt; <xa>class</xa>=<xs>'description'</xs>&gt;</xt></code> element and then
+	 * 	added to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageText</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageText</code> resource bundle value.
+	 * 	<li><code><ja>@RestMethod</ja>(summary)</code> annotation.
+	 * 	<li><code>{servletClass}.{methodName}.summary</code> resource bundle value.
+	 * 	<li><code>summary</code> entry in swagger file for method.
+	 * 	<li><code>{servletClass}.description</code> resource bundle value.
+	 * 	<li><code>info/description</code> entry in swagger file.
+	 * <ol>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * <ul class='doctree'>
+	 * 	<li class='info'>
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(description)</code> or
+	 * 		<code>@RestMethod(summary)</code> annotations to specify the page text.
+	 * 		However, this annotation is provided in cases where you want the text to be different that the values shown
+	 * 		in the swagger document.
+	 * </ul>
 	 * <p>
-	 * This is the programmatic equivalent to the {@link RestResource#pageTitle() @RestResource.pageTitle()} annotation.
+	 * This is the programmatic equivalent to the {@link HtmlDoc#description() @HtmlDoc.description()} annotation.
 	 *
-	 * @param pageTitle The page title text.
+	 * @param value The HTML page description.
 	 * @return This object (for method chaining).
 	 */
-	public RestConfig setPageTitle(String pageTitle) {
-		this.pageTitle = pageTitle;
+	public RestConfig setHtmlDescription(String value) {
+		this.htmlDescription = value;
 		return this;
 	}
 
 	/**
-	 * Sets the page text to use on HTML views of pages.
+	 * 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>
+	 * When a value is specified, the {@link #setHtmlTitle(String)} and {@link #setHtmlDescription(String)} values will be ignored.
+	 * <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>).
+	 * <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).
+	 */
+	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>).
+	 * <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#links() @HtmlDoc.links()} annotation.
+	 *
+	 * @param value The HTML nav section links links.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig setHtmlLinks(String value) {
+		this.htmlLinks = 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 #setHtmlLinks(String)} value will be ignored.
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <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>).
+	 * <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>).
+	 * <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>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#css() @HtmlDoc.css()} annotation.
+	 *
+	 * @param value The HTML CSS style section contents.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig setHtmlCss(String value) {
+		this.htmlCss = 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}.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#cssUrl() @HtmlDoc.cssUrl()} annotation.
+	 *
+	 * @param value The CSS URL in the HTML CSS style section.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig setHtmlCssUrl(String value) {
+		this.htmlCssUrl = 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 RestResource#pageText() @RestResource.pageText()} annotation.
+	 * This is the programmatic equivalent to the {@link HtmlDoc#template() @HtmlDoc.template()} annotation.
 	 *
-	 * @param pageText The page text.
+	 * @param value The HTML page template to use to render the HTML page.
 	 * @return This object (for method chaining).
 	 */
-	public RestConfig setPageText(String pageText) {
-		this.pageText = pageText;
+	public RestConfig setHtmlTemplate(HtmlDocTemplate value) {
+		this.htmlTemplate = value;
 		return this;
 	}
 
 	/**
-	 * Sets the page links to use on HTML views of pages.
+	 * 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>
-	 * This is the programmatic equivalent to the {@link RestResource#pageLinks() @RestResource.pageLinks()} annotation.
+	 * Widgets are inherited from parent to child, but can be overridden by reusing the widget name.
 	 *
-	 * @param pageLinks The page links.
+	 * @param value The widget class to add.
 	 * @return This object (for method chaining).
 	 */
-	public RestConfig setPageLinks(String pageLinks) {
-		this.pageLinks = pageLinks;
+	public RestConfig addWidget(Class<? extends Widget> value) {
+		Widget w = ClassUtils.newInstance(Widget.class, value);
+		this.widgets.put(w.getName(), w);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
index 62aca6c..cec08c0 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -33,6 +33,7 @@ import javax.servlet.*;
 
 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.*;
@@ -41,6 +42,7 @@ 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.urlencoding.*;
@@ -300,7 +302,20 @@ public final class RestContext extends Context {
 		paramFormat,
 		clientVersionHeader,
 		fullPath,
-		pageTitle, pageText, pageLinks;
+		htmlTitle,
+		htmlDescription,
+		htmlHeader,
+		htmlLinks,
+		htmlNav,
+		htmlAside,
+		htmlCss,
+		htmlCssUrl,
+		htmlFooter,
+		htmlNoResultsMessage;
+	private final boolean htmlNoWrap;
+	private final HtmlDocTemplate htmlTemplate;
+	private final Map<String,Widget> widgets;
+
 	private final Set<String> allowMethodParams;
 
 	private final ObjectMap properties;
@@ -398,9 +413,20 @@ public final class RestContext extends Context {
 			this.childResources = Collections.synchronizedMap(new LinkedHashMap<String,RestContext>());  // Not unmodifiable on purpose so that children can be replaced.
 			this.logger = b.logger;
 			this.fullPath = b.fullPath;
-			this.pageTitle = b.pageTitle;
-			this.pageText = b.pageText;
-			this.pageLinks = b.pageLinks;
+			this.widgets = Collections.unmodifiableMap(b.widgets);
+
+			this.htmlTitle = b.htmlTitle;
+			this.htmlDescription = b.htmlDescription;
+			this.htmlHeader = b.htmlHeader;
+			this.htmlLinks = b.htmlLinks;
+			this.htmlNav = b.htmlNav;
+			this.htmlAside = b.htmlAside;
+			this.htmlCss = b.htmlCss;
+			this.htmlCssUrl = b.htmlCssUrl;
+			this.htmlFooter = b.htmlFooter;
+			this.htmlNoWrap = b.htmlNoWrap;
+			this.htmlNoResultsMessage = b.htmlNoResultsMessage;
+			this.htmlTemplate = b.htmlTemplate;
 
 			//----------------------------------------------------------------------------------------------------
 			// Initialize the child resources.
@@ -572,7 +598,11 @@ public final class RestContext extends Context {
 		UrlEncodingSerializer urlEncodingSerializer;
 		UrlEncodingParser urlEncodingParser;
 		EncoderGroup encoders;
-		String clientVersionHeader = "", defaultCharset, paramFormat, pageTitle, pageText, pageLinks;
+		String clientVersionHeader = "", defaultCharset, paramFormat, htmlTitle, htmlDescription, htmlHeader, htmlLinks,
+			htmlNav, htmlAside, htmlCss, htmlCssUrl, htmlFooter, htmlNoResultsMessage;
+		boolean htmlNoWrap;
+		HtmlDocTemplate htmlTemplate;
+
 		List<MediaType> supportedContentTypes, supportedAcceptTypes;
 		Map<String,String> defaultRequestHeaders = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
 		Map<String,Object> defaultResponseHeaders;
@@ -588,6 +618,7 @@ public final class RestContext extends Context {
 		Set<String> allowMethodParams = new LinkedHashSet<String>();
 		RestLogger logger;
 		String fullPath;
+		Map<String,Widget> widgets;
 
 		@SuppressWarnings("unchecked")
 		private Builder(Object resource, RestConfig sc) throws Exception {
@@ -610,7 +641,7 @@ public final class RestContext extends Context {
 					allowMethodParams.add(m.toUpperCase());
 
 			varResolver = sc.varResolverBuilder
-				.vars(LocalizationVar.class, RequestVar.class, SerializedRequestAttrVar.class, ServletInitParamVar.class, UrlEncodeVar.class)
+				.vars(LocalizationVar.class, RequestVar.class, SerializedRequestAttrVar.class, ServletInitParamVar.class, UrlVar.class, UrlEncodeVar.class, WidgetVar.class)
 				.build()
 			;
 			configFile = sc.configFile.getResolving(this.varResolver);
@@ -716,9 +747,20 @@ public final class RestContext extends Context {
 
 			fullPath = (sc.parentContext == null ? "" : (sc.parentContext.fullPath + '/')) + sc.path;
 
-			pageTitle = sc.pageTitle;
-			pageText = sc.pageText;
-			pageLinks = sc.pageLinks;
+			widgets = sc.widgets;
+
+			htmlTitle = sc.htmlTitle;
+			htmlDescription = sc.htmlDescription;
+			htmlHeader = sc.htmlHeader;
+			htmlLinks = sc.htmlLinks;
+			htmlNav = sc.htmlNav;
+			htmlAside = sc.htmlAside;
+			htmlCss = sc.htmlCss;
+			htmlCssUrl = sc.htmlCssUrl;
+			htmlFooter = sc.htmlFooter;
+			htmlNoWrap = sc.htmlNoWrap;
+			htmlNoResultsMessage = sc.htmlNoResultsMessage;
+			htmlTemplate = ClassUtils.newInstance(HtmlDocTemplate.class, sc.htmlTemplate);
 		}
 	}
 
@@ -940,30 +982,146 @@ public final class RestContext extends Context {
 	}
 
 	/**
-	 * Returns the page title as defined by the {@link RestResource#pageTitle()} annotation or {@link RestConfig#setPageTitle(String)} method.
+	 * The HTML page title.
+	 * <p>
+	 * Defined by the {@link HtmlDoc#title()} annotation or {@link RestConfig#setHtmlTitle(String)} method.
 	 *
-	 * @return The page title.
+	 * @return The HTML page title.
 	 */
-	public String getPageTitle() {
-		return pageTitle;
+	public String getHtmlTitle() {
+		return htmlTitle;
 	}
 
 	/**
-	 * Returns the page text as defined by the {@link RestResource#pageText()} annotation or {@link RestConfig#setPageText(String)} method.
+	 * The HTML page description.
+	 * <p>
+	 * Defined by the {@link HtmlDoc#description()} annotation or {@link RestConfig#setHtmlDescription(String)} method.
 	 *
-	 * @return The page text.
+	 * @return The HTML page description.
 	 */
-	public String getPageText() {
-		return pageText;
+	public String getHtmlDescription() {
+		return htmlDescription;
 	}
 
 	/**
-	 * Returns the page links as defined by the {@link RestResource#pageLinks()} annotation or {@link RestConfig#setPageLinks(String)} method.
+	 * 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#links()} annotation or {@link RestConfig#setHtmlLinks(String)} method.
+	 *
+	 * @return The HTML page nav section links.
+	 */
+	public String getHtmlLinks() {
+		return htmlLinks;
+	}
+
+	/**
+	 * 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 CSS URL.
+	 * <p>
+	 * Defined by the {@link HtmlDoc#cssUrl()} annotation or {@link RestConfig#setHtmlCssUrl(String)} method.
+	 *
+	 * @return The HTML page CSS URL.
+	 */
+	public String getHtmlCssUrl() {
+		return htmlCssUrl;
+	}
+
+	/**
+	 * The HTML page CSS contents.
+	 * <p>
+	 * Defined by the {@link HtmlDoc#css()} annotation or {@link RestConfig#setHtmlCss(String)} method.
+	 *
+	 * @return The HTML page CSS contents.
+	 */
+	public String getHtmlCss() {
+		return htmlCss;
+	}
+
+	/**
+	 * 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 RestResource#widgets()} annotation or {@link RestConfig#addWidget(Class)} method.
 	 *
-	 * @return The page links.
+	 * @return The var resolver widgets as a map with keys being the name returned by {@link Widget#getName()}.
 	 */
-	public String getPageLinks() {
-		return pageLinks;
+	public Map<String,Widget> getWidgets() {
+		return widgets;
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
index 18488e6..0254be6 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
@@ -91,18 +91,19 @@ public class RestInfoProvider {
 					title = r.title();
 				if (! r.description().isEmpty())
 					description = r.description();
-				if (! r.termsOfService().isEmpty())
-					termsOfService = r.termsOfService();
-				if (! r.contact().isEmpty())
-					contact = r.contact();
-				if (! r.license().isEmpty())
-					license = r.license();
-				if (! r.version().isEmpty())
-					version = r.version();
-				if (! r.tags().isEmpty())
-					tags = r.tags();
-				if (! r.externalDocs().isEmpty())
-					externalDocs = r.externalDocs();
+				ResourceSwagger sr = r.swagger();
+				if (! sr.termsOfService().isEmpty())
+					termsOfService = sr.termsOfService();
+				if (! sr.contact().isEmpty())
+					contact = sr.contact();
+				if (! sr.license().isEmpty())
+					license = sr.license();
+				if (! sr.version().isEmpty())
+					version = sr.version();
+				if (! sr.tags().isEmpty())
+					tags = sr.tags();
+				if (! sr.externalDocs().isEmpty())
+					externalDocs = sr.externalDocs();
 			}
 		}
 	}
@@ -298,7 +299,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the contact information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#contact() @RestResource.contact()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#contact() @ResourceSwagger.contact()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].contact</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>contact</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
@@ -334,7 +335,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the license information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#license() @RestResource.license()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#license() @ResourceSwagger.license()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].license</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>license</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
@@ -370,7 +371,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the terms-of-service information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#termsOfService() @RestResource.termsOfService()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#termsOfService() @ResourceSwagger.termsOfService()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].termsOfService</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>termsOfService</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
@@ -401,7 +402,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the version information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#version() @RestResource.version()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
@@ -432,7 +433,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the version information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#version() @RestResource.version()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
@@ -468,7 +469,7 @@ public class RestInfoProvider {
 	 * <p>
 	 * The default implementation returns the version information from the following locations (whichever matches first):
 	 * <ol>
-	 * 	<li>{@link RestResource#version() @RestResource.version()} annotation on this class, and then any parent classes.
+	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent classes.
 	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
 	 * 		annotation for this class, then any parent classes.
 	 * 	<li><ck>version</ck> property in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
index 5112e25..74fa22c 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -35,6 +35,7 @@ import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
@@ -87,7 +88,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	private RequestHeaders headers;
 	private ConfigFile cf;
 	private Swagger swagger, fileSwagger;
-	private String pageTitle, pageText, pageLinks;
+	private Map<String,Widget> widgets;
 
 	/**
 	 * Constructor.
@@ -155,7 +156,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,
-			EncoderGroup encoders, String pageTitle, String pageText, String pageLinks) {
+			EncoderGroup encoders, Map<String,Widget> widgets) {
 		this.javaMethod = javaMethod;
 		this.properties = properties;
 		this.urlEncodingParser = mUrlEncodingParser;
@@ -181,10 +182,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		this.serializerGroup = mSerializers;
 		this.parserGroup = mParsers;
 		this.defaultCharset = defaultCharset;
-		this.pageTitle = pageTitle;
-		this.pageText = pageText;
-		this.pageLinks = pageLinks;
 		this.defFormData = defFormData;
+		this.widgets = widgets;
 
 		if (debug) {
 			String msg = ""
@@ -698,57 +697,6 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		return context.getInfoProvider().getMethodDescription(javaMethod.getName(), this);
 	}
 
-	/**
-	 * Returns the localized page title for HTML views.
-	 *
-	 * @return The localized page title for HTML views.
-	 */
-	protected String getPageTitle() {
-		String s = pageTitle;
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageTitle");
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), "pageTitle");
-		if (! isEmpty(s))
-			return resolveVars(s);
-		s = getServletTitle();
-		return s;
-	}
-
-	/**
-	 * Returns the localized page text for HTML views.
-	 *
-	 * @return The localized page text for HTML views.
-	 */
-	protected String getPageText() {
-		String s = pageText;
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageText");
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), "pageText");
-		if (! isEmpty(s))
-			return resolveVars(s);
-		s = getMethodSummary();
-		if (isEmpty(s))
-			s = getServletDescription();
-		return s;
-	}
-
-	/**
-	 * Returns the localized page links for HTML views.
-	 *
-	 * @return The localized page links for HTML views.
-	 */
-	protected String getPageLinks() {
-		String s = pageLinks;
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageLinks");
-		if (isEmpty(s))
-			s = context.getMessages().findFirstString(getLocale(), "pageLinks");
-		return resolveVars(s);
-	}
-
-
 	//--------------------------------------------------------------------------------
 	// Other methods
 	//--------------------------------------------------------------------------------
@@ -955,7 +903,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	/**
 	 * Returns the localized swagger associated with the servlet.
 	 *
-	 * @return The swagger associated with the servlet.  Never <jk>null</jk>.
+	 * @return The swagger associated with the servlet.
+	 * 	Never <jk>null</jk>.
 	 */
 	public Swagger getSwagger() {
 		if (swagger == null)
@@ -964,6 +913,16 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	}
 
 	/**
+	 * Returns the widgets used for resolving <js>"$W{...}"</js> string variables.
+	 *
+	 * @return The widgets used for resolving <js>"$W{...}"</js> string variables.
+	 * 	Never <jk>null</jk>.
+	 */
+	public Map<String,Widget> getWidgets() {
+		return widgets;
+	}
+
+	/**
 	 * Returns the localized Swagger from the file system.
 	 * <p>
 	 * Looks for a file called <js>"{ServletClass}_{locale}.json"</js> in the same package


[2/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
index 50f25f6..725387a 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -424,65 +424,358 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	}
 
 	/**
-	 * Sets the page title for HTML views.
+	 * Sets the HTML page title.
 	 * <p>
-	 * This is the programmatic equivalent to the {@link RestResource#pageTitle() @RestResource#pageTitle()}/
-	 * {@link RestMethod#pageTitle() @RestMethod#pageTitle()} annotations.
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h3&gt; <xa>class</xa>=<xs>'title'</xs>&gt;</xt></code> element and then added
+	 * 	to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageTitle</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageTitle</code> resource bundle value.
+	 * 	<li><code><ja>@RestResource</ja>(title)</code> annotation.
+	 * 	<li><code>{servletClass}.title</code> resource bundle value.
+	 * 	<li><code>info/title</code> entry in swagger file.
+	 * <ol>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
 	 * <p>
-	 * This is a shortcut for calling <code>setProperty(<jsf>HTMLDOC_title</jsf>, title);</code>
 	 * <ul class='doctree'>
 	 * 	<li class='info'>
-	 * 		<b>Tip:</b>  Use {@link StringMessage} to generate a page title with delayed serialization so as not to
-	 * 		waste string concatenation cycles on non-HTML views.
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(title)</code> annotation to specify the
+	 * 		page title.
+	 * 		However, this annotation is provided in cases where you want the page title to be different that the one
+	 * 		shown in the swagger document.
 	 * </ul>
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#title() @HtmlDoc.title()} annotation.
 	 *
-	 * @param title The localized page title to render on the page.
-	 * Object will be converted to a string using {@link Object#toString()}.
+	 * @param value The HTML page title.
+	 * 	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 setPageTitle(Object title) {
-		return setProperty(HtmlDocSerializerContext.HTMLDOC_title, title);
+	public RestResponse setHtmlTitle(Object value) {
+		return setProperty(HtmlDocSerializerContext.HTMLDOC_title, value);
 	}
 
 	/**
-	 * Sets the page text for HTML views.
+	 * Sets the HTML page description.
+	 * <p>
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h5&gt; <xa>class</xa>=<xs>'description'</xs>&gt;</xt></code> element and then
+	 * 	added to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageText</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageText</code> resource bundle value.
+	 * 	<li><code><ja>@RestMethod</ja>(summary)</code> annotation.
+	 * 	<li><code>{servletClass}.{methodName}.summary</code> resource bundle value.
+	 * 	<li><code>summary</code> entry in swagger file for method.
+	 * 	<li><code>{servletClass}.description</code> resource bundle value.
+	 * 	<li><code>info/description</code> entry in swagger file.
+	 * <ol>
 	 * <p>
-	 * This is the programmatic equivalent to the {@link RestResource#pageText() @RestResource#pageText()}/
-	 * {@link RestMethod#pageText() @RestMethod#pageText()} annotations.
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
 	 * <p>
-	 * This is a shortcut for calling <code>setProperty(<jsf>HTMLDOC_text</jsf>, text);</code>
 	 * <ul class='doctree'>
 	 * 	<li class='info'>
-	 * 		<b>Tip:</b>  Use {@link StringMessage} to generate page text with delayed serialization so as not to
-	 * 		waste string concatenation cycles on non-HTML views.
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(description)</code> or
+	 * 		<code>@RestMethod(summary)</code> annotations to specify the page text.
+	 * 		However, this annotation is provided in cases where you want the text to be different that the values shown
+	 * 		in the swagger document.
 	 * </ul>
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#description() @HtmlDoc.description()} annotation.
 	 *
-	 * @param text The localized page text to render on the page.
+	 * @param value The HTML page description.
+	 * 	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 setPageText(Object text) {
-		return setProperty(HtmlDocSerializerContext.HTMLDOC_text, text);
+	public RestResponse setHtmlDescription(Object value) {
+		return setProperty(HtmlDocSerializerContext.HTMLDOC_description, value);
 	}
 
 	/**
-	 * Sets the page text for HTML views.
+	 * 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>
-	 * This is the programmatic equivalent to the {@link RestResource#pageLinks() @RestResource#pageLinks()}/
-	 * {@link RestMethod#pageLinks() @RestMethod#pageLinks()} annotations.
+	 * When a value is specified, the {@link #setHtmlTitle(Object)} and {@link #setHtmlDescription(Object)} values will be ignored.
 	 * <p>
-	 * This is a shortcut for calling <code>setProperty(<jsf>HTMLDOC_links</jsf>, links);</code>
+	 * 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>).
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#header() @HtmlDoc.header()} annotation.
 	 *
-	 * <ul class='doctree'>
-	 * 	<li class='info'>
-	 * 		<b>Tip:</b>  Use {@link StringMessage} to generate page links with delayed serialization so as not to
-	 * 		waste string concatenation cycles on non-HTML views.
-	 * </ul>
+	 * @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_title, 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>).
+	 * <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#links() @HtmlDoc.links()} annotation.
+	 *
+	 * @param value The HTML nav section links links.
+	 * 	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 setHtmlLinks(Object value) {
+		properties.put(HtmlDocSerializerContext.HTMLDOC_links, 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 #setHtmlLinks(Object)} value will be ignored.
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <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>).
+	 * <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>).
+	 * <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>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#css() @HtmlDoc.css()} 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 setHtmlCss(Object value) {
+		properties.put(HtmlDocSerializerContext.HTMLDOC_css, 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}.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link HtmlDoc#cssUrl() @HtmlDoc.cssUrl()} 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 setHtmlCssUrl(Object value) {
+		properties.put(HtmlDocSerializerContext.HTMLDOC_cssUrl, 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 links The localized page links render on the page.
+	 * @param value The HTML page template to use to render the HTML page.
 	 * @return This object (for method chaining).
 	 */
-	public RestResponse setPageLinks(Object links) {
-		properties.put(HtmlDocSerializerContext.HTMLDOC_links, links);
+	public RestResponse setHtmlTemplate(HtmlDocTemplate value) {
+		properties.put(HtmlDocSerializerContext.HTMLDOC_template, value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/RestServletDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestServletDefault.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestServletDefault.java
index 51252b2..050ad0e 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestServletDefault.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestServletDefault.java
@@ -167,8 +167,7 @@ import org.apache.juneau.xml.*;
 		UrlEncodingSerializer.class,
 		MsgPackSerializer.class,
 		SoapXmlSerializer.class,
-		PlainTextSerializer.class,
-		JsoSerializer.class
+		PlainTextSerializer.class
 	},
 	parsers={
 		JsonParser.class,
@@ -197,9 +196,13 @@ public abstract class RestServletDefault extends RestServlet {
 	 * @return A bean containing the contents for the OPTIONS page.
 	 */
 	@RestMethod(name="OPTIONS", path="/*",
-		pageLinks="{back:'$R{servletURI}'}",
+		htmldoc=@HtmlDoc(
+			links="{back:'servlet:/',json:'servlet:/?method=OPTIONS&Accept=text/json&plainText=true'}",
+			description="Swagger documentation",
+			aside="NONE"
+		),
 		summary="Resource options",
-		description="Description of this resource"
+		description="Swagger documentation"
 	)
 	public Swagger getOptions(RestRequest req) {
 		return req.getSwagger();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
new file mode 100644
index 0000000..80ddf10
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
@@ -0,0 +1,339 @@
+// ***************************************************************************************************************************
+// * 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.annotation;
+
+import org.apache.juneau.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.rest.*;
+
+/**
+ * Contains all the configurable annotations for the {@link HtmlDocSerializer}.
+ * <p>
+ * Used with {@link RestResource#htmldoc()} and {@link RestMethod#htmldoc()} to customize the HTML view of
+ * 	serialized POJOs.
+ * <p>
+ * All annotations specified here have no effect on any serializers other than {@link HtmlDocSerializer} and is
+ * 	provided as a shorthand method of for specifying configuration properties.
+ * <p>
+ * For example, the following two methods for defining the HTML document title are considered equivalent:
+ * <p class='bcode'>
+ * 	<ja>@RestResource</ja>(
+ * 		properties={
+ * 			<ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"My Resource Page"</js>)
+ * 		}
+ * 	)
+ *
+ * 	<ja>@RestResource</ja>(
+ * 		htmldoc=<ja>@HtmlDoc</ja>(
+ * 			title=<js>"My Resource Page"</js>
+ * 		)
+ * 	)
+ * </p>
+ * <p>
+ * The purpose of these annotation is to populate the HTML document view which by default consists of the following
+ * 	structure:
+ * <p class='bcode'>
+ * 	<xt>&lt;html&gt;
+ * 		&lt;head&gt;
+ * 			&lt;style <xa>type</xa>=<xs>'text/css'</xs>&gt;
+ * 				<xv>CSS styles and links to stylesheets</xv>
+ * 			&lt/style&gt;
+ * 		&lt;/head&gt;
+ * 		&lt;body&gt;
+ * 			&lt;header&gt;
+ * 				<xv>Page title and description</xv>
+ * 			&lt;/header&gt;
+ * 			&lt;nav&gt;
+ * 				<xv>Page links</xv>
+ * 			&lt;/nav&gt;
+ * 			&lt;aside&gt;
+ * 				<xv>Side-bar page links</xv>
+ * 			&lt;/aside&gt;
+ * 			&lt;article&gt;
+ * 				<xv>Contents of serialized object</xv>
+ * 			&lt;/article&gt;
+ * 			&lt;footer&gt;
+ * 				<xv>Footer message</xv>
+ * 			&lt;/footer&gt;
+ * 		&lt;/body&gt;
+ * 	&lt;/html&gt;</xt>
+ * </p>
+ */
+public @interface HtmlDoc {
+
+	/**
+	 * Sets the HTML page title.
+	 * <p>
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h3&gt; <xa>class</xa>=<xs>'title'</xs>&gt;</xt></code> element and then added
+	 * 	to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageTitle</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageTitle</code> resource bundle value.
+	 * 	<li><code><ja>@RestResource</ja>(title)</code> annotation.
+	 * 	<li><code>{servletClass}.title</code> resource bundle value.
+	 * 	<li><code>info/title</code> entry in swagger file.
+	 * <ol>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * <ul class='doctree'>
+	 * 	<li class='info'>
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(title)</code> annotation to specify the
+	 * 		page title.
+	 * 		However, this annotation is provided in cases where you want the page title to be different that the one
+	 * 		shown in the swagger document.
+	 * </ul>
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlTitle(String)}/{@link RestResponse#setHtmlTitle(Object)} methods.
+	 */
+	String title() default "";
+
+	/**
+	 * Sets the HTML page description.
+	 * <p>
+	 * The format of this value is plain text.
+	 * <p>
+	 * It gets wrapped in a <code><xt>&lt;h5&gt; <xa>class</xa>=<xs>'description'</xs>&gt;</xt></code> element and then
+	 * 	added to the <code><xt>&lt;header&gt;</code> section on the page.
+	 * <p>
+	 * If not specified, the page title is pulled from one of the following locations:
+	 * <ol>
+	 * 	<li><code>{servletClass}.{methodName}.pageText</code> resource bundle value.
+	 * 	<li><code>{servletClass}.pageText</code> resource bundle value.
+	 * 	<li><code><ja>@RestMethod</ja>(summary)</code> annotation.
+	 * 	<li><code>{servletClass}.{methodName}.summary</code> resource bundle value.
+	 * 	<li><code>summary</code> entry in swagger file for method.
+	 * 	<li><code>{servletClass}.description</code> resource bundle value.
+	 * 	<li><code>info/description</code> entry in swagger file.
+	 * <ol>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * <ul class='doctree'>
+	 * 	<li class='info'>
+	 * 		In most cases, you'll simply want to use the <code>@RestResource(description)</code> or
+	 * 		<code>@RestMethod(summary)</code> annotations to specify the page text.
+	 * 		However, this annotation is provided in cases where you want the text to be different that the values shown
+	 * 		in the swagger document.
+	 * </ul>
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlDescription(String)}/{@link RestResponse#setHtmlDescription(Object)} methods.
+	 */
+	String description() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			header=<js>"&lt;p&gtThis is my REST interface&lt;/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * When a value is specified, the {@link #title()} and {@link #description()} values will be ignored.
+	 * <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>).
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlHeader(String)}/{@link RestResponse#setHtmlHeader(Object)} methods.
+	 */
+	String header() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <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>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlLinks(String)}/{@link RestResponse#setHtmlLinks(Object)} methods.
+	 */
+	String links() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			nav=<js>"&lt;p&gt;Custom nav content&lt;/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * When a value is specified, the {@link #links()} value will be ignored.
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlNav(String)}/{@link RestResponse#setHtmlNav(Object)} methods.
+	 */
+	String nav() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			aside=<js>"&lt;p&gt;Custom aside content&lt;/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlAside(String)}/{@link RestResponse#setHtmlAside(Object)} methods.
+	 */
+	String aside() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			footer=<js>"&lt;p&gt;Custom footer content&lt;/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlFooter(String)}/{@link RestResponse#setHtmlFooter(Object)} methods.
+	 */
+	String footer() default "";
+
+	/**
+	 * Sets the HTML CSS style section contents.
+	 * <p>
+	 * The format of this value is CSS.
+	 * <p>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			css=<js>".red{color:red;}\n.blue{color:blue}"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to force no value.
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlCss(String)}/{@link RestResponse#setHtmlCss(Object)} methods.
+	 */
+	String css() default "";
+
+	/**
+	 * 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>
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			cssUrl=<js>"http://someOtherHost/stealTheir.css"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>) and can use URL protocols defined
+	 * 	by {@link UriResolver}.
+	 * <p>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlCssUrl(String)}/{@link RestResponse#setHtmlCssUrl(Object)} methods.
+	 */
+	String cssUrl() default "servlet:/style.css";
+
+	/**
+	 * Shorthand method for forcing the rendered HTML content to be no-wrap.
+	 */
+	boolean nowrap() default false;
+
+	/**
+	 * Specifies the text to display when serializing an empty array or collection.
+	 */
+	String noResultsMessage() default "no results";
+
+	/**
+	 * 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>
+	 * The programmatic equivalent to this annotation are the {@link RestConfig#setHtmlTemplate(Class)}/{@link RestResponse#setHtmlTemplate(Class)} methods.
+	 */
+	Class<? extends HtmlDocTemplate> template() default HtmlDocTemplate.class;
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
new file mode 100644
index 0000000..b43affe
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
@@ -0,0 +1,161 @@
+// ***************************************************************************************************************************
+// * 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.annotation;
+
+/**
+ * Extended annotation for {@link RestMethod#swagger() RestMethod.swagger()}.
+ */
+public @interface MethodSwagger {
+	
+	/**
+	 * Optional external documentation information for the exposed API.
+	 * <p>
+	 * Used to populate the Swagger external documentation field.
+	 * <p>
+	 * A simplified JSON string with the following fields:
+	 * <p class='bcode'>
+	 * 	{
+	 * 		description: string,
+	 * 		url: string
+	 * 	}
+	 * </p>
+	 * <p>
+	 * The default value pulls the description from the <code>(className.?)[javaMethodName].externalDocs</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"MyClass.myMethod.externalDocs = {url:'http://juneau.apache.org'}"</js> or <js>"myMethod.externalDocs = {url:'http://juneau.apache.org'}"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(externalDocs=<js>"{url:'http://juneau.apache.org'}"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/paths/{path}/{method}/externalDocs</code>.
+	 */
+	String externalDocs() default "";
+
+	/**
+	 * Optional tagging information for the exposed API.
+	 * <p>
+	 * Used to populate the Swagger tags field.
+	 * <p>
+	 * A comma-delimited list of tags for API documentation control.
+	 * Tags can be used for logical grouping of operations by resources or any other qualifier.
+	 * <p>
+	 * The default value pulls the description from the <code>(className.?)[javaMethodName].tags</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"MyClass.myMethod.tags = foo,bar"</js> or <js>"myMethod.tags = foo,bar"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(tags=<js>"foo,bar"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/paths/{path}/{method}/tags</code>.
+	 */
+	String tags() default "";
+
+	/**
+	 * Optional deprecated flag for the exposed API.
+	 * <p>
+	 * Used to populate the Swagger deprecated field.
+	 * <p>
+	 * The default value pulls the description from the <code>(className.?)[javaMethodName].deprecated</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"MyClass.myMethod.deprecated = true"</js> or <js>"myMethod.deprecated = foo,bar"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(deprecated=<jk>true</jk>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/paths/{path}/{method}/deprecated</code>.
+	 */
+	boolean deprecated() default false;
+
+	/**
+	 * Optional parameter descriptions.
+	 * <p>
+	 * This annotation is provided for documentation purposes and is used to populate the method <js>"parameters"</js> column
+	 * 	on the Swagger page.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		name=<js>"POST"</js>, path=<js>"/{a}"</js>,
+	 * 		description=<js>"This is my method."</js>,
+	 * 		parameters={
+	 * 			<ja>@Parameter</ja>(in=<js>"path"</js>, name=<js>"a"</js>, description=<js>"The 'a' attribute"</js>),
+	 * 			<ja>@Parameter</ja>(in=<js>"query"</js>, name=<js>"b"</js>, description=<js>"The 'b' parameter"</js>, required=<jk>true</jk>),
+	 * 			<ja>@Parameter</ja>(in=<js>"body"</js>, description=<js>"The HTTP content"</js>),
+	 * 			<ja>@Parameter</ja>(in=<js>"header"</js>, name=<js>"D"</js>, description=<js>"The 'D' header"</js>),
+	 * 		}
+	 * 	)
+	 * </p>
+	 * This is functionally equivalent to specifying the following keys in the resource bundle for the class, except in this case
+	 * 	the strings are internationalized.
+	 * <p class='bcode'>
+	 * 	<jk>MyClass.myMethod.description</jk> = <js>This is my method.</js>
+	 * 	<jk>MyClass.myMethod.req.path.a.description</jk> = <js>The 'a' attribute</js>
+	 * 	<jk>MyClass.myMethod.req.query.b.description</jk> = <js>The 'b' parameter</js>
+	 * 	<jk>MyClass.myMethod.req.body.description</jk> = <js>The HTTP content</js>
+	 * 	<jk>MyClass.myMethod.req.header.d.description</jk> = <js>The 'D' header</js>
+	 * <p>
+	 * As a general rule, use annotations when you don't care about internationalization (i.e. you only want to support English),
+	 * 	and use resource bundles if you need to support localization.
+	 * <p>
+	 * These annotations can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/paths/{path}/{method}/parameters</code>.
+	 */
+	Parameter[] parameters() default {};
+
+	/**
+	 * Optional output description.
+	 * <p>
+	 * This annotation is provided for documentation purposes and is used to populate the method <js>"responses"</js> column
+	 * 	on the Swagger page.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		name=<js>"GET"</js>, path=<js>"/"</js>,
+	 * 		responses={
+	 * 			<ja>@Response</ja>(200),
+	 * 			<ja>@Response</ja>(
+	 * 				value=302,
+	 * 				description=<js>"Thing wasn't found here"</js>,
+	 * 				headers={
+	 * 					<ja>@Parameter</ja>(name=<js>"Location"</js>, description=<js>"The place to find the thing"</js>)
+	 * 				}
+	 * 			)
+	 * 		}
+	 * 	)
+	 * </p>
+	 * This is functionally equivalent to specifying the following keys in the resource bundle for the class, except in this case
+	 * 	the strings are internationalized.
+	 * <p class='bcode'>
+	 * 	<jk>MyClass.myMethod.res.200.description</jk> = <js>OK</js>
+	 * 	<jk>MyClass.myMethod.res.302.description</jk> = <js>Thing wasn't found here</js>
+	 * 	<jk>MyClass.myMethod.res.302.header.Location.description</jk> = <js>The place to find the thing</js>
+	 * <p>
+	 * As a general rule, use annotations when you don't care about internationalization (i.e. you only want to support English),
+	 * 	and use resource bundles if you need to support localization.
+	 * <p>
+	 * These annotations can contain variables (e.g. "$L{my.localized.variable}").
+	 */
+	Response[] responses() default {};
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Parameter.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Parameter.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Parameter.java
index 76c7b77..26c0971 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Parameter.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Parameter.java
@@ -18,16 +18,18 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 
 /**
- * Annotation used in conjunction with {@link RestMethod#parameters()} to identify content and header descriptions
+ * Annotation used in conjunction with {@link MethodSwagger#parameters()} to identify content and header descriptions
  * 	on specific method requests.
  *
  * <h5 class='section'>Example:</h5>
  * <p class='bcode'>
  * 	<ja>@RestMethod</ja>(
  * 		name=<js>"*"</js>,
- * 		parameters={
- * 			<ja>@Parameter</ja>(in=<js>"header"</js>, name=<js>"Range"</js>, description=<js>"$L{ContentRange.description}"</js>)
- * 		}
+ * 		swagger=@MethodSwagger(
+ * 			parameters={
+ * 				<ja>@Parameter</ja>(in=<js>"header"</js>, name=<js>"Range"</js>, description=<js>"$L{ContentRange.description}"</js>)
+ * 			}
+ *			)
  * 	)
  * 	<jk>public void</jk> doAnything(RestRequest req, RestResponse res, <ja>@Method</ja> String method) {
  * 		...

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
new file mode 100644
index 0000000..d925bbc
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
@@ -0,0 +1,177 @@
+// ***************************************************************************************************************************
+// * 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.annotation;
+
+import org.apache.juneau.rest.*;
+
+/**
+ * Extended annotation for {@link RestResource#swagger() @RestResource.swagger()}.
+ */
+public @interface ResourceSwagger {
+	/**
+	 * Optional servlet terms-of-service for this API.
+	 * <p>
+	 * It is used to populate the Swagger terms-of-service field.
+	 * <p>
+	 * The default value pulls the description from the <code>termsOfService</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"termsOfService = foo"</js> or <js>"MyServlet.termsOfService = foo"</js>).
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/info/termsOfService</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getTermsOfService(RestRequest)} method.
+	 */
+	String termsOfService() default "";
+
+	/**
+	 * Optional contact information for the exposed API.
+	 * <p>
+	 * It is used to populate the Swagger contact field and to display on HTML pages.
+	 * <p>
+	 * A simplified JSON string with the following fields:
+	 * <p class='bcode'>
+	 * 	{
+	 * 		name: string,
+	 * 		url: string,
+	 * 		email: string
+	 * 	}
+	 * </p>
+	 * <p>
+	 * The default value pulls the description from the <code>contact</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"contact = {name:'John Smith',email:'john.smith@foo.bar'}"</js> or <js>"MyServlet.contact = {name:'John Smith',email:'john.smith@foo.bar'}"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(contact=<js>"{name:'John Smith',email:'john.smith@foo.bar'}"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/info/contact</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getContact(RestRequest)} method.
+	 */
+	String contact() default "";
+
+	/**
+	 * Optional license information for the exposed API.
+	 * <p>
+	 * It is used to populate the Swagger license field and to display on HTML pages.
+	 * <p>
+	 * A simplified JSON string with the following fields:
+	 * <p class='bcode'>
+	 * 	{
+	 * 		name: string,
+	 * 		url: string
+	 * 	}
+	 * </p>
+	 * <p>
+	 * The default value pulls the description from the <code>license</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"license = {name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js> or <js>"MyServlet.license = {name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/info/license</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getLicense(RestRequest)} method.
+	 */
+	String license() default "";
+
+	/**
+	 * Provides the version of the application API (not to be confused with the specification version).
+	 * <p>
+	 * It is used to populate the Swagger version field and to display on HTML pages.
+	 * <p>
+	 * The default value pulls the description from the <code>version</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"version = 2.0"</js> or <js>"MyServlet.version = 2.0"</js>).
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/info/version</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getVersion(RestRequest)} method.
+	 */
+	String version() default "";
+
+	/**
+	 * Optional tagging information for the exposed API.
+	 * <p>
+	 * It is used to populate the Swagger tags field and to display on HTML pages.
+	 * <p>
+	 * A simplified JSON string with the following fields:
+	 * <p class='bcode'>
+	 * 	[
+	 * 		{
+	 * 			name: string,
+	 * 			description: string,
+	 * 			externalDocs: {
+	 * 				description: string,
+	 * 				url: string
+	 * 			}
+	 * 		}
+	 * 	]
+	 * </p>
+	 * <p>
+	 * The default value pulls the description from the <code>tags</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"tags = [{name:'Foo',description:'Foobar'}]"</js> or <js>"MyServlet.tags = [{name:'Foo',description:'Foobar'}]"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(tags=<js>"[{name:'Foo',description:'Foobar'}]"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/tags</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getTags(RestRequest)} method.
+	 */
+	String tags() default "";
+
+	/**
+	 * Optional external documentation information for the exposed API.
+	 * <p>
+	 * It is used to populate the Swagger external documentation field and to display on HTML pages.
+	 * <p>
+	 * A simplified JSON string with the following fields:
+	 * <p class='bcode'>
+	 * 	{
+	 * 		description: string,
+	 * 		url: string
+	 * 	}
+	 * </p>
+	 * <p>
+	 * The default value pulls the description from the <code>externalDocs</code> entry in the servlet resource bundle.
+	 * 	(e.g. <js>"externalDocs = {url:'http://juneau.apache.org'}"</js> or <js>"MyServlet.externalDocs = {url:'http://juneau.apache.org'}"</js>).
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(externalDocs=<js>"{url:'http://juneau.apache.org'}"</js>)
+	 * </p>
+	 * <p>
+	 * This field can contain variables (e.g. "$L{my.localized.variable}").
+	 * <p>
+	 * Corresponds to the swagger field <code>/tags</code>.
+	 * <p>
+	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getExternalDocs(RestRequest)} method.
+	 */
+	String externalDocs() default "";
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Response.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Response.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Response.java
index 3b72a74..1c1bd39 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Response.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/Response.java
@@ -18,17 +18,19 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 
 /**
- * Annotation used in conjunction with {@link RestMethod#responses()} to identify possible responses by the method.
+ * Annotation used in conjunction with {@link MethodSwagger#responses()} to identify possible responses by the method.
  *
  * <h5 class='section'>Example:</h5>
  * <p class='bcode'>
  * 	<ja>@RestMethod</ja>(
  * 		name=<js>"*"</js>,
- * 		responses={
- * 			<ja>@Response</ja>(value=200,description=<js>"Everything was great."</js>),
- * 			<ja>@Response</ja>(value=404,description=<js>"File was not found."</js>)
- * 			<ja>@Response</ja>(500),
- * 		}
+ * 		swagger=@ResourceSwagger(
+ * 			responses={
+ * 				<ja>@Response</ja>(value=200,description=<js>"Everything was great."</js>),
+ * 				<ja>@Response</ja>(value=404,description=<js>"File was not found."</js>)
+ * 				<ja>@Response</ja>(500),
+ * 			}
+ * 		)
  * 	)
  * 	<jk>public void</jk> doAnything(RestRequest req, RestResponse res, <ja>@Method</ja> String method) {
  * 		...
@@ -70,9 +72,11 @@ public @interface Response {
 	 * <p class='bcode'>
 	 * 	<ja>@RestMethod</ja>(
 	 * 		name=<js>"*"</js>,
-	 * 		responses={
-	 * 			<ja>@Response</ja>(value=200,schema=<js>"{type:'string',description:'A serialized Person bean.'}"</js>),
-	 * 		}
+	 * 		swagger=@MethodSwagger(
+	 * 			responses={
+	 * 				<ja>@Response</ja>(value=200,schema=<js>"{type:'string',description:'A serialized Person bean.'}"</js>),
+	 * 			}
+	 * 		)
 	 * </p>
 	 */
 	String schema() default "";

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index b2fa562..fc770a5 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -21,6 +21,7 @@ import org.apache.juneau.encoders.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.remoteable.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -374,147 +375,6 @@ public @interface RestMethod {
 	String description() default "";
 
 	/**
-	 * Optional external documentation information for the exposed API.
-	 * <p>
-	 * Used to populate the Swagger external documentation field.
-	 * <p>
-	 * A simplified JSON string with the following fields:
-	 * <p class='bcode'>
-	 * 	{
-	 * 		description: string,
-	 * 		url: string
-	 * 	}
-	 * </p>
-	 * <p>
-	 * The default value pulls the description from the <code>(className.?)[javaMethodName].externalDocs</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"MyClass.myMethod.externalDocs = {url:'http://juneau.apache.org'}"</js> or <js>"myMethod.externalDocs = {url:'http://juneau.apache.org'}"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestMethod</ja>(externalDocs=<js>"{url:'http://juneau.apache.org'}"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/paths/{path}/{method}/externalDocs</code>.
-	 */
-	String externalDocs() default "";
-
-	/**
-	 * Optional tagging information for the exposed API.
-	 * <p>
-	 * Used to populate the Swagger tags field.
-	 * <p>
-	 * A comma-delimited list of tags for API documentation control.
-	 * Tags can be used for logical grouping of operations by resources or any other qualifier.
-	 * <p>
-	 * The default value pulls the description from the <code>(className.?)[javaMethodName].tags</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"MyClass.myMethod.tags = foo,bar"</js> or <js>"myMethod.tags = foo,bar"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestMethod</ja>(tags=<js>"foo,bar"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/paths/{path}/{method}/tags</code>.
-	 */
-	String tags() default "";
-
-	/**
-	 * Optional deprecated flag for the exposed API.
-	 * <p>
-	 * Used to populate the Swagger deprecated field.
-	 * <p>
-	 * The default value pulls the description from the <code>(className.?)[javaMethodName].deprecated</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"MyClass.myMethod.deprecated = true"</js> or <js>"myMethod.deprecated = foo,bar"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestMethod</ja>(deprecated=<jk>true</jk>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/paths/{path}/{method}/deprecated</code>.
-	 */
-	boolean deprecated() default false;
-
-	/**
-	 * Optional parameter descriptions.
-	 * <p>
-	 * This annotation is provided for documentation purposes and is used to populate the method <js>"parameters"</js> column
-	 * 	on the Swagger page.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestMethod</ja>(
-	 * 		name=<js>"POST"</js>, path=<js>"/{a}"</js>,
-	 * 		description=<js>"This is my method."</js>,
-	 * 		parameters={
-	 * 			<ja>@Parameter</ja>(in=<js>"path"</js>, name=<js>"a"</js>, description=<js>"The 'a' attribute"</js>),
-	 * 			<ja>@Parameter</ja>(in=<js>"query"</js>, name=<js>"b"</js>, description=<js>"The 'b' parameter"</js>, required=<jk>true</jk>),
-	 * 			<ja>@Parameter</ja>(in=<js>"body"</js>, description=<js>"The HTTP content"</js>),
-	 * 			<ja>@Parameter</ja>(in=<js>"header"</js>, name=<js>"D"</js>, description=<js>"The 'D' header"</js>),
-	 * 		}
-	 * 	)
-	 * </p>
-	 * This is functionally equivalent to specifying the following keys in the resource bundle for the class, except in this case
-	 * 	the strings are internationalized.
-	 * <p class='bcode'>
-	 * 	<jk>MyClass.myMethod.description</jk> = <js>This is my method.</js>
-	 * 	<jk>MyClass.myMethod.req.path.a.description</jk> = <js>The 'a' attribute</js>
-	 * 	<jk>MyClass.myMethod.req.query.b.description</jk> = <js>The 'b' parameter</js>
-	 * 	<jk>MyClass.myMethod.req.body.description</jk> = <js>The HTTP content</js>
-	 * 	<jk>MyClass.myMethod.req.header.d.description</jk> = <js>The 'D' header</js>
-	 * <p>
-	 * As a general rule, use annotations when you don't care about internationalization (i.e. you only want to support English),
-	 * 	and use resource bundles if you need to support localization.
-	 * <p>
-	 * These annotations can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/paths/{path}/{method}/parameters</code>.
-	 */
-	Parameter[] parameters() default {};
-
-	/**
-	 * Optional output description.
-	 * <p>
-	 * This annotation is provided for documentation purposes and is used to populate the method <js>"responses"</js> column
-	 * 	on the Swagger page.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestMethod</ja>(
-	 * 		name=<js>"GET"</js>, path=<js>"/"</js>,
-	 * 		responses={
-	 * 			<ja>@Response</ja>(200),
-	 * 			<ja>@Response</ja>(
-	 * 				value=302,
-	 * 				description=<js>"Thing wasn't found here"</js>,
-	 * 				headers={
-	 * 					<ja>@Parameter</ja>(name=<js>"Location"</js>, description=<js>"The place to find the thing"</js>)
-	 * 				}
-	 * 			)
-	 * 		}
-	 * 	)
-	 * </p>
-	 * This is functionally equivalent to specifying the following keys in the resource bundle for the class, except in this case
-	 * 	the strings are internationalized.
-	 * <p class='bcode'>
-	 * 	<jk>MyClass.myMethod.res.200.description</jk> = <js>OK</js>
-	 * 	<jk>MyClass.myMethod.res.302.description</jk> = <js>Thing wasn't found here</js>
-	 * 	<jk>MyClass.myMethod.res.302.header.Location.description</jk> = <js>The place to find the thing</js>
-	 * <p>
-	 * As a general rule, use annotations when you don't care about internationalization (i.e. you only want to support English),
-	 * 	and use resource bundles if you need to support localization.
-	 * <p>
-	 * These annotations can contain variables (e.g. "$L{my.localized.variable}").
-	 */
-	Response[] responses() default {};
-
-	/**
 	 * Specifies whether this method can be called based on the client version.
 	 * <p>
 	 * The client version is identified via the HTTP request header identified by {@link RestResource#clientVersionHeader()} which
@@ -573,17 +433,22 @@ public @interface RestMethod {
 	String clientVersion() default "";
 
 	/**
-	 * Overrides the HTML page title defined on the servlet via the {@link RestResource#pageTitle() @RestResource.pageTitle()} annotation.
+	 * 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.
 	 */
-	String pageTitle() default "";
+	Class<? extends Widget>[] widgets() default {};
 
 	/**
-	 * Overrides the HTML page text defined on the servlet via the {@link RestResource#pageText() @RestResource.pageText()} annotation.
+	 * Provides swagger-specific metadata on this method.
 	 */
-	String pageText() default "";
+	MethodSwagger swagger() default @MethodSwagger;
 
 	/**
-	 * Overrides the HTML page links defined on the servlet via the {@link RestResource#pageLinks() @RestResource.pageLinks()} annotation.
+	 * Provides HTML-doc-specific metadata on this method.
+	 * <p>
+	 * Information provided here overrides information provided in the servlet-level annotation.
 	 */
-	String pageLinks() default "";
+	HtmlDoc htmldoc() default @HtmlDoc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
index 5e86742..321b11d 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
@@ -21,12 +21,12 @@ import javax.servlet.http.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.Encoder;
-import org.apache.juneau.html.*;
 import org.apache.juneau.ini.*;
 import org.apache.juneau.jena.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.utils.*;
@@ -348,7 +348,7 @@ public @interface RestResource {
 	/**
 	 * Optional servlet title.
 	 * <p>
-	 * It is used to populate the Swagger title field and as a default value for the {@link #pageTitle()} value.
+	 * It is used to populate the Swagger title field and as a default value for the {@link HtmlDoc#title()} value.
 	 * This value can be retrieved programmatically through the {@link RestRequest#getServletTitle()} method.
 	 * <p>
 	 * The default value pulls the label from the <code>label</code> entry in the servlet resource bundle.
@@ -365,7 +365,7 @@ public @interface RestResource {
 	/**
 	 * Optional servlet description.
 	 * <p>
-	 * It is used to populate the Swagger description field and as a default value for the {@link #pageText()} value.
+	 * It is used to populate the Swagger description field and as a default value for the {@link HtmlDoc#description()} value.
 	 * This value can be retrieved programmatically through the {@link RestRequest#getServletDescription()} method.
 	 * <p>
 	 * The default value pulls the description from the <code>description</code> entry in the servlet resource bundle.
@@ -380,161 +380,6 @@ public @interface RestResource {
 	String description() default "";
 
 	/**
-	 * Optional servlet terms-of-service for this API.
-	 * <p>
-	 * It is used to populate the Swagger terms-of-service field.
-	 * <p>
-	 * The default value pulls the description from the <code>termsOfService</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"termsOfService = foo"</js> or <js>"MyServlet.termsOfService = foo"</js>).
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/info/termsOfService</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getTermsOfService(RestRequest)} method.
-	 */
-	String termsOfService() default "";
-
-	/**
-	 * Optional contact information for the exposed API.
-	 * <p>
-	 * It is used to populate the Swagger contact field and to display on HTML pages.
-	 * <p>
-	 * A simplified JSON string with the following fields:
-	 * <p class='bcode'>
-	 * 	{
-	 * 		name: string,
-	 * 		url: string,
-	 * 		email: string
-	 * 	}
-	 * </p>
-	 * <p>
-	 * The default value pulls the description from the <code>contact</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"contact = {name:'John Smith',email:'john.smith@foo.bar'}"</js> or <js>"MyServlet.contact = {name:'John Smith',email:'john.smith@foo.bar'}"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestResource</ja>(contact=<js>"{name:'John Smith',email:'john.smith@foo.bar'}"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/info/contact</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getContact(RestRequest)} method.
-	 */
-	String contact() default "";
-
-	/**
-	 * Optional license information for the exposed API.
-	 * <p>
-	 * It is used to populate the Swagger license field and to display on HTML pages.
-	 * <p>
-	 * A simplified JSON string with the following fields:
-	 * <p class='bcode'>
-	 * 	{
-	 * 		name: string,
-	 * 		url: string
-	 * 	}
-	 * </p>
-	 * <p>
-	 * The default value pulls the description from the <code>license</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"license = {name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js> or <js>"MyServlet.license = {name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestResource</ja>(license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/info/license</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getLicense(RestRequest)} method.
-	 */
-	String license() default "";
-
-	/**
-	 * Provides the version of the application API (not to be confused with the specification version).
-	 * <p>
-	 * It is used to populate the Swagger version field and to display on HTML pages.
-	 * <p>
-	 * The default value pulls the description from the <code>version</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"version = 2.0"</js> or <js>"MyServlet.version = 2.0"</js>).
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/info/version</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getVersion(RestRequest)} method.
-	 */
-	String version() default "";
-
-	/**
-	 * Optional tagging information for the exposed API.
-	 * <p>
-	 * It is used to populate the Swagger tags field and to display on HTML pages.
-	 * <p>
-	 * A simplified JSON string with the following fields:
-	 * <p class='bcode'>
-	 * 	[
-	 * 		{
-	 * 			name: string,
-	 * 			description: string,
-	 * 			externalDocs: {
-	 * 				description: string,
-	 * 				url: string
-	 * 			}
-	 * 		}
-	 * 	]
-	 * </p>
-	 * <p>
-	 * The default value pulls the description from the <code>tags</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"tags = [{name:'Foo',description:'Foobar'}]"</js> or <js>"MyServlet.tags = [{name:'Foo',description:'Foobar'}]"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestResource</ja>(tags=<js>"[{name:'Foo',description:'Foobar'}]"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/tags</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getTags(RestRequest)} method.
-	 */
-	String tags() default "";
-
-	/**
-	 * Optional external documentation information for the exposed API.
-	 * <p>
-	 * It is used to populate the Swagger external documentation field and to display on HTML pages.
-	 * <p>
-	 * A simplified JSON string with the following fields:
-	 * <p class='bcode'>
-	 * 	{
-	 * 		description: string,
-	 * 		url: string
-	 * 	}
-	 * </p>
-	 * <p>
-	 * The default value pulls the description from the <code>externalDocs</code> entry in the servlet resource bundle.
-	 * 	(e.g. <js>"externalDocs = {url:'http://juneau.apache.org'}"</js> or <js>"MyServlet.externalDocs = {url:'http://juneau.apache.org'}"</js>).
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<ja>@RestResource</ja>(externalDocs=<js>"{url:'http://juneau.apache.org'}"</js>)
-	 * </p>
-	 * <p>
-	 * This field can contain variables (e.g. "$L{my.localized.variable}").
-	 * <p>
-	 * Corresponds to the swagger field <code>/tags</code>.
-	 * <p>
-	 * The programmatic equivalent to this annotation is the {@link RestInfoProvider#getExternalDocs(RestRequest)} method.
-	 */
-	String externalDocs() default "";
-
-	/**
 	 * Optional location of configuration file for this servlet.
 	 * <p>
 	 * The configuration file .
@@ -728,116 +573,85 @@ public @interface RestResource {
 	Class<? extends RestInfoProvider> infoProvider() default RestInfoProvider.class;
 
 	/**
-	 * Specifies the page title to use on the HTML view of all pages produced by this resource.
-	 * <p>
-	 * This annotation has no effect on any serializers other than {@link HtmlDocSerializer} and is a shorthand method
-	 * for setting the {@link HtmlDocSerializerContext#HTMLDOC_title} property:
-	 * <p class='bcode'>
-	 * 	<ja>@RestResource</ja>(
-	 * 		properties={
-	 * 			<ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"My Resource Page"</js>)
-	 * 		}
-	 * 	)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault {
-	 * </p>
-	 * <p>
-	 * If not specified, the page title is pulled from one of the following locations:
-	 * <ol>
-	 * 	<li><code>{servletClass}.{methodName}.pageTitle</code> resource bundle value.
-	 * 	<li><code>{servletClass}.pageTitle</code> resource bundle value.
-	 * 	<li><code><ja>@RestResource</ja>(title)</code> annotation.
-	 * 	<li><code>{servletClass}.title</code> resource bundle value.
-	 * 	<li><code>info/title</code> entry in swagger file.
-	 * <ol>
+	 * Specifies the serializer listener class to use for listening for non-fatal errors.
+	 */
+	Class<? extends SerializerListener> serializerListener() default SerializerListener.class;
+
+	/**
+	 * Specifies the parser listener class to use for listening for non-fatal errors.
+	 */
+	Class<? extends ParserListener> parserListener() default ParserListener.class;
+
+	/**
+	 * 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>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
+	 * Widgets are inherited from parent to child, but can be overridden by reusing the widget name.
 	 * <p>
-	 * The programmatic equivalent to this annotation are the {@link RestConfig#setPageTitle(String)}/{@link RestResponse#setPageTitle(Object)} methods.
-	 * <ul class='doctree'>
-	 * 	<li class='info'>
-	 * 		In most cases, you'll simply want to use the <code>@RestResource(title)</code> annotation to specify the page title.
-	 * 		However, this annotation is provided in cases where you want the page title to be different that the one
-	 * 		shown in the swagger document.
-	 * </ul>
+	 * See {@link #htmldoc()} for an example of usage.
 	 */
-	String pageTitle() default "";
+	Class<? extends Widget>[] widgets() default {};
 
 	/**
-	 * Specifies the page text to use on the HTML view of all pages produced by this resource.
+	 * Provides swagger-specific metadata on this resource.
 	 * <p>
-	 * The page text is portion of the page immediately under the title and above the links.
-	 * <p>
-	 * This annotation has no effect on any serializers other than {@link HtmlDocSerializer} and is a shorthand method
-	 * for setting the {@link HtmlDocSerializerContext#HTMLDOC_text} property:
+	 * Used to populate the auto-generated OPTIONS swagger documentation.
+	 *
+	 * <h5 class='section'>Example:</h5>
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		properties={
-	 * 			<ja>@Property</ja>(name=<jsf>HTMLDOC_text</jsf>, value=<js>"This is my awesome resource page"</js>)
-	 * 		}
+	 * 		path=<js>"/addressBook"</js>,
+	 *
+	 * 		<jc>// Swagger info.</jc>
+	 * 		swagger=<ja>@ResourceSwagger</ja>(
+	 * 			contact=<js>"{name:'John Smith',email:'john@smith.com'}"</js>,
+	 * 			license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>,
+	 * 			version=<js>"2.0"</js>,
+	 * 			termsOfService=<js>"You're on your own."</js>,
+	 * 			tags=<js>"[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]"</js>,
+	 * 			externalDocs=<js>"{description:'Home page',url:'http://juneau.apache.org'}"</js>
+	 * 		)
 	 * 	)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault {
 	 * </p>
-	 * If not specified, the page title is pulled from one of the following locations:
-	 * <ol>
-	 * 	<li><code>{servletClass}.{methodName}.pageText</code> resource bundle value.
-	 * 	<li><code>{servletClass}.pageText</code> resource bundle value.
-	 * 	<li><code><ja>@RestMethod</ja>(summary)</code> annotation.
-	 * 	<li><code>{servletClass}.{methodName}.summary</code> resource bundle value.
-	 * 	<li><code>summary</code> entry in swagger file for method.
-	 * 	<li><code>{servletClass}.description</code> resource bundle value.
-	 * 	<li><code>info/description</code> entry in swagger file.
-	 * <ol>
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <p>
-	 * The programmatic equivalent to this annotation are the {@link RestConfig#setPageText(String)}/{@link RestResponse#setPageText(Object)} methods.
-	 * <ul class='doctree'>
-	 * 	<li class='info'>
-	 * 		In most cases, you'll simply want to use the <code>@RestResource(description)</code> or <code>@RestMethod(summary)</code> annotations to specify the page text.
-	 * 		However, this annotation is provided in cases where you want the text to be different that the values shown in the swagger document.
-	 * </ul>
 	 */
-	String pageText() default "";
+	ResourceSwagger swagger() default @ResourceSwagger;
 
 	/**
-	 * Specifies the page hyperlinks to use on the HTML view of all pages produced by this resource.
-	 * <p>
-	 * The page links is positioned immediately under the title and text.
+	 * Provides HTML-doc-specific metadata on this method.
 	 * <p>
-	 * This annotation has no effect on any serializers other than {@link HtmlDocSerializer} and is a shorthand method
-	 * for setting the {@link HtmlDocSerializerContext#HTMLDOC_text} property:
+	 * Used to customize the output from the HTML Doc serializer.
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		properties={
-	 * 			<ja>@Property</ja>(name=<jsf>HTMLDOC_links</jsf>, value=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>)
+	 * 		path=<js>"/addressBook"</js>,
+	 *
+	 * 		<jc>// Links on the HTML rendition page.
+	 * 		// "request:/..." URIs are relative to the request URI.
+	 * 		// "servlet:/..." URIs are relative to the servlet URI.
+	 * 		// "$C{...}" variables are pulled from the config file.</jc>
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>,
+	 * 				aside=<js>""</js>
+	 * 					+ <js>"&lt;div style='max-width:400px;min-width:200px'&gt;"</js>
+	 * 					+ <js>"	&lt;p&gt;Proof-of-concept resource that shows off the capabilities of working with POJO resources.&lt;/p&gt;"</js>
+	 * 					+ <js>"	&lt;p&gt;Provides examples of: &lt;/p&gt;"</js>
+	 * 					+ <js>"		&lt;ul&gt;"</js>
+	 * 					+ <js>"			&lt;li&gt;XML and RDF namespaces"</js>
+	 * 					+ <js>"			&lt;li&gt;Swagger documentation"</js>
+	 * 					+ <js>"			&lt;li&gt;Widgets"</js>
+	 * 					+ <js>"		&lt;/ul&gt;"</js>
+	 * 					+ <js>"	&lt;p style='text-weight:bold;text-decoration:underline;'&gt;Available Content Types&lt;/p&gt;"</js>
+	 * 					+ <js>"	$W{contentTypeLinks}"</js>
+	 * 					+ <js>"&lt;/div&gt;"</js>,
+	 * 			footer=<js>"$W{poweredByJuneau}"</js>
+	 * 		),
+	 *
+	 * 		<jc>// Widgets for $W variables above.</jc>
+	 * 		widgets={
+	 * 			PoweredByJuneauWidget.<jk>class</jk>,
+	 * 			ContentTypeLinksWidget.<jk>class</jk>
 	 * 		}
 	 * 	)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault {
 	 * </p>
-	 * <p>
-	 * The format of this value is a lax-JSON string of key/value pairs where the keys are the link text and the values are relative (to the servlet) or
-	 * absolute URLs.
-	 * If not specified, the page title is pulled from one of the following locations:
-	 * <ol>
-	 * 	<li><code>{servletClass}.{methodName}.pageLinks</code> resource bundle value.
-	 * 	<li><code>{servletClass}.pageLinks</code> resource bundle value.
-	 * <ol>
-	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <p>
-	 * This field can also use URIs of any support type in {@link UriResolver}.
-	 * <p>
-	 * The programmatic equivalent to this annotation are the {@link RestConfig#setPageLinks(String)}/{@link RestResponse#setPageLinks(Object)} methods.
 	 */
-	String pageLinks() default "";
-
-	/**
-	 * Specifies the serializer listener class to use for listening for non-fatal errors.
-	 */
-	Class<? extends SerializerListener> serializerListener() default SerializerListener.class;
-
-	/**
-	 * Specifies the parser listener class to use for listening for non-fatal errors.
-	 */
-	Class<? extends ParserListener> parserListener() default ParserListener.class;
+	HtmlDoc htmldoc() default @HtmlDoc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java
index 4b26bcb..a2099d3 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java
@@ -200,7 +200,6 @@ import org.apache.juneau.xml.*;
 		UrlEncodingSerializer.class,
 		MsgPackSerializer.class,
 		SoapXmlSerializer.class,
-		JsoSerializer.class,
 		PlainTextSerializer.class,
 		RdfSerializer.Xml.class,
 		RdfSerializer.XmlAbbrev.class,
@@ -239,8 +238,10 @@ public abstract class RestServletJenaDefault extends RestServlet {
 	 */
 	@RestMethod(name="OPTIONS", path="/*",
 		summary="Resource options",
-		pageLinks="{back:'$R{servletURI}'}",
-		description="Resource options"
+		description="Resource options",
+		htmldoc=@HtmlDoc(
+			links="{back:'$R{servletURI}'}"
+		)
 	)
 	public Swagger getOptions(RestRequest req) {
 		return req.getSwagger();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
index 5214b64..a5bed6e 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/package.html
@@ -226,7 +226,9 @@
 	 */</jd>
 	<ja>@RestResource</ja>(
 		messages=<js>"nls/HelloWorldResource"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		)
 	)
 	<jk>public class</jk> HelloWorldResource <jk>extends</jk> Resource {
 	
@@ -1084,7 +1086,9 @@
 	 */</jd>
 	<ja>@RestMethod</ja>(name=<js>"OPTIONS"</js>, path=<js>"/*"</js>,
 		summary=<js>"Resource options"</js>,
-		pageLinks=<js>"{back:'$R{servletURI}'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{back:'$R{servletURI}'}"</js>
+		)
 	)
 	<jk>public</jk> Swagger getOptions(RestRequest req) {
 		<jk>return</jk> req.getSwagger();
@@ -1194,8 +1198,8 @@
 		<img class='bordered' src='doc-files/Options2.png'>
 		<p>
 			This method is described through the {@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()}, 
-				{@link org.apache.juneau.rest.annotation.RestMethod#parameters() @RestMethod.parameters()},
-				and {@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()} annotations.
+				{@link org.apache.juneau.rest.annotation.RestMethod#swagger() @RestMethod.swagger()},
+				and {@link org.apache.juneau.rest.annotation.MethodSwagger @MethodSwagger} annotations.
 		</p>
 		<p class='bcode'>
 	<ja>@RestMethod</ja>(
@@ -1275,7 +1279,7 @@
 				<td>
 					A description of the HTTP request body.
 				</td>
-				<td>{@link org.apache.juneau.rest.annotation.RestMethod#parameters() @RestMethod.parameters()}</td>
+				<td>{@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}</td>
 			</tr>
 			<tr>
 				<td><ck>[javaMethodName].req.[category].[name].description</ck></td>
@@ -1283,38 +1287,35 @@
 					A request input variable.
 					<br>Categories: <l>path, query, formData, header</l>
 				</td>
-				<td>{@link org.apache.juneau.rest.annotation.RestMethod#parameters() @RestMethod.parameters()}</td>
+				<td>{@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}</td>
 			</tr>
 			<tr>
 				<td><ck>[javaMethodName].res.[code].description</ck></td>
 				<td>
 					A possible HTTP response code and description.
 				</td>
-				<td>{@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+				<td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
 			</tr>
 			<tr>
 				<td><ck>[javaMethodName].res.[code].body.description</ck></td>
 				<td>
 					A description of response content for the specified HTTP response.
 				</td>
-				<td>{@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+				<td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
 			</tr>
 			<tr>
 				<td><ck>[javaMethodName].res.[code].header.[name].description</ck></td>
 				<td>
 					A response header.
 				</td>
-				<td>{@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+				<td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
 			</tr>
 		</table>
 		<h6 class='topic'>Additional Information</h6>
 		<ul class='doctree'>
 			<li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()}
-			<li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#parameters() @RestMethod.parameters()}
-			<li class='ja'>{@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()}
-			<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getServletTitle()}
-			<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getServletDescription()}
-			<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getMethodDescription()}
+			<li class='ja'>{@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}
+			<li class='ja'>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}
 		</ul>
 	</div>
 
@@ -2174,7 +2175,9 @@
 		messages=<js>"nls/UrlEncodedFormResource"</js>, 
 		title=<js>"URL-encoded Form Post Resource"</js>, 
 		description=<js>"Shows how form posts are converted into beans."</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		)
 	) 
 	<jk>public class</jk> UrlEncodedFormResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -2929,7 +2932,9 @@
 		messages=<js>"nls/PhotosResource"</js>,
 		title=<js>"Photo REST service"</js>,
 		description=<js>"Use a tool like Poster to upload and retrieve jpeg and png images."</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		)
 	)
 	<jk>public class</jk> PhotosResource <jk>extends</jk> RestServletDefault {
 	
@@ -3215,7 +3220,9 @@
 		// "request:/..." URIs are relative to the request URI.
 		// "servlet:/..." URIs are relative to the servlet URI.
 		// "$C{...}" variables are pulled from the config file.</jc>
-		pageLinks=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>
+		),
 
 		<jc>// Properties that get applied to all serializers and parsers.</jc>
 		properties={

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java b/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
index 158aca7..fe7aab6 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
@@ -19,6 +19,7 @@ import java.io.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.serializer.*;
 
@@ -58,11 +59,21 @@ public class DefaultHandler implements ResponseHandler {
 				}
 				p.append("mediaType", mediaType).append("characterEncoding", res.getCharacterEncoding());
 				if (! s.isWriterSerializer()) {
-					OutputStreamSerializer s2 = (OutputStreamSerializer)s;
-					OutputStream os = res.getNegotiatedOutputStream();
-					SerializerSession session = s.createSession(os, p, req.getJavaMethod(), req.getLocale(), req.getHeaders().getTimeZone(), mediaType, req.getUriContext());
-					s2.serialize(session, output);
-					os.close();
+					if (req.isPlainText()) {
+						OutputStreamSerializer s2 = (OutputStreamSerializer)s;
+						Writer w = res.getNegotiatedWriter();
+						ByteArrayOutputStream baos = new ByteArrayOutputStream();
+						SerializerSession session = s.createSession(baos, p, req.getJavaMethod(), req.getLocale(), req.getHeaders().getTimeZone(), mediaType, req.getUriContext());
+						s2.serialize(session, output);
+						w.write(StringUtils.toHex(baos.toByteArray()));
+						w.close();
+					} else {
+						OutputStreamSerializer s2 = (OutputStreamSerializer)s;
+						OutputStream os = res.getNegotiatedOutputStream();
+						SerializerSession session = s.createSession(os, p, req.getJavaMethod(), req.getLocale(), req.getHeaders().getTimeZone(), mediaType, req.getUriContext());
+						s2.serialize(session, output);
+						os.close();
+					}
 				} else {
 					WriterSerializer s2 = (WriterSerializer)s;
 					Writer w = res.getNegotiatedWriter();


[5/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Posted by ja...@apache.org.
Enhancements to HTML Doc rendering.

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

Branch: refs/heads/master
Commit: f4812b7ce2d5f6115f62b0045f8f7983f406c597
Parents: 3bdc0d8
Author: JamesBognar <ja...@apache.org>
Authored: Tue Jun 6 20:27:36 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Tue Jun 6 20:27:36 2017 -0400

----------------------------------------------------------------------
 .../apache/juneau/jena/RdfParserBuilder.java    |   4 +-
 .../juneau/jena/RdfSerializerBuilder.java       |   4 +-
 .../java/org/apache/juneau/jena/package.html    |   4 +-
 .../org/apache/juneau/CoreObjectBuilder.java    |   5 +-
 .../main/java/org/apache/juneau/ObjectMap.java  |   7 +-
 .../java/org/apache/juneau/PropertyStore.java   |  34 ++
 .../org/apache/juneau/csv/CsvParserBuilder.java |   4 +-
 .../apache/juneau/csv/CsvSerializerBuilder.java |   4 +-
 .../apache/juneau/dto/jsonschema/package.html   |   4 +-
 .../juneau/encoders/EncoderGroupBuilder.java    |   2 +-
 .../juneau/html/HtmlBeanPropertyMeta.java       |   3 +-
 .../org/apache/juneau/html/HtmlClassMeta.java   |  12 +
 .../apache/juneau/html/HtmlDocSerializer.java   | 101 +-----
 .../juneau/html/HtmlDocSerializerContext.java   | 289 +++++++++++++--
 .../juneau/html/HtmlDocSerializerSession.java   | 126 +++++--
 .../org/apache/juneau/html/HtmlDocTemplate.java | 164 +++++++++
 .../juneau/html/HtmlDocTemplateBasic.java       | 188 ++++++++++
 .../apache/juneau/html/HtmlParserBuilder.java   |   4 +-
 .../java/org/apache/juneau/html/HtmlRender.java |   2 +-
 .../org/apache/juneau/html/HtmlSerializer.java  |  17 +-
 .../juneau/html/HtmlSerializerBuilder.java      |   4 +-
 .../java/org/apache/juneau/html/HtmlWriter.java |   1 -
 .../org/apache/juneau/html/annotation/Html.java |   2 +-
 .../java/org/apache/juneau/http/MediaType.java  |   7 +-
 .../org/apache/juneau/internal/ClassUtils.java  |  36 +-
 .../org/apache/juneau/internal/ObjectUtils.java |   3 +
 .../org/apache/juneau/jso/JsoParserBuilder.java |   4 +-
 .../apache/juneau/jso/JsoSerializerBuilder.java |   4 +-
 .../apache/juneau/json/JsonParserBuilder.java   |   4 +-
 .../json/JsonSchemaSerializerBuilder.java       |   4 +-
 .../juneau/json/JsonSerializerBuilder.java      |   4 +-
 .../java/org/apache/juneau/json/package.html    |   4 +-
 .../juneau/msgpack/MsgPackParserBuilder.java    |   4 +-
 .../msgpack/MsgPackSerializerBuilder.java       |   4 +-
 .../org/apache/juneau/parser/ParserBuilder.java |   4 +-
 .../juneau/parser/ParserGroupBuilder.java       |   5 +-
 .../plaintext/PlainTextParserBuilder.java       |   4 +-
 .../plaintext/PlainTextSerializerBuilder.java   |   4 +-
 .../juneau/remoteable/RemoteMethodArg.java      |   2 +-
 .../juneau/serializer/SerializerBuilder.java    |   4 +-
 .../serializer/SerializerGroupBuilder.java      |   7 +-
 .../apache/juneau/soap/SoapXmlSerializer.java   |   4 +-
 .../juneau/soap/SoapXmlSerializerBuilder.java   |   4 +-
 .../org/apache/juneau/uon/UonParserBuilder.java |   4 +-
 .../apache/juneau/uon/UonSerializerBuilder.java |   4 +-
 .../java/org/apache/juneau/uon/package.html     |   4 +-
 .../urlencoding/UrlEncodingParserBuilder.java   |   4 +-
 .../UrlEncodingSerializerBuilder.java           |   4 +-
 .../org/apache/juneau/urlencoding/package.html  |   4 +-
 .../org/apache/juneau/xml/XmlParserBuilder.java |   4 +-
 .../juneau/xml/XmlSchemaSerializerBuilder.java  |   4 +-
 .../apache/juneau/xml/XmlSerializerBuilder.java |   4 +-
 .../java/org/apache/juneau/xml/package.html     |   4 +-
 .../main/javadoc/doc-files/NewExamplesPage.png  | Bin 0 -> 426946 bytes
 juneau-core/src/main/javadoc/overview.html      | 221 +++++++++---
 .../juneau/examples/rest/AtomFeedResource.java  |  14 +-
 .../examples/rest/CodeFormatterResource.java    |  57 ++-
 .../juneau/examples/rest/DirectoryResource.java |   4 +-
 .../examples/rest/DockerRegistryResource.java   |   9 +-
 .../juneau/examples/rest/FileSpaceResource.java |   8 +-
 .../examples/rest/HelloWorldResource.java       |  13 +-
 .../examples/rest/JsonSchemaResource.java       |  13 +-
 .../examples/rest/MethodExampleResource.java    |   9 +-
 .../juneau/examples/rest/PhotosResource.java    |  41 ++-
 .../examples/rest/RequestEchoResource.java      |  12 +-
 .../juneau/examples/rest/RootResources.java     |  21 +-
 .../examples/rest/SampleRemoteableServlet.java  |  13 +-
 .../juneau/examples/rest/SqlQueryResource.java  |  15 +-
 .../examples/rest/SystemPropertiesResource.java | 155 ++++----
 .../juneau/examples/rest/TempDirResource.java   |   9 +-
 .../examples/rest/TumblrParserResource.java     |  15 +-
 .../examples/rest/UrlEncodedFormResource.java   |   9 +-
 .../rest/addressbook/AddressBookResource.java   |  49 ++-
 .../examples/rest/CodeFormatterResource.html    |  68 ----
 .../juneau/examples/rest/RootResourcesTest.java |  14 +-
 .../apache/juneau/microservice/Resource.java    |   4 +-
 .../juneau/microservice/ResourceGroup.java      |   4 +-
 .../juneau/microservice/ResourceJena.java       |   4 +-
 .../microservice/resources/ConfigResource.java  |  60 ++--
 .../resources/DirectoryResource.java            |   4 +-
 .../microservice/resources/LogsResource.java    |  47 ++-
 .../org/apache/juneau/rest/client/RestCall.java |   5 +-
 .../juneau/rest/client/RestClientBuilder.java   |   8 +-
 .../org/apache/juneau/rest/client/package.html  |   2 +-
 .../rest/test/HtmlPropertiesResource.java       | 103 ++++--
 .../apache/juneau/rest/test/NlsResource.java    |  76 ++--
 .../juneau/rest/test/HtmlPropertiesTest.java    |  24 --
 .../apache/juneau/rest/test/RestTestcase.java   |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java | 111 ++++--
 .../java/org/apache/juneau/rest/RestConfig.java | 352 ++++++++++++++++--
 .../org/apache/juneau/rest/RestContext.java     | 200 +++++++++--
 .../apache/juneau/rest/RestInfoProvider.java    |  37 +-
 .../org/apache/juneau/rest/RestRequest.java     |  73 +---
 .../org/apache/juneau/rest/RestResponse.java    | 355 +++++++++++++++++--
 .../apache/juneau/rest/RestServletDefault.java  |  11 +-
 .../apache/juneau/rest/annotation/HtmlDoc.java  | 339 ++++++++++++++++++
 .../juneau/rest/annotation/MethodSwagger.java   | 161 +++++++++
 .../juneau/rest/annotation/Parameter.java       |  10 +-
 .../juneau/rest/annotation/ResourceSwagger.java | 177 +++++++++
 .../apache/juneau/rest/annotation/Response.java |  22 +-
 .../juneau/rest/annotation/RestMethod.java      | 159 +--------
 .../juneau/rest/annotation/RestResource.java    | 314 ++++------------
 .../rest/jena/RestServletJenaDefault.java       |   7 +-
 .../java/org/apache/juneau/rest/package.html    |  41 ++-
 .../juneau/rest/response/DefaultHandler.java    |  21 +-
 .../org/apache/juneau/rest/vars/UrlVar.java     |  59 +++
 .../org/apache/juneau/rest/vars/WidgetVar.java  |  63 ++++
 .../rest/widget/ContentTypeLinksWidget.java     |  48 +++
 .../rest/widget/PoweredByJuneauWidget.java      |  35 ++
 .../org/apache/juneau/rest/widget/Widget.java   |  44 +++
 .../org/apache/juneau/rest/styles/devops.css    | 151 ++++----
 111 files changed, 3726 insertions(+), 1317 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index f5ddfdc..05687fa 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -680,8 +680,8 @@ public class RdfParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public RdfParserBuilder debug(boolean value) {
-		super.debug(value);
+	public RdfParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 6bc1a50..f254734 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -855,8 +855,8 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public RdfSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public RdfSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
index c3073ec..c81d3fd 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
@@ -1064,7 +1064,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=RdfProperties.<jsf>RDF_rdfxml_tab</jsf>, value=<js>"3"</js>),
 			<ja>@Property</ja>(name=RdfSerializerContext.<jsf>RDF_addRootProperty</jsf>, value=<js>"true"</js>),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
index f1fb525..5c67e6d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
@@ -1406,12 +1406,11 @@ public abstract class CoreObjectBuilder {
 	 * 	<li>This is equivalent to calling <code>property(<jsf>BEAN_debug</jsf>, value)</code>.
 	 * </ul>
 	 *
-	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @see BeanContext#BEAN_debug
 	 */
-	public CoreObjectBuilder debug(boolean value) {
-		return property(BEAN_debug, value);
+	public CoreObjectBuilder debug() {
+		return property(BEAN_debug, true);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
index 8b057ed..3f6fe6f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
@@ -376,11 +376,16 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 * @param def The default value if the entry doesn't exist.
 	 * @return The value, or the default value if the entry doesn't exist.
 	 */
+	@SuppressWarnings("unchecked")
 	public <T> T get(Class<T> type, String key, T def) {
 		Object o = get(key);
 		if (o == null)
 			return def;
-		T t = session.convertToType(o, type);
+		T t = null;
+		if (session != null)
+			t = session.convertToType(o, type);
+		else if (ClassUtils.isParentClass(type, o.getClass()))
+			t = (T)o;
 		if (t == null)
 			return def;
 		return t;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java b/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
index dc5f064..9e2a33c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
+++ b/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
@@ -645,6 +645,40 @@ public final class PropertyStore {
 	}
 
 	/**
+	 * Returns a property value either cast to the specified type, or a new instance of the specified type.
+	 * <p>
+	 * It's assumed that the current property value is either an instance of that type, or a <code>Class</code> that's
+	 * a subclass of the type to be instantiated.
+	 *
+	 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>)
+	 * @param type The class type to convert the property value to.
+	 * @param def The type to instantiate if the property is not set.
+	 * @param args The arguments to pass to the default type constructor.
+	 *
+	 * @return The property either cast to the specified type, or instantiated from a <code>Class</code> object.
+	 * @throws ConfigException If property has a value that cannot be converted to a boolean.
+	 */
+	@SuppressWarnings("unchecked")
+	public <T> T getTypedProperty(String name, Class<T> type, Class<? extends T> def, Object...args) {
+		rl.lock();
+		try {
+			Object o = null;
+			PropertyMap pm = getPropertyMap(prefix(name));
+			if (pm != null)
+				o = pm.get(name, type, null);
+			if (o == null && def != null)
+				o = ClassUtils.newInstance(type, def, args);
+			if (o == null)
+				return null;
+			if (ClassUtils.isParentClass(type, o.getClass()))
+				return (T)o;
+			throw new FormattedRuntimeException("Invalid object of type {0} found in call to PropertyStore.getTypeProperty({1},{2},{3},...)", o.getClass(), name, type, def);
+		} finally {
+			rl.unlock();
+		}
+	}
+
+	/**
 	 * Returns a property value converted to a {@link LinkedHashMap} with the specified
 	 * 	key and value types.
 	 *

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index a33f9d6..6124708 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -408,8 +408,8 @@ public class CsvParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public CsvParserBuilder debug(boolean value) {
-		super.debug(value);
+	public CsvParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index e752a82..098e9df 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -493,8 +493,8 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public CsvSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public CsvSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
index 8353a46..1551244 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
@@ -407,7 +407,9 @@
 		path=<js>"/jsonSchema"</js>,
 		messages=<js>"nls/JsonSchemaResource"</js>,
 		title=<js>"Sample JSON-Schema document"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		)
 	)
 	<jk>public class</jk> JsonSchemaResource <jk>extends</jk> RestServletJenaDefault {
 	

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
index 4f4de06..2d9a8ed 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
@@ -95,7 +95,7 @@ public class EncoderGroupBuilder {
 	public EncoderGroup build() {
 		List<Encoder> l = new ArrayList<Encoder>();
 		for (Object e : encoders)
-			l.add(e instanceof Class ? newInstance(Encoder.class, (Class<?>)e) : (Encoder)e);
+			l.add(newInstance(Encoder.class, e));
 		Collections.reverse(l);
 		return new EncoderGroup(l.toArray(new Encoder[l.size()]));
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index 63ecbb4..ce0be74 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -14,6 +14,7 @@ package org.apache.juneau.html;
 
 import org.apache.juneau.*;
 import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Metadata on bean properties specific to the HTML serializers and parsers pulled from the {@link Html @Html} annotation on the bean property.
@@ -45,7 +46,7 @@ public final class HtmlBeanPropertyMeta extends BeanPropertyMetaExtended {
 		this.noTables = b.noTables;
 		this.noTableHeaders = b.noTableHeaders;
 		this.asPlainText = b.asPlainText;
-		this.render = b.render.newInstance();
+		this.render = ClassUtils.newInstance(HtmlRender.class, b.render);
 		this.link = b.link;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
index 0ea336e..5442a2d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
@@ -23,6 +23,7 @@ public class HtmlClassMeta extends ClassMetaExtended {
 
 	private final Html html;
 	private final boolean asXml, noTables, noTableHeaders, asPlainText;
+	private final HtmlRender<?> render;
 
 	/**
 	 * Constructor.
@@ -37,11 +38,13 @@ public class HtmlClassMeta extends ClassMetaExtended {
 			noTables = html.noTables();
 			noTableHeaders = html.noTableHeaders();
 			asPlainText = html.asPlainText();
+			render = ClassUtils.newInstance(HtmlRender.class, html.render());
 		} else {
 			asXml = false;
 			noTables = false;
 			noTableHeaders = false;
 			asPlainText = false;
+			render = null;
 		}
 	}
 
@@ -89,4 +92,13 @@ public class HtmlClassMeta extends ClassMetaExtended {
 	public boolean isNoTableHeaders() {
 		return noTableHeaders;
 	}
+
+	/**
+	 * Returns the {@link Html#render()} annotation defined on the class.
+	 *
+	 * @return The value of the {@link Html#render()} annotation.
+	 */
+	public HtmlRender<?> getRender() {
+		return render;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index b51c8d6..65c980a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -17,7 +17,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.dto.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
@@ -47,10 +46,6 @@ import org.apache.juneau.serializer.*;
 @SuppressWarnings("hiding")
 public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
-	// Properties defined in RestServletProperties
-	private static final String
-		REST_method = "RestServlet.method";
-
 	/** Default serializer, all default settings. */
 	public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(PropertyStore.create());
 
@@ -81,89 +76,25 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
 		HtmlDocSerializerSession s = (HtmlDocSerializerSession)session;
 		HtmlWriter w = s.getWriter();
-		UriResolver uriResolver = s.getUriResolver();
-
-		boolean isOptionsPage = session.getProperty(REST_method, "").equalsIgnoreCase("OPTIONS");
+		HtmlDocTemplate t = s.getTemplate();
 
-		// Render the header.
 		w.sTag("html").nl();
-		w.sTag("head").nl();
-
-		String cssUrl = s.getCssUrl();
-		if (cssUrl == null)
-			cssUrl = "servlet:/style.css";
-		cssUrl = uriResolver.resolve(cssUrl);
-
-		w.oTag(1, "style")
-			.attr("type", "text/css")
-			.appendln(">")
-			.append(2, "@import ").q().append(cssUrl).q().appendln(";");
-		if (s.isNoWrap())
-			w.appendln("\n* {white-space:nowrap;}");
-		if (s.getCssImports() != null)
-			for (String cssImport : s.getCssImports())
-				w.append(2, "@import ").q().append(cssImport).q().appendln(";");
-		w.eTag(1, "style").nl();
-		w.eTag("head").nl();
-		w.sTag("body").nl();
-		// Write the title of the page.
-		String title = s.getTitle();
-		if (title == null && isOptionsPage)
-			title = "Options";
-		String description = s.getText();
-		if (title != null)
-			w.oTag(1, "h3").attr("class", "title").append('>').text(title).eTag("h3").nl();
-		if (description != null)
-			w.oTag(1, "h5").attr("class", "description").append('>').text(description).eTag("h5").nl();
-
-		// Write the action links that render above the results.
-		List<Link> actions = new LinkedList<Link>();
-
-		// If this is an OPTIONS request, provide a 'back' link to return to the GET request page.
-		if (! isOptionsPage) {
-			Map<String,String> htmlLinks = s.getLinks();
-			if (htmlLinks != null) {
-				for (Map.Entry<String,String> e : htmlLinks.entrySet()) {
-					String uri = uriResolver.resolve(e.getValue());
-					actions.add(new Link(e.getKey(), uri));
-				}
-			}
-		}
-
-		if (actions.size() > 0) {
-			w.oTag(1, "p").attr("class", "links").append('>').nl();
-			for (Iterator<Link> i = actions.iterator(); i.hasNext();) {
-				Link h = i.next();
-				w.oTag(2, "a").attr("class", "link").attr("href", h.getHref(), true).append('>').append(h.getName()).eTag("a").nl();
-				if (i.hasNext())
-					w.append(3, " - ").nl();
-			}
-			w.eTag(1, "p").nl();
-		}
-
-		s.indent = 3;
-
-		// To allow for page formatting using CSS, we encapsulate the data inside two div tags:
-		// <div class='outerdata'><div class='data' id='data'>...</div></div>
-		w.oTag(1, "div").attr("class","outerdata").append('>').nl();
-		w.oTag(2, "div").attr("class","data").attr("id", "data").append('>').nl();
-		if (isEmptyList(o))
-			w.oTag(3, "p").append('>').append("no results").eTag("p");
-		else
-			super.doSerialize(s, o);
-		w.eTag(2, "div").nl();
-		w.eTag(1, "div").nl();
-
-		w.eTag("body").nl().eTag("html").nl();
+		w.sTag(1, "head").nl();
+		t.head(s, w, this, o);
+		w.eTag(1, "head").nl();
+		w.sTag(1, "body").nl();
+		t.body(s, w, this, o);
+		w.eTag(1, "body").nl();
+		w.eTag("html").nl();
 	}
 
-	private static boolean isEmptyList(Object o) {
-		if (o == null)
-			return false;
-		if (o instanceof Collection && ((Collection<?>)o).size() == 0)
-			return true;
-		if (o.getClass().isArray() && Array.getLength(o) == 0)
-			return true;
-		return false;
+	/**
+	 * Calls the parent {@link #doSerialize(SerializerSession, Object)} method which invokes just the HTML serializer.
+	 * @param session The serializer session.
+	 * @param o The object being serialized.
+	 * @throws Exception
+	 */
+	public void parentSerialize(SerializerSession session, Object o) throws Exception {
+		super.doSerialize(session, o);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
index f2dc494..3d7616a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
@@ -39,11 +39,12 @@ import org.apache.juneau.*;
  * <p class='bcode'>
  * 	<ja>@RestResource</ja>(
  * 		messages=<js>"nls/AddressBookResource"</js>,
- * 		title=<js>"$L{title}"</js>,  <jc>// or pageTitle</jc>
- * 		description=<js>"$L{description}"</js>,  <jc>// or pageText</jc>
- * 		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+ * 		htmldoc=<ja>@HtmlDoc</ja>(
+ * 			title=<js>"$L{title}"</js>,
+ * 			description=<js>"$L{description}"</js>,
+ * 			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+ * 		)
  * 	)
- * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
  * </p>
  *
  * <p>
@@ -101,12 +102,23 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * Shortcuts on <ja>@RestResource</ja> are also provided for this setting:
 	 * <p class='bcode'>
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same title.</jc>
 	 * 	<ja>@RestResource</ja>(
 	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		title=<js>"My title"</js>,  <jc>// or pageTitle</jc>
+	 * 		title=<js>"My title"</js>
+	 * 	)
+	 *
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same title.</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		messages=<js>"nls/AddressBookResource"</js>,
+	 * 		title=<js>"My title in Swagger"</js>,
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			title=<js>"My title in HTML"</js>
+	 * 		)
 	 * 	)
-	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
+	 * <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_title = "HtmlSerializer.title";
 
@@ -147,14 +159,54 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * Shortcuts on <ja>@RestResource</ja> are also provided for this setting:
 	 * <p class='bcode'>
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same description.</jc>
 	 * 	<ja>@RestResource</ja>(
 	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		description=<js>"My description"</js>,  <jc>// or pageText</jc>
+	 * 		description=<js>"My description"</js>
+	 * 	)
+	 *
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same description.</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		messages=<js>"nls/AddressBookResource"</js>,
+	 * 		description=<js>"My description in Swagger"</js>,
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			description=<js>"My description in HTML"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <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_description = "HtmlSerializer.description";
+
+	/**
+	 * <b>Configuration property:</b>  Header section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.header"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to override the contents of the header section on the HTML page.
+	 * The header section normally contains the title and description at the top of the page.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			nav=<js>"&lt:p class='special-navigation'&gt;This is my special navigation content&lt:/p&gt;"</js>
+	 * 		)
 	 * 	)
-	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
+	 * <p>
+	 * When this property is specified, the {@link #HTMLDOC_title} and {@link #HTMLDOC_description} properties are ignored.
+	 * <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_text = "HtmlSerializer.description";
+	public static final String HTMLDOC_header = "HtmlDocSerializer.header";
 
 	/**
 	 * <b>Configuration property:</b>  Page links.
@@ -184,7 +236,6 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * </p>
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		messages=<js>"nls/AddressBookResource"</js>,
 	 * 		properties={
 	 * 			<ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_links</jsf>, value=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>)
 	 * 		}
@@ -199,8 +250,9 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+	 * 		htmldoc=@HtmlDoc(
+	 * 			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+	 * 		)
 	 * 	)
 	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
@@ -213,6 +265,133 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	public static final String HTMLDOC_links_put = "HtmlDocSerializer.links.map.put";
 
 	/**
+	 * <b>Configuration property:</b>  Nav section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nav"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to override the contents of the nav section on the HTML page.
+	 * The nav section normally contains the page links at the top of the page.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			nav=<js>"&lt:p class='special-navigation'&gt;This is my special navigation content&lt:/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * When this property is specified, the {@link #HTMLDOC_links} property is ignored.
+	 * <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";
+
+	/**
+	 * <b>Configuration property:</b>  Aside section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.aside"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specifigy the contents of the aside section on the HTML page.
+	 * The aside section floats on the right of the page for providing content supporting the serialized content of
+	 * 	the page.
+	 * <p>
+	 * By default, the aside section is empty.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			aside=<js>"&lt:ul&gt;&lt:li&gt;Item 1&lt:li&gt;Item 2&lt:li&gt;Item 3&lt:/ul&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <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";
+
+	/**
+	 * <b>Configuration property:</b>  Footer section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.footer"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specify the contents of the footer section on the HTML page.
+	 * <p>
+	 * By default, the footer section is empty.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			footer=<js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <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";
+
+	/**
+	 * <b>Configuration property:</b>  No-results message.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.noResultsMessage"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>"&lt;p&gt;no results&lt;/p&gt;"</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specify the string message used when trying to serialize an empty array or empty list.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			=<js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <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";
+
+	/**
+	 * <b>Configuration property:</b>  Prevent word wrap on page.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nowrap"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <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";
+
+	/**
 	 * <b>Configuration property:</b>  Stylesheet URL.
 	 * <p>
 	 * <ul>
@@ -226,46 +405,80 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * If not specified, defaults to the built-in stylesheet located at <js>"style.css"</js>.
 	 * Note that this stylesheet is controlled by the <code><ja>@RestResource</ja>.stylesheet()</code> annotation.
+	 * <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_cssUrl = "HtmlDocSerializer.cssUrl";
 
 	/**
-	 * <b>Configuration property:</b>  CSS imports.
+	 * <b>Configuration property:</b>  CSS code.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.cssImports.list"</js>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.css.list"</js>
 	 * 	<li><b>Data type:</b> <code>List&lt;String&gt;</code>
 	 * 	<li><b>Default:</b> empty list
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * Imports the specified CSS page URLs into the page.
+	 * Adds the specified CSS instructions to the HTML page.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * </p>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		properties={
+	 * 			<ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_css</jsf>, value=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>)
+	 * 		}
+	 * 	)
+	 * </p>
+	 * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=@HtmlDoc(
+	 * 			css=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>
+	 * 		)
+	 * 	)
+	 * </p>
 	 */
-	public static final String HTMLDOC_cssImports = "HtmlDocSerializer.cssImports.list";
+	public static final String HTMLDOC_css = "HtmlDocSerializer.css.list";
 
 	/**
-	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_cssImports} property.
+	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_css} property.
 	 */
-	public static final String HTMLDOC_cssImports_add = "HtmlDocSerializer.cssImports.list.add";
+	public static final String HTMLDOC_css_add = "HtmlDocSerializer.css.list.add";
 
 	/**
-	 * <b>Configuration property:</b>  Prevent word wrap on page.
+	 * <b>Configuration property:</b>  HTML document template.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nowrap"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.template"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? <jk>extends</jk> HtmlDocTemplate&gt;</code> or {@link HtmlDocTemplate}
+	 * 	<li><b>Default:</b> <code>HtmlDocTemplateBasic.<jk>class</jk></code>
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * Adds <js>"* {white-space:nowrap}"</js> to the style header to prevent word wrapping.
+	 * Specifies the template to use for serializing the page.
+	 * <p>
+	 * By default, the {@link HtmlDocTemplateBasic} class is used to construct the contents of the HTML page, but
+	 * can be overridden with your own custom implementation class.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=@HtmlDoc(
+	 * 			template=MySpecialDocTemplate.<jk>class</jk>
+	 * 		)
+	 * 	)
+	 * </p>
 	 */
-	public static final String HTMLDOC_nowrap = "HtmlDocSerializer.nowrap";
+	public static final String HTMLDOC_template = "HtmlDocSerializer.template";
+
 
-	final String[] cssImports;
+	final String[] css;
 	final Map<String,String> links;
-	final String title, text, cssUrl;
+	final String title, description, header, nav, aside, footer, cssUrl, noResultsMessage;
 	final boolean nowrap;
+	final HtmlDocTemplate template;
 
 	/**
 	 * Constructor.
@@ -276,24 +489,36 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 */
 	public HtmlDocSerializerContext(PropertyStore ps) {
 		super(ps);
-		cssImports = ps.getProperty(HTMLDOC_cssImports, String[].class, new String[0]);
+		css = ps.getProperty(HTMLDOC_css, String[].class, new String[0]);
 		title = ps.getProperty(HTMLDOC_title, String.class, null);
-		text = ps.getProperty(HTMLDOC_text, String.class, null);
+		description = ps.getProperty(HTMLDOC_description, String.class, null);
+		header = ps.getProperty(HTMLDOC_header, String.class, null);
+		nav = ps.getProperty(HTMLDOC_nav, String.class, null);
+		aside = ps.getProperty(HTMLDOC_aside, String.class, null);
+		footer = ps.getProperty(HTMLDOC_footer, String.class, null);
 		cssUrl = ps.getProperty(HTMLDOC_cssUrl, String.class, null);
 		nowrap = ps.getProperty(HTMLDOC_nowrap, boolean.class, false);
-		links = ps.getMap(HTMLDOC_links, String.class, String.class, Collections.<String,String>emptyMap());
+		links = ps.getMap(HTMLDOC_links, String.class, String.class, null);
+		noResultsMessage = ps.getProperty(HTMLDOC_noResultsMessage, String.class, "<p>no results</p>");
+		template = ps.getTypedProperty(HTMLDOC_template, HtmlDocTemplate.class, HtmlDocTemplateBasic.class);
 	}
 
 	@Override /* Context */
 	public ObjectMap asMap() {
 		return super.asMap()
 			.append("HtmlDocSerializerContext", new ObjectMap()
-				.append("cssImports", cssImports)
+				.append("cssImports", css)
 				.append("title", title)
-				.append("text", text)
+				.append("text", description)
+				.append("header", header)
+				.append("nav", nav)
+				.append("links", links)
+				.append("aside", aside)
+				.append("footer", footer)
 				.append("cssUrl", cssUrl)
 				.append("nowrap", nowrap)
-				.append("links", links)
+				.append("template", template)
+				.append("noResultsMessage", noResultsMessage)
 			);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index c9c69b7..5cb8d91 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 
@@ -32,10 +33,11 @@ import org.apache.juneau.serializer.*;
  */
 public final class HtmlDocSerializerSession extends HtmlSerializerSession {
 
-	private final String title, text, cssUrl;
-	private final String[] cssImports;
+	private final String title, description, header, nav, aside, footer, cssUrl, noResultsMessage;
+	private final String[] css;
 	private final Map<String,String> links;
 	private final boolean nowrap;
+	private final HtmlDocTemplate template;
 
 	/**
 	 * Create a new session using properties specified in the context.
@@ -59,73 +61,139 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession {
 		super(ctx, op, output, javaMethod, locale, timeZone, mediaType, uriContext);
 		if (op == null || op.isEmpty()) {
 			title = ctx.title;
-			text = ctx.text;
+			description = ctx.description;
+			header = ctx.header;
+			nav = ctx.nav;
+			aside = ctx.aside;
+			footer = ctx.footer;
 			links = ctx.links;
 			cssUrl = ctx.cssUrl;
-			cssImports = ctx.cssImports;
+			css = ctx.css;
 			nowrap = ctx.nowrap;
+			noResultsMessage = ctx.noResultsMessage;
+			template = ClassUtils.newInstance(HtmlDocTemplate.class, ctx.template);
 		} else {
 			title = op.getString(HTMLDOC_title, ctx.title);
-			text = op.getString(HTMLDOC_text, ctx.text);
-			links = new LinkedHashMap(op.getMap(HTMLDOC_links, ctx.links));
+			description = op.getString(HTMLDOC_description, ctx.description);
+			header = op.getString(HTMLDOC_header, ctx.nav);
+			nav = op.getString(HTMLDOC_nav, ctx.nav);
+			aside = op.getString(HTMLDOC_aside, ctx.aside);
+			footer = op.getString(HTMLDOC_footer, ctx.footer);
+			Map m = op.getMap(HTMLDOC_links, ctx.links);
+			links = ObjectUtils.isEmpty(m) ? null : new LinkedHashMap(m);
 			cssUrl = op.getString(HTMLDOC_cssUrl, ctx.cssUrl);
-			cssImports = split(op.getString(HTMLDOC_cssImports, null), ',');
+			css = split(op.getString(HTMLDOC_css, null), ',');
 			nowrap = op.getBoolean(HTMLDOC_cssUrl, ctx.nowrap);
+			noResultsMessage = op.getString(HTMLDOC_noResultsMessage, ctx.noResultsMessage);
+			template = ClassUtils.newInstance(HtmlDocTemplate.class, op.get(HTMLDOC_template, ctx.template));
 		}
 	}
 
 	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getCssUrl() {
+		return cssUrl;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty array.
+	 */
+	public final String[] getCss() {
+		return css;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 */
+	public final boolean isNoWrap() {
+		return nowrap;
+	}
+
+	/**
 	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_title} setting value in this context.
-	 *
 	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_title} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
 	public final String getTitle() {
 		return title;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_text} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_text} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_description} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_description} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_header} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_header} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final String getText() {
-		return text;
+	public final String getHeader() {
+		return header;
 	}
 
 	/**
 	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_links} setting value in this context.
-	 *
 	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_links} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty map.
 	 */
 	public final Map<String,String> getLinks() {
 		return links;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * Returns the template to use for generating the HTML page.
+	 * @return The HTML page generator.
+	 * 	Never <jk>null</jk>.
 	 */
-	public final String getCssUrl() {
-		return cssUrl;
+	public final HtmlDocTemplate getTemplate() {
+		return template;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssImports} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssImports} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nav} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nav} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final String[] getCssImports() {
-		return cssImports;
+	public final String getNav() {
+		return nav;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_aside} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_aside} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final boolean isNoWrap() {
-		return nowrap;
+	public final String getAside() {
+		return aside;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_footer} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_footer} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getFooter() {
+		return footer;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_noResultsMessage} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_noResultsMessage} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getNoResultsMessage() {
+		return noResultsMessage;
 	}
 
 	@Override /* XmlSerializerSession */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
new file mode 100644
index 0000000..f850b6b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
@@ -0,0 +1,164 @@
+// ***************************************************************************************************************************
+// * 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.html;
+
+/**
+ * Defines the interface for rendering the contents of an HTML page produced by the {@link HtmlDocSerializer} serializer.
+ * <p>
+ * The HTML doc serializer produces the following document structure with the typical contents:
+ * <p class='bcode'>
+ * 	<xt>&lt;html&gt;
+ * 		&lt;head&gt;
+ * 			&lt;style <xa>type</xa>=<xs>'text/css'</xs>&gt;
+ * 				<xv>CSS styles and links to stylesheets</xv>
+ * 			&lt/style&gt;
+ * 		&lt;/head&gt;
+ * 		&lt;body&gt;
+ * 			&lt;header&gt;
+ * 				<xv>Page title and description</xv>
+ * 			&lt;/header&gt;
+ * 			&lt;nav&gt;
+ * 				<xv>Page links</xv>
+ * 			&lt;/nav&gt;
+ * 			&lt;aside&gt;
+ * 				<xv>Side-bar page links</xv>
+ * 			&lt;/aside&gt;
+ * 			&lt;article&gt;
+ * 				<xv>Contents of serialized object</xv>
+ * 			&lt;/article&gt;
+ * 			&lt;footer&gt;
+ * 				<xv>Footer message</xv>
+ * 			&lt;/footer&gt;
+ * 		&lt;/body&gt;
+ * 	&lt;/html&gt;</xt>
+ * </p>
+ * <p>
+ * This interface allows you to control how these sections get rendered.
+ */
+public interface HtmlDocTemplate {
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;head&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;head&gt;</xt> / <xt>&lt;style</xt> <xa>type</xa>=<xs>"text/css"</xs><xt>&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void body(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;header&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void header(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;nav&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void nav(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;article&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void article(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;aside&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void aside(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;footer&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void footer(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;head&gt;</xt> / <xt>&lt;style</xt> <xa>type</xa>=<xs>"text/css"</xs><xt>&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasCss(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>header</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasHeader(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>nav</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasNav(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>aside</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasAside(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>footer</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasFooter(HtmlDocSerializerSession session);
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
new file mode 100644
index 0000000..6553fdb
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
@@ -0,0 +1,188 @@
+// ***************************************************************************************************************************
+// * 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.html;
+
+import java.util.Map;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * A basic template for the HTML doc serializer.
+ * <p>
+ * This class can be subclassed to customize page rendering.
+ */
+public class HtmlDocTemplateBasic implements HtmlDocTemplate {
+
+	@Override /* HtmlDocTemplate */
+	public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		if (hasCss(session)) {
+			w.oTag(1, "style").attr("type", "text/css").appendln(">").nl();
+			css(session, w, s, o);
+			w.eTag(1, "style").nl();
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+
+		String cssUrl = session.getCssUrl();
+		if (cssUrl == null)
+			cssUrl = "servlet:/style.css";
+		cssUrl = session.resolveUri(cssUrl);
+
+		w.append(2, "@import ").q().append(cssUrl).q().appendln(";");
+		if (session.isNoWrap())
+			w.appendln("\n* {white-space:nowrap;}");
+		if (session.getCss() != null)
+			for (String css : session.getCss())
+				w.appendln(css);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void body(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+
+		if (hasHeader(session)) {
+			w.sTag(1, "header").nl();
+			header(session, w, s, o);
+			w.eTag(1, "header").nl();
+		}
+
+		if (hasNav(session)) {
+			w.sTag(1, "nav").nl();
+			nav(session, w, s, o);
+			w.eTag(1, "nav").nl();
+		}
+
+		w.sTag(1, "section").nl();
+
+		w.sTag(2, "article").nl();
+		article(session, w, s, o);
+		w.eTag(2, "article").nl();
+
+		if (hasAside(session)) {
+			w.sTag(2, "aside").nl();
+			aside(session, w, s, o);
+			w.eTag(2, "aside").nl();
+		}
+
+		w.eTag(1, "section").nl();
+
+		if (hasFooter(session)) {
+			w.sTag(1, "footer").nl();
+			footer(session, w, s, o);
+			w.eTag(1, "footer").nl();
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void header(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		// Write the title of the page.
+		String header = session.getHeader();
+		if (header != null) {
+			if (exists(header))
+				w.append(header).nl();
+		} else {
+			String title = session.getTitle();
+			String description = session.getDescription();
+			if (exists(title))
+				w.oTag(1, "h3").attr("class", "title").append('>').text(title).eTag("h3").nl();
+			if (exists(description))
+				w.oTag(1, "h5").attr("class", "description").append('>').text(description).eTag("h5").nl();
+		}
+	}
+
+
+	@Override /* HtmlDocTemplate */
+	public void nav(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String nav = session.getNav();
+		if (nav != null) {
+			if (exists(nav))
+				w.append(nav).nl();
+		} else {
+			Map<String,String> htmlLinks = session.getLinks();
+			boolean first = true;
+			if (htmlLinks != null) {
+				for (Map.Entry<String,String> e : htmlLinks.entrySet()) {
+					if (! first)
+						w.append(3, " - ").nl();
+					first = false;
+					w.oTag("a").attr("class", "link").attr("href", session.resolveUri(e.getValue()), true).cTag().text(e.getKey(), true).eTag("a");
+				}
+			}
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void aside(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String aside = session.getAside();
+		if (exists(aside))
+			w.append(aside);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void article(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		// To allow for page formatting using CSS, we encapsulate the data inside two div tags:
+		// <div class='outerdata'><div class='data' id='data'>...</div></div>
+		w.oTag(3, "div").attr("class","outerdata").append('>').nl();
+		w.oTag(4, "div").attr("class","data").attr("id", "data").append('>').nl();
+
+		if (o == null) {
+			w.append("<null/>").nl();
+		} else if (ObjectUtils.isEmpty(o)){
+			String m = session.getNoResultsMessage();
+			if (exists(m))
+				w.append(m).nl();
+		} else {
+			s.parentSerialize(session, o);
+		}
+
+		w.eTag(4, "div").nl();
+		w.eTag(3, "div").nl();
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void footer(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String footer = session.getFooter();
+		if (exists(footer))
+			w.append(footer);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasCss(HtmlDocSerializerSession session) {
+		return true;
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasHeader(HtmlDocSerializerSession session) {
+		return exists(session.getHeader()) || exists(session.getTitle()) || exists(session.getDescription());
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasNav(HtmlDocSerializerSession session) {
+		return exists(session.getNav()) || session.getLinks() != null;
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasAside(HtmlDocSerializerSession session) {
+		return exists(session.getAside());
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasFooter(HtmlDocSerializerSession session) {
+		return exists(session.getFooter());
+	}
+
+	private static boolean exists(String s) {
+		return s != null && ! "NONE".equals(s);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index 4c2c283..7418e1b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -437,8 +437,8 @@ public class HtmlParserBuilder extends XmlParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public HtmlParserBuilder debug(boolean value) {
-		super.debug(value);
+	public HtmlParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
index b30c67e..b31fea7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
@@ -118,7 +118,7 @@ import org.apache.juneau.serializer.*;
  * </p>
  * @param <T> The bean property type.
  */
-public class HtmlRender<T> {
+public abstract class HtmlRender<T> {
 
 	/**
 	 * Returns the CSS style of the element containing the bean property value.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 0bb39b8..f17f7d7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -424,6 +424,8 @@ public class HtmlSerializer extends XmlSerializer {
 			HtmlBeanPropertyMeta hbpMeta = pMeta.getExtendedMeta(HtmlBeanPropertyMeta.class);
 			String link = hbpMeta.getLink();
 			HtmlRender render = hbpMeta.getRender();
+			if (render == null)
+				render = cMeta.getExtendedMeta(HtmlClassMeta.class).getRender();
 
 			String key = p.getName();
 			Object value = p.getValue();
@@ -437,7 +439,7 @@ public class HtmlSerializer extends XmlSerializer {
 			out.sTag(i+1, "tr").nl();
 			out.sTag(i+2, "td").text(key).eTag("td").nl();
 			out.oTag(i+2, "td");
-			String style = render.getStyle(session, value);
+			String style = render == null ? null : render.getStyle(session, value);
 			if (style != null)
 				out.attr("style", style);
 			out.cTag();
@@ -445,7 +447,7 @@ public class HtmlSerializer extends XmlSerializer {
 			try {
 				if (link != null)
 					out.oTag(i+3, "a").attrUri("href", m.resolveVars(link)).cTag();
-				ContentResult cr = serializeAnything(session, out, render.getContent(session, value), cMeta, key, 2, pMeta, false);
+				ContentResult cr = serializeAnything(session, out, render == null ? value : render.getContent(session, value), cMeta, key, 2, pMeta, false);
 				if (cr == CR_NORMAL)
 					out.i(i+2);
 				if (link != null)
@@ -548,17 +550,22 @@ public class HtmlSerializer extends XmlSerializer {
 						BeanPropertyMeta pMeta = p.getMeta();
 						HtmlBeanPropertyMeta hpMeta = pMeta.getExtendedMeta(HtmlBeanPropertyMeta.class);
 						String link = hpMeta.getLink();
-						HtmlRender render = hpMeta.getRender();
 
 						Object value = p.getValue();
+						ClassMeta<?> cMeta = session.getClassMetaForObject(value);
+
+						HtmlRender render = hpMeta.getRender();
+						if (render == null)
+							render = cMeta.getExtendedMeta(HtmlClassMeta.class).getRender();
+
 						out.oTag(i+2, "td");
-						String style = render.getStyle(session, value);
+						String style = render == null ? null : render.getStyle(session, value);
 						if (style != null)
 							out.attr("style", style);
 						out.cTag();
 						if (link != null)
 							out.oTag(i+3, "a").attrUri("href", m2.resolveVars(link)).cTag();
-						ContentResult cr = serializeAnything(session, out, render.getContent(session, value), pMeta.getClassMeta(), p.getKey().toString(), 2, pMeta, false);
+						ContentResult cr = serializeAnything(session, out, render == null ? value : render.getContent(session, value), pMeta.getClassMeta(), p.getKey().toString(), 2, pMeta, false);
 						if (cr == CR_NORMAL)
 							out.i(i+2);
 						if (link != null)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index c2f4112..13aa762 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -671,8 +671,8 @@ public class HtmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public HtmlSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public HtmlSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
index d8648b4..192a73b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
@@ -347,5 +347,4 @@ public class HtmlWriter extends XmlWriter {
 		super.append(c);
 		return this;
 	}
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java b/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
index dcfc53c..3ada90e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
@@ -57,7 +57,7 @@ public @interface Html {
 	/**
 	 * Associates an {@link HtmlRender} with a bean property for custom HTML rendering of the property.
 	 * <p>
-	 * This annotation applies to bean properties only.
+	 * This annotation applies to bean properties and classes.
 	 */
 	@SuppressWarnings("rawtypes")
 	Class<? extends HtmlRender> render() default HtmlRender.class;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
index a11d658..fc6452a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
+++ b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
@@ -32,7 +32,7 @@ import org.apache.juneau.json.*;
  */
 @BeanIgnore
 @SuppressWarnings("unchecked")
-public class MediaType {
+public class MediaType implements Comparable<MediaType> {
 
 	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
 	private static final ConcurrentHashMap<String,MediaType> cache = new ConcurrentHashMap<String,MediaType>();
@@ -280,4 +280,9 @@ public class MediaType {
 	public boolean equals(Object o) {
 		return this == o;
 	}
+
+	@Override
+	public int compareTo(MediaType o) {
+		return mediaType.compareTo(o.mediaType);
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
index ef46ffc..f4ebf10 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -301,6 +301,16 @@ public final class ClassUtils {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if the specified class is abstract.
+	 *
+	 * @param c The class.
+	 * @return <jk>true</jk> if the specified class is abstract.
+	 */
+	public static boolean isAbstract(Class<?> c) {
+		return Modifier.isAbstract(c.getModifiers());
+	}
+
+	/**
 	 * Returns <jk>true</jk> if the specified method is public.
 	 *
 	 * @param m The method.
@@ -745,20 +755,30 @@ public final class ClassUtils {
 	 *
 	 * @param c The class to cast to.
 	 * @param c2 The class to instantiate.
+	 * 	Can also be an instance of the class.
 	 * @param args The arguments to pass to the constructor.
-	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk>.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
 	 * @throws RuntimeException if constructor could not be found or called.
 	 */
 	@SuppressWarnings("unchecked")
-	public static <T> T newInstance(Class<T> c, Class<?> c2, Object...args) {
+	public static <T> T newInstance(Class<T> c, Object c2, Object...args) {
 		if (c2 == null)
 			return null;
-		try {
-			if (args.length == 0)
-				return (T)c2.newInstance();
-			return (T)c2.getConstructor(getClasses(args)).newInstance(args);
-		} catch (Exception e) {
-			throw new RuntimeException("Could not instantiate class " + c.getName(), e);
+		if (c2 instanceof Class) {
+			try {
+				Class<?> c3 = (Class<?>)c2;
+				if (c3.isInterface() || isAbstract(c3))
+					return null;
+				if (args.length == 0)
+					return (T)c3.newInstance();
+				return (T)c3.getConstructor(getClasses(args)).newInstance(args);
+			} catch (Exception e) {
+				throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName());
+			}
+		} else if (isParentClass(c, c2.getClass())) {
+			return (T)c2;
+		} else {
+			throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass());
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
index 699b0fc..73f73d4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
@@ -44,6 +44,7 @@ public class ObjectUtils {
 	 * <ul>
 	 * 	<li><jk>null</jk>
 	 * 	<li>An empty Collection
+	 * 	<li>An empty Map
 	 * 	<li>An empty array
 	 * 	<li>An empty CharSequence
 	 * 	<li>An empty String when serialized to a string using {@link Object#toString()}.
@@ -58,6 +59,8 @@ public class ObjectUtils {
 			return true;
 		if (o instanceof Collection)
 			return ((Collection)o).isEmpty();
+		if (o instanceof Map)
+			return ((Map)o).isEmpty();
 		if (o.getClass().isArray())
 			return (Array.getLength(o) == 0);
 		return o.toString().isEmpty();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index aa5e448..2052f42 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -409,8 +409,8 @@ public class JsoParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsoParserBuilder debug(boolean value) {
-		super.debug(value);
+	public JsoParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index 1da92e6..bd2e498 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -493,8 +493,8 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsoSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsoSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index 40cfd30..94b3340 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -409,8 +409,8 @@ public class JsonParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonParserBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index d58aca2..e9ee47f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -511,8 +511,8 @@ public class JsonSchemaSerializerBuilder extends JsonSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonSchemaSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonSchemaSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 98ed08c..92adbd4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -558,8 +558,8 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/package.html b/juneau-core/src/main/java/org/apache/juneau/json/package.html
index 960ea0b..c32bd3c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/json/package.html
@@ -1004,7 +1004,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>),
 			<ja>@Property</ja>(name=HtmlSerializerContext.<jsf>HTML_uriAnchorText</jsf>, value=<jsf>TO_STRING</jsf>)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 38d2841..de0744c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -409,8 +409,8 @@ public class MsgPackParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public MsgPackParserBuilder debug(boolean value) {
-		super.debug(value);
+	public MsgPackParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index fc4935f..d0e79b7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -493,8 +493,8 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public MsgPackSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public MsgPackSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index dbc9d86..b15ab39 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -537,8 +537,8 @@ public class ParserBuilder extends CoreObjectBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public ParserBuilder debug(boolean value) {
-		super.debug(value);
+	public ParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index 0eb2e92..1731af9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -860,12 +860,11 @@ public class ParserGroupBuilder {
 	/**
 	 * Sets the {@link BeanContext#BEAN_debug} property on all parsers in this group.
 	 *
-	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @see BeanContext#BEAN_debug
 	 */
-	public ParserGroupBuilder debug(boolean value) {
-		return property(BEAN_debug, value);
+	public ParserGroupBuilder debug() {
+		return property(BEAN_debug, true);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index 9f9177d..3540188 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -409,8 +409,8 @@ public class PlainTextParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public PlainTextParserBuilder debug(boolean value) {
-		super.debug(value);
+	public PlainTextParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index 883053a..8995da2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -493,8 +493,8 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public PlainTextSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public PlainTextSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
index cf2326b..140d9f8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
+++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
@@ -55,6 +55,6 @@ public class RemoteMethodArg {
 		this.name = name.isEmpty() ? name2 : name;
 		this.index = index;
 		this.skipIfNE = skipIfNE;
-		this.serializer = (serializer == PartSerializer.class ? null : newInstance(PartSerializer.class, serializer));
+		this.serializer = newInstance(PartSerializer.class, serializer);
 	}
 }



[4/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index 3716d23..0d3a773 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -902,8 +902,8 @@ public class SerializerBuilder extends CoreObjectBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public SerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public SerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index 74f923a..65c188d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -1017,14 +1017,13 @@ public class SerializerGroupBuilder {
 	}
 
 	/**
-	 * Sets the {@link BeanContext#BEAN_debug} property on all serializers in this group.
+	 * Sets the {@link BeanContext#BEAN_debug} property to <jk>true</jk> on all serializers in this group.
 	 *
-	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @see BeanContext#BEAN_debug
 	 */
-	public SerializerGroupBuilder debug(boolean value) {
-		return property(BEAN_debug, value);
+	public SerializerGroupBuilder debug() {
+		return property(BEAN_debug, true);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
index 81580f2..580a799 100644
--- a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
@@ -68,14 +68,14 @@ public final class SoapXmlSerializer extends XmlSerializer {
 			.attr("xmlns", "soap", s.getProperty(SOAPXML_SOAPAction, "http://www.w3.org/2003/05/soap-envelope"))
 			.appendln(">");
 		w.sTag(1, "soap", "Body").nl();
-		super.serialize(s, o);
+		super.doSerialize(s, o);
 		w.eTag(1, "soap", "Body").nl();
 		w.eTag("soap", "Envelope").nl();
 	}
 
 	@Override /* Serializer */
 	public ObjectMap getResponseHeaders(ObjectMap properties) {
-		return super.getResponseHeaders(properties)
+		return new ObjectMap(super.getResponseHeaders(properties))
 			.append("SOAPAction", properties.getString(SOAPXML_SOAPAction, "http://www.w3.org/2003/05/soap-envelope"));
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
index ad67be4..c95c349 100644
--- a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
@@ -555,8 +555,8 @@ public class SoapXmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public SoapXmlSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public SoapXmlSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
index 4d1f576..e4eccd1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
@@ -447,8 +447,8 @@ public class UonParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public UonParserBuilder debug(boolean value) {
-		super.debug(value);
+	public UonParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index b64350e..d031a9b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -535,8 +535,8 @@ public class UonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public UonSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public UonSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/uon/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/package.html b/juneau-core/src/main/java/org/apache/juneau/uon/package.html
index 440f5b2..0050e8a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/package.html
@@ -988,7 +988,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_useWhitespace</jsf>, value=<js>"true"</js>)
 		},

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
index 56b8448..731ea51 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
@@ -466,8 +466,8 @@ public class UrlEncodingParserBuilder extends UonParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public UrlEncodingParserBuilder debug(boolean value) {
-		super.debug(value);
+	public UrlEncodingParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
index 5fee28f..4c307b5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
@@ -598,8 +598,8 @@ public class UrlEncodingSerializerBuilder extends UonSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public UrlEncodingSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public UrlEncodingSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html b/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html
index 88349fc..445bcc6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html
@@ -988,7 +988,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_useWhitespace</jsf>, value=<js>"true"</js>)
 		},

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
index fcde50e..eaf97f8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
@@ -568,8 +568,8 @@ public class XmlParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public XmlParserBuilder debug(boolean value) {
-		super.debug(value);
+	public XmlParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
index 37e7061..7fba517 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
@@ -535,8 +535,8 @@ public class XmlSchemaSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public XmlSchemaSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public XmlSchemaSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index 339904b..a4db76c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -681,8 +681,8 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public XmlSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public XmlSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/xml/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/package.html b/juneau-core/src/main/java/org/apache/juneau/xml/package.html
index 4b293da..672ca2f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/package.html
@@ -2922,7 +2922,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>),
 			<ja>@Property</ja>(name=HtmlSerializerContext.<jsf>HTML_uriAnchorText</jsf>, value=<jsf>TO_STRING</jsf>)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/javadoc/doc-files/NewExamplesPage.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/doc-files/NewExamplesPage.png b/juneau-core/src/main/javadoc/doc-files/NewExamplesPage.png
new file mode 100644
index 0000000..265e727
Binary files /dev/null and b/juneau-core/src/main/javadoc/doc-files/NewExamplesPage.png differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html
index 9488d20..bc56b1e 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -2196,7 +2196,9 @@
 		<jc>// Links on the HTML rendition page.
 		// "request:/..." URIs are relative to the request URI.
 		// "servlet:/..." URIs are relative to the servlet URI.</jc>
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		),
 		
 		<jc>// Properties that get applied to all serializers and parsers.</jc>
 		properties={
@@ -2211,12 +2213,14 @@
 		encoders=GzipEncoder.<jk>class</jk>,
 
 		<jc>// Swagger info.</jc>
-		contact=<js>"{name:'John Smith',email:'john@smith.com'}"</js>,
-		license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>,
-		version=<js>"2.0"</js>,
-		termsOfService=<js>"You're on your own."</js>,
-		tags=<js>"[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]"</js>,
-		externalDocs=<js>"{description:'Home page',url:'http://juneau.apache.org'}"</js>
+		swagger=<ja>@ResourceSwagger</ja>(
+			contact=<js>"{name:'John Smith',email:'john@smith.com'}"</js>,
+			license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>,
+			version=<js>"2.0"</js>,
+			termsOfService=<js>"You're on your own."</js>,
+			tags=<js>"[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]"</js>,
+			externalDocs=<js>"{description:'Home page',url:'http://juneau.apache.org'}"</js>
+		)
 	)
 	<jk>public class</jk> SystemPropertiesResource <jk>extends</jk> RestServletDefault {
 	
@@ -3000,7 +3004,9 @@
 	<ja>@RestResource</ja>(
 		path=<js>"/"</js>,
 		messages=<js>"nls/RootResources"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		children={
 			HelloWorldResource.<jk>class</jk>, 
 			MethodExampleResource.<jk>class</jk>, 
@@ -3093,7 +3099,9 @@
 	<ja>@RestResource</ja>( 
 		messages=<js>"nls/HelloWorldResource"</js>, 
 		path=<js>"/helloWorld"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		)
 	) 
 	<jk>public class</jk> HelloWorldResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -3168,7 +3176,9 @@
 	<ja>@RestResource</ja>( 
 		path=<js>"/methodExample"</js>, 
 		messages=<js>"nls/MethodExampleResource"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		)
 	) 
 	<jk>public class</jk> MethodExampleResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -3372,7 +3382,9 @@
 		</p>
 		<p class='bcode'>
 	<ja>@RestResource</ja>(
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		)
 	)
 		</p>
 		<p>
@@ -3637,7 +3649,9 @@
 	<ja>@RestResource</ja>(
 		path=<js>"/echo"</js>,
 		messages=<js>"nls/RequestEchoResource"</js>,
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
+		),
 		properties={
 			<ja>@Property</ja>(name=<jsf>SERIALIZER_maxDepth</jsf>, value=<js>"10"</js>),
 			<ja>@Property</ja>(name=<jsf>SERIALIZER_detectRecursions</jsf>, value=<js>"true"</js>)
@@ -4098,7 +4112,9 @@
 		// "request:/..." URIs are relative to the request URI.
 		// "servlet:/..." URIs are relative to the servlet URI.
 		// "$C{...}" variables are pulled from the config file.</jc>
-		pageLinks=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>
+		),
 
 		<jc>// Properties that get applied to all serializers and parsers.</jc>
 		properties={
@@ -4766,7 +4782,9 @@
 		messages=<js>"nls/SampleRemoteableServlet"</js>, 
 		title=<js>"Remoteable Service Proxy API"</js>, 
 		description=<js>"Sample class showing how to use remoteable proxies. The list below are exposed services that can be retrieved using RestClient.getProxyInterface(Class)."</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>, 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		),
 		properties={ 
 			<jc>// Allow us to use method=POST from a browser.</jc> 
 			<ja>@Property</ja>(name=<jsf>REST_allowMethodParam</jsf>, value=<js>"*"</js>) 
@@ -4870,7 +4888,9 @@
 	<ja>@RestResource</ja>( 
 		path=<js>"/tempDir"</js>, 
 		messages=<js>"nls/TempDirResource"</js>, 
-		pageLinks=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>
+		),
 		properties={ 
 			<ja>@Property</ja>(name=<js>"DirectoryResource.rootDir"</js>, value=<js>"$S{java.io.tmpdir}"</js>), 
 			<ja>@Property</ja>(name=<js>"DirectoryResource.allowViews"</js>, value=<js>"true"</js>), 
@@ -4988,7 +5008,9 @@
 	<ja>@RestResource</ja>( 
 		path=<js>"/atom"</js>, 
 		messages=<js>"nls/AtomFeedResource"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
+		),
 		properties={ 
 			<ja>@Property</ja>(name=<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>), 
 			<ja>@Property</ja>(name=<jsf>RDF_rdfxml_tab</jsf>, value=<js>"5"</js>), 
@@ -5096,7 +5118,9 @@
 	<ja>@RestResource</ja>( 
 		path=<js>"/docker"</js>, 
 		title=<js>"Sample Docker resource"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		)
 	) 
 	<jk>public class</jk> DockerRegistryResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -5177,7 +5201,9 @@
 		messages=<js>"nls/TumblrParserResource"</js>, 
 		title=<js>"Tumblr parser service"</js>, 
 		description=<js>"Specify a URL to a Tumblr blog and parse the results."</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		)
 	) 
 	<jk>public class</jk> TumblrParserResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -5259,7 +5285,9 @@
 		messages=<js>"nls/PhotosResource"</js>,
 		title=<js>"Photo REST service"</js>,
 		description=<js>"Use a tool like Poster to upload and retrieve jpeg and png images."</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		)
 	)
 	<jk>public class</jk> PhotosResource <jk>extends</jk> RestServletDefault {
 	
@@ -5398,7 +5426,9 @@
 		path=<js>"/jsonSchema"</js>, 
 		messages=<js>"nls/JsonSchemaResource"</js>, 
 		title=<js>"Sample JSON-Schema document"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		)
 	) 
 	<jk>public class</jk> JsonSchemaResource <jk>extends</jk> ResourceJena { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -5479,7 +5509,9 @@
 		messages=<js>"nls/SqlQueryResource"</js>, 
 		title=<js>"SQL query service"</js>, 
 		description=<js>"Executes queries against the local derby '$C{SqlQueryResource/connectionUrl}' database"</js>, 
-		pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
+		)
 	) 
 	<jk>public class</jk> SqlQueryResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -5666,7 +5698,9 @@
 		path=<js>"/config"</js>, 
 		title=<js>"Configuration"</js>, 
 		description=<js>"Contents of configuration file."</js>, 
-		pageLinks=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', edit:'servlet:/edit'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{up:'request:/..', options:'servlet:/?method=OPTIONS', edit:'servlet:/edit'}"</js>
+		)
 	) 
 	<jk>public class</jk> ConfigResource <jk>extends</jk> Resource { 
 		<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; 
@@ -6166,9 +6200,6 @@
 					<li>{@link org.apache.juneau.ini.ConfigFile#getObjectWithDefault(String,Object,Class) getObjectWithDefault(String,Object,Class)} 
 				</ul>
 			<li>New ability to interact with config file sections with proxy interfaces with new method {@link org.apache.juneau.ini.ConfigFile#getSectionAsInterface(String,Class)}.
-			<li>New {@link org.apache.juneau.html.annotation.Html#render() @Html.render()} annotation and {@link org.apache.juneau.html.HtmlRender} class that allows you
-				to customize the HTML output and CSS style on bean properties:<br>
-				<img class='bordered' src='doc-files/HtmlRender_1.png'>
 			<li>{@link org.apache.juneau.annotation.BeanProperty @BeanProperty} annotation can now be applied to getters
 				and setters defined on interfaces.
 			<li>New methods on {@link org.apache.juneau.serializer.SerializerSession} and {@link org.apache.juneau.parser.ParserSession}
@@ -6203,11 +6234,11 @@
 						</ul>
 						For example, currently we define HTML page links using variables and servlet-relative URIs...
 						<p class='bcode'>
-	pageLinks=<js>"{up:'$R{requestParentURI}', options:'?method=OPTIONS', upload:'upload'}"</js>
+	pages=<js>"{up:'$R{requestParentURI}', options:'?method=OPTIONS', upload:'upload'}"</js>
 						</p>
 						With these new protocols, we can define them like so:
 						<p class='bcode'>
-	pageLinks=<js>"{top:'context:/', up:'request:/..' ,options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>
+	links=<js>"{top:'context:/', up:'request:/..' ,options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>
 						</p>
 						The old method of using variables and servlet-relative URIs will still be supported, but using 
 						these new protocols should (hopefully) be easier to understand.
@@ -6252,10 +6283,35 @@
 			<li>The {@link org.apache.juneau.BeanContext#BEAN_debug} flag will now capture parser input and make it
 				available through the {@link org.apache.juneau.parser.ParserSession#getInputAsString()} method so that it can be used
 				in the listeners.
+			<li>Significant new functionality introduced to the HTML serializer.  
+				<br>Lots of new options for customizing the HTML output.
+				<ul>
+					<li>New {@link org.apache.juneau.html.annotation.Html#render() @Html.render()} annotation and {@link org.apache.juneau.html.HtmlRender} class that allows you
+						to customize the HTML output and CSS style on bean properties:
+						<br><img class='bordered' src='doc-files/HtmlRender_1.png'>
+						<br>Annotation can be applied to POJO classes and bean properties.
+					<li>Several new properties for customizing parts of the HTML page:
+						<ul>
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_title}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_description}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_header}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_nav}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_aside}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_footer}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_noResultsMessage}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_cssUrl}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_css}
+							<li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_template}
+						</ul>
+					<li>New interface {@link org.apache.juneau.html.HtmlDocTemplate} that allows full control over rendering
+						of HTML produced by {@link org.apache.juneau.html.HtmlDocSerializer}.
+					
+				</ul>
 		</ul>
 
 		<h6 class='topic'>org.apache.juneau.rest</h6>
 		<ul class='spaced-list'>
+			<li>MAJOR enhancements made to the REST API.
 			<li>The {@link org.apache.juneau.rest.RestRequest} class functionality has been broken up into the following
 				functional pieces to reduce its complexity:
 				<ul>
@@ -6374,7 +6430,67 @@
 					<li>{@link org.apache.juneau.rest.annotation.Header#def @Header.def()} - Default header value.
 					<li>{@link org.apache.juneau.rest.annotation.Query#def @Query.def()} - Default query parameter value.
 					<li>{@link org.apache.juneau.rest.annotation.FormData#def @FormData.def()} - Default form data parameter value.
-				</ul>	
+				</ul>
+			<li>New attributes on {@link org.apache.juneau.rest.annotation.RestResource @RestResource}:
+				<ul>
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#serializerListener() serializerListener()}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#parserListener() parserListener()}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#widgets() widgets()}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#swagger() swagger()}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#htmldoc() htmldoc()}
+				</ul>
+			<li>New attributes on {@link org.apache.juneau.rest.annotation.RestMethod @RestMethod}:
+				<ul>
+					<li>{@link org.apache.juneau.rest.annotation.RestMethod#widgets() widgets()}
+					<li>{@link org.apache.juneau.rest.annotation.RestMethod#swagger() swagger()}
+					<li>{@link org.apache.juneau.rest.annotation.RestMethod#htmldoc() htmldoc()}
+				</ul>
+			<li>New string vars:
+				<ul>
+					<li>{@link org.apache.juneau.rest.vars.UrlVar} - Resolve <js>"$U{...}"</js> variables to URLs.
+					<li>{@link org.apache.juneau.rest.vars.WidgetVar} - Resolve <js>"$W{...}"</js> variables to widget contents.
+				</ul>
+			<li>New methods on {@link org.apache.juneau.rest.RestConfig}:
+				<ul>
+					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlTitle(String) setHtmlTitle(String)}
+					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlDescription(String) setHtmlDescription(String)}
+					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlHeader(String) setHtmlHeader(String)}
+					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlLinks(String) setHtmlLinks(String)}
+					<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>{@link org.apache.juneau.rest.RestConfig#setHtmlCss(String) setHtmlCss(String)}
+					<li>{@link org.apache.juneau.rest.RestConfig#setHtmlCssUrl(String) setHtmlCssUrl(String)}
+					<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>{@link org.apache.juneau.rest.RestConfig#addWidget(Class) addWidget(Class)}
+				</ul>
+			<li>New methods on {@link org.apache.juneau.rest.RestResponse}:
+				<ul>
+					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlTitle(Object) setHtmlTitle(Object)}
+					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlDescription(Object) setHtmlDescription(Object)}
+					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlHeader(Object) setHtmlHeader(Object)}
+					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlLinks(Object) setHtmlLinks(Object)}
+					<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>{@link org.apache.juneau.rest.RestResponse#setHtmlCss(Object) setHtmlCss(Object)}
+					<li>{@link org.apache.juneau.rest.RestResponse#setHtmlCssUrl(Object) setHtmlCssUrl(Object)}
+					<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)}
+				</ul>
+			<li><code>&amp;plainText=true</code> parameter now works on byte-based serializers by converting the output to hex.
+			<li>New classes for widget support:
+				<ul>
+					<li>{@link org.apache.juneau.rest.widget.Widget}
+					<li>{@link org.apache.juneau.rest.widget.PoweredByJuneauWidget}
+					<li>{@link org.apache.juneau.rest.widget.ContentTypeLinksWidget}
+				</ul>
+			<li><code>devops.css</code> cleaned up.
 		</ul>
 
 		<h6 class='topic'>org.apache.juneau.rest.client</h6>
@@ -6392,6 +6508,13 @@
 		<h6 class='topic'>org.apache.juneau.microservice</h6>
 		<ul class='spaced-list'>
 		</ul>
+
+		<h6 class='topic'>org.apache.juneau.examples.rest</h6>
+		<ul class='spaced-list'>
+			<li>Many code enhancements make to examples to reflect new functionality.
+				<li>All pages now render aside comments to help explain what feature they're trying to explain.
+				<br><img class='bordered' src='doc-files/NewExamplesPage.png'>
+		</ul>
 	</div>
 
 	<!-- ======================================================================================================== -->
@@ -6538,12 +6661,12 @@
 			<li>New annotations added to {@link org.apache.juneau.rest.annotation.RestResource @RestResource} and {@link org.apache.juneau.rest.annotation.RestMethod @RestMethod}
 				to simplify defining page title, text, and links on HTML views:
 				<ul>
-					<li>{@link org.apache.juneau.rest.annotation.RestResource#pageTitle() @RestResource.pageTitle()} 
-					<li>{@link org.apache.juneau.rest.annotation.RestMethod#pageTitle() @RestMethod.pageTitle()} 
-					<li>{@link org.apache.juneau.rest.annotation.RestResource#pageText() @RestResource.pageText()} 
-					<li>{@link org.apache.juneau.rest.annotation.RestMethod#pageText() @RestMethod.pageText()} 
-					<li>{@link org.apache.juneau.rest.annotation.RestResource#pageLinks() @RestResource.pageLinks()} 
-					<li>{@link org.apache.juneau.rest.annotation.RestMethod#pageLinks() @RestMethod.pageLinks()} 
+					<li><code><del>@RestResource.pageTitle()</del></code>
+					<li><code><del>@RestMethod.pageTitle()</del></code> 
+					<li><code><del>@RestResource.pageText()</del></code> 
+					<li><code><del>@RestMethod.pageText()</del></code> 
+					<li><code><del>@RestResource.pageLinks()</del></code> 
+					<li><code><del>@RestMethod.pageLinks()</del></code> 
 				</ul>				
 				<p class='bcode'>
 	<jc>// Old method</jc>
@@ -6650,7 +6773,7 @@
 					<li>{@link org.apache.juneau.rest.client.RestClientBuilder#noTrace() noTrace()} - Adds a <code>No-Trace: true</code> header on all requests to prevent
 						the servlet from logging errors.
 						<br>Useful for testing scenarios when you don't want the console to end up showing errors done on purpose.
-					<li>{@link org.apache.juneau.rest.client.RestClientBuilder#debug(boolean) debug(boolean)} now adds a <code>Debug: true</code> header on all requests.
+					<li>{@link org.apache.juneau.rest.client.RestClientBuilder#debug() debug()} now adds a <code>Debug: true</code> header on all requests.
 				</ul>
 			<li>New methods added/updated to {@link org.apache.juneau.rest.client.RestCall}:
 				<ul>
@@ -7065,19 +7188,19 @@
 						<ul>
 							<li>{@link org.apache.juneau.rest.annotation.RestResource#title() @RestResource.title()} / {@link org.apache.juneau.rest.RestInfoProvider#getTitle(RestRequest)}
 							<li>{@link org.apache.juneau.rest.annotation.RestResource#description() @RestResource.description()} / {@link org.apache.juneau.rest.RestInfoProvider#getDescription(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#termsOfService() @RestResource.termsOfService()} / {@link org.apache.juneau.rest.RestInfoProvider#getTermsOfService(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#contact() @RestResource.contact()} / {@link org.apache.juneau.rest.RestInfoProvider#getContact(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#license() @RestResource.license()} / {@link org.apache.juneau.rest.RestInfoProvider#getLicense(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#version() @RestResource.version()} / {@link org.apache.juneau.rest.RestInfoProvider#getVersion(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#tags() @RestResource.tags()} / {@link org.apache.juneau.rest.RestInfoProvider#getTags(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestResource#externalDocs() @RestResource.externalDocs()} / {@link org.apache.juneau.rest.RestInfoProvider#getExternalDocs(RestRequest)}
+							<li><code><del>@RestResource.termsOfService()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getTermsOfService(RestRequest)}
+							<li><code><del>@RestResource.contact()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getContact(RestRequest)}
+							<li><code><del>@RestResource.license()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getLicense(RestRequest)}
+							<li><code><del>@RestResource.version()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getVersion(RestRequest)}
+							<li><code><del>@RestResource.tags()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getTags(RestRequest)}
+							<li><code><del>@RestResource.externalDocs()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getExternalDocs(RestRequest)}
 							<li>{@link org.apache.juneau.rest.annotation.RestMethod#summary() @RestMethod.summary()} / {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(String,RestRequest)}
 							<li>{@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()} / {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(String,RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#externalDocs() @RestMethod.externalDocs()} 
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#tags() @RestMethod.tags()} 
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#deprecated() @RestMethod.deprecated()} 
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#parameters() @RestMethod.parameters()} 
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#responses() @RestMethod.responses()} 
+							<li><code><del>@RestMethod.externalDocs()</del></code>
+							<li><code><del>@RestMethod.tags()</del></code>
+							<li><code><del>@RestMethod.deprecated()</del></code> 
+							<li><code><del>@RestMethod.parameters()</del></code> 
+							<li><code><del>@RestMethod.responses()</del></code>
 						</ul>
 					</li>					
 				</ul>
@@ -7747,7 +7870,7 @@
 		<ul class='spaced-list'>
 			<li>Fixed bug where localized strings weren't resolving when using chained resource bundles.
 			<li>Servlet and method labels and descriptions can now contain embedded string variables.
-			<li>New <del><code>RestMethod.input()</code></del> and org.apache.juneau.rest.annotation.RestMethod#responses()}
+			<li>New <del><code>RestMethod.input()</code></del> and <code><del>RestMethod.responses()</del></code>
 				annotations.
 				These replace the various <code>description</code> annotations added 2 days ago with a simpler design.
 			<li>New methods on {@link org.apache.juneau.rest.RestServlet}:
@@ -7861,7 +7984,7 @@
 					<li><del><code>RestResource.label()</code></del>
 					<li>{@link org.apache.juneau.rest.annotation.RestResource#description()}
 					<li>{@link org.apache.juneau.rest.annotation.RestMethod#description()}
-					<li>{@link org.apache.juneau.rest.annotation.RestMethod#responses()}
+					<li><del><code>RestMethod#responses()</code></del>
 					<li><del><code>Attr.description()</code></del>
 					<li><del><code>Content.description()</code></del>
 					<li><del><code>HasParam.description()</code></del>
@@ -7901,7 +8024,7 @@
 				</ul>
 			<li>New {@link org.apache.juneau.dto.jsonschema.JsonType#ANY} enum.
 			<li>New {@link org.apache.juneau.html.annotation.Html#asPlainText @Html.asPlainText()} annotation.
-			<li>New {@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_cssImports} property.
+			<li>New <code><del>HtmlDocSerializerContext.HTMLDOC_cssImports</del></code> property.
 			<li>Signifant changes to RDF support.
 				<ul>
 					<li>New {@link org.apache.juneau.jena.annotation.Rdf @Rdf} and {@link org.apache.juneau.jena.annotation.RdfSchema @RdfSchema}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
index 49fc847..fcfe9b9 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
@@ -23,6 +23,7 @@ import org.apache.juneau.dto.atom.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
 
 /**
  * Sample resource that shows how to generate ATOM feeds.
@@ -31,12 +32,23 @@ import org.apache.juneau.rest.annotation.*;
 	path="/atom",
 	title="Sample ATOM feed resource",
 	description="Sample resource that shows how to render ATOM feeds",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>Shows how to produce ATOM feeds in a variety of languages.</p>"
+			+ "	<p>$W{contentTypeLinks}</p>"
+			+ "</div>",
+		css="aside {display:table-caption;}"
+	),
 	properties={
 		@Property(name=SERIALIZER_quoteChar, value="'"),
 		@Property(name=RDF_rdfxml_tab, value="5"),
 		@Property(name=RDF_addRootProperty, value="true")
 	},
+	widgets={
+		ContentTypeLinksWidget.class
+	},
 	encoders=GzipEncoder.class
 )
 public class AtomFeedResource extends ResourceJena {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
index 10a0b07..ed66794 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java
@@ -12,8 +12,9 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest;
 
-import java.io.*;
+import static org.apache.juneau.dto.html5.HtmlBuilder.*;
 
+import org.apache.juneau.dto.html5.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
@@ -27,15 +28,63 @@ import org.apache.juneau.rest.annotation.*;
 	messages="nls/CodeFormatterResource",
 	title="Code Formatter",
 	description="Utility for generating HTML code-formatted source code",
-	pageLinks="{options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/CodeFormatterResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'servlet:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/CodeFormatterResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>Utility for adding code syntax tags to Java and XML/HTML code.</p>"
+			+ "	<p>It's by no means perfect, but provides a good starting point.</p>"
+			+ "</div>",
+		css="aside {display:table-caption;}"
+	)
 )
 @SuppressWarnings({"serial"})
 public class CodeFormatterResource extends Resource {
 
 	/** [GET /] - Display query entry page. */
 	@RestMethod(name="GET", path="/")
-	public ReaderResource getQueryEntryPage(RestRequest req) throws IOException {
-		return req.getReaderResource("CodeFormatterResource.html", true);
+	public Div getQueryEntryPage(RestRequest req) {
+		return div(
+			script("text/javascript",
+				"\n	// Quick and dirty function to allow tabs in textarea."
+				+"\n	function checkTab(e) {"
+				+"\n		if (e.keyCode == 9) {"
+				+"\n			var t = e.target;"
+				+"\n			var ss = t.selectionStart, se = t.selectionEnd;"
+				+"\n			t.value = t.value.slice(0,ss).concat('\\t').concat(t.value.slice(ss,t.value.length));"
+				+"\n			e.preventDefault();"
+				+"\n		}"
+				+"\n	}"
+				+"\n	// Load results from IFrame into this document."
+				+"\n	function loadResults(b) {"
+				+"\n		var doc = b.contentDocument || b.contentWindow.document;"
+				+"\n		var data = doc.getElementById('data') || doc.getElementsByTagName('body')[0];"
+				+"\n		document.getElementById('results').innerHTML = data.innerHTML;"
+				+"\n	}"
+			),
+			form("form").action("codeFormatter").method("POST").target("buff").children(
+				table(
+					tr(
+						th("Language: "),
+						td(
+							select().name("lang").children(
+								option("java","Java"),
+								option("xml", "XML")
+							)
+						),
+						td(button("submit", "Submit"), button("reset", "Reset"))
+					),
+					tr(
+						td().colspan(3).children(
+							textarea().name("code").style("min-width:800px;min-height:400px;font-family:Courier;font-size:9pt;").onkeydown("checkTab(event)")
+						)
+					)
+				)
+			),
+			br(),
+			div().id("results")._class("monospace"),
+			iframe().name("buff").style("display:none").onload("parent.loadResults(this)")
+		);
 	}
 
 	/** [POST /] - Add syntax highlighting to input. */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
index 753fcf7..31a845c 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
@@ -35,7 +35,9 @@ import org.apache.juneau.utils.*;
  */
 @RestResource(
 	messages="nls/DirectoryResource",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}"
+	),
 	properties={
 		@Property(name=HTML_uriAnchorText, value=PROPERTY_NAME),
 		@Property(name=REST_allowMethodParam, value="*"),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
index 1b021f0..ae3f18b 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
@@ -27,7 +27,14 @@ import org.apache.juneau.rest.labels.*;
 @RestResource(
 	path="/docker",
 	title="Sample Docker resource",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DockerRegistryResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DockerRegistryResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>REST API for searching Docker registries.</p>"
+			+ "	<p>To use, you must first specify the Docker registry URL in the <code>[Docker]</code> section of the config file.</p>"
+			+ "</div>"
+	)
 )
 public class DockerRegistryResource extends Resource {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java
index 6a32824..8cd48ce 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java
@@ -32,7 +32,13 @@ import org.apache.juneau.serializer.*;
 	path="/fileSpace",
 	title="Available file space resource",
 	description="Shows how to use HtmlRender class to customize HTML output.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/EnhancedHtmlResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/EnhancedHtmlResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>Shows how you can use <code>HtmlRender</code> class to customize the output generated by the HTML serializer.</p>"
+			+ "</div>"
+	)
 )
 public class FileSpaceResource extends Resource {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
index 49e9a06..d062eda 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/HelloWorldResource.java
@@ -20,10 +20,17 @@ import org.apache.juneau.rest.annotation.*;
  */
 @RestResource(
 	messages="nls/HelloWorldResource",
-	title="Hello World sample resource",
-	description="Simplest possible resource",
+	title="Hello World",
+	description="An example of the simplest-possible resource",
 	path="/helloWorld",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/HelloWorldResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/HelloWorldResource.java'}",
+		aside=""
+			+ "<div style='max-width:400px' class='text'>"
+			+ "	<p>This page shows a resource that simply response with a 'Hello world!' message</p>"
+			+ "	<p>The POJO serialized is a simple String.</p>"
+			+ "</div>"
+	)
 )
 public class HelloWorldResource extends Resource {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
index 9e71264..6b1fffb 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java
@@ -15,6 +15,7 @@ package org.apache.juneau.examples.rest;
 import org.apache.juneau.dto.jsonschema.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
 
 /**
  * Sample resource that shows how to serialize JSON-Schema documents.
@@ -24,7 +25,17 @@ import org.apache.juneau.rest.annotation.*;
 	messages="nls/JsonSchemaResource",
 	title="Sample JSON-Schema document",
 	description="Sample resource that shows how to generate JSON-Schema documents",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/JsonSchemaResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/JsonSchemaResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>Shows how to produce JSON-Schema documents in a variety of languages using the JSON-Schema DTOs.</p>"
+			+ "	<p>$W{contentTypeLinks}</p>"
+			+ "</div>"
+	),
+	widgets={
+		ContentTypeLinksWidget.class
+	}
 )
 public class JsonSchemaResource extends ResourceJena {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
index f396cd8..3c8c789 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/MethodExampleResource.java
@@ -26,7 +26,14 @@ import org.apache.juneau.rest.annotation.Method;
 @RestResource(
 	path="/methodExample",
 	messages="nls/MethodExampleResource",
-	pageLinks="{up:'servlet:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/MethodExampleResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'servlet:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/MethodExampleResource.java'}",
+		aside=""
+			+ "<div style='max-width:400px' class='text'>"
+			+ "	<p>Shows the different methods for retrieving HTTP query/form-data parameters, headers, and path variables.</p>"
+			+ "	<p>The top-level path simply redirects to the first example method and spits out the results as a string.</p>"
+			+ "</div>"
+	)
 )
 public class MethodExampleResource extends Resource {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
index f8875ff..0121c84 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PhotosResource.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.examples.rest;
 
 import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.html.HtmlSerializerContext.*;
 
 import java.awt.image.*;
 import java.io.*;
@@ -38,13 +39,24 @@ import org.apache.juneau.serializer.*;
 	messages="nls/PhotosResource",
 	title="Photo REST service",
 	description="Sample resource that allows images to be uploaded and retrieved.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PhotosResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PhotosResource.java'}",
+		aside=""
+			+ "<div style='max-width:400px;min-width:200px' class='text'>"
+			+ "	<p>Shows an example of using custom serializers and parsers to create REST interfaces over binary resources.</p>"
+			+ "	<p>In this case, our resources are marshalled jpeg and png binary streams and are stored in an in-memory 'database' (also known as a <code>TreeMap</code>).</p>"
+			+ "</div>"
+	),
+	properties={
+		// Make the anchor text on URLs be just the path relative to the servlet.
+		@Property(name=HTML_uriAnchorText, value="SERVLET_RELATIVE")
+	}
 )
 public class PhotosResource extends Resource {
 	private static final long serialVersionUID = 1L;
 
 	// Our cache of photos
-	private Map<Integer,Photo> photos = new TreeMap<Integer,Photo>();
+	private Map<String,Photo> photos = new TreeMap<String,Photo>();
 
 	@Override /* Servlet */
 	public void init() {
@@ -52,7 +64,7 @@ public class PhotosResource extends Resource {
 			// Preload an image.
 			InputStream is = getClass().getResourceAsStream("averycutecat.jpg");
 			BufferedImage image = ImageIO.read(is);
-			Photo photo = new Photo(0, image);
+			Photo photo = new Photo("cat", image);
 			photos.put(photo.id, photo);
 		} catch (IOException e) {
 			throw new RuntimeException(e);
@@ -61,16 +73,16 @@ public class PhotosResource extends Resource {
 
 	/** Our bean class for storing photos */
 	public static class Photo {
-		int id;
+		String id;
 		BufferedImage image;
 
-		Photo(int id, BufferedImage image) {
+		Photo(String id, BufferedImage image) {
 			this.id = id;
 			this.image = image;
 		}
 
 		public URI getURI() throws URISyntaxException {
-			return new URI(""+id);
+			return new URI("servlet:/" + id);
 		}
 	}
 
@@ -82,7 +94,7 @@ public class PhotosResource extends Resource {
 
 	/** GET request handler for single photo */
 	@RestMethod(name="GET", path="/{id}", serializers=ImageSerializer.class, summary="Get a photo by ID")
-	public BufferedImage getPhoto(@Path int id) throws Exception {
+	public BufferedImage getPhoto(@Path String id) throws Exception {
 		Photo p = photos.get(id);
 		if (p == null)
 			throw new RestException(SC_NOT_FOUND, "Photo not found");
@@ -90,24 +102,23 @@ public class PhotosResource extends Resource {
 	}
 
 	/** PUT request handler */
-	@RestMethod(name="PUT", path="/{id}", parsers=ImageParser.class, summary="Add a photo")
-	public String addPhoto(@Path int id, @Body BufferedImage image) throws Exception {
+	@RestMethod(name="PUT", path="/{id}", parsers=ImageParser.class, summary="Add or overwrite a photo")
+	public String addPhoto(@Path String id, @Body BufferedImage image) throws Exception {
 		photos.put(id, new Photo(id, image));
 		return "OK";
 	}
-
+	
 	/** POST request handler */
-	@RestMethod(name="POST", path="/", parsers=ImageParser.class, summary="Overwrite a photo by ID")
+	@RestMethod(name="POST", path="/", parsers=ImageParser.class, summary="Add a photo")
 	public Photo setPhoto(@Body BufferedImage image) throws Exception {
-		int id = photos.size();
-		Photo p = new Photo(id, image);
-		photos.put(id, p);
+		Photo p = new Photo(UUID.randomUUID().toString(), image);
+		photos.put(p.id, p);
 		return p;
 	}
 
 	/** DELETE request handler */
 	@RestMethod(name="DELETE", path="/{id}", summary="Delete a photo by ID")
-	public String deletePhoto(@Path int id) throws Exception {
+	public String deletePhoto(@Path String id) throws Exception {
 		Photo p = photos.remove(id);
 		if (p == null)
 			throw new RestException(SC_NOT_FOUND, "Photo not found");

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
index 84c7d7a..e17458a 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
@@ -31,7 +31,15 @@ import org.apache.juneau.transforms.*;
 	path="/echo",
 	title="Request echo service",
 	description="Echos the current HttpServletRequest object back to the browser.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RequestEchoResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RequestEchoResource.java'}",
+		aside=""
+			+ "<div style='max-width:400px;min-width:200px' class='text'>"
+			+ "	<p>Shows how even arbitrary POJOs such as <code>HttpServletRequest</code> can be serialized by the framework.</p>"
+			+ "	<p>Also shows how to specify serializer properties, filters, and swaps at the servlet level to control how POJOs are serialized.</p>"
+			+ "	<p>Also provides an example of how to use the Traversable and Queryable APIs.</p>"
+			+ "</div>"
+	),
 	properties={
 		@Property(name=SERIALIZER_maxDepth, value="5"),
 		@Property(name=SERIALIZER_detectRecursions, value="true")
@@ -52,7 +60,7 @@ public class RequestEchoResource extends Resource {
 	@RestMethod(name="*", path="/*", converters={Traversable.class,Queryable.class}, summary="Serializes the incoming HttpServletRequest object.")
 	public HttpServletRequest doGet(RestRequest req, RestResponse res, @Properties ObjectMap properties) {
 		// Set the HtmlDocSerializer title programmatically.
-		res.setPageTitle("Contents of HttpServletRequest object");
+		res.setHtmlTitle("Contents of HttpServletRequest object");
 
 		// Just echo the request back as the response.
 		return req;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
index 726ae3b..2637411 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
@@ -16,6 +16,7 @@ import org.apache.juneau.examples.rest.addressbook.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.microservice.resources.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
 
 /**
  * Sample REST resource showing how to implement a "router" resource page.
@@ -23,8 +24,24 @@ import org.apache.juneau.rest.annotation.*;
 @RestResource(
 	path="/",
 	title="Root resources",
-	description="This is an example of a router resource that is used to access other resources.",
-	pageLinks="{options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java'}",
+	description="Example of a router resource page.",
+	htmldoc=@HtmlDoc(
+		links="{options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java'}",
+		aside=""
+			+ "<div style='max-width:400px' class='text'>"
+			+ "	<p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>"
+			+ "	<p>Resources can be nested arbitrarily deep through router pages.</p>"
+			+ "	<p>Note the <span class='link'>OPTIONS</span> link provided that lets you see the generated swagger doc for this page.</p>"
+			+ "	<p>Also note the <span class='link'>SOURCE</span> link on these pages to view the source code for the page.</p>"
+			+ "	<p>All content on pages in the UI are serialized POJOs.  In this case, it's a serialized array of beans with 2 properties.</p>"
+			+ "	<p>Other features (such as this aside) are added through annotations.</p>"
+			+ "</div>",
+		footer="$W{poweredByJuneau}"
+	),
+	widgets={
+		PoweredByJuneauWidget.class,
+		ContentTypeLinksWidget.class
+	},
 	children={
 		HelloWorldResource.class,
 		SystemPropertiesResource.class,

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java
index dd8da66..9451692 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java
@@ -28,8 +28,17 @@ import org.apache.juneau.rest.remoteable.*;
 	path="/remoteable",
 	messages="nls/SampleRemoteableServlet",
 	title="Remoteable Service Proxy API",
-	description="Sample class showing how to use remoteable proxies.  The list below are exposed services that can be retrieved using RestClient.getProxyInterface(Class).",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SampleRemoteableServlet.java'}",
+	description="Sample class showing how to use remoteable proxies.",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SampleRemoteableServlet.java'}",
+		aside=""
+			+ "<div style='max-width:400px;min-width:200px' class='text'>"
+			+ "	<p>Shows how to use the <code>RemoteableServlet</code> class to define RPC-style remoteable interfaces using REST as a protocol.</p>"
+			+ "	<p>Remoteable proxies are retrieved on the client side using <code>RestClient.getInterfaceProxy(Class)</code>.</p>"
+			+ "	<p>Methods are invoked using POSTs of serialized arrays of objects and the returned value is marshalled back as a response.</p>"
+			+ "	<p>GET requests (as shown here) show the available methods on the interface.</p>"
+			+ "</div>"
+	),
 	properties={
 		// Allow us to use method=POST from a browser.
 		@Property(name=REST_allowMethodParam, value="*")

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
index ea7c661..54a5415 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java
@@ -35,7 +35,14 @@ import org.apache.juneau.rest.annotation.Body;
 	messages="nls/SqlQueryResource",
 	title="SQL query service",
 	description="Executes queries against the local derby '$C{SqlQueryResource/connectionUrl}' database",
-	pageLinks="{up:'request:/..',options:'servlet:/..',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SqlQueryResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/..',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SqlQueryResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>An example of a REST interface over a relational database.</p>"
+			+ "	<p><a class='link' href='?sql=select+*+from sys.systables'>try me</a></p>"
+			+ "</div>"
+	)
 )
 public class SqlQueryResource extends Resource {
 	private static final long serialVersionUID = 1L;
@@ -63,7 +70,7 @@ public class SqlQueryResource extends Resource {
 
 	/** GET request handler - Display the query entry page. */
 	@RestMethod(name="GET", path="/", summary="Display the query entry page")
-	public Div doGet(RestRequest req) {
+	public Div doGet(RestRequest req, @Query("sql") String sql) {
 		return div(
 			script("text/javascript",
 				"\n	// Quick and dirty function to allow tabs in textarea."
@@ -93,7 +100,7 @@ public class SqlQueryResource extends Resource {
 					),
 					tr(
 						td().colspan(5).children(
-							textarea().name("sql").style("width:100%;height:200px;font-family:Courier;font-size:9pt;").onkeydown("checkTab(event)")
+							textarea().name("sql").text(sql == null ? " " : sql).style("width:100%;height:200px;font-family:Courier;font-size:9pt;").onkeydown("checkTab(event)")
 						)
 					)
 				)
@@ -114,8 +121,6 @@ public class SqlQueryResource extends Resource {
 		if (isEmpty(in.sql))
 			return results;
 		
-		System.err.println("SQL=["+in.sql+"]");
-
 		if (in.pos < 1 || in.pos > 10000)
 			throw new RestException(SC_BAD_REQUEST, "Invalid value for position.  Must be between 1-10000");
 		if (in.limit < 1 || in.limit > 10000)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
index 4b494ac..8cb01e5 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
@@ -19,7 +19,6 @@ import java.util.*;
 import java.util.Map;
 
 import org.apache.juneau.dto.html5.*;
-import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
@@ -38,7 +37,14 @@ import org.apache.juneau.rest.annotation.Body;
 	// "request:/..." URIs are relative to the request URI.
 	// "servlet:/..." URIs are relative to the servlet URI.
 	// "$C{...}" variables are pulled from the config file.
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',form:'servlet:/formPage',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SystemPropertiesResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',form:'servlet:/formPage',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/SystemPropertiesResource.java'}",
+		aside=""
+			+ "<div style='max-width:800px' class='text'>"
+			+ "	<p>Shows standard GET/PUT/POST/DELETE operations and use of Swagger annotations.</p>"
+			+ "</div>",
+		css="aside {display:table-caption;}"
+	),
 	
 	// Properties that get applied to all serializers and parsers.
 	properties={
@@ -52,12 +58,14 @@ import org.apache.juneau.rest.annotation.Body;
 	// Support GZIP encoding on Accept-Encoding header.
 	encoders=GzipEncoder.class,
 	
-	contact="{name:'John Smith',email:'john@smith.com'}",
-	license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}",
-	version="2.0",
-	termsOfService="You're on your own.",
-	tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]",
-	externalDocs="{description:'Home page',url:'http://juneau.apache.org'}"
+	swagger=@ResourceSwagger(
+		contact="{name:'John Smith',email:'john@smith.com'}",
+		license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}",
+		version="2.0",
+		termsOfService="You're on your own.",
+		tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]",
+		externalDocs="{description:'Home page',url:'http://juneau.apache.org'}"
+	)
 )
 public class SystemPropertiesResource extends Resource {
 	private static final long serialVersionUID = 1L;
@@ -66,12 +74,14 @@ public class SystemPropertiesResource extends Resource {
 		name="GET", path="/",
 		summary="Show all system properties",
 		description="Returns all system properties defined in the JVM.",
-		parameters={
-			@Parameter(in="query", name="sort", description="Sort results alphabetically.", _default="false")
-		},
-		responses={
-			@Response(value=200, description="Returns a map of key/value pairs.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="query", name="sort", description="Sort results alphabetically.", _default="false")
+			},
+			responses={
+				@Response(value=200, description="Returns a map of key/value pairs.")
+			}
+		)
 	)
 	@SuppressWarnings({"rawtypes", "unchecked"})
 	public Map getSystemProperties(@Query("sort") boolean sort) throws Throwable {
@@ -84,12 +94,14 @@ public class SystemPropertiesResource extends Resource {
 		name="GET", path="/{propertyName}",
 		summary="Get system property",
 		description="Returns the value of the specified system property.",
-		parameters={
-			@Parameter(in="path", name="propertyName", description="The system property name.")
-		},
-		responses={
-			@Response(value=200, description="The system property value, or null if not found.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="propertyName", description="The system property name.")
+			},
+			responses={
+				@Response(value=200, description="The system property value, or null if not found.")
+			}
+		)
 	)
 	public String getSystemProperty(@Path String propertyName) throws Throwable {
 		return System.getProperty(propertyName);
@@ -100,22 +112,24 @@ public class SystemPropertiesResource extends Resource {
 		summary="Replace system property",
 		description="Sets a new value for the specified system property.",
 		guards=AdminGuard.class,
-		parameters={
-			@Parameter(in="path", name="propertyName", description="The system property name."),
-			@Parameter(in="body", description="The new system property value."),
-		},
-		responses={
-			@Response(value=302,
-				headers={
-					@Parameter(name="Location", description="The root URL of this resource.")
-				}
-			),	
-			@Response(value=403, description="User is not an admin.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="propertyName", description="The system property name."),
+				@Parameter(in="body", description="The new system property value."),
+			},
+			responses={
+				@Response(value=302,
+					headers={
+						@Parameter(name="Location", description="The root URL of this resource.")
+					}
+				),	
+				@Response(value=403, description="User is not an admin.")
+			}
+		)
 	)
 	public Redirect setSystemProperty(@Path String propertyName, @Body String value) {
 		System.setProperty(propertyName, value);
-		return new Redirect();
+		return new Redirect("servlet:/");
 	}
 
 	@RestMethod(
@@ -123,22 +137,24 @@ public class SystemPropertiesResource extends Resource {
 		summary="Add an entire set of system properties",
 		description="Takes in a map of key/value pairs and creates a set of new system properties.",
 		guards=AdminGuard.class,
-		parameters={
-			@Parameter(in="path", name="propertyName", description="The system property key."),
-			@Parameter(in="body", description="The new system property values.", schema="{example:{key1:'val1',key2:123}}"),
-		},
-		responses={
-			@Response(value=302,
-				headers={
-					@Parameter(name="Location", description="The root URL of this resource.")
-				}
-			),	
-			@Response(value=403, description="Unauthorized:  User is not an admin.")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="propertyName", description="The system property key."),
+				@Parameter(in="body", description="The new system property values.", schema="{example:{key1:'val1',key2:123}}"),
+			},
+			responses={
+				@Response(value=302,
+					headers={
+						@Parameter(name="Location", description="The root URL of this resource.")
+					}
+				),	
+				@Response(value=403, description="Unauthorized:  User is not an admin.")
+			}
+		)
 	)
 	public Redirect setSystemProperties(@Body java.util.Properties newProperties) {
 		System.setProperties(newProperties);
-		return new Redirect();
+		return new Redirect("servlet:/");
 	}
 
 	@RestMethod(
@@ -146,38 +162,37 @@ public class SystemPropertiesResource extends Resource {
 		summary="Delete system property",
 		description="Deletes the specified system property.",
 		guards=AdminGuard.class,
-		parameters={
-			@Parameter(in="path", name="propertyName", description="The system property name."),
-		},
-		responses={
-			@Response(value=302,
-				headers={
-					@Parameter(name="Location", description="The root URL of this resource.")
-				}
-			),	
-			@Response(value=403, description="Unauthorized:  User is not an admin")
-		}
+		swagger=@MethodSwagger(
+			parameters={
+				@Parameter(in="path", name="propertyName", description="The system property name."),
+			},
+			responses={
+				@Response(value=302,
+					headers={
+						@Parameter(name="Location", description="The root URL of this resource.")
+					}
+				),	
+				@Response(value=403, description="Unauthorized:  User is not an admin")
+			}
+		)
 	)
 	public Redirect deleteSystemProperty(@Path String propertyName) {
 		System.clearProperty(propertyName);
-		return new Redirect();
+		return new Redirect("servlet:/");
 	}
 
-	@Override
-	@RestMethod(
-		name="OPTIONS", path="/*",
-		summary="Show resource options",
-		description="Show resource options as a Swagger doc"
-	)
-	public Swagger getOptions(RestRequest req) {
-		return req.getSwagger();
-	}
-	
 	@RestMethod(
 		name="GET", path="/formPage",
 		summary="Form entry page",
 		description="A form post page for setting a single system property value",
-		guards=AdminGuard.class
+		guards=AdminGuard.class,
+		htmldoc=@HtmlDoc(
+			aside=""
+				+ "<div style='max-width:400px' class='text'>"
+				+ "	<p>Shows how HTML5 beans can be used to quickly create arbitrary HTML.</p>"
+				+ "</div>",
+			css="aside {display:table-cell;}"
+		)
 	)
 	public Form getFormPage() {
 		return form().method("POST").action("formPagePost").children(
@@ -195,6 +210,6 @@ public class SystemPropertiesResource extends Resource {
 	)
 	public Redirect formPagePost(@FormData("name") String name, @FormData("value") String value) {
 		System.setProperty(name, value);
-		return new Redirect();
+		return new Redirect("servlet:/");
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
index e3ac5bd..f6f949d 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
@@ -30,7 +30,14 @@ import org.apache.juneau.utils.*;
 	path="/tempDir",
 	title="Temp Directory View Service",
 	description="View and download files in the '$S{java.io.tmpdir}' directory.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',upload:'servlet:/upload',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/TempDirResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',upload:'servlet:/upload',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/TempDirResource.java'}",
+		aside=""
+			+ "<div style='max-width:400px' class='text'>"
+			+ "	<p>Shows how to use the predefined DirectoryResource class.</p>"
+			+ "	<p>Also shows how to use HTML5 beans to create a form entry page.</p>"
+			+ "</div>"
+	),
 	properties={
 		@Property(name="rootDir", value="$S{java.io.tmpdir}"),
 		@Property(name="allowViews", value="true"),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java
index 62920fb..2e98fdf 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java
@@ -24,14 +24,23 @@ import org.apache.juneau.rest.client.*;
 	messages="nls/TumblrParserResource",
 	title="Tumblr parser service",
 	description="Specify a URL to a Tumblr blog and parse the results.",
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/TumblrParserResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/TumblrParserResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>An example of a REST interface that retrieves data from another REST interface.</p>"
+			+ "	<p><a class='link' href='$U{servlet:/ibmblr}'>try me</a></p>"
+			+ "</div>"
+	)
 )
 public class TumblrParserResource extends Resource {
 	private static final long serialVersionUID = 1L;
+	
+	private static final int MAX_POSTS = 100;
 
 	@RestMethod(name="GET", path="/", summary="Get the instructions page")
 	public String getInstructions() throws Exception {
-		return "Append the Tumblr blog name to the URL above (e.g. /juneau/sample/tumblrParser/mytumblrblog)";
+		return "Append the Tumblr blog name to the URL above (e.g. /tumblrParser/mytumblrblog)";
 	}
 
 	@RestMethod(name="GET", path="/{blogName}", summary="Parse the specified blog")
@@ -41,7 +50,7 @@ public class TumblrParserResource extends Resource {
 		try {
 			String site = "http://" + blogName + ".tumblr.com/api/read/json";
 			ObjectMap m = rc.doGet(site).getResponse(ObjectMap.class);
-			int postsTotal = m.getInt("posts-total");
+			int postsTotal = Math.min(m.getInt("posts-total"), MAX_POSTS);
 			for (int i = 0; i < postsTotal; i += 20) {
 				m = rc.doGet(site + "?start=" + i + "&num=20&filter=text").getResponse(ObjectMap.class);
 				ObjectList ol = m.getObjectList("posts");

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
index 06541ab..95b2198 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java
@@ -32,7 +32,14 @@ import org.apache.juneau.transforms.*;
 	messages="nls/UrlEncodedFormResource",
 	title="Tumblr parser service",
 	description="Specify a URL to a Tumblr blog and parse the results.",
-	pageLinks="{up:'request:/..',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/UrlEncodedFormResource.java'}"
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/UrlEncodedFormResource.java'}",
+		aside=""
+			+ "<div style='min-width:200px' class='text'>"
+			+ "	<p>Shows how to process a FORM POST body into a bean using the <code>@Body</code> annotation.</p>"
+			+ "	<p>Submitting the form post will simply echo the bean back on the response.</p>"
+			+ "</div>"
+	)
 )
 public class UrlEncodedFormResource extends Resource {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
index d228173..6677c29 100644
--- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
+++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java
@@ -23,7 +23,6 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.dto.*;
 import org.apache.juneau.dto.cognos.*;
-import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.examples.addressbook.*;
 import org.apache.juneau.examples.rest.*;
@@ -31,6 +30,7 @@ import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.converters.*;
+import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.utils.*;
 
@@ -47,7 +47,28 @@ import org.apache.juneau.utils.*;
 	// "request:/..." URIs are relative to the request URI.
 	// "servlet:/..." URIs are relative to the servlet URI.
 	// "$C{...}" variables are pulled from the config file.
-	pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}",
+	htmldoc=@HtmlDoc(
+		links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}",
+			aside=""
+				+ "<div style='max-width:400px;min-width:200px'>"
+				+ "	<p>Proof-of-concept resource that shows off the capabilities of working with POJO resources.</p>"
+				+ "	<p>Provides examples of: </p>"
+				+ "		<ul>"
+				+ "			<li>XML and RDF namespaces"
+				+ "			<li>Swagger documentation"
+				+ "			<li>Widgets"
+				+ "		</ul>"
+				+ "	<p style='text-weight:bold;text-decoration:underline;'>Available Content Types</p>"
+				+ "	$W{contentTypeLinks}"
+				+ "</div>",
+		footer="$W{poweredByJuneau}"
+	),
+	
+	// Widgets for $W variables above.
+	widgets={
+		PoweredByJuneauWidget.class,
+		ContentTypeLinksWidget.class
+	},
 	
 	// Properties that get applied to all serializers and parsers.
 	properties={
@@ -78,12 +99,14 @@ import org.apache.juneau.utils.*;
 	encoders=GzipEncoder.class,
 	
 	// Swagger info.
-	contact="{name:'John Smith',email:'john@smith.com'}",
-	license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}",
-	version="2.0",
-	termsOfService="You're on your own.",
-	tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]",
-	externalDocs="{description:'Home page',url:'http://juneau.apache.org'}"
+	swagger=@ResourceSwagger(
+		contact="{name:'John Smith',email:'john@smith.com'}",
+		license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}",
+		version="2.0",
+		termsOfService="You're on your own.",
+		tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]",
+		externalDocs="{description:'Home page',url:'http://juneau.apache.org'}"
+	)
 )
 public class AddressBookResource extends ResourceJena {
 	private static final long serialVersionUID = 1L;
@@ -307,16 +330,6 @@ public class AddressBookResource extends ResourceJena {
 		return addressBook;
 	}
 
-	/**
-	 * [OPTIONS /*]
-	 * View resource options
-	 */
-	@Override /* RestServletJenaDefault */
-	@RestMethod(name="OPTIONS", path="/*")
-	public Swagger getOptions(RestRequest req) {
-		return req.getSwagger();
-	}
-
 	/** Convenience method - Find a person by ID */
 	private Person findPerson(int id) throws RestException {
 		Person p = addressBook.findPerson(id);