juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [juneau] branch master updated: Swagger UI support.
Date Sun, 18 Mar 2018 20:34:28 GMT
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/master by this push:
     new ae2508c  Swagger UI support.
ae2508c is described below

commit ae2508cac879b767aa47ad1fe64ae10681334b35
Author: JamesBognar <jamesbognar@apache.org>
AuthorDate: Sun Mar 18 16:33:54 2018 -0400

    Swagger UI support.
---
 .../java/org/apache/juneau/utils/MultiSetTest.java |   1 -
 juneau-core/juneau-dto/.classpath                  |   1 +
 .../org/apache/juneau/dto/swagger/Contact.java     |  12 +
 .../juneau/dto/swagger/ExternalDocumentation.java  |  11 +
 .../org/apache/juneau/dto/swagger/HeaderInfo.java  |  27 ++
 .../java/org/apache/juneau/dto/swagger/Info.java   |  17 ++
 .../java/org/apache/juneau/dto/swagger/Items.java  |  25 ++
 .../org/apache/juneau/dto/swagger/License.java     |  11 +
 .../org/apache/juneau/dto/swagger/Operation.java   |  57 ++++
 .../apache/juneau/dto/swagger/ParameterInfo.java   |  31 ++
 .../apache/juneau/dto/swagger/ResponseInfo.java    |  21 ++
 .../org/apache/juneau/dto/swagger/SchemaInfo.java  | 164 ++++++++++-
 .../apache/juneau/dto/swagger/SecurityScheme.java  |  16 ++
 .../org/apache/juneau/dto/swagger/Swagger.java     |  40 +++
 .../apache/juneau/dto/swagger/SwaggerElement.java  |   9 +
 .../java/org/apache/juneau/dto/swagger/Tag.java    |  14 +
 .../java/org/apache/juneau/dto/swagger/Xml.java    |  16 ++
 .../apache/juneau/dto/swagger/ui/SwaggerUI.java    | 264 +++++++++++++++++
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.css | 316 +++++++++++++++++++++
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.js  |  59 ++++
 .../apache/juneau/html/HtmlBeanPropertyMeta.java   |   2 +-
 .../apache/juneau/html/HtmlSerializerSession.java  |  41 ++-
 .../org/apache/juneau/html/annotation/Html.java    |   2 +-
 .../apache/juneau/html/annotation/HtmlFormat.java  |  10 +-
 .../java/org/apache/juneau/internal/MultiSet.java  |   2 +-
 .../main/java/org/apache/juneau/utils/ASet.java    |  13 +
 juneau-doc/src/main/javadoc/overview.html          |   6 +-
 .../juneau/examples/rest/StaticFilesResource.java  |  10 +-
 .../juneau/examples/rest/files/petstore.html       | 143 ++++++----
 .../juneau/examples/rest/files/petstore.json       |  35 ++-
 30 files changed, 1285 insertions(+), 91 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiSetTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiSetTest.java
index 9a3041c..cd67523 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiSetTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiSetTest.java
@@ -23,7 +23,6 @@ import org.junit.*;
 public class MultiSetTest {
 
 	@Test
-	@SuppressWarnings({ "unchecked" })
 	public void doTest() throws Exception {
 		List<String> l1, l2;
 		MultiSet<String> ms;
diff --git a/juneau-core/juneau-dto/.classpath b/juneau-core/juneau-dto/.classpath
index 82763f1..5a77437 100644
--- a/juneau-core/juneau-dto/.classpath
+++ b/juneau-core/juneau-dto/.classpath
@@ -6,6 +6,7 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
+	<classpathentry kind="src" path="src/main/resources"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Contact.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Contact.java
index 4beca30..f1565d0 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Contact.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Contact.java
@@ -16,9 +16,12 @@ import static org.apache.juneau.internal.BeanPropertyUtils.*;
 
 import java.net.*;
 import java.net.URI;
+import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Contact information for the exposed API.
@@ -209,4 +212,13 @@ public class Contact extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(name != null, "name")
+			.appendIf(url != null, "url")
+			.appendIf(email != null, "email");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ExternalDocumentation.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ExternalDocumentation.java
index 6e3625a..3b2aeb3 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ExternalDocumentation.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ExternalDocumentation.java
@@ -16,9 +16,12 @@ import static org.apache.juneau.internal.BeanPropertyUtils.*;
 
 import java.net.*;
 import java.net.URI;
+import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Allows referencing an external resource for extended documentation.
@@ -168,4 +171,12 @@ public class ExternalDocumentation extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+			.appendIf(url != null, "url");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
index 7a03e8b..ebd9b95 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
@@ -19,6 +19,8 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Describes a single HTTP header.
@@ -1018,4 +1020,29 @@ public class HeaderInfo extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+			.appendIf(type != null, "type")
+			.appendIf(format != null, "format")
+			.appendIf(items != null, "items")
+			.appendIf(collectionFormat != null, "collectionFormat")
+			.appendIf(_default != null, "default")
+			.appendIf(maximum != null, "maximum")
+			.appendIf(exclusiveMaximum != null, "exclusiveMaximum")
+			.appendIf(minimum != null, "minimum")
+			.appendIf(exclusiveMinimum != null, "exclusiveMinimum")
+			.appendIf(maxLength != null, "maxLength")
+			.appendIf(minLength != null, "minLength")
+			.appendIf(pattern != null, "pattern")
+			.appendIf(maxItems != null, "maxItems")
+			.appendIf(minItems != null, "minItems")
+			.appendIf(uniqueItems != null, "uniqueItems")
+			.appendIf(_enum != null, "enum")
+			.appendIf(multipleOf != null, "multipleOf");
+		return new MultiSet<>(s, super.keySet());
+		
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Info.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Info.java
index ea2caf5..b77e490 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Info.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Info.java
@@ -13,7 +13,12 @@
 package org.apache.juneau.dto.swagger;
 
 import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+import java.util.*;
+
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * The object provides metadata about the API. The metadata can be used by the clients if needed, and can be presented
@@ -368,4 +373,16 @@ public class Info extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(title != null, "title")
+			.appendIf(description != null, "description")
+			.appendIf(termsOfService != null, "termsOfService")
+			.appendIf(contact != null, "contact")
+			.appendIf(license != null, "license")
+			.appendIf(version != null, "version");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
index ce34fb1..95f3727 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
@@ -19,7 +19,9 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.utils.*;
 
 /**
  * A limited subset of JSON-Schema's items object. It is used by parameter definitions that are not located in "body".
@@ -992,4 +994,27 @@ public class Items extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(type != null, "type")
+			.appendIf(format != null, "format")
+			.appendIf(items != null, "items")
+			.appendIf(collectionFormat != null, "collectionFormat")
+			.appendIf(_default != null, "default")
+			.appendIf(maximum != null, "maximum")
+			.appendIf(exclusiveMaximum != null, "exclusiveMaximum")
+			.appendIf(minimum != null, "minimum")
+			.appendIf(exclusiveMinimum != null, "exclusiveMinimum")
+			.appendIf(maxLength != null, "maxLength")
+			.appendIf(minLength != null, "minLength")
+			.appendIf(pattern != null, "pattern")
+			.appendIf(maxItems != null, "maxItems")
+			.appendIf(minItems != null, "minItems")
+			.appendIf(uniqueItems != null, "uniqueItems")
+			.appendIf(_enum != null, "enum")
+			.appendIf(multipleOf != null, "multipleOf");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/License.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/License.java
index 9ed161e..3ca8fb4 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/License.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/License.java
@@ -15,9 +15,12 @@ package org.apache.juneau.dto.swagger;
 import static org.apache.juneau.internal.BeanPropertyUtils.*;
 import java.net.*;
 import java.net.URI;
+import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * License information for the exposed API.
@@ -165,4 +168,12 @@ public class License extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(name != null, "name")
+			.appendIf(url != null, "url");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
index edfd442..e05da41 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
@@ -17,6 +17,8 @@ import java.util.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Describes a single API operation on a path.
@@ -1029,4 +1031,59 @@ public class Operation extends SwaggerElement {
 				return this;
 		}
 	}
+
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(tags != null, "tags")
+			.appendIf(summary != null, "summary")
+			.appendIf(description != null, "description")
+			.appendIf(externalDocs != null, "externalDocs")
+			.appendIf(operationId != null, "operationId")
+			.appendIf(consumes != null, "consumes")
+			.appendIf(produces != null, "produces")
+			.appendIf(parameters != null, "parameters")
+			.appendIf(responses != null, "responses")
+			.appendIf(schemes != null, "schemes")
+			.appendIf(deprecated != null, "deprecated")
+			.appendIf(security != null, "security");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this operation has the specified tag associated with it.
+	 * 
+	 * @param name The tag name.
+	 * @return <jk>true</jk> if this operation has the specified tag associated with it.
+	 */
+	public boolean hasTag(String name) {
+		return tags != null && tags.contains(name);
+	}
+	
+	/**
+	 * Returns <jk>true</jk> if this operation has no tags associated with it.
+	 * 
+	 * @return <jk>true</jk> if this operation has no tags associated with it.
+	 */
+	public boolean hasNoTags() {
+		return tags == null || tags.isEmpty();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this operation has parameters associated with it.
+	 * 
+	 * @return <jk>true</jk> if this operation has parameters associated with it.
+	 */
+	public boolean hasParameters() {
+		return parameters != null && ! parameters.isEmpty();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this operation has responses associated with it.
+	 * 
+	 * @return <jk>true</jk> if this operation has responses associated with it.
+	 */
+	public boolean hasResponses() {
+		return responses != null && ! responses.isEmpty();
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
index df17745..2af5a2c 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
@@ -19,6 +19,8 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Describes a single operation parameter.
@@ -1419,4 +1421,33 @@ public class ParameterInfo extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(name != null, "name")
+			.appendIf(in != null, "in")
+			.appendIf(description != null, "description")
+			.appendIf(required != null, "required")
+			.appendIf(schema != null, "schema")
+			.appendIf(type != null, "type")
+			.appendIf(format != null, "format")
+			.appendIf(allowEmptyValue != null, "allowEmptyValue")
+			.appendIf(items != null, "items")
+			.appendIf(collectionFormat != null, "collectionFormat")
+			.appendIf(_default != null, "default")
+			.appendIf(maximum != null, "maximum")
+			.appendIf(exclusiveMaximum != null, "exclusiveMaximum")
+			.appendIf(minimum != null, "minimum")
+			.appendIf(exclusiveMinimum != null, "exclusiveMinimum")
+			.appendIf(maxLength != null, "maxLength")
+			.appendIf(minLength != null, "minLength")
+			.appendIf(pattern != null, "pattern")
+			.appendIf(maxItems != null, "maxItems")
+			.appendIf(minItems != null, "minItems")
+			.appendIf(uniqueItems != null, "uniqueItems")
+			.appendIf(_enum != null, "enum")
+			.appendIf(multipleOf != null, "multipleOf");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
index d7ba1bb..341a9a8 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
@@ -16,6 +16,8 @@ import static org.apache.juneau.internal.BeanPropertyUtils.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Describes a single response from an API Operation.
@@ -379,4 +381,23 @@ public class ResponseInfo extends SwaggerElement {
 				return this;
 		}
 	}
+
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+			.appendIf(schema != null, "schema")
+			.appendIf(headers != null, "headers")
+			.appendIf(examples != null, "examples");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this response info has headers associated with it.
+	 * 
+	 * @return <jk>true</jk> if this response info has headers associated with it.
+	 */
+	public boolean hasHeaders() {
+		return headers != null && ! headers.isEmpty();
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
index 90438a0..59e1980 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
@@ -16,6 +16,8 @@ import static org.apache.juneau.internal.BeanPropertyUtils.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * The Schema Object allows the definition of input and output data types.
@@ -55,7 +57,7 @@ import org.apache.juneau.annotation.*;
  * 	<li class='link'><a class='doclink' href='../../../../../overview-summary.html#juneau-dto.Swagger'>Overview &gt; juneau-dto &gt; Swagger</a>
  * </ul>
  */
-@Bean(properties="format,title,description,default,multipleOf,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,maxProperties,minProperties,required,enum,type,items,allOf,properties,additionalProperties,discriminator,readOnly,xml,externalDocs,example,*")
+@Bean(properties="format,title,description,default,multipleOf,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,maxProperties,minProperties,required,enum,type,items,allOf,properties,additionalProperties,discriminator,readOnly,xml,externalDocs,example,x-examples,$ref,*")
 public class SchemaInfo extends SwaggerElement {
 
 	private String 
@@ -64,7 +66,8 @@ public class SchemaInfo extends SwaggerElement {
 		description,
 		pattern,
 		type,
-		discriminator;
+		discriminator, 
+		ref;
 	private Number 
 		multipleOf,
 		maximum,
@@ -94,6 +97,7 @@ public class SchemaInfo extends SwaggerElement {
 		required;
 	private Map<String,Map<String,Object>> properties;
 	private Map<String,Object> additionalProperties;
+	private Map<String,String> examples;
 
 	/**
 	 * Bean property getter:  <property>format</property>.
@@ -1095,7 +1099,7 @@ public class SchemaInfo extends SwaggerElement {
 	}
 
 	/**
-	 * Adds one or more values to the <property>properties</property> property.
+	 * Adds one or more values to the <property>additionalProperties</property> property.
 	 * 
 	 * @param values
 	 * 	The values to add to this property.
@@ -1117,6 +1121,77 @@ public class SchemaInfo extends SwaggerElement {
 	}
 
 	/**
+	 * Bean property getter:  <property>x-examples</property>.
+	 * 
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	@BeanProperty("x-examples")
+	public Map<String,String> getExamples() {
+		return examples;
+	}
+
+	/**
+	 * Bean property setter:  <property>examples</property>.
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty("x-examples")
+	public SchemaInfo setExamples(Map<String,String> value) {
+		examples = newMap(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>examples</property> property.
+	 * 
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo addExamples(Map<String,String> values) {
+		examples = addToMap(examples, values);
+		return this;
+	}
+
+	/**
+	 * Adds a single value to the <property>examples</property> property.
+	 * 
+	 * @param name The extra property name.
+	 * @param value The extra property value.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo example(String name, String value) {
+		additionalProperties = addToMap(additionalProperties, name, value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>examples</property> property.
+	 * 
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Map&lt;String,String&gt;</code>
+	 * 		<li><code>String</code> - JSON object representation of <code>Map&lt;String,Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode'>
+	 * 	examples(<js>"{'text/json':'{foo:\\'bar\\'}'}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo examples(Object...values) {
+		examples = addToMap(examples, values, String.class, String.class);
+		return this;
+	}
+
+	/**
 	 * Bean property getter:  <property>discriminator</property>.
 	 * 
 	 * @return The property value, or <jk>null</jk> if it is not set.
@@ -1306,6 +1381,42 @@ public class SchemaInfo extends SwaggerElement {
 		return setExample(value);
 	}
 
+	/**
+	 * Bean property getter:  <property>$ref</property>.
+	 * 
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	@BeanProperty("$ref")
+	public String getRef() {
+		return ref;
+	}
+
+	/**
+	 * Bean property setter:  <property>$ref</property>.
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty("$ref")
+	public SchemaInfo setRef(Object value) {
+		ref = StringUtils.asString(value);
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setRef(Object)}.
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo ref(Object value) {
+		return setRef(value);
+	}
+
 	@Override /* SwaggerElement */
 	public <T> T get(String property, Class<T> type) {
 		if (property == null)
@@ -1340,6 +1451,7 @@ public class SchemaInfo extends SwaggerElement {
 			case "xml": return toType(getXml(), type);
 			case "externalDocs": return toType(getExternalDocs(), type);
 			case "example": return toType(getExample(), type);
+			case "x-examples": return toType(getExamples(), type);
 			default: return super.get(property, type);
 		}
 	}
@@ -1378,9 +1490,55 @@ public class SchemaInfo extends SwaggerElement {
 			case "xml": return xml(value);
 			case "externalDocs": return externalDocs(value);
 			case "example": return example(value);
+			case "x-examples": return examples(value);
 			default: 
 				super.set(property, value);
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(format != null, "format")
+			.appendIf(title != null, "title")
+			.appendIf(description != null, "description")
+			.appendIf(_default != null, "default")
+			.appendIf(multipleOf != null, "multipleOf")
+			.appendIf(maximum != null, "maximum")
+			.appendIf(exclusiveMaximum != null, "exclusiveMaximum")
+			.appendIf(minimum != null, "minimum")
+			.appendIf(exclusiveMinimum != null, "exclusiveMinimum")
+			.appendIf(maxLength != null, "maxLength")
+			.appendIf(minLength != null, "minLength")
+			.appendIf(pattern != null, "pattern")
+			.appendIf(maxItems != null, "maxItems")
+			.appendIf(minItems != null, "minItems")
+			.appendIf(uniqueItems != null, "uniqueItems")
+			.appendIf(maxProperties != null, "maxProperties")
+			.appendIf(minProperties != null, "minProperties")
+			.appendIf(required != null, "required")
+			.appendIf(_enum != null, "enum")
+			.appendIf(type != null, "type")
+			.appendIf(items != null, "items")
+			.appendIf(allOf != null, "allOf")
+			.appendIf(properties != null, "properties")
+			.appendIf(additionalProperties != null, "additionalProperties")
+			.appendIf(discriminator != null, "discriminator")
+			.appendIf(readOnly != null, "readOnly")
+			.appendIf(xml != null, "xml")
+			.appendIf(externalDocs != null, "externalDocs")
+			.appendIf(example != null, "example")
+			.appendIf(examples != null, "x-examples");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this schema info has one or more properties defined on it.
+	 * 
+	 * @return <jk>true</jk> if this schema info has one or more properties defined on it.
+	 */
+	public boolean hasProperties() {
+		return properties != null && ! properties.isEmpty();
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
index 5076e70..986002f 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
@@ -19,6 +19,8 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Allows the definition of a security scheme that can be used by the operations.
@@ -512,4 +514,18 @@ public class SecurityScheme extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(type != null, "type")
+			.appendIf(description != null, "description")
+			.appendIf(name != null, "name")
+			.appendIf(in != null, "in")
+			.appendIf(flow != null, "flow")
+			.appendIf(authorizationUrl != null, "authorizationUrl")
+			.appendIf(tokenUrl != null, "tokenUrl")
+			.appendIf(scopes != null, "scopes");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index 20c581b..c0bc13e 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -13,11 +13,15 @@
 package org.apache.juneau.dto.swagger;
 
 import static org.apache.juneau.internal.BeanPropertyUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.utils.*;
 
 /**
  * This is the root document object for the API specification.
@@ -1216,6 +1220,27 @@ public class Swagger extends SwaggerElement {
 		}
 	}
 
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(swagger != null, "swagger")
+			.appendIf(info != null, "info")
+			.appendIf(host != null, "host")
+			.appendIf(basePath != null, "basePath")
+			.appendIf(schemes != null, "schemes")
+			.appendIf(consumes != null, "consumes")
+			.appendIf(produces != null, "produces")
+			.appendIf(paths != null, "paths")
+			.appendIf(definitions != null, "definitions")
+			.appendIf(parameters != null, "parameters")
+			.appendIf(responses != null, "responses")
+			.appendIf(securityDefinitions != null, "securityDefinitions")
+			.appendIf(security != null, "security")
+			.appendIf(tags != null, "tags")
+			.appendIf(externalDocs != null, "externalDocs");
+		return new MultiSet<>(s, super.keySet());
+	}
+	
 //	static final class MethodSorter implements Comparator<String> {
 //		private final Map<String,Integer> methods = new AMap<String,Integer>()
 //			.append("get",7)
@@ -1242,4 +1267,19 @@ public class Swagger extends SwaggerElement {
 	public String toString() {
 		return JsonSerializer.DEFAULT.toString(this);
 	}
+
+	/**
+	 * Resolves a <js>"$ref"</js> tags to nodes in this swagger document.
+	 * 
+	 * @param ref The ref tag value.
+	 * @param c The class to convert the reference to.
+	 * @return The referenced node, or <jk>null</jk> if the ref was <jk>null</jk> or empty or not found.
+	 */
+	public <T> T findRef(String ref, Class<T> c) {
+		if (isEmpty(ref))
+			return null;
+		if (! ref.startsWith("#/"))
+			throw new RuntimeException("Unspported reference:  '" + ref + '"');
+		return new PojoRest(this).get(ref.substring(1), c);
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
index 7c6d5d1..98dfdfd 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
@@ -127,6 +127,15 @@ public abstract class SwaggerElement {
 		}
 	}
 	
+	/**
+	 * Returns all the keys on this element.
+	 * 
+	 * @return All the keys on this element.
+	 */
+	public Set<String> keySet() {
+		return extra == null ? Collections.EMPTY_SET : extra.keySet();
+	}
+	
 	@Override /* Object */
 	public String toString() {
 		return JsonSerializer.DEFAULT.toString(this);
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Tag.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Tag.java
index b3ebd1c..620a04b 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Tag.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Tag.java
@@ -13,7 +13,12 @@
 package org.apache.juneau.dto.swagger;
 
 import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+import java.util.*;
+
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Allows adding meta data to a single tag that is used by the <a class="doclink" href="http://swagger.io/specification/#operationObject">Operation Object</a>.
@@ -212,4 +217,13 @@ public class Tag extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(name != null, "name")
+			.appendIf(description != null, "description")
+			.appendIf(externalDocs != null, "externalDocs");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Xml.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Xml.java
index a1b17b7..ee6c3a2 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Xml.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Xml.java
@@ -13,7 +13,12 @@
 package org.apache.juneau.dto.swagger;
 
 import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+import java.util.*;
+
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
 
 /**
  * A metadata object that allows for more fine-tuned XML model definitions.
@@ -323,4 +328,15 @@ public class Xml extends SwaggerElement {
 				return this;
 		}
 	}
+	
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(name != null, "name")
+			.appendIf(namespace != null, "namespace")
+			.appendIf(prefix != null, "prefix")
+			.appendIf(attribute != null, "attribute")
+			.appendIf(wrapped != null, "wrapped");
+		return new MultiSet<>(s, super.keySet());
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
new file mode 100644
index 0000000..0361031
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
@@ -0,0 +1,264 @@
+// ***************************************************************************************************************************
+// * 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.dto.swagger.ui;
+
+import static org.apache.juneau.dto.html5.HtmlBuilder.*;
+
+import java.util.Map;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.html5.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.transform.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * 
+ */
+public class SwaggerUI extends PojoSwap<Swagger,Div> {
+	
+	static final ClasspathResourceManager RM = new ClasspathResourceManager(SwaggerUI.class);
+	
+	@Override
+	public MediaType[] forMediaTypes() {
+		return new MediaType[] {MediaType.HTML};
+	}
+	
+	@Override
+	public Div swap(BeanSession session, Swagger s) throws Exception {
+		Div outer = div(
+			style(RM.getString("SwaggerUI.css")),
+			script("text/javascript", RM.getString("SwaggerUI.js"))
+		);
+		
+		for (Tag t : s.getTags()) {
+			Div tagBlock = div()._class("tag-block tag-block-open").children(
+				tagBlockSummary(t),
+				tagBlockContents(s, t)
+			);
+			outer.child(tagBlock);
+		}
+		
+		return outer;
+	}
+	
+	private Div tagBlockSummary(Tag t) {
+		ExternalDocumentation ed = t.getExternalDocs();
+		String edd = ed == null ? null : ed.getDescription();
+		
+		return (Div)div()._class("tag-block-summary").children(
+			span(t.getName())._class("name"),
+			span(t.getDescription())._class("description"),
+			ed == null ? null : span(a(ed.getUrl(), edd == null ? ed.getUrl() : edd))._class("extdocs")
+		).onclick("toggleTagBlock(this)");
+	}
+	
+	private Div tagBlockContents(Swagger s, Tag t) {
+		Div tagBlockContents = div()._class("tag-block-contents");
+		
+		for (Map.Entry<String,Map<String,Operation>> e : s.getPaths().entrySet()) {
+			String path = e.getKey();
+			for (Map.Entry<String,Operation> e2 : e.getValue().entrySet()) {
+				String opName = e2.getKey();
+				Operation op = e2.getValue();
+				if (op.hasTag(t.getName())) 
+					tagBlockContents.child(opBlock(s, path, opName, op));
+			}
+		}
+		return tagBlockContents;
+	}
+	
+	private Div opBlock(Swagger s, String path, String opName, Operation op) {
+		String opNameLc = opName.toLowerCase();
+		
+		return div()._class("op-block op-block-closed " + opNameLc).children(
+			opBlockSummary(path, opName, op),
+			div(tableContainer(s, op))._class("op-block-contents")
+		);
+	}
+
+	private Div tableContainer(Swagger s, Operation op) {
+		Div tableContainer = div()._class("table-container");
+		
+		String description = op.getDescription();
+		if (! StringUtils.isEmpty(description)) 
+			tableContainer.child(div(description)._class("op-block-description"));
+			
+		if (op.hasParameters()) {
+			tableContainer.child(
+				div(h4("Parameters")._class("title"))._class("op-block-section-header")
+			);
+			
+			Table parameters = table(tr(th("Name")._class("parameter-key"), th("Description")._class("parameter-key")))._class("parameters");
+			
+			for (ParameterInfo pi : op.getParameters()) {
+				String piName = "body".equals(pi.getIn()) ? "body" : pi.getName();
+				
+				Td parameterKey = td(
+					div(piName)._class("name" + (pi.getRequired() ? " required" : "")),
+					div(pi.getType())._class("type"),
+					div('(' + pi.getIn() + ')')._class("in")
+				)._class("parameter-key");
+				
+				Td parameterValue = td(
+					div(
+						pi.getDescription()
+					)._class("description"),
+					examples(s, pi)
+				)._class("parameter-value");
+				
+				parameters.child(tr(parameterKey, parameterValue));
+			}
+			
+			tableContainer.child(parameters);
+		}
+		
+		if (op.hasResponses()) {
+			tableContainer.child(
+				div(h4("Responses")._class("title"))._class("op-block-section-header")
+			);
+			
+			Table responses = table(tr(th("Code")._class("response-key"), th("Description")._class("response-key")))._class("responses");
+			tableContainer.child(responses);
+			
+			for (Map.Entry<String,ResponseInfo> e3 : op.getResponses().entrySet()) {
+				ResponseInfo ri = e3.getValue();
+				
+				Td code = td(e3.getKey())._class("response-key");
+
+				Td codeValue = td(
+					div(
+						ri.getDescription()
+					)._class("description"),
+					examples(s, ri),
+					headers(s, ri)
+				)._class("response-value");
+				
+				responses.child(tr(code, codeValue));
+			}
+		}
+		
+		return tableContainer;
+	}
+	
+	private Object headers(Swagger s, ResponseInfo ri) {
+		if (! ri.hasHeaders())
+			return null;
+		
+		Table sectionTable = table(
+			tr(th("Name"),th("Description"),th("Type"))
+		)._class("section-table");
+		
+		Div headers = div(
+			div("Headers:")._class("section-name"),
+			sectionTable
+		)._class("headers");
+		
+		for (Map.Entry<String,HeaderInfo> e : ri.getHeaders().entrySet()) {
+			String name = e.getKey();
+			HeaderInfo hi = e.getValue();
+			sectionTable.child(
+				tr(
+					td(name)._class("name"),
+					td(hi.getDescription())._class("description"),
+					td(hi.getType())._class("type")
+				)
+			);
+		}
+		
+		return headers;
+	}
+
+	private Div examples(Swagger s, ParameterInfo pi) {
+		return examples(s, pi.getSchema());
+	}
+	
+	private Div examples(Swagger s, ResponseInfo ri) {
+		return examples(s, ri.getSchema());
+	}
+	
+	private SchemaInfo resolve(Swagger s, SchemaInfo si) {
+		String ref = si.getRef();
+		if (ref != null) 
+			si = s.findRef(ref, SchemaInfo.class);
+		return si;
+	}
+	
+	private Div examples(Swagger s, SchemaInfo si) {
+		if (si == null)
+			return null;
+		
+		si = resolve(s, si);
+		
+		Map<String,String> examples = si.getExamples();
+		if (examples == null)
+			return null;
+		
+		Ul ul = ul()._class("tab");
+		Div div = div(ul)._class("examples");
+		
+		ul.child(li("model").onclick("selectExample(this)").attr("data-name", "model")._class("active"));
+		div.child(div(getSchemaModel(s, si))._class("model active").attr("data-name", "model"));
+
+		for (Map.Entry<String,String> e : examples.entrySet()) {
+			String name = e.getKey();
+			String value = e.getValue();
+			
+			ul.child(li(name).onclick("selectExample(this)").attr("data-name", name));
+			div.child(div(value.replaceAll("\\n", "\n"))._class("example").attr("data-name", name));
+		}
+		
+		return div;
+	}
+	
+	@SuppressWarnings("rawtypes")
+	private ObjectMap getSchemaModel(Swagger s, SchemaInfo si) {
+
+		ObjectMap m = new ObjectMap();
+
+		for (String k1 : si.keySet()) {
+			if (k1.equals("properties")) {
+				ObjectMap m2 = new ObjectMap();
+				for (Map.Entry<String,Map<String,Object>> e : si.getProperties().entrySet()) {
+					String pName = e.getKey();
+					Map<String,Object> pEntry = e.getValue();
+					if (pEntry.containsKey("$ref")) 
+						pEntry = getSchemaModel(s, s.findRef(pEntry.get("$ref").toString(), SchemaInfo.class));
+					if (pEntry.containsKey("items")) {
+						Object items = pEntry.get("items");
+						if (items instanceof Map && ((Map)items).containsKey("$ref"))
+							pEntry.put("items", getSchemaModel(s, s.findRef(((Map)items).get("$ref").toString(), SchemaInfo.class)));
+					}
+					m2.put(pName, pEntry);
+				}
+				m.put(k1, m2);
+			} else if (k1.equals("x-examples")) {
+				// Ignore these.
+			} else {
+				m.append(k1, si.get(k1, Object.class));
+			}
+		}
+		
+		return m;
+	}
+
+	private Div opBlockSummary(String path, String opName, Operation op) {
+		return (Div)div()._class("op-block-summary").children(
+			span(opName.toUpperCase())._class("method-button"),
+			span(path)._class("path"),
+			span(op.getSummary())._class("summary")
+		).onclick("toggleOpBlock(this)");
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
new file mode 100644
index 0000000..47083fd
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
@@ -0,0 +1,316 @@
+/*
+ ***************************************************************************************************************************
+ * 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.                                              *
+ ***************************************************************************************************************************
+*/
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Method buttons (e.g GET/PUT/... buttons)                                                                
+ ----------------------------------------------------------------------------------------------------------*/
+.method-button {
+  	display: inline-block;
+	font-size: 14px;
+    font-weight: bold;
+    min-width: 60px;
+    padding: 6px 15px;
+    text-align: center;
+    border-radius: 3px;
+    text-shadow: 0 1px 0 rgba(0,0,0,.1);
+    font-family: sans-serif;
+    color: #fff;
+}
+.get .method-button        { background: rgb(97,175,254); }
+.put .method-button        { background: rgb(252,161,48); }
+.post .method-button       { background: rgb(73,204,144); }
+.delete .method-button     { background: rgb(249,62,62); }
+.options .method-button    { background: rgb(153,102,255); }
+.deprecated .method-button { background: rgb(170,170,170); }
+.other .method-button      { background: rgb(230,230,0); }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Tag block                                                                                                -
+ - Encapsulates one or more op-blocks.
+ ----------------------------------------------------------------------------------------------------------*/
+
+.tag-block-summary {
+	margin: 10px 0px;
+	padding: 10px 0px;
+	font-family: sans-serif;	
+    align-items: center;
+    cursor: pointer;
+	border-bottom: 1px solid rgba(59,65,81,.2);
+	user-select: none;
+}
+.tag-block-summary .name {
+	font-family: sans-serif;
+	font-size: 22px;
+	padding: 0px 20px;
+}
+.tag-block-summary .description {
+	font-size: 16px;
+	padding: 0px 20px;
+}
+.tag-block-summary .extdocs {
+	float: right;
+	font-size: 14px;
+	padding: 0px 20px;
+}
+
+.tag-block-open .tag-block-contents { display: block; }
+.tag-block-closed .tag-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block                                                                                          
+ - Encapsulates a single http-method + http-path
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block {
+	margin-bottom: 10px;
+	font-family: sans-serif;	
+    align-items: center;
+    border-radius: 4px;
+}
+
+.op-block.get        { background: rgba(97,175,254,.1); border: 1px solid rgb(97,175,254); }
+.op-block.put        { background: rgba(252,161,48,.1); border: 1px solid rgb(252,161,48); }
+.op-block.post       { background: rgba(73,204,144,.1); border: 1px solid rgb(73,204,144); }
+.op-block.options    { background: rgba(153,102,255,.1); border: 1px solid rgb(153,102,255); }
+.op-block.delete     { background: rgba(249,62,62,.1); border: 1px solid rgb(249,62,62); }
+.op-block.deprecated { background: rgba(170,170,170,.1); border: 1px solid rgb(170,170,170); }
+.op-block.other      { background: rgba(230,230,0,0.1); border: 1px solid rgb(230,230,0); }
+
+.op-block-summary {	
+	padding: 5px;
+    cursor: pointer;
+	user-select: none;
+}
+
+.op-block-summary .path {
+	font-size: 16px;
+	word-break: break-all;
+    font-family: monospace;
+    font-weight: bold;
+    padding:10px;
+}
+
+.op-block.deprecated .op-block-summary .path { color: #8f9199; text-decoration: line-through;}
+.op-block.deprecated .op-block-summary .description { color: #8f9199 }
+
+.op-block-summary .summary {
+    font-family: sans-serif;
+    font-size: 14px;
+    padding: 10px;
+}
+
+.op-block-description {
+    font-family: sans-serif;
+    font-size: 14px;
+    padding: 10px;
+}
+
+
+.op-block-open .op-block-contents { display: block; }
+.op-block-closed .op-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block section header                                                                                               -
+ - 'Parameters' and 'Responses' subsections in an op-block
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block-section-header {
+	padding: 8px 20px;
+    background: hsla(0,0%,100%,.2);
+    box-shadow: 0 1px 2px rgba(0,0,0,.1);
+    font-family: sans-serif;
+}
+
+.op-block-section-header .title {
+    font-size: 14px;
+	font-family: sans-serif;
+    margin: 0px;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameters and Responses sections
+ ----------------------------------------------------------------------------------------------------------*/
+
+table.parameters, table.responses {
+    border-collapse: collapse;
+    margin: 20px;
+	width: 95%;
+	border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+th.parameter-key, th.response-key {
+	font-size: 12px;
+    font-weight: bold;
+    padding: 10px;
+    text-align: left;
+	border: none;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+    font-family: sans-serif;
+	background-color: inherit;
+}
+
+td.parameter-value, td.response-value {
+    padding: 10px;
+    text-align: left;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameter name
+ ----------------------------------------------------------------------------------------------------------*/
+
+.parameter-key .in {
+	font-size: 12px;
+    font-family: monospace;
+    font-weight: bold;
+    font-style: italic;
+    color: gray;
+}
+
+.parameter-key .name {
+	font-size: 16px;
+    font-family: sans-serif;
+}
+
+.parameter-key .name.required {
+    font-weight: bold;
+}
+
+.parameter-key .type {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: monospace;
+    font-weight: bold;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Examples
+ ----------------------------------------------------------------------------------------------------------*/
+ 
+.op-block-contents .tab {
+    display: flex;
+    margin: 20px 0 10px;
+    padding: 0;
+    list-style: none;
+}
+
+.op-block-contents .tab li {
+    font-family: sans-serif;
+    font-weight: bold;
+    opacity: 0.5;
+    font-size: 12px;
+	margin: 0px 2px;
+    cursor: pointer;
+}
+
+.op-block-contents .tab li.active {
+    opacity: 1.0;
+	cursor: auto;
+}
+
+.op-block-contents .tab li:not(:last-child):after {
+    content: " -";
+    box-sizing: inherit;
+}
+
+.op-block-contents .tab li:hover {
+    opacity: 1.0;
+}
+
+.op-block-contents .example {
+    font-size: 12px;
+    margin: 0;
+    padding: 5px 20px;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+    hyphens: auto;
+    border-radius: 4px;
+    background: #41444e;
+    overflow-wrap: break-word;
+    font-family: monospace;
+    font-weight: 400;
+    color: #fff;
+	display: none;
+}
+
+.op-block-contents .example.active {
+	display:block;
+}
+
+.op-block-contents .model {
+	display: none;
+}
+
+.op-block-contents .model th, 
+.op-block-contents .model td {
+    padding: 0px;
+}
+
+.op-block-contents .model.active {
+	display:block;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Headers
+ ----------------------------------------------------------------------------------------------------------*/
+
+.section {
+	font-size: 12px;
+    font-weight: bold;
+    padding: 5px 0;
+    text-align: left;
+    font-family: sans-serif;
+}
+
+.headers .name {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: monospace;
+    font-weight: bold;
+}
+
+div.headers {
+	margin: 20px 0px;
+}
+
+.headers .type {
+    font-size: 12px;
+    padding: 5px 0;
+    font-family: monospace;
+    font-weight: bold;
+}
+
+.section-name {
+	display: inline-block;
+	vertical-align: top;
+	margin-right: 20px;
+	font-size: 12px;
+    font-weight: bold;
+    padding: 5px 0;
+    text-align: left;
+    font-family: sans-serif;
+	
+}
+
+.section-table {
+	display: inline-block;
+}
+
+.responses .section-table td {
+	padding: 5px 20px 5px 0px;
+	text-align: left;
+    border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
diff --git a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js
new file mode 100644
index 0000000..5d59506
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js
@@ -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.                                              *
+ ***************************************************************************************************************************
+*/
+
+/* Toggles visibility of tag-group block */
+function toggleTagBlock(e) {
+	e = e.parentNode;
+	var isOpen = e.classList.contains("tag-block-open");
+	if (isOpen) {
+		e.classList.add("tag-block-closed");
+		e.classList.remove("tag-block-open");
+	} else {
+		e.classList.add("tag-block-open");
+		e.classList.remove("tag-block-closed");
+	}
+}
+
+/* Toggles visibility of operation block */
+function toggleOpBlock(e) {
+	e = e.parentNode;
+	var isOpen = e.classList.contains("op-block-open");
+	if (isOpen) {
+		e.classList.add("op-block-closed");
+		e.classList.remove("op-block-open");
+	} else {
+		e.classList.add("op-block-open");
+		e.classList.remove("op-block-closed");
+	}
+}
+
+/* Shows an example */
+function selectExample(e) {
+	var dataName = e.getAttribute("data-name");
+	var examplesNode = e.parentNode.parentNode;
+	var lis = examplesNode.getElementsByTagName("li");
+	var divs = examplesNode.getElementsByTagName("div");
+	
+	for (var i in lis) {
+		var li = lis[i], div = divs[i];
+		if (li.getAttribute("data-name") == dataName) {
+			li.classList.add("active");
+			div.classList.add("active");
+		} else {
+			li.classList.remove("active");
+			div.classList.remove("active");
+		}
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index 6416811..5380ebf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -53,7 +53,7 @@ public final class HtmlBeanPropertyMeta extends BeanPropertyMetaExtended {
 
 	static final class Builder {
 		boolean noTables, noTableHeaders;
-		HtmlFormat format = HtmlFormat.DEFAULT;
+		HtmlFormat format = HtmlFormat.HTML;
 		Class<? extends HtmlRender> render = HtmlRender.class;
 		String link, anchorText;
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index f94fb30..bef6d36 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -210,18 +210,39 @@ public class HtmlSerializerSession extends XmlSerializerSession {
 		return w;
 	}
 	
+	@SuppressWarnings({ "rawtypes", "unchecked" })
 	@Override /* XmlSerializerSession */
 	protected ContentResult serializeAnything(
-		XmlWriter out,
-		Object o,
-		ClassMeta<?> eType,
-		String elementName,
-		Namespace elementNamespace,
-		boolean addNamespaceUris,
-		XmlFormat format,
-		boolean isMixed,
-		boolean preserveWhitespace,
-		BeanPropertyMeta pMeta) throws Exception {
+			XmlWriter out,
+			Object o,
+			ClassMeta<?> eType,
+			String elementName,
+			Namespace elementNamespace,
+			boolean addNamespaceUris,
+			XmlFormat format,
+			boolean isMixed,
+			boolean preserveWhitespace,
+			BeanPropertyMeta pMeta) throws Exception {
+		
+		// If this is a bean, then we want to serialize it as HTML unless it's @Html(format=XML). 
+		ClassMeta<?> type = push(elementName, o, eType);
+		pop();
+		
+		if (type == null) 
+			type = object();
+		else if (type.isDelegate()) 
+			type = ((Delegate)o).getClassMeta();
+		PojoSwap swap = type.getPojoSwap(this);
+		if (swap != null) {
+			o = swap.swap(this, o);
+			type = swap.getSwapClassMeta(this);
+			if (type.isObject())
+				type = getClassMetaForObject(o);
+		}
+
+		HtmlClassMeta html = type.getExtendedMeta(HtmlClassMeta.class);
+		if (type.isMapOrBean() && ! html.isXml()) 
+			return serializeAnything(out, o, eType, elementName, pMeta, 0, false);
 		
 		return super.serializeAnything(out, o, eType, elementName, elementNamespace, addNamespaceUris, format, isMixed, preserveWhitespace, pMeta);
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/Html.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/Html.java
index 3298e88..d18cf64 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/Html.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/Html.java
@@ -51,7 +51,7 @@ public @interface Html {
 	 * Specifies what format to use for the HTML element.
 	 * 
 	 */
-	HtmlFormat format() default HtmlFormat.DEFAULT;
+	HtmlFormat format() default HtmlFormat.HTML;
 
 	/**
 	 * Adds a hyperlink to a bean property when rendered as HTML.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlFormat.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlFormat.java
index 9d82f95..eef5c1e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlFormat.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlFormat.java
@@ -25,8 +25,7 @@ public enum HtmlFormat {
 	
 	/**
 	 * Object is serialized to HTML.
-	 * <br>Useful if you want to switch back to serializing POJOs as HTML within elements
-	 * marked for XML serialization.
+	 * <br>This is the default value for serialization.
 	 */
 	HTML,
 	
@@ -34,10 +33,5 @@ public enum HtmlFormat {
 	 * Object is serialized to XML.
 	 * <br>Useful when creating beans that model HTML elements.
 	 */
-	XML,
-	
-	/**
-	 * Object is serialized using whatever the current context is.
-	 */
-	DEFAULT
+	XML
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
index 5734f20..b6d5535 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
@@ -31,7 +31,7 @@ public class MultiSet<E> extends AbstractSet<E> {
 	 * 
 	 * @param c Zero or more collections to add to this set.
 	 */
-	@SuppressWarnings("unchecked")
+	@SafeVarargs
 	public MultiSet(Collection<E>...c) {
 		for (Collection<E> cc : c)
 			append(cc);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
index 036cb21..f606573 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
@@ -50,4 +50,17 @@ public final class ASet<T> extends LinkedHashSet<T> {
 		addAll(Arrays.asList(t));
 		return this;
 	}
+	
+	/**
+	 * Adds a value to this set if the boolean value is <jk>true</jk>
+	 * 
+	 * @param b The boolean value.
+	 * @param t The value to add.
+	 * @return This object (for method chaining).
+	 */
+	public ASet<T> appendIf(boolean b, T t) {
+		if (b)
+			append(t);
+		return this;
+	}
 }
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index e657521..9702e63 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21253,6 +21253,10 @@
 			<li>
 				<code><ja>@Html</ja>(asXml)</code> and <code><ja>@Html</ja>(asPlainText)</code> replaced with
 				{@link org.apache.juneau.html.annotation.Html#format() @Html(format)}.
+			<li>
+				HTML serializer will now serializers beans and maps as HTML even when those objects are embedded
+				within an object with <code><ja>@Html</ja>(format=<jsf>XML</jsf>)</code>.
+				<br>The previous behavior was to serialize it as XML.
 		</ul>
 		
 		<h5 class='topic w800'>juneau-dto</h5>
@@ -24548,7 +24552,7 @@
 					<li><del><code>ClassMeta.getRdfMeta()</code></del>
 				</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 <code><del>@Html.asPlainText()</del></code> annotation.
 			<li>New <code><del>HtmlDocSerializerContext.HTMLDOC_cssImports</del></code> property.
 			<li>Significant changes to RDF support.
 				<ul>
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
index d0b9597..330c262 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/StaticFilesResource.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.http.HttpMethodName.*;
 
 import org.apache.juneau.dto.*;
 import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.dto.swagger.ui.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.microservice.*;
 import org.apache.juneau.rest.annotation.*;
@@ -26,7 +27,7 @@ import org.apache.juneau.rest.widget.*;
  */
 @RestResource(
 	path="/staticFiles",
-	title="Sample static files resource",
+	title="SwaggerUI testbed",
 	description="Sample resource that shows how to use static files.",
 	htmldoc=@HtmlDoc(
 		widgets={
@@ -59,10 +60,15 @@ public class StaticFilesResource extends BasicRestServletJena {
 		};
 	}
 	
-	@RestMethod(name=GET, path="/swagger", summary="xxx")
+	@RestMethod(name=GET, path="/swagger", summary="Normal")
 	public Swagger testSwagger() throws Exception {
 		Swagger s = getContext().getClasspathResource(Swagger.class, MediaType.JSON, "files/petstore.json", null);
 		return s;
 	}
 	
+	@RestMethod(name=GET, path="/swagger2", summary="SwaggerUI", pojoSwaps=SwaggerUI.class)
+	public Swagger testSwagger2() throws Exception {
+		Swagger s = getContext().getClasspathResource(Swagger.class, MediaType.JSON, "files/petstore.json", null);
+		return s;
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
index b3a42d4..080e07c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.html
@@ -18,19 +18,21 @@
 
 <style class='text/css'>
 
+/*-----------------------------------------------------------------------------------------------------------
+ - Method buttons (e.g GET/PUT/... buttons)                                                                
+ ----------------------------------------------------------------------------------------------------------*/
 .method-button {
   	display: inline-block;
 	font-size: 14px;
-    font-weight: 700;
+    font-weight: bold;
     min-width: 60px;
     padding: 6px 15px;
     text-align: center;
     border-radius: 3px;
     text-shadow: 0 1px 0 rgba(0,0,0,.1);
-    font-family: Titillium Web,sans-serif;
+    font-family: sans-serif;
     color: #fff;
 }
-	
 .get .method-button        { background: rgb(97,175,254); }
 .put .method-button        { background: rgb(252,161,48); }
 .post .method-button       { background: rgb(73,204,144); }
@@ -39,40 +41,48 @@
 .deprecated .method-button { background: rgb(170,170,170); }
 .other .method-button      { background: rgb(230,230,0); }
 
-.op-block {
-	margin: 0 0 15px;
-	font-family: Open Sans,sans-serif;	
-    align-items: center;
-    cursor: pointer;
-    border-radius: 4px;
-}
+/*-----------------------------------------------------------------------------------------------------------
+ - Tag block                                                                                                -
+ - Encapsulates one or more op-blocks.
+ ----------------------------------------------------------------------------------------------------------*/
 
 .tag-block-summary {
 	margin: 10px 0px;
 	padding: 10px 0px;
-	font-family: Open Sans,sans-serif;	
+	font-family: sans-serif;	
     align-items: center;
     cursor: pointer;
 	border-bottom: 1px solid rgba(59,65,81,.2);
 }
-
 .tag-block-summary .name {
-	font-family: Titillium Web,sans-serif;
+	font-family: sans-serif;
 	font-size: 22px;
 	padding: 0px 20px;
 }
 .tag-block-summary .description {
 	font-size: 16px;
-	font-weight: 400;
 	padding: 0px 20px;
 }
 .tag-block-summary .extdocs {
 	float: right;
 	font-size: 14px;
-	font-weight: 400;
 	padding: 0px 20px;
 }
 
+.is-tag-block-open .tag-block-contents { display: block; }
+.is-tag-block-closed .tag-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block                                                                                          
+ - Encapsulates a single http-method + http-path
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block {
+	margin-bottom: 10px;
+	font-family: sans-serif;	
+    align-items: center;
+    border-radius: 4px;
+}
 
 .op-block.get        { background: rgba(97,175,254,.1); border: 1px solid rgb(97,175,254); }
 .op-block.put        { background: rgba(252,161,48,.1); border: 1px solid rgb(252,161,48); }
@@ -83,14 +93,15 @@
 .op-block.other      { background: rgba(230,230,0,0.1); border: 1px solid rgb(230,230,0); }
 
 .op-block-summary {	
-	padding:5px;
+	padding: 5px;
+    cursor: pointer;
 }
 
 .op-block-summary .path {
 	font-size: 16px;
 	word-break: break-all;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
+    font-family: monospace;
+    font-weight: bold;
 	color: #3b4151;
     padding:10px;
 }
@@ -99,40 +110,38 @@
 .op-block.deprecated .op-block-summary .description { color: #8f9199 }
 
 .op-block-summary .description {
-    font-family: Open Sans,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
-    font-size: 13px;
-    padding:10px;
+    font-size: 14px;
+    padding: 10px;
 }
 
+.is-op-block-open .op-block-contents { display: block; }
+.is-op-block-closed .op-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block section header                                                                                               -
+ - 'Parameters' and 'Responses' subsections in an op-block
+ ----------------------------------------------------------------------------------------------------------*/
+
 .op-block-section-header {
 	padding: 8px 20px;
     background: hsla(0,0%,100%,.8);
     box-shadow: 0 1px 2px rgba(0,0,0,.1);
-    font-family: Open Sans,sans-ser;
+    font-family: sans-serif;
     color: #8f9199;      
 }
 
 .op-block-section-header .title {
     font-size: 14px;
-	font-family: Titillium Web,sans-serif;
+	font-family: sans-serif;
     color: #3b4151;
     margin: 0px;
 }
 
-.is-tag-block-open .tag-block-contents {
-	display: block;
-}
-.is-tag-block-closed .tag-block-contents {
-	display: none;
-}
-
-.is-op-block-open .op-block-contents {
-	display: block;
-}
-.is-op-block-closed .op-block-contents {
-	display: none;
-}
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameters and Respones sections
+ ----------------------------------------------------------------------------------------------------------*/
 
 .parameters, .responses {
     border-collapse: collapse;
@@ -143,11 +152,11 @@
 
 .parameters th, .responses th {
 	font-size: 12px;
-    font-weight: 700;
+    font-weight: bold;
     padding: 5px 0;
     text-align: left;
     border-bottom: 1px solid rgba(59,65,81,.2);
-    font-family: Open Sans,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
 }
 
@@ -157,40 +166,47 @@
     border-bottom: 1px solid rgba(59,65,81,.2);
 }
 
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameter name
+ ----------------------------------------------------------------------------------------------------------*/
+
 .parameter-key .in {
 	font-size: 12px;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
+    font-family: monospace;
+    font-weight: bold;
     font-style: italic;
     color: gray;
 }
 
 .parameter-key .name {
 	font-size: 16px;
-    font-weight: 400;
-    font-family: Titillium Web,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
 }
 
 .parameter-key .name.required {
-    font-weight: 700;
+    font-weight: bold;
 }
 
 .parameter-key .type {
     font-size: 12px;
     padding: 5px 0;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
+    font-family: monospace;
+    font-weight: bold;
     color: #3b4151;
 }
 
+/*-----------------------------------------------------------------------------------------------------------
+ - Examples
+ ----------------------------------------------------------------------------------------------------------*/
+ 
 .tab {
     display: flex;
     margin: 20px 0 10px;
     padding: 0;
     list-style: none;
     cursor: pointer;
-    font-family: Titillium Web,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
     font-size: 12px;
 }
@@ -200,17 +216,18 @@
 }
 
 .tab .active {
-    font-weight: 700;
+    font-weight: bold;
+    cursor: auto;
 }
 
 .tab li:not(:last-child):after {
     content: " -";
-    font-weight:400;
+    font-weight: normal;
     box-sizing: inherit;
 }
 
 .tab li:hover {
-    font-weight:700;
+    font-weight: bold;
 }
 
 .example {
@@ -223,30 +240,34 @@
     border-radius: 4px;
     background: #41444e;
     overflow-wrap: break-word;
-    font-family: Source Code Pro,monospace;
+    font-family: monospace;
     font-weight: 400;
     color: #fff;
-	display:none;
+	display: none;
 }
 
 .example.active {
 	display:block;
 }
 
+/*-----------------------------------------------------------------------------------------------------------
+ - Headers
+ ----------------------------------------------------------------------------------------------------------*/
+
 .section {
 	font-size: 12px;
-    font-weight: 700;
+    font-weight: bold;
     padding: 5px 0;
     text-align: left;
-    font-family: Open Sans,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
 }
 
 .headers .name {
     font-size: 12px;
     padding: 5px 0;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
+    font-family: monospace;
+    font-weight: bold;
     color: #3b4151;
 }
 
@@ -257,8 +278,8 @@ div.headers {
 .headers .type {
     font-size: 12px;
     padding: 5px 0;
-    font-family: Source Code Pro,monospace;
-    font-weight: 600;
+    font-family: monospace;
+    font-weight: bold;
     color: #3b4151;
 }
 
@@ -267,10 +288,10 @@ div.headers {
 	vertical-align: top;
 	margin-right: 20px;
 	font-size: 12px;
-    font-weight: 700;
+    font-weight: bold;
     padding: 5px 0;
     text-align: left;
-    font-family: Open Sans,sans-serif;
+    font-family: sans-serif;
     color: #3b4151;
 	
 }
@@ -285,7 +306,6 @@ div.headers {
     border-bottom: 1px solid rgba(59,65,81,.2);
 }
 
-
 	</style>
 	<script>
 
@@ -351,6 +371,9 @@ div.headers {
 			</div>
 			<div class='op-block-contents'>
 				<div class="table-container">
+					<div class='op-block-description'>
+					</div>			
+				
 					<div class="op-block-section-header">
 						<h4 class="title">Parameters</h4>
 					</div>	
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
index 54791ba..50c2ecc 100644
--- a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/files/petstore.json
@@ -906,6 +906,12 @@
 			},
 			"xml": {
 				"name": "Order"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
 			}
 		},
 		"User": {
@@ -941,6 +947,12 @@
 			},
 			"xml": {
 				"name": "User"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
 			}
 		},
 		"Category": {
@@ -956,6 +968,12 @@
 			},
 			"xml": {
 				"name": "Category"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123,\n\tflags:[\n\t\t'f1',\n\t\t'f1',\n\t\t'f3'\n\t]\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
 			}
 		},
 		"Tag": {
@@ -971,6 +989,12 @@
 			},
 			"xml": {
 				"name": "Tag"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
 			}
 		},
 		"Pet": {
@@ -1025,11 +1049,10 @@
 				"name": "Pet"
 			},
 			"x-examples": {
-				"model": "{foo:}",
-				"application/json": "{foo:'bar'}",
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123,\n\tflags:[\n\t\t'f1',\n\t\t'f1',\n\t\t'f3'\n\t]\n}",
 				"text/xml": "<foo>bar</foo>",
 				"text/html": "<table>foo</table>",
-				"octal-messagepack": "123456ABCDEF"
+				"octal-messagepack": "12 34 56 AB CD EF"
 			},
 		},
 		"ApiResponse": {
@@ -1045,6 +1068,12 @@
 				"message": {
 					"type": "string"
 				}
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
 			}
 		}
 	},

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.

Mime
View raw message