juneau-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] Akayeshmantha closed pull request #44: initial commit on open api spec 3
Date Wed, 09 Jan 2019 05:14:25 GMT
Akayeshmantha closed pull request #44: initial commit on open api spec 3
URL: https://github.com/apache/juneau/pull/44
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Contact.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Contact.java
new file mode 100644
index 000000000..3bedc60d1
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Contact.java
@@ -0,0 +1,282 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * Contact information for the exposed API.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Contact x = <jsm>contact</jsm>(<js>"API Support"</js>, <js>"http://www.swagger.io/support"</js>, <js>"support@swagger.io"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"API Support"</js>,
+ * 		<js>"url"</js>: <js>"http://www.swagger.io/support"</js>,
+ * 		<js>"email"</js>: <js>"support@swagger.io"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="name,url,email,*")
+public class Contact extends OpenApiElement {
+
+	private String name;
+	private URI url;
+	private String email;
+
+	/**
+	 * Default constructor.
+	 */
+	public Contact() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Contact(Contact copyFrom) {
+		super(copyFrom);
+
+		this.name = copyFrom.name;
+		this.url = copyFrom.url;
+		this.email = copyFrom.email;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Contact copy() {
+		return new Contact(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Bean property setter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @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 Contact setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Contact name(Object value) {
+		return setName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>url</property>.
+	 *
+	 * <p>
+	 * The URL pointing to the contact information.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public URI getUrl() {
+		return url;
+	}
+
+	/**
+	 * Bean property setter:  <property>url</property>.
+	 *
+	 * <p>
+	 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+	 * <br>Strings must be valid URIs.
+	 *
+	 * <p>
+	 * URIs defined by {@link UriResolver} can be used for values.
+	 *
+	 * @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 Contact setUrl(URI value) {
+		url = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setUrl(URI)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Contact url(Object value) {
+		return setUrl(StringUtils.toURI(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>email</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getEmail() {
+		return email;
+	}
+
+	/**
+	 * Bean property setter:  <property>email</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Contact setEmail(String value) {
+		email = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setEmail(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Contact email(Object value) {
+		return setEmail(toStringVal(value));
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the name property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the name property is not null or empty.
+	 */
+	public boolean hasName() {
+		return isNotEmpty(name);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the URL property is not null.
+	 *
+	 * @return <jk>true</jk> if the URL property is not null.
+	 */
+	public boolean hasUrl() {
+		return url != null;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the email property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the email property is not null or empty.
+	 */
+	public boolean hasEmail() {
+		return isNotEmpty(email);
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "name": return toType(getName(), type);
+			case "url": return toType(getUrl(), type);
+			case "email": return toType(getEmail(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Contact set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "name": return name(value);
+			case "url": return url(value);
+			case "email": return email(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/Discriminator.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Discriminator.java
new file mode 100644
index 000000000..602339b57
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Discriminator.java
@@ -0,0 +1,200 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * Used to aid in serialization, deserialization, and validation.
+ */
+@Bean(properties="propertyName,mapping,*")
+public class Discriminator extends OpenApiElement {
+
+	private String propertyName;
+	private Map<String,String> mapping;
+
+	/**
+	 * Default constructor.
+	 */
+	public Discriminator() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Discriminator(Discriminator copyFrom) {
+		super(copyFrom);
+
+		this.propertyName = copyFrom.propertyName;
+		if (copyFrom.mapping == null)
+			this.mapping = null;
+		else
+			this.mapping = new LinkedHashMap<>(copyFrom.mapping);
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Discriminator copy() {
+		return new Discriminator(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>propertyName</property>.
+	 *
+	 * <p>
+	 * A short description of the target documentation.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getPropertyName() {
+		return propertyName;
+	}
+
+	/**
+	 * Bean property setter:  <property>propertyName</property>.
+	 *
+	 * <p>
+	 * A short description of the target documentation.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Discriminator setPropertyName(String value) {
+		propertyName = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setPropertyName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Discriminator propertyName(Object value) {
+		return setPropertyName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>mapping</property>.
+	 *
+	 * <p>
+	 * The URL for the target documentation.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Map<String, String> getMapping() {
+		return mapping;
+	}
+
+	/**
+	 * Bean property setter:  <property>mapping</property>.
+	 *
+	 * <p>
+	 * The URL for the target documentation.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * 	<br>URIs defined by {@link UriResolver} can be used for values.
+	 * @return This object (for method chaining).
+	 */
+	public Discriminator setMapping(Map<String,String> value) {
+		mapping = newMap(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>mapping</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Discriminator addMapping(Map<String,String> values) {
+		mapping = addToMap(mapping, values);
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMapping(Map<String,String>)}.
+	 *
+	 * @param values
+	 * @return This object (for method chaining).
+	 */
+	public Discriminator mapping(Object...values) {
+		mapping = addToMap(mapping, values, String.class, String.class);
+		return this;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the property is not null.
+	 *
+	 * @return <jk>true</jk> if the property is not null.
+	 */
+	public boolean hasPropertyName() {
+		return ! propertyName.isEmpty();
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "propertyName": return toType(getPropertyName(), type);
+			case "mapping": return toType(getMapping(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Discriminator set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "propertyName": return propertyName(value);
+			case "mapping": return mapping(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(propertyName != null, "propertyName")
+			.appendIf(mapping != null, "mapping");
+		return new MultiSet<>(s, super.keySet());
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Encoding.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Encoding.java
new file mode 100644
index 000000000..3a021e300
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Encoding.java
@@ -0,0 +1,363 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+@Bean(properties="contentType,style,explode,headers,allowReserved,*")
+public class Encoding extends OpenApiElement{
+
+    private String contentType,
+            style;
+    private Map<String,HeaderInfo> headers;
+    private Boolean explode,
+            allowReserved;
+
+    /**
+     * Default constructor.
+     */
+    public Encoding() { }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public Encoding(Encoding copyFrom) {
+        super(copyFrom);
+
+        this.contentType = copyFrom.contentType;
+        this.style = copyFrom.style;
+        this.explode = copyFrom.explode;
+        this.allowReserved = copyFrom.allowReserved;
+        if (copyFrom.headers == null) {
+            this.headers = null;
+        } else {
+            this.headers = new LinkedHashMap<>();
+            for (Map.Entry<String,HeaderInfo> e : copyFrom.headers.entrySet())
+                this.headers.put(e.getKey(),	e.getValue().copy());
+        }
+    }
+
+    /**
+     * Make a deep copy of this object.
+     *
+     * @return A deep copy of this object.
+     */
+    public Encoding copy() {
+        return new Encoding(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected Encoding strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>contentType</property>.
+     *
+     * <p>
+     * The URL pointing to the contact information.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Bean property setter:  <property>url</property>.
+     *
+     * <p>
+     * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+     * <br>Strings must be valid URIs.
+     *
+     * <p>
+     * URIs defined by {@link UriResolver} can be used for values.
+     *
+     * @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 Encoding setContentType(String value) {
+        contentType = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setContentType(String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public Encoding contentType(Object value) {
+        return setContentType(toStringVal(value));
+    }
+
+    /**
+     * Bean property getter:  <property>style</property>.
+     */
+    public String getStyle() {
+        return style;
+    }
+
+    /**
+     * Bean property setter:  <property>description</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Encoding setStyle(String value) {
+        style = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setStyle(String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Encoding style(Object value) {
+        return setStyle(toStringVal(value));
+    }
+
+    /**
+     * Bean property getter:  <property>variables</property>.
+     */
+    public Map<String, HeaderInfo> getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Bean property setter:  <property>variables</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Encoding setHeaders(Map<String, HeaderInfo> value) {
+        headers = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Encoding addHeader(Map<String, HeaderInfo> value) {
+        headers = addToMap(headers,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Encoding addHeaders(String keyval, HeaderInfo value) {
+        headers = addToMap(headers,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public Encoding header(String name, HeaderInfo value) {
+        addHeader(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Encoding headers(Object...values) {
+        headers = addToMap(headers, values, String.class, HeaderInfo.class);
+        return this;
+    }
+
+    public Encoding headers(Object value) {
+        return setHeaders((HashMap<String,HeaderInfo>)value);
+    }
+
+
+    /**
+     * Bean property getter:  <property>required</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public Boolean getExplode() {
+        return explode;
+    }
+
+    /**
+     * Bean property setter:  <property>explode</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul class='doctree'>
+     * 	<li class='extlink'>{@doc SwaggerDataTypes}
+     * </ul>
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Property value is required.
+     * 	</ul>
+     * @return This object (for method chaining).
+     */
+    public Encoding setExplode(Boolean value) {
+        explode = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setExplode(Boolean)}
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public Encoding explode(Object value) {
+        return setExplode(toBoolean(value));
+    }
+
+
+    /**
+     * Bean property getter:  <property>required</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public Boolean getAllowReserved() {
+        return allowReserved;
+    }
+
+    /**
+     * Bean property setter:  <property>explode</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul class='doctree'>
+     * 	<li class='extlink'>{@doc SwaggerDataTypes}
+     * </ul>
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Property value is required.
+     * 	</ul>
+     * @return This object (for method chaining).
+     */
+    public Encoding setAllowReserved(Boolean value) {
+        allowReserved = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setExplode(Boolean)}
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public Encoding allowReserved(Object value) {
+        return setAllowReserved(toBoolean(value));
+    }
+
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "contentType": return toType(getContentType(), type);
+            case "style": return toType(getStyle(), type);
+            case "headers": return toType(getHeaders(), type);
+            case "explode": return toType(getExplode(), type);
+            case "allowReserved": return toType(getAllowReserved(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Encoding set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "contentType": return contentType(value);
+            case "style": return style(value);
+            case "headers": return headers(value);
+            case "explode": return explode(value);
+            case "allowReserved": return allowReserved(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(contentType != null, "contentType")
+                .appendIf(style != null, "style")
+                .appendIf(headers != null, "headers")
+                .appendIf(explode != null, "explode")
+                .appendIf(allowReserved != null, "allowReserved");
+        return new MultiSet<>(s, super.keySet());
+    }
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Example.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Example.java
new file mode 100644
index 000000000..d829487d4
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Example.java
@@ -0,0 +1,305 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * information for Examples object.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Contact x = <jsm>contact</jsm>(<js>"API Support"</js>, <js>"http://www.swagger.io/support"</js>, <js>"support@swagger.io"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"API Support"</js>,
+ * 		<js>"url"</js>: <js>"http://www.swagger.io/support"</js>,
+ * 		<js>"email"</js>: <js>"support@swagger.io"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="summary,description,externalValue,value,*")
+public class Example extends OpenApiElement {
+
+	private String summary;
+	private String description;
+	private String externalValue;
+	private Object value;
+
+	/**
+	 * Default constructor.
+	 */
+	public Example() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Example(Example copyFrom) {
+		super(copyFrom);
+
+		this.summary = copyFrom.summary;
+		this.description = copyFrom.description;
+		this.externalValue = copyFrom.externalValue;
+		this.value = copyFrom.value;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Example copy() {
+		return new Example(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>summary</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getSummary() {
+		return summary;
+	}
+
+	/**
+	 * Bean property setter:  <property>summary</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @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 Example setSummary(String value) {
+		summary = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setSummary(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Example summary(Object value) {
+		return setSummary(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * The URL pointing to the contact information.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</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).
+	 */
+	public Example setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Example description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getExternalValue() {
+		return externalValue;
+	}
+
+	/**
+	 * Bean property setter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Example setExternalValue(String value) {
+		externalValue = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExternalValue(String)} (String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Example externalValue(Object value) {
+		return setExternalValue(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
+	 * to control the number of results per page might default to 100 if not supplied by the client in the request.
+	 *
+	 * (Note: <js>"value"</js> has no meaning for required parameters.)
+	 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for this parameter.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Object getValue() {
+		return value;
+	}
+
+	/**
+	 * Bean property setter:  <property>value</property>.
+	 *
+	 * <p>
+	 * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
+	 * to control the number of results per page might default to 100 if not supplied by the client in the request.
+	 * (Note: <js>"default"</js> has no meaning for required parameters.)
+	 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for this parameter.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @param val The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public Example setValue(Object val) {
+		value = val;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setValue(Object)}.
+	 *
+	 * @param val The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public Example value(Object val) {
+		return setValue(val);
+	}
+
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "description": return toType(getDescription(), type);
+			case "externalValue": return toType(getExternalValue(), type);
+			case "summary": return toType(getSummary(), type);
+			case "value": return toType(getValue(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Example set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "description": return description(value);
+			case "externalValue": return externalValue(value);
+			case "summary": return summary(value);
+			case "value": return value(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+				.appendIf(summary != null, "summary")
+				.appendIf(externalValue != null, "externalValue")
+			.appendIf(value != null, "value");
+		return new MultiSet<>(s, super.keySet());
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ExternalDocumentation.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ExternalDocumentation.java
new file mode 100644
index 000000000..98b37337e
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ExternalDocumentation.java
@@ -0,0 +1,206 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * Allows referencing an external resource for extended documentation.
+ */
+@Bean(properties="description,url,*")
+public class ExternalDocumentation extends OpenApiElement {
+
+	private String description;
+	private URI url;
+
+	/**
+	 * Default constructor.
+	 */
+	public ExternalDocumentation() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public ExternalDocumentation(ExternalDocumentation copyFrom) {
+		super(copyFrom);
+
+		this.description = copyFrom.description;
+		this.url = copyFrom.url;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public ExternalDocumentation copy() {
+		return new ExternalDocumentation(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the target documentation.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the target documentation.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public ExternalDocumentation setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public ExternalDocumentation description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>url</property>.
+	 *
+	 * <p>
+	 * The URL for the target documentation.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public URI getUrl() {
+		return url;
+	}
+
+	/**
+	 * Bean property setter:  <property>url</property>.
+	 *
+	 * <p>
+	 * The URL for the target documentation.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * 	<br>URIs defined by {@link UriResolver} can be used for values.
+	 * @return This object (for method chaining).
+	 */
+	public ExternalDocumentation setUrl(URI value) {
+		url = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setUrl(URI)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>URIs defined by {@link UriResolver} can be used for values.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link URI}
+	 * 		<li>{@link URL}
+	 * 		<li>{@link String}
+	 * 			<br>Converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 		<li>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public ExternalDocumentation url(Object value) {
+		return setUrl(StringUtils.toURI(value));
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the url property is not null.
+	 *
+	 * @return <jk>true</jk> if the url property is not null.
+	 */
+	public boolean hasUrl() {
+		return url != null;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the description property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the description property is not null or empty.
+	 */
+	public boolean hasDescription() {
+		return isNotEmpty(description);
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "description": return toType(getDescription(), type);
+			case "url": return toType(getUrl(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public ExternalDocumentation set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "description": return description(value);
+			case "url": return url(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/HeaderInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/HeaderInfo.java
new file mode 100644
index 000000000..09f9369e3
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/HeaderInfo.java
@@ -0,0 +1,671 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.annotation.BeanProperty;
+import org.apache.juneau.dto.swagger.ResponseInfo;
+import org.apache.juneau.dto.swagger.Swagger;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.util.*;
+
+import static org.apache.juneau.internal.ArrayUtils.contains;
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * Describes a single HTTP header.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	HeaderInfo x = <jsm>headerInfo</jsm>(<js>"integer"</js>).description(<js>"The number of allowed requests in the current period"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"description"</js>: <js>"The number of allowed requests in the current period"</js>,
+ * 		<js>"type"</js>: <js>"integer"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="description,explode,deprecated,allowEmptyValue,allowReserved,schema,example,examples,$ref,*")
+@SuppressWarnings({"unchecked"})
+public class HeaderInfo extends OpenApiElement {
+
+	private static final String[] VALID_TYPES = {"string", "number", "integer", "boolean", "array"};
+	private static final String[] VALID_COLLECTION_FORMATS = {"csv","ssv","tsv","pipes","multi"};
+
+	private String
+		description,
+		ref;
+	private Boolean
+		required,
+		explode,
+		deprecated,
+		allowEmptyValue,
+		allowReserved;
+	private SchemaInfo schema;
+	private Object example;
+	private Map<String,Example> examples;
+
+
+	/**
+	 * Default constructor.
+	 */
+	public HeaderInfo() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public HeaderInfo(HeaderInfo copyFrom) {
+		super(copyFrom);
+
+		this.description = copyFrom.description;
+		this.example = copyFrom.example;
+		this.allowEmptyValue = copyFrom.allowEmptyValue;
+		this.schema = copyFrom.schema;
+		this.allowReserved = copyFrom.allowReserved;
+		this.required = copyFrom.required;
+		this.ref = copyFrom.ref;
+		this.explode = copyFrom.explode;
+		this.deprecated = copyFrom.deprecated;
+		if (copyFrom.examples == null)
+			this.examples = null;
+		else
+			this.examples = new LinkedHashMap<>();
+			for (Map.Entry<String,Example> e : copyFrom.examples.entrySet())
+				this.examples.put(e.getKey(),	e.getValue().copy());
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public HeaderInfo copy() {
+		return new HeaderInfo(this);
+	}
+
+	@Override /* OpenApiElement */
+	protected HeaderInfo strict() {
+		super.strict();
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the header.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the header.
+	 *
+	 * @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 HeaderInfo setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>required</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getRequired() {
+		return required;
+	}
+
+	/**
+	 * Bean property setter:  <property>required</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo setRequired(Boolean value) {
+		required = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setRequired(Boolean)}
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo required(Object value) {
+		return setRequired(toBoolean(value));
+	}
+
+
+	/**
+	 * Bean property getter:  <property>required</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getExplode() {
+		return explode;
+	}
+
+	/**
+	 * Bean property setter:  <property>explode</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo setExplode(Boolean value) {
+		explode = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExplode(Boolean)}
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo explode(Object value) {
+		return setExplode(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>deprecated</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getDeprecated() {
+		return deprecated;
+	}
+
+	/**
+	 * Bean property setter:  <property>deprecated</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo setDeprecated(Boolean value) {
+		deprecated = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDeprecated(Boolean)}
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo deprecated(Object value) {
+		return setDeprecated(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>allowEmptyValue</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getAllowEmptyValue() {
+		return allowEmptyValue;
+	}
+
+	/**
+	 * Bean property setter:  <property>allowEmptyValue</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo setAllowEmptyValue(Boolean value) {
+		allowEmptyValue = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDeprecated(Boolean)}
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo allowEmptyValue(Object value) {
+		return setAllowEmptyValue(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>allowReserved</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getAllowReserved() {
+		return allowReserved;
+	}
+
+	/**
+	 * Bean property setter:  <property>allowReserved</property>.
+	 *
+	 * <p>
+	 * The type of the object.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo setAllowReserved(Boolean value) {
+		allowReserved = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDeprecated(Boolean)}
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo allowReserved(Object value) {
+		return setAllowReserved(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>schema</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public SchemaInfo getSchema() {
+		return schema;
+	}
+
+	/**
+	 * Bean property setter:  <property>schema</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).
+	 */
+	public HeaderInfo setSchema(SchemaInfo value) {
+		schema = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setSchema(SchemaInfo)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo schema(Object value) {
+		return setSchema(toType(value, SchemaInfo.class));
+	}
+
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 *
+	 * @return <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 */
+	public boolean hasRef() {
+		return ref != null;
+	}
+
+	/**
+	 * 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 HeaderInfo 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 HeaderInfo ref(Object value) {
+		return setRef(value);
+	}
+
+	/**
+	 * Bean property getter:  <property>x-example</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	@BeanProperty("x-example")
+	public Object getExample() {
+		return example;
+	}
+
+	/**
+	 * 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-example")
+	public HeaderInfo setExample(Object value) {
+		example = value;
+		return this;
+	}
+
+	/**
+	 * 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).
+	 */
+	public HeaderInfo example(Object value) {
+		example = value;
+		return this;
+	}
+
+
+	/**
+	 * Bean property getter:  <property>examples</property>.
+	 *
+	 * <p>
+	 * The list of possible responses as they are returned from executing this operation.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Map<String,Example> getExamples() {
+		return examples;
+	}
+
+	/**
+	 * Bean property setter:  <property>headers</property>.
+	 *
+	 * <p>
+	 * A list of examples that are sent with the response.
+	 *
+	 * @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 HeaderInfo setExamples(Map<String,Example> value) {
+		examples = newMap(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>headers</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo addExamples(Map<String,Example> values) {
+		examples = addToMap(examples, values);
+		return this;
+	}
+
+	/**
+	 * Adds a single value to the <property>examples</property> property.
+	 *
+	 * @param name The example name.
+	 * @param example The example.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo example(String name, Example example) {
+		addExamples(Collections.singletonMap(name, example));
+		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,{@link org.apache.juneau.dto.swagger.HeaderInfo}|String&gt;</code>
+	 * 		<li><code>String</code> - JSON object representation of <code>Map&lt;String,{@link org.apache.juneau.dto.swagger.HeaderInfo}&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	headers(<js>"{headerName:{description:'description',...}}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HeaderInfo examples(Object...values) {
+		examples = addToMap(examples,values, String.class, Example.class);
+		return this;
+	}
+
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "description": return (T)getDescription();
+			case "required": return toType(getRequired(), type);
+			case "explode": return toType(getExplode(), type);
+			case "deprecated": return toType(getDeprecated(), type);
+			case "allowEmptyValue": return toType(getAllowEmptyValue(), type);
+			case "allowReserved": return toType(getAllowReserved(), type);
+			case "$ref": return toType(getRef(), type);
+			case "schema": return toType(getSchema(), type);
+			case "x-example": return toType(getExample(), type);
+			case "examples": return toType(getExamples(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public HeaderInfo set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "description": return description(value);
+			case "required": return required(value);
+			case "explode": return explode(value);
+			case "deprecated": return deprecated(value);
+			case "allowEmptyValue": return allowEmptyValue(value);
+			case "$ref": return ref(value);
+			case "schema": return schema(value);
+			case "x-example": return example(value);
+			case "examples": return setExamples(null).examples(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+			.appendIf(required != null, "required")
+			.appendIf(explode != null, "explode")
+			.appendIf(deprecated != null, "deprecated")
+			.appendIf(allowEmptyValue != null, "allowEmptyValue")
+			.appendIf(ref != null, "$ref")
+			.appendIf(allowReserved != null, "allowReserved")
+			.appendIf(schema != null, "schema")
+			.appendIf(example != null, "example")
+			.appendIf(examples != null, "examples");
+		return new MultiSet<>(s, super.keySet());
+
+	}
+
+	/**
+	 * Resolves any <js>"$ref"</js> attributes in this element.
+	 *
+	 * @param swagger The swagger document containing the definitions.
+	 * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
+	 * @param maxDepth
+	 * 	The maximum depth to resolve references.
+	 * 	<br>After that level is reached, <code>$ref</code> references will be left alone.
+	 * 	<br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
+	 * @return
+	 * 	This object with references resolved.
+	 * 	<br>May or may not be the same object.
+	 */
+	public HeaderInfo resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
+
+		if (ref != null) {
+			if (refStack.contains(ref) || refStack.size() >= maxDepth)
+				return this;
+			refStack.addLast(ref);
+			HeaderInfo r = swagger.findRef(ref, HeaderInfo.class).resolveRefs(swagger, refStack, maxDepth);
+			refStack.removeLast();
+			return r;
+		}
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Info.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Info.java
new file mode 100644
index 000000000..32f1b51ed
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Info.java
@@ -0,0 +1,463 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.Contact;
+import org.apache.juneau.dto.swagger.License;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * The object provides metadata about the API.
+ *
+ * <p>
+ * The metadata can be used by the clients if needed, and can be presented
+ * in the Swagger-UI for convenience.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Info x = <jsm>info</jsm>(<js>"Swagger Sample App"</js>, <js>"1.0.1"</js>)
+ * 		.description(<js>"This is a sample server Petstore server."</js>)
+ * 		.termsOfService(<js>"http://swagger.io/terms/"</js>)
+ * 		.contact(
+ * 			<jsm>contact</jsm>(<js>"API Support"</js>, <js>"http://www.swagger.io/support"</js>, <js>"support@swagger.io"</js>)
+ * 		)
+ * 		.license(
+ * 			<jsm>license</jsm>(<js>"Apache 2.0"</js>, <js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>)
+ * 		);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"title"</js>: <js>"Swagger Sample App"</js>,
+ * 		<js>"description"</js>: <js>"This is a sample server Petstore server."</js>,
+ * 		<js>"termsOfService"</js>: <js>"http://swagger.io/terms/"</js>,
+ * 		<js>"contact"</js>: {
+ * 			<js>"name"</js>: <js>"API Support"</js>,
+ * 			<js>"url"</js>: <js>"http://www.swagger.io/support"</js>,
+ * 			<js>"email"</js>: <js>"support@swagger.io"</js>
+ * 		},
+ * 		<js>"license"</js>: {
+ * 			<js>"name"</js>: <js>"Apache 2.0"</js>,
+ * 			<js>"url"</js>: <js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
+ * 		},
+ * 		<js>"version"</js>: <js>"1.0.1"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="title,description,version,contact,license,termsOfService,*")
+public class Info extends OpenApiElement {
+
+	private String
+		title,
+		description,
+		termsOfService,
+		version;
+	private Contact contact;
+	private License license;
+
+	/**
+	 * Default constructor.
+	 */
+	public Info() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Info(Info copyFrom) {
+		super(copyFrom);
+
+		this.title = copyFrom.title;
+		this.description = copyFrom.description;
+		this.termsOfService = copyFrom.termsOfService;
+		this.version = copyFrom.version;
+		this.contact = copyFrom.contact == null ? null : copyFrom.contact.copy();
+		this.license = copyFrom.license == null ? null : copyFrom.license.copy();
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Info copy() {
+		return new Info(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>title</property>.
+	 *
+	 * <p>
+	 * The title of the application.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * Bean property setter:  <property>title</property>.
+	 *
+	 * <p>
+	 * The title of the application.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public Info setTitle(String value) {
+		title = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setTitle(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info title(Object value) {
+		return setTitle(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the application.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description of the application.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>termsOfService</property>.
+	 *
+	 * <p>
+	 * The Terms of Service for the API.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getTermsOfService() {
+		return termsOfService;
+	}
+
+	/**
+	 * Bean property setter:  <property>termsOfService</property>.
+	 *
+	 * <p>
+	 * The Terms of Service for the API.
+	 *
+	 * @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 Info setTermsOfService(String value) {
+		termsOfService = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setTermsOfService(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info termsOfService(Object value) {
+		return setTermsOfService(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>contact</property>.
+	 *
+	 * <p>
+	 * The contact information for the exposed API.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Contact getContact() {
+		return contact;
+	}
+
+	/**
+	 * Bean property setter:  <property>contact</property>.
+	 *
+	 * <p>
+	 * The contact information for the exposed API.
+	 *
+	 * @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 Info setContact(Contact value) {
+		contact = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setContact(Contact)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Contact}
+	 * 		<li><code>String</code> - JSON object representation of {@link Contact}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	contact(<js>"{name:'name',url:'url',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info contact(Object value) {
+		return setContact(toType(value, Contact.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>license</property>.
+	 *
+	 * <p>
+	 * The license information for the exposed API.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public License getLicense() {
+		return license;
+	}
+
+	/**
+	 * Bean property setter:  <property>license</property>.
+	 *
+	 * <p>
+	 * The license information for the exposed API.
+	 *
+	 * @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 Info setLicense(License value) {
+		license = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setLicense(License)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link License}
+	 * 		<li><code>String</code> - JSON object representation of {@link License}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	license(<js>"{name:'name',url:'url',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info license(Object value) {
+		return setLicense(toType(value, License.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>version</property>.
+	 *
+	 * <p>
+	 * Provides the version of the application API (not to be confused with the specification version).
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getVersion() {
+		return version;
+	}
+
+	/**
+	 * Bean property setter:  <property>version</property>.
+	 *
+	 * <p>
+	 * Provides the version of the application API (not to be confused with the specification version).
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public Info setVersion(String value) {
+		version = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setVersion(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Info version(Object value) {
+		return setVersion(toStringVal(value));
+	}
+
+
+	/**
+	 * Returns <jk>true</jk> if the title property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the title property is not null or empty.
+	 */
+	public boolean hasTitle() {
+		return isNotEmpty(title);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the description property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the description property is not null or empty.
+	 */
+	public boolean hasDescription() {
+		return isNotEmpty(description);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the version property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the version property is not null or empty.
+	 */
+	public boolean hasVersion() {
+		return isNotEmpty(version);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the termsOfService property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the termsOfService property is not null or empty.
+	 */
+	public boolean hasTermsOfService() {
+		return isNotEmpty(termsOfService);
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "title": return toType(getTitle(), type);
+			case "description": return toType(getDescription(), type);
+			case "termsOfService": return toType(getTermsOfService(), type);
+			case "contact": return toType(getContact(), type);
+			case "license": return toType(getLicense(), type);
+			case "version": return toType(getVersion(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Info set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "title": return title(value);
+			case "description": return description(value);
+			case "termsOfService": return termsOfService(value);
+			case "contact": return contact(value);
+			case "license": return license(value);
+			case "version": return version(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/Items.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Items.java
new file mode 100644
index 000000000..63fb18453
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Items.java
@@ -0,0 +1,1187 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.FormattedRuntimeException;
+import org.apache.juneau.ObjectList;
+import org.apache.juneau.ObjectMap;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.annotation.BeanProperty;
+import org.apache.juneau.dto.swagger.Swagger;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.json.SimpleJsonSerializer;
+import org.apache.juneau.utils.ASet;
+
+import java.util.*;
+
+import static org.apache.juneau.internal.ArrayUtils.contains;
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * A limited subset of JSON-Schema's items object.
+ *
+ * <p>
+ * It is used by parameter definitions that are not located in "body".
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Items x = <jsm>items</jsm>(<js>"string"</js>).minLength(2);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"type"</js>: <js>"string"</js>,
+ * 		<js>"minLength"</js>: 2
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="type,format,items,collectionFormat,default,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,enum,multipleOf,$ref,*")
+public class Items extends OpenApiElement {
+
+	private static final String[] VALID_TYPES = {"string", "number", "integer", "boolean", "array"};
+	private static final String[] VALID_COLLECTION_FORMATS = {"csv","ssv","tsv","pipes","multi"};
+
+	private String
+		type,
+		format,
+		collectionFormat,
+		pattern,
+		ref;
+	private Number
+		maximum,
+		minimum,
+		multipleOf;
+	private Integer
+		maxLength,
+		minLength,
+		maxItems,
+		minItems;
+	private Boolean
+		exclusiveMaximum,
+		exclusiveMinimum,
+		uniqueItems;
+	private Items items;
+	private Object _default;
+	private List<Object> _enum;
+
+	/**
+	 * Default constructor.
+	 */
+	public Items() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Items(Items copyFrom) {
+		super(copyFrom);
+
+		this.type = copyFrom.type;
+		this.format = copyFrom.format;
+		this.collectionFormat = copyFrom.collectionFormat;
+		this.pattern = copyFrom.pattern;
+		this.maximum = copyFrom.maximum;
+		this.minimum = copyFrom.minimum;
+		this.multipleOf = copyFrom.multipleOf;
+		this.maxLength = copyFrom.maxLength;
+		this.minLength = copyFrom.minLength;
+		this.maxItems = copyFrom.maxItems;
+		this.minItems = copyFrom.minItems;
+		this.exclusiveMaximum = copyFrom.exclusiveMaximum;
+		this.exclusiveMinimum = copyFrom.exclusiveMinimum;
+		this.uniqueItems = copyFrom.uniqueItems;
+		this.items = copyFrom.items == null ? null : copyFrom.items.copy();
+		this._default = copyFrom._default;
+		this._enum = newList(copyFrom._enum);
+		this.ref = copyFrom.ref;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Items copy() {
+		return new Items(this);
+	}
+
+
+	@Override /* SwaggerElement */
+	protected Items strict() {
+		super.strict();
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>type</property>.
+	 *
+	 * <p>
+	 * The internal type of the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Bean property setter:  <property>type</property>.
+	 *
+	 * <p>
+	 * The internal type of the array.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 	</ul>
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public Items setType(String value) {
+		if (isStrict() && ! contains(value, VALID_TYPES))
+			throw new RuntimeException(
+				"Invalid value passed in to setType(String).  Value='"+value+"', valid values="
+				+ SimpleJsonSerializer.DEFAULT.toString(VALID_TYPES));
+		type = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setType(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items type(Object value) {
+		return setType(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>format</property>.
+	 *
+	 * <p>
+	 * The extending format for the previously mentioned <code>type</code>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypeFormats}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getFormat() {
+		return format;
+	}
+
+	/**
+	 * Bean property setter:  <property>format</property>.
+	 *
+	 * <p>
+	 * The extending format for the previously mentioned <code>type</code>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypeFormats}
+	 * </ul>
+	 *
+	 * @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 Items setFormat(String value) {
+		format = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setFormat(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items format(Object value) {
+		return setFormat(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Items getItems() {
+		return items;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items setItems(Items value) {
+		items = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setItems(Items)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items items(Object value) {
+		return setItems(toType(value, Items.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>collectionFormat</property>.
+	 *
+	 * <p>
+	 * Determines the format of the array if type array is used.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getCollectionFormat() {
+		return collectionFormat;
+	}
+
+	/**
+	 * Bean property setter:  <property>collectionFormat</property>.
+	 *
+	 * <p>
+	 * Determines the format of the array if type array is used.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"csv"</js> (default) - comma separated values <code>foo,bar</code>.
+	 * 		<li><js>"ssv"</js> - space separated values <code>foo bar</code>.
+	 * 		<li><js>"tsv"</js> - tab separated values <code>foo\tbar</code>.
+	 * 		<li><js>"pipes"</js> - pipe separated values <code>foo|bar</code>.
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items setCollectionFormat(String value) {
+		if (isStrict() && ! contains(value, VALID_COLLECTION_FORMATS))
+			throw new FormattedRuntimeException(
+				"Invalid value passed in to setCollectionFormat(String).  Value=''{0}'', valid values={1}",
+				value, VALID_COLLECTION_FORMATS
+			);
+		collectionFormat = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setCollectionFormat(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"csv"</js> (default) - comma separated values <code>foo,bar</code>.
+	 * 		<li><js>"ssv"</js> - space separated values <code>foo bar</code>.
+	 * 		<li><js>"tsv"</js> - tab separated values <code>foo\tbar</code>.
+	 * 		<li><js>"pipes"</js> - pipe separated values <code>foo|bar</code>.
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items collectionFormat(Object value) {
+		return setCollectionFormat(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Declares the value of the item that the server will use if none is provided.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"default"</js> has no meaning for required items.
+	 * 	<li>
+	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Object getDefault() {
+		return _default;
+	}
+
+	/**
+	 * Bean property setter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Declares the value of the item that the server will use if none is provided.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"default"</js> has no meaning for required items.
+	 * 	<li>
+	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setDefault(Object value) {
+		_default = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDefault(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 Items _default(Object value) {
+		return setDefault(value);
+	}
+
+	/**
+	 * Bean property getter:  <property>maximum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMaximum() {
+		return maximum;
+	}
+
+	/**
+	 * Bean property setter:  <property>maximum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMaximum(Number value) {
+		maximum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaximum(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items maximum(Object value) {
+		return setMaximum(toNumber(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>exclusiveMaximum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getExclusiveMaximum() {
+		return exclusiveMaximum;
+	}
+
+	/**
+	 * Bean property setter:  <property>exclusiveMaximum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setExclusiveMaximum(Boolean value) {
+		exclusiveMaximum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExclusiveMaximum(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items exclusiveMaximum(Object value) {
+		return setExclusiveMaximum(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minimum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMinimum() {
+		return minimum;
+	}
+
+	/**
+	 * Bean property setter:  <property>minimum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMinimum(Number value) {
+		minimum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinimum(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items minimum(Object value) {
+		return setMinimum(toNumber(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>exclusiveMinimum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getExclusiveMinimum() {
+		return exclusiveMinimum;
+	}
+
+	/**
+	 * Bean property setter:  <property>exclusiveMinimum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setExclusiveMinimum(Boolean value) {
+		exclusiveMinimum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExclusiveMinimum(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items exclusiveMinimum(Object value) {
+		return setExclusiveMinimum(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maxLength</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMaxLength() {
+		return maxLength;
+	}
+
+	/**
+	 * Bean property setter:  <property>maxLength</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMaxLength(Integer value) {
+		maxLength = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaxLength(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items maxLength(Object value) {
+		return setMaxLength(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minLength</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMinLength() {
+		return minLength;
+	}
+
+	/**
+	 * Bean property setter:  <property>minLength</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMinLength(Integer value) {
+		minLength = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinLength(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items minLength(Object value) {
+		return setMinLength(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>pattern</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getPattern() {
+		return pattern;
+	}
+
+	/**
+	 * Bean property setter:  <property>pattern</property>.
+	 *
+	 * <p>
+	 * This string SHOULD be a valid regular expression.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setPattern(String value) {
+		pattern = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setPattern(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items pattern(Object value) {
+		return setPattern(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maxItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMaxItems() {
+		return maxItems;
+	}
+
+	/**
+	 * Bean property setter:  <property>maxItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMaxItems(Integer value) {
+		maxItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaxItems(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items maxItems(Object value) {
+		return setMaxItems(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMinItems() {
+		return minItems;
+	}
+
+	/**
+	 * Bean property setter:  <property>minItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMinItems(Integer value) {
+		minItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinItems(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items minItems(Object value) {
+		return setMinItems(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>uniqueItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getUniqueItems() {
+		return uniqueItems;
+	}
+
+	/**
+	 * Bean property setter:  <property>uniqueItems</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setUniqueItems(Boolean value) {
+		uniqueItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setUniqueItems(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items uniqueItems(Object value) {
+		return setUniqueItems(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>enum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<Object> getEnum() {
+		return _enum;
+	}
+
+	/**
+	 * Bean property setter:  <property>enum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setEnum(Collection<Object> value) {
+		_enum = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>enum</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Items addEnum(Collection<Object> values) {
+		_enum = addToList(_enum, values);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>enum</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Object</code>
+	 * 		<li><code>Collection&lt;Object&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	_enum(<js>"['foo','bar']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	_enum(<js>"foo"</js>, <js>"bar"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Items _enum(Object...values) {
+		_enum = addToList(_enum, values, Object.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>multipleOf</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMultipleOf() {
+		return multipleOf;
+	}
+
+	/**
+	 * Bean property setter:  <property>multipleOf</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 Items setMultipleOf(Number value) {
+		multipleOf = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMultipleOf(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Items multipleOf(Object value) {
+		return setMultipleOf(toNumber(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;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 *
+	 * @return <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 */
+	public boolean hasRef() {
+		return ref != null;
+	}
+
+	/**
+	 * 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 Items 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 Items ref(Object value) {
+		return setRef(value);
+	}
+
+	@Override /* SwaggerElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "type": return toType(getType(), type);
+			case "format": return toType(getFormat(), type);
+			case "items": return toType(getItems(), type);
+			case "collectionFormat": return toType(getCollectionFormat(), type);
+			case "default": return toType(getDefault(), type);
+			case "maximum": return toType(getMaximum(), type);
+			case "exclusiveMaximum": return toType(getExclusiveMaximum(), type);
+			case "minimum": return toType(getMinimum(), type);
+			case "exclusiveMinimum": return toType(getExclusiveMinimum(), type);
+			case "maxLength": return toType(getMaxLength(), type);
+			case "minLength": return toType(getMinLength(), type);
+			case "pattern": return toType(getPattern(), type);
+			case "maxItems": return toType(getMaxItems(), type);
+			case "minItems": return toType(getMinItems(), type);
+			case "uniqueItems": return toType(getUniqueItems(), type);
+			case "enum": return toType(getEnum(), type);
+			case "multipleOf": return toType(getMultipleOf(), type);
+			case "$ref": return toType(getRef(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public Items set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "type": return type(value);
+			case "format": return format(value);
+			case "items": return items(value);
+			case "collectionFormat": return collectionFormat(value);
+			case "default": return _default(value);
+			case "maximum": return maximum(value);
+			case "exclusiveMaximum": return exclusiveMaximum(value);
+			case "minimum": return minimum(value);
+			case "exclusiveMinimum": return exclusiveMinimum(value);
+			case "maxLength": return maxLength(value);
+			case "minLength": return minLength(value);
+			case "pattern": return pattern(value);
+			case "maxItems": return maxItems(value);
+			case "minItems": return minItems(value);
+			case "uniqueItems": return uniqueItems(value);
+			case "enum": return setEnum(null)._enum(value);
+			case "multipleOf": return multipleOf(value);
+			case "$ref": return ref(value);
+			default:
+				super.set(property, value);
+				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")
+			.appendIf(ref != null, "$ref");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+	/**
+	 * Resolves any <js>"$ref"</js> attributes in this element.
+	 *
+	 * @param swagger The swagger document containing the definitions.
+	 * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
+	 * @param maxDepth
+	 * 	The maximum depth to resolve references.
+	 * 	<br>After that level is reached, <code>$ref</code> references will be left alone.
+	 * 	<br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
+	 * @return
+	 * 	This object with references resolved.
+	 * 	<br>May or may not be the same object.
+	 */
+	public Items resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
+
+		if (ref != null) {
+			if (refStack.contains(ref) || refStack.size() >= maxDepth)
+				return this;
+			refStack.addLast(ref);
+			Items r = swagger.findRef(ref, Items.class).resolveRefs(swagger, refStack, maxDepth);
+			refStack.removeLast();
+			return r;
+		}
+
+		set("properties", resolveRefs(get("properties"), swagger, refStack, maxDepth));
+
+		if (items != null)
+			items = items.resolveRefs(swagger, refStack, maxDepth);
+
+		set("example", null);
+
+		return this;
+	}
+
+	/* Resolve references in extra attributes */
+	private Object resolveRefs(Object o, Swagger swagger, Deque<String> refStack, int maxDepth) {
+		if (o instanceof ObjectMap) {
+			ObjectMap om = (ObjectMap)o;
+			Object ref = om.get("$ref");
+			if (ref instanceof CharSequence) {
+				String sref = ref.toString();
+				if (refStack.contains(sref) || refStack.size() >= maxDepth)
+					return o;
+				refStack.addLast(sref);
+				Object o2 = swagger.findRef(sref, Object.class);
+				o2 = resolveRefs(o2, swagger, refStack, maxDepth);
+				refStack.removeLast();
+				return o2;
+			}
+			for (Map.Entry<String,Object> e : om.entrySet())
+				e.setValue(resolveRefs(e.getValue(), swagger, refStack, maxDepth));
+		}
+		if (o instanceof ObjectList)
+			for (ListIterator<Object> li = ((ObjectList)o).listIterator(); li.hasNext();)
+				li.set(resolveRefs(li.next(), swagger, refStack, maxDepth));
+		return o;
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/License.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/License.java
new file mode 100644
index 000000000..7e716de4f
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/License.java
@@ -0,0 +1,228 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+import static org.apache.juneau.internal.StringUtils.isNotEmpty;
+
+/**
+ * License information for the exposed API.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	License x = <jsm>license</jsm>(<js>"Apache 2.0"</js>, <js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"Apache 2.0"</js>,
+ * 		<js>"url"</js>: <js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="name,url,*")
+public class License extends OpenApiElement {
+
+	private String name;
+	private URI url;
+
+	/**
+	 * Default constructor.
+	 */
+	public License() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public License(License copyFrom) {
+		super(copyFrom);
+
+		this.name = copyFrom.name;
+		this.url = copyFrom.url;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public License copy() {
+		return new License(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The license name used for the API.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Bean property setter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The license name used for the API.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public License setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public License name(Object value) {
+		return setName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>url</property>.
+	 *
+	 * <p>
+	 * A URL to the license used for the API.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public URI getUrl() {
+		return url;
+	}
+
+	/**
+	 * Bean property setter:  <property>url</property>.
+	 *
+	 * <p>
+	 * A URL to the license used for the API.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>URIs defined by {@link UriResolver} can be used for values.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public License setUrl(URI value) {
+		url = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setUrl(URI)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link URI}
+	 * 		<li>{@link URL}
+	 * 		<li>{@link String}
+	 * 			<br>Converted to a URI using <code>URI.<jsm>create</jsm>(value.toString())</code>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public License url(Object value) {
+		return setUrl(StringUtils.toURI(value));
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the name property is not null or empty.
+	 *
+	 * @return <jk>true</jk> if the name property is not null or empty.
+	 */
+	public boolean hasName() {
+		return isNotEmpty(name);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the url property is not null.
+	 *
+	 * @return <jk>true</jk> if the url property is not null.
+	 */
+	public boolean hasUrl() {
+		return url != null;
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "name": return toType(getName(), type);
+			case "url": return toType(getUrl(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public License set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "name": return name(value);
+			case "url": return url(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/Link.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Link.java
new file mode 100644
index 000000000..e4184aa6b
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Link.java
@@ -0,0 +1,428 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * information for Link object.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Contact x = <jsm>contact</jsm>(<js>"API Support"</js>, <js>"http://www.swagger.io/support"</js>, <js>"support@swagger.io"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"API Support"</js>,
+ * 		<js>"url"</js>: <js>"http://www.swagger.io/support"</js>,
+ * 		<js>"email"</js>: <js>"support@swagger.io"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="operationRef,operationId,description,requestBody,server,parameters,*")
+public class Link extends OpenApiElement {
+
+	private String operationRef;
+	private String operationId;
+	private String description;
+	private Object requestBody;
+	private Server server;
+	private Map<String,Object> parameters;
+
+
+	/**
+	 * Default constructor.
+	 */
+	public Link() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Link(Link copyFrom) {
+		super(copyFrom);
+
+		this.operationRef = copyFrom.operationRef;
+		this.description = copyFrom.description;
+		this.operationId = copyFrom.operationId;
+		this.requestBody = copyFrom.requestBody;
+		this.server = copyFrom.server == null ? null : copyFrom.server.copy();
+
+		if (copyFrom.parameters == null)
+			this.parameters = null;
+		else
+			this.parameters = new LinkedHashMap<>(copyFrom.parameters);
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Link copy() {
+		return new Link(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>operationRef</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getOperationRef() {
+		return operationRef;
+	}
+
+	/**
+	 * Bean property setter:  <property>operationRef</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @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 Link setOperationRef(String value) {
+		operationRef = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setOperationRef(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Link operationRef(Object value) {
+		return setOperationRef(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * The URL pointing to the contact information.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</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).
+	 */
+	public Link setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Link description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getOperationId() {
+		return operationId;
+	}
+
+	/**
+	 * Bean property setter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Link setOperationId(String value) {
+		operationId = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setOperationId(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Link operationId(Object value) {
+		return setOperationId(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
+	 * to control the number of results per page might default to 100 if not supplied by the client in the request.
+	 *
+	 * (Note: <js>"value"</js> has no meaning for required parameters.)
+	 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for this parameter.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Object getRequestBody() {
+		return requestBody;
+	}
+
+	/**
+	 * Bean property setter:  <property>value</property>.
+	 *
+	 * <p>
+	 * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
+	 * to control the number of results per page might default to 100 if not supplied by the client in the request.
+	 * (Note: <js>"default"</js> has no meaning for required parameters.)
+	 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for this parameter.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @param val The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public Link setRequestBody(Object val) {
+		requestBody = val;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setRequestBody(Object)}.
+	 *
+	 * @param val The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public Link requestBody(Object val) {
+		return setRequestBody(val);
+	}
+
+
+	/**
+	 * Bean property getter:  <property>additionalProperties</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Server getServer() {
+		return server;
+	}
+
+	/**
+	 * Bean property setter:  <property>additionalProperties</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).
+	 */
+	public Link setServer(Server value) {
+		server = value;
+		return this;
+	}
+
+	/**
+	 * Bean property setter:  <property>additionalProperties</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).
+	 */
+	public Link server(Object value) {
+		server = toType(value, Server.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>examples</property>.
+	 *
+	 * <p>
+	 * An example of the response message.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Map<String,Object> getParameters() {
+		return parameters;
+	}
+
+	/**
+	 * Bean property setter:  <property>examples</property>.
+	 *
+	 * <p>
+	 * An example of the response message.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Keys must be MIME-type strings.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Link setParameters(Map<String,Object> value) {
+		parameters = 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 Link addParameters(Map<String,Object> values) {
+		parameters = addToMap(parameters, values);
+		return this;
+	}
+
+	/**
+	 * Adds a single value to the <property>examples</property> property.
+	 *
+	 * @param mimeType The mime-type string.
+	 * @param parameter The example.
+	 * @return This object (for method chaining).
+	 */
+	public Link parameter(String mimeType, Object parameter) {
+		parameters = addToMap(parameters, mimeType, parameter);
+		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,Object&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 w800'>
+	 * 	examples(<js>"{'text/json':{foo:'bar'}}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Link parameters(Object...values) {
+		parameters = addToMap(parameters, values, String.class, Object.class);
+		return this;
+	}
+
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "description": return toType(getDescription(), type);
+			case "operationRef": return toType(getOperationRef(), type);
+			case "operationId": return toType(getOperationId(), type);
+			case "requestBody": return toType(getRequestBody(), type);
+			case "parameters": return toType(getParameters(), type);
+			case "server": return toType(getServer(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Link set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "description": return description(value);
+			case "operationId": return operationId(value);
+			case "operationRef": return operationRef(value);
+			case "requestBody": return requestBody(value);
+			case "server": return server(value);
+			case "parameters": return parameters(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(description != null, "description")
+			.appendIf(operationId != null, "operationId")
+			.appendIf(operationRef != null, "operationRef")
+			.appendIf(requestBody != null, "requestBody")
+			.appendIf(parameters != null, "parameters")
+			.appendIf(server != null, "server");
+		return new MultiSet<>(s, super.keySet());
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/MediaType.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/MediaType.java
new file mode 100644
index 000000000..d5454d490
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/MediaType.java
@@ -0,0 +1,326 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.annotation.BeanProperty;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+@Bean(properties="schema,example,examples,encoding,*")
+public class MediaType extends OpenApiElement{
+    private SchemaInfo schema;
+    private Object example;
+    private Map<String,Example> examples;
+    private Map<String,Encoding> encoding;
+
+    /**
+     * Default constructor.
+     */
+    public MediaType() { }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public MediaType(MediaType copyFrom) {
+        super(copyFrom);
+
+        this.schema = copyFrom.schema;
+        this.example = copyFrom.example;
+        if (copyFrom.examples == null)
+            this.examples = null;
+        else
+            this.examples = new LinkedHashMap<>();
+        for (Map.Entry<String,Example> e : copyFrom.examples.entrySet())
+            this.examples.put(e.getKey(),	e.getValue().copy());
+
+        if (copyFrom.encoding == null)
+            this.encoding = null;
+        else
+            this.encoding = new LinkedHashMap<>();
+        for (Map.Entry<String,Encoding> e : copyFrom.encoding.entrySet())
+            this.encoding.put(e.getKey(),	e.getValue().copy());
+    }
+
+    /**
+     * Make a deep copy of this object.
+     *
+     * @return A deep copy of this object.
+     */
+    public MediaType copy() {
+        return new MediaType(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected MediaType strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>schema</property>.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public SchemaInfo getSchema() {
+        return schema;
+    }
+
+    /**
+     * Bean property setter:  <property>schema</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).
+     */
+    public MediaType setSchema(SchemaInfo value) {
+        schema = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setSchema(SchemaInfo)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Valid types:
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public MediaType schema(Object value) {
+        return setSchema(toType(value, SchemaInfo.class));
+    }
+
+
+    /**
+     * Bean property getter:  <property>x-example</property>.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    @BeanProperty("x-example")
+    public Object getExample() {
+        return example;
+    }
+
+    /**
+     * 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-example")
+    public MediaType setExample(Object value) {
+        example = value;
+        return this;
+    }
+
+    /**
+     * 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).
+     */
+    public MediaType example(Object value) {
+        example = value;
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>variables</property>.
+     */
+    public Map<String, Encoding> getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * Bean property setter:  <property>variables</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public MediaType setEncoding(Map<String, Encoding> value) {
+        encoding = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>encoding</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public MediaType addEncoding(Map<String, Encoding> value) {
+        encoding = addToMap(encoding,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public MediaType addEncoding(String keyval, Encoding value) {
+        encoding = addToMap(encoding,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public MediaType encoding(String name, Encoding value) {
+        addEncoding(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    public MediaType encoding(Object value) {
+        return setEncoding((HashMap<String,Encoding>)value);
+    }
+
+
+    /**
+     * Bean property getter:  <property>examples</property>.
+     *
+     * <p>
+     * The list of possible responses as they are returned from executing this operation.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public Map<String,Example> getExamples() {
+        return examples;
+    }
+
+    /**
+     * Bean property setter:  <property>headers</property>.
+     *
+     * <p>
+     * A list of examples that are sent with the response.
+     *
+     * @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 MediaType setExamples(Map<String,Example> value) {
+        examples = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public MediaType addExamples(Map<String,Example> values) {
+        examples = addToMap(examples, values);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>examples</property> property.
+     *
+     * @param name The example name.
+     * @param example The example.
+     * @return This object (for method chaining).
+     */
+    public MediaType example(String name, Example example) {
+        addExamples(Collections.singletonMap(name, example));
+        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,{@link org.apache.juneau.dto.swagger.HeaderInfo}|String&gt;</code>
+     * 		<li><code>String</code> - JSON object representation of <code>Map&lt;String,{@link org.apache.juneau.dto.swagger.HeaderInfo}&gt;</code>
+     * 			<h5 class='figure'>Example:</h5>
+     * 			<p class='bcode w800'>
+     * 	headers(<js>"{headerName:{description:'description',...}}"</js>);
+     * 			</p>
+     * 	</ul>
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public MediaType examples(Object...values) {
+        examples = addToMap(examples,values, String.class, Example.class);
+        return this;
+    }
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "schema": return toType(getSchema(), type);
+            case "example": return toType(getExample(), type);
+            case "examples": return toType(getExamples(), type);
+            case "encoding": return toType(getEncoding(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public MediaType set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "schema": return schema(value);
+            case "example": return example(value);
+            case "examples": return examples(value);
+            case "encoding": return encoding(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(schema != null, "schema")
+                .appendIf(example != null, "example")
+                .appendIf(encoding != null, "encoding")
+                .appendIf(examples != null, "examples");
+        return new MultiSet<>(s, super.keySet());
+    }
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlow.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlow.java
new file mode 100644
index 000000000..a627660ec
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlow.java
@@ -0,0 +1,329 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * information for Link object.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Contact x = <jsm>contact</jsm>(<js>"API Support"</js>, <js>"http://www.swagger.io/support"</js>, <js>"support@swagger.io"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"API Support"</js>,
+ * 		<js>"url"</js>: <js>"http://www.swagger.io/support"</js>,
+ * 		<js>"email"</js>: <js>"support@swagger.io"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="authorizationUrl,tokenUrl,refreshUrl,scopes,*")
+public class OAuthFlow extends OpenApiElement {
+
+	private String authorizationUrl;
+	private String tokenUrl;
+	private String refreshUrl;
+	private Map<String,String> scopes;
+
+
+	/**
+	 * Default constructor.
+	 */
+	public OAuthFlow() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public OAuthFlow(OAuthFlow copyFrom) {
+		super(copyFrom);
+
+		this.authorizationUrl = copyFrom.authorizationUrl;
+		this.tokenUrl = copyFrom.tokenUrl;
+		this.refreshUrl = copyFrom.refreshUrl;
+
+		if (copyFrom.scopes == null)
+			this.scopes = null;
+		else
+			this.scopes = new LinkedHashMap<>(copyFrom.scopes);
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public OAuthFlow copy() {
+		return new OAuthFlow(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>operationRef</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getAuthorizationUrl() {
+		return authorizationUrl;
+	}
+
+	/**
+	 * Bean property setter:  <property>operationRef</property>.
+	 *
+	 * <p>
+	 * The identifying name of the contact person/organization.
+	 *
+	 * @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 OAuthFlow setAuthorizationUrl(String value) {
+		authorizationUrl = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setAuthorizationUrl(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow authorizationUrl(Object value) {
+		return setAuthorizationUrl(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * The URL pointing to the contact information.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getTokenUrl() {
+		return tokenUrl;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</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).
+	 */
+	public OAuthFlow setTokenUrl(String value) {
+		tokenUrl = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setTokenUrl(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow tokenUrl(Object value) {
+		return setTokenUrl(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getRefreshUrl() {
+		return refreshUrl;
+	}
+
+	/**
+	 * Bean property setter:  <property>externalValue</property>.
+	 *
+	 * <p>
+	 * The email address of the contact person/organization.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow setRefreshUrl(String value) {
+		refreshUrl = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setRefreshUrl(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>MUST be in the format of an email address.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow refreshUrl(Object value) {
+		return setRefreshUrl(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>examples</property>.
+	 *
+	 * <p>
+	 * An example of the response message.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Map<String,String> getScopes() {
+		return scopes;
+	}
+
+	/**
+	 * Bean property setter:  <property>examples</property>.
+	 *
+	 * <p>
+	 * An example of the response message.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Keys must be MIME-type strings.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow setScopes(Map<String,String> value) {
+		scopes = 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 OAuthFlow addScopes(Map<String,String> values) {
+		scopes = addToMap(scopes, values);
+		return this;
+	}
+
+	/**
+	 * Adds a single value to the <property>examples</property> property.
+	 *
+	 * @param name The mime-type string.
+	 * @param descriptiom The example.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow scopes(String name, String descriptiom) {
+		scopes = addToMap(scopes, name, descriptiom);
+		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,Object&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 w800'>
+	 * 	examples(<js>"{'text/json':{foo:'bar'}}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlow scopes(Object...values) {
+		scopes = addToMap(scopes, values, String.class, String.class);
+		return this;
+	}
+
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "refreshUrl": return toType(getRefreshUrl(), type);
+			case "tokenUrl": return toType(getTokenUrl(), type);
+			case "authorizationUrl": return toType(getAuthorizationUrl(), type);
+			case "scopes": return toType(getScopes(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public OAuthFlow set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "authorizationUrl": return authorizationUrl(value);
+			case "tokenUrl": return tokenUrl(value);
+			case "refreshUrl": return refreshUrl(value);
+			case "scopes": return scopes(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(authorizationUrl != null, "authorizationUrl")
+			.appendIf(tokenUrl != null, "tokenUrl")
+			.appendIf(refreshUrl != null, "refreshUrl")
+			.appendIf(scopes != null, "scopes");
+		return new MultiSet<>(s, super.keySet());
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlows.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlows.java
new file mode 100644
index 000000000..666c225de
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OAuthFlows.java
@@ -0,0 +1,381 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.FormattedRuntimeException;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.Items;
+import org.apache.juneau.dto.swagger.SchemaInfo;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Set;
+
+import static org.apache.juneau.internal.ArrayUtils.contains;
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+
+/**
+ * Describes a single operation parameter.
+ *
+ * <p>
+ * A unique parameter is defined by a combination of a name and location.
+ *
+ * <p>
+ * There are five possible parameter types.
+ * <ul class='spaced-list'>
+ * 	<li><js>"path"</js> - Used together with Path Templating, where the parameter value is actually part of the
+ * 		operation's URL.
+ * 		This does not include the host or base path of the API.
+ * 		For example, in <code>/items/{itemId}</code>, the path parameter is <code>itemId</code>.
+ * 	<li><js>"query"</js> - Parameters that are appended to the URL.
+ * 		For example, in <code>/items?id=###</code>, the query parameter is <code>id</code>.
+ * 	<li><js>"header"</js> - Custom headers that are expected as part of the request.
+ * 	<li><js>"body"</js> - The payload that's appended to the HTTP request.
+ * 		Since there can only be one payload, there can only be one body parameter.
+ * 		The name of the body parameter has no effect on the parameter itself and is used for documentation purposes
+ * 		only.
+ * 		Since Form parameters are also in the payload, body and form parameters cannot exist together for the same
+ * 		operation.
+ * 	<li><js>"formData"</js> - Used to describe the payload of an HTTP request when either
+ * 		<code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code> or both are used as the
+ * 		content type of the request (in Swagger's definition, the consumes property of an operation).
+ * 		This is the only parameter type that can be used to send files, thus supporting the file type.
+ * 		Since form parameters are sent in the payload, they cannot be declared together with a body parameter for the
+ * 		same operation.
+ * 		Form parameters have a different format based on the content-type used (for further details, consult
+ * 		<code>http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4</code>):
+ * 		<ul>
+ * 			<li><js>"application/x-www-form-urlencoded"</js> - Similar to the format of Query parameters but as a
+ * 				payload.
+ * 				For example, <code>foo=1&amp;bar=swagger</code> - both <code>foo</code> and <code>bar</code> are form
+ * 				parameters.
+ * 				This is normally used for simple parameters that are being transferred.
+ * 			<li><js>"multipart/form-data"</js> - each parameter takes a section in the payload with an internal header.
+ * 				For example, for the header <code>Content-Disposition: form-data; name="submit-name"</code> the name of
+ * 				the parameter is <code>submit-name</code>.
+ * 				This type of form parameters is more commonly used for file transfers.
+ * 		</ul>
+ * 	</li>
+ * </ul>
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	ParameterInfo x = <jsm>parameterInfo</jsm>(<js>"query"</js>, <js>"foo"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"in"</js>: <js>"query"</js>,
+ * 		<js>"name"</js>: <js>"foo"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="implicit,password,clientCredentials,authorizationCode,*")
+public class OAuthFlows extends OpenApiElement {
+
+	private OAuthFlow implicit,
+			password,
+			clientCredentials,
+			authorizationCode;
+
+	/**
+	 * Default constructor.
+	 */
+	public OAuthFlows() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public OAuthFlows(OAuthFlows copyFrom) {
+		super(copyFrom);
+
+		this.implicit = copyFrom.implicit;
+		this.password = copyFrom.password;
+		this.clientCredentials = copyFrom.clientCredentials;
+		this.authorizationCode = copyFrom.authorizationCode;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public OAuthFlows copy() {
+		return new OAuthFlows(this);
+	}
+
+	@Override /* SwaggerElement */
+	protected OAuthFlows strict() {
+		super.strict();
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>implicit</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public OAuthFlow getImplicit() {
+		return implicit;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows setImplicit(OAuthFlow value) {
+		implicit = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setImplicit(OAuthFlow)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows implicit(Object value) {
+		return setImplicit(toType(value, OAuthFlow.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>password</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public OAuthFlow getPassword() {
+		return password;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows setPassword(OAuthFlow value) {
+		password = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setPassword(OAuthFlow)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows password(Object value) {
+		return setPassword(toType(value, OAuthFlow.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>clientCredentials</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public OAuthFlow getClientCredentials() {
+		return clientCredentials;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows setClientCredentials(OAuthFlow value) {
+		clientCredentials = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setClientCredentials(OAuthFlow)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows clientCredentials(Object value) {
+		return setClientCredentials(toType(value, OAuthFlow.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>authorizationCode</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public OAuthFlow getAuthorizationCode() {
+		return authorizationCode;
+	}
+
+	/**
+	 * Bean property setter:  <property>authorizationCode</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows setAuthorizationCode(OAuthFlow value) {
+		authorizationCode = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setAuthorizationCode(OAuthFlow)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public OAuthFlows authorizationCode(Object value) {
+		return setAuthorizationCode(toType(value, OAuthFlow.class));
+	}
+
+
+	@Override /* SwaggerElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "implicit": return toType(getImplicit(), type);
+			case "password": return toType(getPassword(), type);
+			case "clientCredentials": return toType(getClientCredentials(), type);
+			case "authorizationCode": return toType(getAuthorizationCode(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public OAuthFlows set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "implicit": return implicit(value);
+			case "password": return password(value);
+			case "clientCredentials": return clientCredentials(value);
+			case "authorizationCode": return authorizationCode(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(implicit != null, "implicit")
+			.appendIf(password != null, "password")
+			.appendIf(clientCredentials != null, "clientCredentials")
+			.appendIf(authorizationCode != null, "authorizationCode");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OpenApiElement.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OpenApiElement.java
new file mode 100644
index 000000000..725797b3f
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/OpenApiElement.java
@@ -0,0 +1,185 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.ObjectMap;
+import org.apache.juneau.annotation.BeanProperty;
+import org.apache.juneau.json.JsonSerializer;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toBoolean;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+
+/**
+ * Root class for all Swagger beans.
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+public abstract class OpenApiElement {
+
+	private boolean strict;
+	private Map<String,Object> extra;
+
+	OpenApiElement() {}
+
+	OpenApiElement(OpenApiElement copyFrom) {
+		this.strict = copyFrom.strict;
+		this.extra = copyFrom.extra == null ? null : new LinkedHashMap<>(copyFrom.extra);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if contents should be validated per the Swagger spec.
+	 *
+	 * @return <jk>true</jk> if contents should be validated per the Swagger spec.
+	 */
+	protected boolean isStrict() {
+		return strict;
+	}
+
+	/**
+	 * Sets strict mode on this bean.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	protected OpenApiElement strict() {
+		strict = true;
+		return this;
+	}
+
+	/**
+	 * Sets strict mode on this bean.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> (interpreted as <jk>false</jk>).
+	 * @return This object (for method chaining).
+	 */
+	protected OpenApiElement strict(Object value) {
+		strict = value == null ? false : toBoolean(value);
+		return this;
+	}
+
+	/**
+	 * Generic property getter.
+	 *
+	 * <p>
+	 * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>.
+	 *
+	 * @param property The property name to retrieve.
+	 * @param type The datatype to cast the value to.
+	 * @return The property value, or <jk>null</jk> if the property does not exist or is not set.
+	 */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "strict": return toType(isStrict(), type);
+			default: return toType(get(property), type);
+		}
+	};
+
+	/**
+	 * Generic property getter.
+	 *
+	 * <p>
+	 * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>.
+	 *
+	 * @param property The property name to retrieve.
+	 * @return The property value, or <jk>null</jk> if the property does not exist or is not set.
+	 */
+	@BeanProperty("*")
+	public Object get(String property) {
+		if (property == null || extra == null)
+			return null;
+		return extra.get(property);
+	};
+
+	/**
+	 * Generic property setter.
+	 *
+	 * <p>
+	 * Can be used to set non-standard Swagger fields such as <js>"$ref"</js>.
+	 *
+	 * @param property The property name to set.
+	 * @param value The new value for the property.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty("*")
+	public OpenApiElement set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "strict": return strict(value);
+			default:
+				if (extra == null)
+					extra = new LinkedHashMap<>();
+				extra.put(property, value);
+				return this;
+		}
+	}
+
+	/**
+	 * Generic property keyset.
+	 *
+	 * @return
+	 * 	All the non-standard keys on this element.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	@BeanProperty("*")
+	public Set<String> extraKeys() {
+		return extra == null ? Collections.EMPTY_SET : extra.keySet();
+	}
+
+	/**
+	 * Returns all the keys on this element.
+	 *
+	 * @return
+	 * 	All the keys on this element.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	public Set<String> keySet() {
+		ASet<String> s = new ASet<String>()
+			.appendIf(strict, "strict");
+		s.addAll(extraKeys());
+		return s;
+	}
+
+	/**
+	 * Returns a copy of this swagger element as a modifiable map.
+	 *
+	 * <p>
+	 * Each call produces a new map.
+	 *
+	 * @return A map containing all the values in this swagger element.
+	 */
+	public ObjectMap asMap() {
+		ObjectMap m = new ObjectMap();
+		for (String s : keySet())
+			m.put(s, get(s, Object.class));
+		return m;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return JsonSerializer.DEFAULT.toString(this);
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/RequestBodyInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/RequestBodyInfo.java
new file mode 100644
index 000000000..c605ab7e9
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/RequestBodyInfo.java
@@ -0,0 +1,273 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+@Bean(properties="description,content,required,*")
+public class RequestBodyInfo extends OpenApiElement{
+
+    private String description;
+    private Map<String,MediaType> content;
+    private Boolean required;
+
+    /**
+     * Default constructor.
+     */
+    public RequestBodyInfo() { }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public RequestBodyInfo(RequestBodyInfo copyFrom) {
+        super(copyFrom);
+
+        this.description = copyFrom.description;
+        this.required = copyFrom.required;
+        if (copyFrom.content == null) {
+            this.content = null;
+        } else {
+            this.content = new LinkedHashMap<>();
+            for (Map.Entry<String,MediaType> e : copyFrom.content.entrySet())
+                this.content.put(e.getKey(),	e.getValue().copy());
+        }
+    }
+
+    /**
+     * Make a deep copy of this object.
+     *
+     * @return A deep copy of this object.
+     */
+    public RequestBodyInfo copy() {
+        return new RequestBodyInfo(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected RequestBodyInfo strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>contentType</property>.
+     *
+     * <p>
+     * The URL pointing to the contact information.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Bean property setter:  <property>url</property>.
+     *
+     * <p>
+     * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+     * <br>Strings must be valid URIs.
+     *
+     * <p>
+     * URIs defined by {@link UriResolver} can be used for values.
+     *
+     * @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 RequestBodyInfo setDescription(String value) {
+        description = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setDescription(String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo description(Object value) {
+        return setDescription(toStringVal(value));
+    }
+
+    /**
+     * Bean property getter:  <property>content</property>.
+     */
+    public Map<String, MediaType> getContent() {
+        return content;
+    }
+
+    /**
+     * Bean property setter:  <property>content</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo setContent(Map<String, MediaType> value) {
+        content = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>content</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo addContent(Map<String, MediaType> value) {
+        content = addToMap(content,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>content</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo addContent(String keyval, MediaType value) {
+        content = addToMap(content,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>content</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo content(String name, MediaType value) {
+        addContent(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>content</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo content(Object...values) {
+        content = addToMap(content, values, String.class, MediaType.class);
+        return this;
+    }
+
+    public RequestBodyInfo content(Object value) {
+        return setContent((HashMap<String,MediaType>)value);
+    }
+
+
+    /**
+     * Bean property getter:  <property>required</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public Boolean getRequired() {
+        return required;
+    }
+
+    /**
+     * Bean property setter:  <property>explode</property>.
+     *
+     * <p>
+     * The type of the object.
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul class='doctree'>
+     * 	<li class='extlink'>{@doc SwaggerDataTypes}
+     * </ul>
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Property value is required.
+     * 	</ul>
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo setRequired(Boolean value) {
+        required = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setRequired(Boolean)}
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-String values will be converted to String using <code>toBoolean()</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public RequestBodyInfo required(Object value) {
+        return setRequired(toBoolean(value));
+    }
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "description": return toType(getDescription(), type);
+            case "content": return toType(getContent(), type);
+            case "required": return toType(getRequired(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public RequestBodyInfo set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "description": return description(value);
+            case "content": return content(value);
+            case "required": return required(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(description != null, "description")
+                .appendIf(content != null, "content")
+                .appendIf(required != null, "required");
+        return new MultiSet<>(s, super.keySet());
+    }
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Response.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Response.java
new file mode 100644
index 000000000..9a070fe0e
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Response.java
@@ -0,0 +1,393 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+@Bean(properties="contentType,style,explode,headers,allowReserved,*")
+public class Response extends OpenApiElement{
+
+    private String description;
+    private Map<String,HeaderInfo> headers;
+    private Map<String,MediaType> content;
+    private Map<String,Link> links;
+
+    /**
+     * Default constructor.
+     */
+    public Response() { }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public Response(Response copyFrom) {
+        super(copyFrom);
+
+        this.description = copyFrom.description;
+        if (copyFrom.headers == null) {
+            this.headers = null;
+        } else {
+            this.headers = new LinkedHashMap<>();
+            for (Map.Entry<String,HeaderInfo> e : copyFrom.headers.entrySet())
+                this.headers.put(e.getKey(),	e.getValue().copy());
+        }
+
+        if (copyFrom.content == null) {
+            this.content = null;
+        } else {
+            this.content = new LinkedHashMap<>();
+            for (Map.Entry<String,MediaType> e : copyFrom.content.entrySet())
+                this.content.put(e.getKey(),	e.getValue().copy());
+        }
+
+        if (copyFrom.links == null) {
+            this.links = null;
+        } else {
+            this.links = new LinkedHashMap<>();
+            for (Map.Entry<String,Link> e : copyFrom.links.entrySet())
+                this.links.put(e.getKey(),	e.getValue().copy());
+        }
+    }
+
+    /**
+     * Make a deep copy of this object.
+     *
+     * @return A deep copy of this object.
+     */
+    public Response copy() {
+        return new Response(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected Response strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>Description</property>.
+     *
+     * <p>
+     * The URL pointing to the contact information.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Bean property setter:  <property>Description</property>.
+     *
+     * <p>
+     * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+     * <br>Strings must be valid URIs.
+     *
+     * <p>
+     * URIs defined by {@link UriResolver} can be used for values.
+     *
+     * @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 Response setDescription(String value) {
+        description = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setDescription(String)} (String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public Response description(Object value) {
+        return setDescription(toStringVal(value));
+    }
+
+    /**
+     * Bean property getter:  <property>headers</property>.
+     */
+    public Map<String, HeaderInfo> getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Bean property setter:  <property>headers</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Response setHeaders(Map<String, HeaderInfo> value) {
+        headers = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addHeader(Map<String, HeaderInfo> value) {
+        headers = addToMap(headers,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addHeaders(String keyval, HeaderInfo value) {
+        headers = addToMap(headers,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public Response header(String name, HeaderInfo value) {
+        addHeader(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response headers(Object...values) {
+        headers = addToMap(headers, values, String.class, HeaderInfo.class);
+        return this;
+    }
+
+    public Response headers(Object value) {
+        return setHeaders((HashMap<String,HeaderInfo>)value);
+    }
+
+    /**
+     * Bean property getter:  <property>headers</property>.
+     */
+    public Map<String, MediaType> getContent() {
+        return content;
+    }
+
+    /**
+     * Bean property setter:  <property>content</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Response setContent(Map<String, MediaType> value) {
+        content = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>content</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addContent(Map<String, MediaType> value) {
+        content = addToMap(content,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addContent(String keyval, MediaType value) {
+        content = addToMap(content,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public Response content(String name, MediaType value) {
+        addContent(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response content(Object...values) {
+        content = addToMap(content, values, String.class, MediaType.class);
+        return this;
+    }
+
+    public Response content(Object value) {
+        return setContent((HashMap<String,MediaType>)value);
+    }
+
+    /**
+     * Bean property getter:  <property>link</property>.
+     */
+    public Map<String, Link> getLinks() {
+        return links;
+    }
+
+    /**
+     * Bean property setter:  <property>Link</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Response setLinks(Map<String, Link> value) {
+        links = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addLink(Map<String, Link> value) {
+        links = addToMap(links,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response addLink(String keyval, Link value) {
+        links = addToMap(links,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public Response links(String name, Link value) {
+        addLink(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>headers</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Response links(Object...values) {
+        links = addToMap(links, values, String.class, Link.class);
+        return this;
+    }
+
+    public Response links(Object value) {
+        return setLinks((HashMap<String,Link>)value);
+    }
+
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "description": return toType(getDescription(), type);
+            case "content": return toType(getContent(), type);
+            case "headers": return toType(getHeaders(), type);
+            case "links": return toType(getLinks(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Response set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "description": return description(value);
+            case "headers": return headers(value);
+            case "content": return content(value);
+            case "links": return links(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(description != null, "description")
+                .appendIf(headers != null, "headers")
+                .appendIf(content != null, "content")
+                .appendIf(links != null, "links");
+        return new MultiSet<>(s, super.keySet());
+    }
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SchemaInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SchemaInfo.java
new file mode 100644
index 000000000..4e6f38a32
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SchemaInfo.java
@@ -0,0 +1,1879 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.annotation.BeanProperty;
+import org.apache.juneau.dto.swagger.ExternalDocumentation;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.dto.swagger.Xml;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * The Schema Object allows the definition of input and output data types.
+ *
+ * <p>
+ * These types can be objects, but also primitives and arrays.
+ * This object is based on the JSON Schema Specification Draft 4 and uses a predefined subset of it.
+ * On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
+ *
+ * <p>
+ * Further information about the properties can be found in JSON Schema Core and JSON Schema Validation.
+ * Unless stated otherwise, the property definitions follow the JSON Schema specification as referenced here.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	SchemaInfo x = <jsm>schemaInfo</jsm>()
+ * 		.type("string")
+ * 		.title("foo")
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"type"</js>: <js>"string"</js>,
+ * 		<js>"title"</js>: <js>"foo"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </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,anyOf,oneOf,properties,additionalProperties,not,discriminator,readOnly,writeOnly,nullable,deprecated,xml,externalDocs,example,$ref,*")
+public class SchemaInfo extends OpenApiElement {
+
+	private String
+		format,
+		title,
+		description,
+		pattern,
+		ref,
+		type;
+	private Number
+		multipleOf,
+		maximum,
+		minimum;
+	private Integer
+		maxLength,
+		minLength,
+		maxItems,
+		minItems,
+		maxProperties,
+		minProperties;
+	private Boolean
+		exclusiveMaximum,
+		exclusiveMinimum,
+		uniqueItems,
+		nullable,
+		writeOnly,
+		readOnly,
+		deprecated;
+	private Object
+		_default,
+		example;
+	private Items items;
+	private Xml xml;
+	private ExternalDocumentation externalDocs;
+	private List<Object>
+			allOf,
+			oneOf,
+			anyOf,
+			_enum;
+	private List<String>
+		required;
+	private Discriminator discriminator;
+	private Map<String, SchemaInfo> properties;
+	private SchemaInfo additionalProperties;
+	private SchemaInfo not;
+
+	/**
+	 * Default constructor.
+	 */
+	public SchemaInfo() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public SchemaInfo(SchemaInfo copyFrom) {
+		super(copyFrom);
+
+		this.format = copyFrom.format;
+		this.title = copyFrom.title;
+		this.description = copyFrom.description;
+		this.ref = copyFrom.ref;
+		this.nullable = copyFrom.nullable;
+		this.writeOnly = copyFrom.writeOnly;
+		this.deprecated = copyFrom.deprecated;
+		this.pattern = copyFrom.pattern;
+		this.type = copyFrom.type;
+		this.discriminator = copyFrom.discriminator;
+		this.multipleOf = copyFrom.multipleOf;
+		this.maximum = copyFrom.maximum;
+		this.minimum = copyFrom.minimum;
+		this.maxLength = copyFrom.maxLength;
+		this.minLength = copyFrom.minLength;
+		this.maxItems = copyFrom.maxItems;
+		this.minItems = copyFrom.minItems;
+		this.maxProperties = copyFrom.maxProperties;
+		this.minProperties = copyFrom.minProperties;
+		this.exclusiveMaximum = copyFrom.exclusiveMaximum;
+		this.exclusiveMinimum = copyFrom.exclusiveMinimum;
+		this.uniqueItems = copyFrom.uniqueItems;
+		this.readOnly = copyFrom.readOnly;
+		this._default = copyFrom._default;
+		this.example = copyFrom.example;
+		this.items = copyFrom.items == null ? null : copyFrom.items.copy();
+		this.xml = copyFrom.xml == null ? null : copyFrom.xml.copy();
+		this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy();
+		this._enum = newList(copyFrom._enum);
+		this.allOf = newList(copyFrom.allOf);
+		this.required = newList(copyFrom.required);
+		this.anyOf = newList(copyFrom.anyOf);
+		this.oneOf = newList(copyFrom.oneOf);
+
+		if (copyFrom.properties == null) {
+			this.properties = null;
+		} else {
+			this.properties = new LinkedHashMap<>();
+			for (Map.Entry<String, SchemaInfo> e : copyFrom.properties.entrySet())
+				this.properties.put(e.getKey(), e.getValue().copy());
+		}
+
+		this.additionalProperties = copyFrom.additionalProperties == null ? null : copyFrom.additionalProperties.copy();
+		this.not = copyFrom.not == null ? null : copyFrom.not.copy();
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public SchemaInfo copy() {
+		return new SchemaInfo(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>format</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypeFormats}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getFormat() {
+		return format;
+	}
+
+	/**
+	 * Bean property setter:  <property>format</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * 	<br>Formats defined by the OAS include:
+	 * 	<ul>
+	 * 		<li><js>"int32"</js>
+	 * 		<li><js>"int64"</js>
+	 * 		<li><js>"float"</js>
+	 * 		<li><js>"double"</js>
+	 * 		<li><js>"byte"</js>
+	 * 		<li><js>"binary"</js>
+	 * 		<li><js>"date"</js>
+	 * 		<li><js>"date-time"</js>
+	 * 		<li><js>"password"</js>
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo setFormat(String value) {
+		format = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setFormat(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo format(Object value) {
+		return setFormat(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>title</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * Bean property setter:  <property>title</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).
+	 */
+	public SchemaInfo setTitle(String value) {
+		title = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setTitle(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo title(Object value) {
+		return setTitle(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Object getDefault() {
+		return _default;
+	}
+
+	/**
+	 * Bean property setter:  <property>default</property>.
+	 *
+	 * <p>
+	 * Unlike JSON Schema, the value MUST conform to the defined type for the Schema 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 setDefault(Object value) {
+		_default = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDefault(Object)}.
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo _default(Object value) {
+		return setDefault(value);
+	}
+
+	/**
+	 * Bean property getter:  <property>multipleOf</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMultipleOf() {
+		return multipleOf;
+	}
+
+	/**
+	 * Bean property setter:  <property>multipleOf</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).
+	 */
+	public SchemaInfo setMultipleOf(Number value) {
+		multipleOf = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMultipleOf(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo multipleOf(Object value) {
+		return setMultipleOf(toNumber(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maximum</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMaximum() {
+		return maximum;
+	}
+
+	/**
+	 * Bean property setter:  <property>maximum</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).
+	 */
+	public SchemaInfo setMaximum(Number value) {
+		maximum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaximum(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo maximum(Object value) {
+		return setMaximum(toNumber(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>exclusiveMaximum</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getExclusiveMaximum() {
+		return exclusiveMaximum;
+	}
+
+	/**
+	 * Bean property setter:  <property>exclusiveMaximum</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).
+	 */
+	public SchemaInfo setExclusiveMaximum(Boolean value) {
+		exclusiveMaximum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExclusiveMaximum(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo exclusiveMaximum(Object value) {
+		return setExclusiveMaximum(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minimum</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Number getMinimum() {
+		return minimum;
+	}
+
+	/**
+	 * Bean property setter:  <property>minimum</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).
+	 */
+	public SchemaInfo setMinimum(Number value) {
+		minimum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinimum(Number)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Number values will be converted to Number using <code>toString()</code> then best number match.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo minimum(Object value) {
+		return setMinimum(toNumber(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>exclusiveMinimum</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getExclusiveMinimum() {
+		return exclusiveMinimum;
+	}
+
+	/**
+	 * Bean property setter:  <property>exclusiveMinimum</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).
+	 */
+	public SchemaInfo setExclusiveMinimum(Boolean value) {
+		exclusiveMinimum = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExclusiveMinimum(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo exclusiveMinimum(Object value) {
+		return setExclusiveMinimum(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maxLength</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMaxLength() {
+		return maxLength;
+	}
+
+	/**
+	 * Bean property setter:  <property>maxLength</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).
+	 */
+	public SchemaInfo setMaxLength(Integer value) {
+		maxLength = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaxLength(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo maxLength(Object value) {
+		return setMaxLength(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minLength</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMinLength() {
+		return minLength;
+	}
+
+	/**
+	 * Bean property setter:  <property>minLength</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).
+	 */
+	public SchemaInfo setMinLength(Integer value) {
+		minLength = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinLength(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo minLength(Object value) {
+		return setMinLength(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>pattern</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getPattern() {
+		return pattern;
+	}
+
+	/**
+	 * Bean property setter:  <property>pattern</property>.
+	 *
+	 * <p>
+	 * This string SHOULD be a valid regular expression.
+	 *
+	 * @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 setPattern(String value) {
+		pattern = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setPattern(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo pattern(Object value) {
+		return setPattern(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maxItems</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMaxItems() {
+		return maxItems;
+	}
+
+	/**
+	 * Bean property setter:  <property>maxItems</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).
+	 */
+	public SchemaInfo setMaxItems(Integer value) {
+		maxItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaxItems(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo maxItems(Object value) {
+		return setMaxItems(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minItems</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMinItems() {
+		return minItems;
+	}
+
+	/**
+	 * Bean property setter:  <property>minItems</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).
+	 */
+	public SchemaInfo setMinItems(Integer value) {
+		minItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinItems(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo minItems(Object value) {
+		return setMinItems(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>uniqueItems</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getUniqueItems() {
+		return uniqueItems;
+	}
+	/**
+	 * Bean property setter:  <property>uniqueItems</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).
+	 */
+	public SchemaInfo setUniqueItems(Boolean value) {
+		uniqueItems = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setUniqueItems(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo uniqueItems(Object value) {
+		return setUniqueItems(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>uniqueItems</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getNullable() {
+		return nullable;
+	}
+	/**
+	 * Bean property setter:  <property>nullable</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).
+	 */
+	public SchemaInfo setNullable(Boolean value) {
+		nullable = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setNullable(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo nullable(Object value) {
+		return setNullable(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>maxProperties</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMaxProperties() {
+		return maxProperties;
+	}
+
+	/**
+	 * Bean property setter:  <property>maxProperties</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).
+	 */
+	public SchemaInfo setMaxProperties(Integer value) {
+		maxProperties = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMaxProperties(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo maxProperties(Object value) {
+		return setMaxProperties(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>minProperties</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Integer getMinProperties() {
+		return minProperties;
+	}
+
+	/**
+	 * Bean property setter:  <property>minProperties</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).
+	 */
+	public SchemaInfo setMinProperties(Integer value) {
+		minProperties = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setMinProperties(Integer)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-Integer values will be converted to Integer using <code>Integer.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo minProperties(Object value) {
+		return setMinProperties(toInteger(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>required</property>.
+	 *
+	 * <p>
+	 * The list of required properties.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<String> getRequired() {
+		return required;
+	}
+
+	/**
+	 * Bean property setter:  <property>required</property>.
+	 *
+	 * <p>
+	 * The list of required properties.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"http"</js>
+	 * 		<li><js>"https"</js>
+	 * 		<li><js>"ws"</js>
+	 * 		<li><js>"wss"</js>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo setRequired(Collection<String> value) {
+		required = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>required</property> property.
+	 *
+	 * <p>
+	 * The list of required properties.
+	 *
+	 * @param value
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo addRequired(Collection<String> value) {
+		required = addToList(required, value);
+		return this;
+	}
+
+	/**
+	 * Same as {@link #addRequired(Collection)}.
+	 *
+	 * @param values
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Collection&lt;String&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;String&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	schemes(<js>"['scheme1','scheme2']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	schemes(<js>"scheme1</js>, <js>"scheme2"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo required(Object...values) {
+		required = addToList(required, values, String.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>enum</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<Object> getEnum() {
+		return _enum;
+	}
+
+	/**
+	 * Bean property setter:  <property>enum</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc JsonSchemaValidation}
+	 * </ul>
+	 *
+	 * @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 setEnum(Collection<Object> value) {
+		_enum = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>enum</property> property.
+	 *
+	 * @param value
+	 * 	The values to add to this property.
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo addEnum(Collection<Object> value) {
+		_enum = addToList(_enum, value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>enum</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Object</code>
+	 * 		<li><code>Collection&lt;Object&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	_enum(<js>"['foo','bar']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	_enum(<js>"foo"</js>, <js>"bar"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo _enum(Object...values) {
+		_enum = addToList(_enum, values, Object.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>type</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Bean property setter:  <property>type</property>.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * 	<br>Possible values include:
+	 * 	<ul>
+	 * 		<li><js>"object"</js>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 		<li><js>"file"</js>
+	 * 	</ul>
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo setType(String value) {
+		type = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setType(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo type(Object value) {
+		return setType(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>items</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Items getItems() {
+		return items;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</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).
+	 */
+	public SchemaInfo setItems(Items value) {
+		items = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setItems(Items)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo items(Object value) {
+		return setItems(toType(value, Items.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>allOf</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<Object> getAllOf() {
+		return allOf;
+	}
+
+	/**
+	 * Bean property setter:  <property>allOf</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).
+	 */
+	public SchemaInfo setAllOf(Collection<Object> value) {
+		allOf = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</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 addAllOf(Collection<Object> values) {
+		allOf = addToList(allOf, values);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Object</code>
+	 * 		<li><code>Collection&lt;Object&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"['foo','bar']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"foo"</js>, <js>"bar"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo allOf(Object...values) {
+		allOf = addToList(allOf, values, Object.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>allOf</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<Object> getAnyOf() {
+		return anyOf;
+	}
+
+	/**
+	 * Bean property setter:  <property>allOf</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).
+	 */
+	public SchemaInfo setAnyOf(Collection<Object> value) {
+		anyOf = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</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 addAnyOf(Collection<Object> values) {
+		anyOf = addToList(anyOf, values);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Object</code>
+	 * 		<li><code>Collection&lt;Object&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"['foo','bar']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"foo"</js>, <js>"bar"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo anyOf(Object...values) {
+		anyOf = addToList(anyOf, values, Object.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>allOf</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public List<Object> getOneOf() { return oneOf; }
+
+	/**
+	 * Bean property setter:  <property>allOf</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).
+	 */
+	public SchemaInfo setOneOf(Collection<Object> value) {
+		oneOf = newList(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</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 addOneOf(Collection<Object> values) {
+		oneOf = addToList(oneOf, values);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>allOf</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Object</code>
+	 * 		<li><code>Collection&lt;Object&gt;</code>
+	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"['foo','bar']"</js>);
+	 * 			</p>
+	 * 		<li><code>String</code> - Individual values
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	allOf(<js>"foo"</js>, <js>"bar"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo oneOf(Object...values) {
+		oneOf = addToList(oneOf, values, Object.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>properties</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Map<String, SchemaInfo> getProperties() {
+		return properties;
+	}
+
+	/**
+	 * Bean property setter:  <property>properties</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).
+	 */
+	public SchemaInfo setProperties(Map<String, SchemaInfo> value) {
+		properties = newMap(value);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>properties</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 addProperties(Map<String, SchemaInfo> values) {
+		properties = addToMap(properties, values);
+		return this;
+	}
+
+	/**
+	 * Adds one or more values to the <property>properties</property> property.
+	 *
+	 * @param values
+	 * 	The values to add to this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li><code>Map&lt;String,Map&lt;String,Object&gt;&gt;</code>
+	 * 		<li><code>String</code> - JSON object representation of <code>Map&lt;String,Map&lt;String,Object&gt;&gt;</code>
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	properties(<js>"{name:{foo:'bar'}}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Ignored if <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo properties(Object...values) {
+		properties = addToMap(properties, values, String.class, SchemaInfo.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>additionalProperties</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public SchemaInfo getAdditionalProperties() {
+		return additionalProperties;
+	}
+
+	/**
+	 * Bean property setter:  <property>additionalProperties</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).
+	 */
+	public SchemaInfo setAdditionalProperties(SchemaInfo value) {
+		additionalProperties = value;
+		return this;
+	}
+
+	/**
+	 * Bean property setter:  <property>additionalProperties</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).
+	 */
+	public SchemaInfo additionalProperties(Object value) {
+		additionalProperties = toType(value, SchemaInfo.class);
+		return this;
+	}
+
+	/**
+	 * Bean property getter:  <property>not</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public SchemaInfo getNot() {
+		return not;
+	}
+
+	/**
+	 * Bean property setter:  <property>not</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).
+	 */
+	public SchemaInfo setNot(SchemaInfo value) {
+		not = value;
+		return this;
+	}
+
+	/**
+	 * Bean property setter:  <property>not</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).
+	 */
+	public SchemaInfo not(Object value) {
+		not = toType(value, SchemaInfo.class);
+		return this;
+	}
+	/**
+	 * Bean property getter:  <property>discriminator</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Discriminator getDiscriminator() {
+		return discriminator;
+	}
+
+	/**
+	 * Bean property setter:  <property>discriminator</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).
+	 */
+	public SchemaInfo setDiscriminator(Discriminator value) {
+		discriminator = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDiscriminator(Discriminator)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo discriminator(Object value) {
+		return setDiscriminator(toType(value,Discriminator.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>readOnly</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getReadOnly() {
+		return readOnly;
+	}
+
+	/**
+	 * Bean property setter:  <property>readOnly</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).
+	 */
+	public SchemaInfo setReadOnly(Boolean value) {
+		readOnly = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setReadOnly(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo readOnly(Object value) {
+		return setReadOnly(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>WriteOnly</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getWriteOnly() {
+		return writeOnly;
+	}
+
+	/**
+	 * Bean property setter:  <property>WriteOnly</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).
+	 */
+	public SchemaInfo setWriteOnly(Boolean value) {
+		writeOnly = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setWriteOnly(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo writeOnly(Object value) {
+		return setWriteOnly(toBoolean(value));
+	}
+
+
+	/**
+	 * Bean property getter:  <property>deprecated</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getDeprecated() {
+		return deprecated;
+	}
+
+	/**
+	 * Bean property setter:  <property>deprecated</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).
+	 */
+	public SchemaInfo setDeprecated(Boolean value) {
+		deprecated = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDeprecated(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo deprecated(Object value) {
+		return setDeprecated(toBoolean(value));
+	}
+
+
+	/**
+	 * Bean property getter:  <property>xml</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Xml getXml() {
+		return xml;
+	}
+
+	/**
+	 * Bean property setter:  <property>xml</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).
+	 */
+	public SchemaInfo setXml(Xml value) {
+		xml = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setXml(Xml)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Xml}
+	 * 		<li><code>String</code> - JSON object representation of {@link Xml}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	xml(<js>"{name:'name',namespace:'namespace',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo xml(Object value) {
+		return setXml(toType(value, Xml.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>externalDocs</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public ExternalDocumentation getExternalDocs() {
+		return externalDocs;
+	}
+
+	/**
+	 * Bean property setter:  <property>externalDocs</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).
+	 */
+	public SchemaInfo setExternalDocs(ExternalDocumentation value) {
+		externalDocs = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExternalDocs(ExternalDocumentation)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link ExternalDocumentation}
+	 * 		<li><code>String</code> - JSON object representation of {@link ExternalDocumentation}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	externalDocs(<js>"{description:'description',url:'url'}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SchemaInfo externalDocs(Object value) {
+		return setExternalDocs(toType(value, ExternalDocumentation.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>example</property>.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Object getExample() {
+		return example;
+	}
+
+	/**
+	 * Bean property setter:  <property>example</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).
+	 */
+	public SchemaInfo setExample(Object value) {
+		example = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExample(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 example(Object value) {
+		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;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 *
+	 * @return <jk>true</jk> if this object has a <js>"$ref"</js> attribute.
+	 */
+	public boolean hasRef() {
+		return ref != null;
+	}
+
+	/**
+	 * 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)
+			return null;
+		switch (property) {
+			case "format": return toType(getFormat(), type);
+			case "title": return toType(getTitle(), type);
+			case "description": return toType(getDescription(), type);
+			case "default": return toType(getDefault(), type);
+			case "multipleOf": return toType(getMultipleOf(), type);
+			case "maximum": return toType(getMaximum(), type);
+			case "exclusiveMaximum": return toType(getExclusiveMaximum(), type);
+			case "minimum": return toType(getMinimum(), type);
+			case "exclusiveMinimum": return toType(getExclusiveMinimum(), type);
+			case "maxLength": return toType(getMaxLength(), type);
+			case "minLength": return toType(getMinLength(), type);
+			case "pattern": return toType(getPattern(), type);
+			case "maxItems": return toType(getMaxItems(), type);
+			case "minItems": return toType(getMinItems(), type);
+			case "uniqueItems": return toType(getUniqueItems(), type);
+			case "maxProperties": return toType(getMaxProperties(), type);
+			case "minProperties": return toType(getMinProperties(), type);
+			case "required": return toType(getRequired(), type);
+			case "enum": return toType(getEnum(), type);
+			case "type": return toType(getType(), type);
+			case "items": return toType(getItems(), type);
+			case "allOf": return toType(getAllOf(), type);
+			case "oneOf": return toType(getOneOf(), type);
+			case "anyOf": return toType(getAnyOf(), type);
+			case "properties": return toType(getProperties(), type);
+			case "additionalProperties": return toType(getAdditionalProperties(), type);
+			case "not": return toType(getNot(), type);
+			case "nullable": return toType(getNullable(), type);
+			case "deprecated": return toType(getDeprecated(), type);
+			case "discriminator": return toType(getDiscriminator(), type);
+			case "readOnly": return toType(getReadOnly(), type);
+			case "writeOnly": return toType(getWriteOnly(), type);
+			case "xml": return toType(getXml(), type);
+			case "externalDocs": return toType(getExternalDocs(), type);
+			case "example": return toType(getExample(), type);
+			case "$ref": return toType(getRef(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public SchemaInfo set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "format": return format(value);
+			case "title": return title(value);
+			case "description": return description(value);
+			case "default": return _default(value);
+			case "multipleOf": return multipleOf(value);
+			case "maximum": return maximum(value);
+			case "exclusiveMaximum": return exclusiveMaximum(value);
+			case "minimum": return minimum(value);
+			case "exclusiveMinimum": return exclusiveMinimum(value);
+			case "maxLength": return maxLength(value);
+			case "minLength": return minLength(value);
+			case "pattern": return pattern(value);
+			case "maxItems": return maxItems(value);
+			case "minItems": return minItems(value);
+			case "uniqueItems": return uniqueItems(value);
+			case "maxProperties": return maxProperties(value);
+			case "minProperties": return minProperties(value);
+			case "required": return setRequired(null).required(value);
+			case "enum": return setEnum(null)._enum(value);
+			case "type": return type(value);
+			case "items": return items(value);
+			case "allOf": return setAllOf(null).allOf(value);
+			case "anyOf": return setAnyOf(null).anyOf(value);
+			case "oneOf": return setOneOf(null).oneOf(value);
+			case "properties": return setProperties(null).properties(value);
+			case "additionalProperties": return additionalProperties(value);
+			case "not": return not(value);
+			case "nullable": return nullable(value);
+			case "deprecated": return deprecated(value);
+			case "discriminator": return discriminator(value);
+			case "readOnly": return readOnly(value);
+			case "writeOnly": return writeOnly(value);
+			case "xml": return xml(value);
+			case "externalDocs": return externalDocs(value);
+			case "example": return example(value);
+			case "$ref": return ref(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(anyOf != null, "anyOf")
+			.appendIf(oneOf != null, "oneOf")
+			.appendIf(properties != null, "properties")
+			.appendIf(additionalProperties != null, "additionalProperties")
+			.appendIf(nullable != null, "nullable")
+			.appendIf(deprecated != null, "deprecated")
+			.appendIf(not != null, "not")
+			.appendIf(discriminator != null, "discriminator")
+			.appendIf(readOnly != null, "readOnly")
+			.appendIf(writeOnly != null, "writeOnly")
+			.appendIf(xml != null, "xml")
+			.appendIf(externalDocs != null, "externalDocs")
+			.appendIf(example != null, "example")
+			.appendIf(ref != null, "$ref");
+		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();
+	}
+
+	/**
+	 * Resolves any <js>"$ref"</js> attributes in this element.
+	 *
+	 * @param swagger The swagger document containing the definitions.
+	 * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
+	 * @param maxDepth
+	 * 	The maximum depth to resolve references.
+	 * 	<br>After that level is reached, <code>$ref</code> references will be left alone.
+	 * 	<br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
+	 * @return
+	 * 	This object with references resolved.
+	 * 	<br>May or may not be the same object.
+	 */
+	public SchemaInfo resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
+
+		if (ref != null) {
+			if (refStack.contains(ref) || refStack.size() >= maxDepth)
+				return this;
+			refStack.addLast(ref);
+			SchemaInfo r = swagger.findRef(ref, SchemaInfo.class).resolveRefs(swagger, refStack, maxDepth);
+			refStack.removeLast();
+			return r;
+		}
+
+		if (items != null)
+			items = items.resolveRefs(swagger, refStack, maxDepth);
+
+		if (properties != null)
+			for (Map.Entry<String, SchemaInfo> e : properties.entrySet())
+				e.setValue(e.getValue().resolveRefs(swagger, refStack, maxDepth));
+
+		if (additionalProperties != null)
+			additionalProperties = additionalProperties.resolveRefs(swagger, refStack, maxDepth);
+
+		this.example = null;
+
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SecuritySchemeInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SecuritySchemeInfo.java
new file mode 100644
index 000000000..980486d4f
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/SecuritySchemeInfo.java
@@ -0,0 +1,644 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.FormattedRuntimeException;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.Items;
+import org.apache.juneau.dto.swagger.SchemaInfo;
+import org.apache.juneau.dto.swagger.Swagger;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.*;
+
+import static org.apache.juneau.internal.ArrayUtils.contains;
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * Describes a single operation parameter.
+ *
+ * <p>
+ * A unique parameter is defined by a combination of a name and location.
+ *
+ * <p>
+ * There are five possible parameter types.
+ * <ul class='spaced-list'>
+ * 	<li><js>"path"</js> - Used together with Path Templating, where the parameter value is actually part of the
+ * 		operation's URL.
+ * 		This does not include the host or base path of the API.
+ * 		For example, in <code>/items/{itemId}</code>, the path parameter is <code>itemId</code>.
+ * 	<li><js>"query"</js> - Parameters that are appended to the URL.
+ * 		For example, in <code>/items?id=###</code>, the query parameter is <code>id</code>.
+ * 	<li><js>"header"</js> - Custom headers that are expected as part of the request.
+ * 	<li><js>"body"</js> - The payload that's appended to the HTTP request.
+ * 		Since there can only be one payload, there can only be one body parameter.
+ * 		The name of the body parameter has no effect on the parameter itself and is used for documentation purposes
+ * 		only.
+ * 		Since Form parameters are also in the payload, body and form parameters cannot exist together for the same
+ * 		operation.
+ * 	<li><js>"formData"</js> - Used to describe the payload of an HTTP request when either
+ * 		<code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code> or both are used as the
+ * 		content type of the request (in Swagger's definition, the consumes property of an operation).
+ * 		This is the only parameter type that can be used to send files, thus supporting the file type.
+ * 		Since form parameters are sent in the payload, they cannot be declared together with a body parameter for the
+ * 		same operation.
+ * 		Form parameters have a different format based on the content-type used (for further details, consult
+ * 		<code>http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4</code>):
+ * 		<ul>
+ * 			<li><js>"application/x-www-form-urlencoded"</js> - Similar to the format of Query parameters but as a
+ * 				payload.
+ * 				For example, <code>foo=1&amp;bar=swagger</code> - both <code>foo</code> and <code>bar</code> are form
+ * 				parameters.
+ * 				This is normally used for simple parameters that are being transferred.
+ * 			<li><js>"multipart/form-data"</js> - each parameter takes a section in the payload with an internal header.
+ * 				For example, for the header <code>Content-Disposition: form-data; name="submit-name"</code> the name of
+ * 				the parameter is <code>submit-name</code>.
+ * 				This type of form parameters is more commonly used for file transfers.
+ * 		</ul>
+ * 	</li>
+ * </ul>
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	ParameterInfo x = <jsm>parameterInfo</jsm>(<js>"query"</js>, <js>"foo"</js>);
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"in"</js>: <js>"query"</js>,
+ * 		<js>"name"</js>: <js>"foo"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="in,name,type,description,scheme,bearerFormat,flows,*")
+public class SecuritySchemeInfo extends OpenApiElement {
+
+	private static final String[] VALID_IN = {"query", "header", "cookie"};
+	private static final String[] VALID_TYPES = {"apiKey", "http", "oauth2", "openIdConnect"};
+
+	private String
+		type,
+		description,
+		name,
+		in,
+		scheme,
+		bearerFormat,
+		openIdConnectUrl;
+
+	private OAuthFlow flows;
+
+	/**
+	 * Default constructor.
+	 */
+	public SecuritySchemeInfo() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public SecuritySchemeInfo(SecuritySchemeInfo copyFrom) {
+		super(copyFrom);
+
+		this.name = copyFrom.name;
+		this.in = copyFrom.in;
+		this.description = copyFrom.description;
+		this.type = copyFrom.type;
+		this.scheme = copyFrom.scheme;
+		this.bearerFormat = copyFrom.bearerFormat;
+		this.openIdConnectUrl = copyFrom.openIdConnectUrl;
+		this.flows = copyFrom.flows;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public SecuritySchemeInfo copy() {
+		return new SecuritySchemeInfo(this);
+	}
+
+	@Override /* SwaggerElement */
+	protected SecuritySchemeInfo strict() {
+		super.strict();
+		return this;
+	}
+
+
+	/**
+	 * Bean property getter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The name of the parameter.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Parameter names are case sensitive.
+	 * 	<li>
+	 * 		If <code>in</code> is <js>"path"</js>, the <code>name</code> field MUST correspond to the associated path segment
+	 * 		from the <code>path</code> field in the {@doc SwaggerPathsObject Paths Object}.
+	 * 	<li>
+	 * 		For all other cases, the name corresponds to the parameter name used based on the <code>in</code> property.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerPathTemplating Path Templating}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Bean property setter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The name of the parameter.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Parameter names are case sensitive.
+	 * 	<li>
+	 * 		If <code>in</code> is <js>"path"</js>, the <code>name</code> field MUST correspond to the associated path segment
+	 * 		from the <code>path</code> field in the {@doc SwaggerPathsObject Paths Object}.
+	 * 	<li>
+	 * 		For all other cases, the name corresponds to the parameter name used based on the <code>in</code> property.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerPathTemplating Path Templating}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo name(Object value) {
+		return setName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>in</property>.
+	 *
+	 * <p>
+	 * The location of the parameter.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getIn() {
+		return in;
+	}
+
+	/**
+	 * Bean property setter:  <property>in</property>.
+	 *
+	 * <p>
+	 * The location of the parameter.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"query"</js>
+	 * 		<li><js>"header"</js>
+	 * 		<li><js>"path"</js>
+	 * 		<li><js>"formData"</js>
+	 * 		<li><js>"body"</js>
+	 * 	</ul>
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setIn(String value) {
+		if (isStrict() && ! contains(value, VALID_IN))
+			throw new FormattedRuntimeException(
+				"Invalid value passed in to setIn(String).  Value=''{0}'', valid values={1}",
+				value, VALID_IN
+			);
+		in = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setIn(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"query"</js>
+	 * 		<li><js>"header"</js>
+	 * 		<li><js>"path"</js>
+	 * 		<li><js>"formData"</js>
+	 * 		<li><js>"body"</js>
+	 * 	</ul>
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo in(Object value) {
+		return setIn(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A brief description of the parameter.
+	 * <br>This could contain examples of use.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A brief description of the parameter.
+	 * <br>This could contain examples of use.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>schema</property>.
+	 *
+	 * <p>
+	 * The schema defining the type used for the body parameter.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getScheme() {
+		return scheme;
+	}
+
+	/**
+	 * Bean property setter:  <property>schema</property>.
+	 *
+	 * <p>
+	 * The schema defining the type used for the body parameter.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setScheme(String value) {
+		scheme = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setScheme(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link SchemaInfo}
+	 * 		<li><code>String</code> - JSON object representation of {@link SchemaInfo}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	schema(<js>"{type:'type',description:'description',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo scheme(Object value) {
+		return setScheme(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>type</property>.
+	 *
+	 * <p>
+	 * The type of the parameter.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Bean property setter:  <property>type</property>.
+	 *
+	 * <p>
+	 * The type of the parameter.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 		<li><js>"file"</js>
+	 * 	</ul>
+	 * 	<br>If type is <js>"file"</js>, the <code>consumes</code> MUST be either <js>"multipart/form-data"</js>, <js>"application/x-www-form-urlencoded"</js>
+	 * 		or both and the parameter MUST be <code>in</code> <js>"formData"</js>.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setType(String value) {
+		if (isStrict() && ! contains(value, VALID_TYPES))
+			throw new FormattedRuntimeException(
+				"Invalid value passed in to setType(String).  Value=''{0}'', valid values={1}",
+				value, VALID_TYPES
+			);
+		type = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setType(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Valid values:
+	 * 	<ul>
+	 * 		<li><js>"string"</js>
+	 * 		<li><js>"number"</js>
+	 * 		<li><js>"integer"</js>
+	 * 		<li><js>"boolean"</js>
+	 * 		<li><js>"array"</js>
+	 * 		<li><js>"file"</js>
+	 * 	</ul>
+	 * 	<br>If type is <js>"file"</js>, the <code>consumes</code> MUST be either <js>"multipart/form-data"</js>, <js>"application/x-www-form-urlencoded"</js>
+	 * 		or both and the parameter MUST be <code>in</code> <js>"formData"</js>.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo type(Object value) {
+		return setType(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>format</property>.
+	 *
+	 * <p>
+	 * The extending format for the previously mentioned type.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypeFormats}
+	 * </ul>
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getBearerFormat() {
+		return bearerFormat;
+	}
+
+	/**
+	 * Bean property setter:  <property>format</property>.
+	 *
+	 * <p>
+	 * The extending format for the previously mentioned type.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='extlink'>{@doc SwaggerDataTypes}
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setBearerFormat(String value) {
+		bearerFormat = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setBearerFormat(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo bearerFormat(Object value) {
+		return setBearerFormat(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public OAuthFlow getFlows() {
+		return flows;
+	}
+
+	/**
+	 * Bean property setter:  <property>items</property>.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setFlows(OAuthFlow value) {
+		flows = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setFlows(OAuthFlow)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required if <code>type</code> is <js>"array"</js>.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link Items}
+	 * 		<li><code>String</code> - JSON object representation of {@link Items}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	items(<js>"{type:'type',format:'format',...}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo flows(Object value) {
+		return setFlows(toType(value, OAuthFlow.class));
+	}
+
+	/**
+	 * Bean property getter:  <property>collectionFormat</property>.
+	 *
+	 * <p>
+	 * Determines the format of the array if type array is used.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getOpenIdConnectUrl() {
+		return openIdConnectUrl;
+	}
+
+	/**
+	 * Bean property setter:  <property>collectionFormat</property>.
+	 *
+	 * <p>
+	 * Determines the format of the array if type array is used.
+	 *
+	 * @param value
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo setOpenIdConnectUrl(String value) {
+		openIdConnectUrl = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setOpenIdConnectUrl(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Valid values:
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public SecuritySchemeInfo openIdConnectUrl(Object value) {
+		return setOpenIdConnectUrl(toStringVal(value));
+	}
+
+	@Override /* SwaggerElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "name": return toType(getName(), type);
+			case "in": return toType(getIn(), type);
+			case "description": return toType(getDescription(), type);
+			case "scheme": return toType(getScheme(), type);
+			case "flows": return toType(getFlows(), type);
+			case "bearerFormat": return toType(getBearerFormat(), type);
+			case "openIdConnectUrl": return toType(getOpenIdConnectUrl(), type);
+			case "type": return toType(getType(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* SwaggerElement */
+	public SecuritySchemeInfo set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "name": return name(value);
+			case "in": return in(value);
+			case "description": return description(value);
+			case "scheme": return scheme(value);
+			case "bearerFormat": return bearerFormat(value);
+			case "type": return type(value);
+			case "flows": return flows(value);
+			case "openIdConnectUrl": return openIdConnectUrl(value);
+			default:
+				super.set(property, value);
+				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(scheme != null, "scheme")
+			.appendIf(bearerFormat != null, "bearerFormat")
+			.appendIf(type != null, "type")
+			.appendIf(flows != null, "flows")
+			.appendIf(openIdConnectUrl != null, "openIdConnectUrl");
+		return new MultiSet<>(s, super.keySet());
+	}
+
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Server.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Server.java
new file mode 100644
index 000000000..8749099f8
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Server.java
@@ -0,0 +1,257 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.UriResolver;
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.Contact;
+import org.apache.juneau.dto.swagger.HeaderInfo;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.internal.StringUtils;
+import org.apache.juneau.utils.ASet;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+@Bean(properties="url,description,variables,*")
+public class Server extends OpenApiElement{
+    private URI url;
+    private String description;
+    private Map<String,ServerVariable> variables;
+
+    /**
+     * Default constructor.
+     */
+    public Server() { }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public Server(Server copyFrom) {
+        super(copyFrom);
+
+        this.url = copyFrom.url;
+        this.description = copyFrom.description;
+        if (copyFrom.variables == null) {
+            this.variables = null;
+        } else {
+            this.variables = new LinkedHashMap<>();
+            for (Map.Entry<String,ServerVariable> e : copyFrom.variables.entrySet())
+                this.variables.put(e.getKey(),	e.getValue().copy());
+        }
+    }
+
+    /**
+     * Make a deep copy of this object.
+     *
+     * @return A deep copy of this object.
+     */
+    public Server copy() {
+        return new Server(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected Server strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>url</property>.
+     *
+     * <p>
+     * The URL pointing to the contact information.
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public URI getUrl() {
+        return url;
+    }
+
+    /**
+     * Bean property setter:  <property>url</property>.
+     *
+     * <p>
+     * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+     * <br>Strings must be valid URIs.
+     *
+     * <p>
+     * URIs defined by {@link UriResolver} can be used for values.
+     *
+     * @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 Server setUrl(URI value) {
+        url = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setUrl(URI)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * 	<br>Non-URI values will be converted to URI using <code><jk>new</jk> URI(value.toString())</code>.
+     * 	<br>Can be <jk>null</jk> to unset the property.
+     * @return This object (for method chaining).
+     */
+    public Server url(Object value) {
+        return setUrl(StringUtils.toURI(value));
+    }
+
+    /**
+     * Bean property getter:  <property>description</property>.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Bean property setter:  <property>description</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Server setDescription(String value) {
+        description = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setDescription(String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Server description(Object value) {
+        return setDescription(toStringVal(value));
+    }
+
+    /**
+     * Bean property getter:  <property>variables</property>.
+     */
+    public Map<String, ServerVariable> getVariables() {
+        return variables;
+    }
+
+    /**
+     * Bean property setter:  <property>variables</property>.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public Server setVariables(Map<String, ServerVariable> value) {
+        variables = newMap(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Server addVariables(Map<String, ServerVariable> value) {
+        variables = addToMap(variables,value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param value
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Server addVariables(String keyval, ServerVariable value) {
+        variables = addToMap(variables,keyval,value);
+        return this;
+    }
+
+    /**
+     * Adds a single value to the <property>headers</property> property.
+     *
+     * @param name variable name.
+     * @param value The server variable instance.
+     * @return This object (for method chaining).
+     */
+    public Server variable(String name, ServerVariable value) {
+        addVariables(Collections.singletonMap(name, value));
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>variables</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public Server headers(Object...values) {
+        variables = addToMap(variables, values, String.class, ServerVariable.class);
+        return this;
+    }
+
+    public Server variables(Object value) {
+        return setVariables((HashMap<String,ServerVariable>)value);
+    }
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "url": return toType(getUrl(), type);
+            case "description": return toType(getDescription(), type);
+            case "variables": return toType(getVariables(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Server set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "url": return url(value);
+            case "description": return description(value);
+            case "variables": return variables(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(url != null, "url")
+                .appendIf(description != null, "description")
+                .appendIf(variables != null, "variables");
+        return new MultiSet<>(s, super.keySet());
+    }
+}
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ServerVariable.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ServerVariable.java
new file mode 100644
index 000000000..fd7bcc301
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/ServerVariable.java
@@ -0,0 +1,313 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.Items;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+
+@Bean(properties="enum,default,description,*")
+public class ServerVariable extends OpenApiElement {
+
+    private List<Object> _enum;
+    private String _default;
+    private String description;
+
+    /**
+     * Default constructor.
+     */
+    public ServerVariable() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyFrom The object to copy.
+     */
+    public ServerVariable(ServerVariable copyFrom) {
+        super(copyFrom);
+
+        this._enum = newList(copyFrom._enum);
+        this._default = copyFrom._default;
+        this.description = copyFrom.description;
+    }
+
+    /**
+     * Make a deep copy of this object.
+     * @return A deep copy of this object.
+     */
+    public ServerVariable copy() {
+        return new ServerVariable(this);
+    }
+
+    @Override /* OpenApiElement */
+    protected ServerVariable strict() {
+        super.strict();
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>enum</property>.
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public List<Object> getEnum() {
+        return _enum;
+    }
+
+    /**
+     * Bean property setter:  <property>enum</property>.
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     * @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 ServerVariable setEnum(Collection<Object> value) {
+        _enum = newList(value);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>enum</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public ServerVariable addEnum(Collection<Object> values) {
+        _enum = addToList(_enum, values);
+        return this;
+    }
+
+    /**
+     * Adds one or more values to the <property>enum</property> property.
+     *
+     * @param values
+     * 	The values to add to this property.
+     * 	<br>Valid types:
+     * 	<ul>
+     * 		<li><code>Object</code>
+     * 		<li><code>Collection&lt;Object&gt;</code>
+     * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
+     * 			<h5 class='figure'>Example:</h5>
+     * 			<p class='bcode w800'>
+     * 	_enum(<js>"['foo','bar']"</js>);
+     * 			</p>
+     * 		<li><code>String</code> - Individual values
+     * 			<h5 class='figure'>Example:</h5>
+     * 			<p class='bcode w800'>
+     * 	_enum(<js>"foo"</js>, <js>"bar"</js>);
+     * 			</p>
+     * 	</ul>
+     * 	<br>Ignored if <jk>null</jk>.
+     * @return This object (for method chaining).
+     */
+    public ServerVariable _enum(Object...values) {
+        _enum = addToList(_enum, values, Object.class);
+        return this;
+    }
+
+    /**
+     * Bean property getter:  <property>default</property>.
+     *
+     * <p>
+     * Declares the value of the item that the server will use if none is provided.
+     *
+     * <h5 class='section'>Notes:</h5>
+     * <ul class='spaced-list'>
+     * 	<li>
+     * 		<js>"default"</js> has no meaning for required items.
+     * 	<li>
+     * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+     * </ul>
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     * @return The property value, or <jk>null</jk> if it is not set.
+     */
+    public String getDefault() {
+        return _default;
+    }
+
+    /**
+     * Bean property setter:  <property>default</property>.
+     *
+     * <p>
+     * Declares the value of the item that the server will use if none is provided.
+     *
+     * <h5 class='section'>Notes:</h5>
+     * <ul class='spaced-list'>
+     * 	<li>
+     * 		<js>"default"</js> has no meaning for required items.
+     * 	<li>
+     * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+     * </ul>
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     * @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 ServerVariable setDefault(String value) {
+        _default = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setDefault(String)}.
+     *
+     * @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 ServerVariable _default(Object value) {
+        return setDefault(toStringVal(value));
+    }
+
+    /**
+     * Returns <jk>true</jk> if the defualt property is not null or empty.
+     *
+     * @return <jk>true</jk> if the defualt property is not null or empty.
+     */
+    public boolean hasDefault() {
+        return ! _default.isEmpty();
+    }
+
+    /**
+     * Bean property getter:  <property>description</property>.
+     *
+     * <p>
+     * Declares the value of the item that the server will use if none is provided.
+     *
+     * <h5 class='section'>Notes:</h5>
+     * <ul class='spaced-list'>
+     * 	<li>
+     * 		<js>"description"</js> has no meaning for required items.
+     * 	<li>
+     * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+     * </ul>
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Bean property setter:  <property>description</property>.
+     *
+     * <p>
+     * Declares the value of the item that the server will use if none is provided.
+     *
+     * <h5 class='section'>Notes:</h5>
+     * <ul class='spaced-list'>
+     * 	<li>
+     * 		<js>"description"</js> has no meaning for required items.
+     * 	<li>
+     * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
+     * </ul>
+     *
+     * <h5 class='section'>See Also:</h5>
+     * <ul>
+     * 	<li class='extlink'>{@doc JsonSchemaValidation}
+     * </ul>
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public ServerVariable setDescription(String value) {
+        description = value;
+        return this;
+    }
+
+    /**
+     * Same as {@link #setDescription(String)}.
+     *
+     * @param value
+     * 	The new value for this property.
+     * @return This object (for method chaining).
+     */
+    public ServerVariable description(Object value) {
+        return setDefault(toStringVal(value));
+    }
+
+    @Override /* OpenApiElement */
+    public <T> T get(String property, Class<T> type) {
+        if (property == null)
+            return null;
+        switch (property) {
+            case "enum": return toType(getEnum(), type);
+            case "default": return toType(getDefault(), type);
+            case "description": return toType(getDescription(), type);
+            default: return super.get(property, type);
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public ServerVariable set(String property, Object value) {
+        if (property == null)
+            return this;
+        switch (property) {
+            case "default": return _default(value);
+            case "enum": return setEnum(null)._enum(value);
+            case "description": return description(value);
+            default:
+                super.set(property, value);
+                return this;
+        }
+    }
+
+    @Override /* OpenApiElement */
+    public Set<String> keySet() {
+        ASet<String> s = new ASet<String>()
+                .appendIf(_enum != null, "enum")
+                .appendIf(_default != null,"default" )
+                .appendIf(description != null, "description");
+        return new MultiSet<>(s, super.keySet());
+
+
+    }
+}
\ No newline at end of file
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Tag.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Tag.java
new file mode 100644
index 000000000..5a0cd83fe
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Tag.java
@@ -0,0 +1,259 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.ExternalDocumentation;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.toStringVal;
+import static org.apache.juneau.internal.BeanPropertyUtils.toType;
+
+/**
+ * Allows adding meta data to a single tag that is used by the {@doc SwaggerOperationObject Operation Object}.
+ *
+ * <p>
+ * It is not mandatory to have a Tag Object per tag used there.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Construct using SwaggerBuilder.</jc>
+ * 	Tag x = <jsm>tag</jsm>()
+ * 		.name(<js>"pet"</js>)
+ * 		.description(<js>"Pets operations"</js>)
+ *
+ * 	<jc>// Serialize using JsonSerializer.</jc>
+ * 	String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
+ *
+ * 	<jc>// Or just use toString() which does the same as above.</jc>
+ * 	String json = x.toString();
+ * </p>
+ * <p class='bcode w800'>
+ * 	<jc>// Output</jc>
+ * 	{
+ * 		<js>"name"</js>: <js>"pet"</js>,
+ * 		<js>"description"</js>: <js>"Pets operations"</js>
+ * 	}
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul class='doctree'>
+ * 	<li class='link'>{@doc juneau-dto.Swagger}
+ * </ul>
+ */
+@Bean(properties="name,description,externalDocs,*")
+public class Tag extends OpenApiElement {
+
+	private String
+		name,
+		description;
+	private ExternalDocumentation externalDocs;
+
+	/**
+	 * Default constructor.
+	 */
+	public Tag() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Tag(Tag copyFrom) {
+		super(copyFrom);
+
+		this.name = copyFrom.name;
+		this.description = copyFrom.description;
+		this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy();
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Tag copy() {
+		return new Tag(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The name of the tag.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Bean property setter:  <property>name</property>.
+	 *
+	 * <p>
+	 * The name of the tag.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Property value is required.
+	 * @return This object (for method chaining).
+	 */
+	public Tag setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Tag name(Object value) {
+		return setName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description for the tag.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Bean property setter:  <property>description</property>.
+	 *
+	 * <p>
+	 * A short description for the tag.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>{@doc GFM} can be used for rich text representation.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Tag setDescription(String value) {
+		description = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setDescription(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Tag description(Object value) {
+		return setDescription(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>externalDocs</property>.
+	 *
+	 * <p>
+	 * Additional external documentation for this tag.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public ExternalDocumentation getExternalDocs() {
+		return externalDocs;
+	}
+
+	/**
+	 * Bean property setter:  <property>externalDocs</property>.
+	 *
+	 * <p>
+	 * Additional external documentation for this tag.
+	 *
+	 * @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 Tag setExternalDocs(ExternalDocumentation value) {
+		externalDocs = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setExternalDocs(ExternalDocumentation)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Valid types:
+	 * 	<ul>
+	 * 		<li>{@link ExternalDocumentation}
+	 * 		<li><code>String</code> - JSON object representation of {@link ExternalDocumentation}
+	 * 			<h5 class='figure'>Example:</h5>
+	 * 			<p class='bcode w800'>
+	 * 	externalDocs(<js>"{description:'description',url:'url'}"</js>);
+	 * 			</p>
+	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Tag externalDocs(Object value) {
+		return setExternalDocs(toType(value, ExternalDocumentation.class));
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "name": return toType(getName(), type);
+			case "description": return toType(getDescription(), type);
+			case "externalDocs": return toType(getExternalDocs(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Tag set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "name": return name(value);
+			case "description": return description(value);
+			case "externalDocs": return externalDocs(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/Xml.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Xml.java
new file mode 100644
index 000000000..2a569d327
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/Xml.java
@@ -0,0 +1,345 @@
+// ***************************************************************************************************************************
+// * 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.openapi;
+
+import org.apache.juneau.annotation.Bean;
+import org.apache.juneau.dto.swagger.SwaggerElement;
+import org.apache.juneau.internal.MultiSet;
+import org.apache.juneau.utils.ASet;
+
+import java.util.Set;
+
+import static org.apache.juneau.internal.BeanPropertyUtils.*;
+
+/**
+ * A metadata object that allows for more fine-tuned XML model definitions.
+ *
+ * When using arrays, XML element names are not inferred (for singular/plural forms) and the name property should be
+ * used to add that information.
+ */
+@Bean(properties="name,namespace,prefix,attribute,wrapped,*")
+public class Xml extends OpenApiElement {
+
+	private String
+		name,
+		namespace,
+		prefix;
+	private Boolean
+		attribute,
+		wrapped;
+
+	/**
+	 * Default constructor.
+	 */
+	public Xml() {}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The object to copy.
+	 */
+	public Xml(Xml copyFrom) {
+		super(copyFrom);
+
+		this.name = copyFrom.name;
+		this.namespace = copyFrom.namespace;
+		this.prefix = copyFrom.prefix;
+		this.attribute = copyFrom.attribute;
+		this.wrapped = copyFrom.wrapped;
+	}
+
+	/**
+	 * Make a deep copy of this object.
+	 *
+	 * @return A deep copy of this object.
+	 */
+	public Xml copy() {
+		return new Xml(this);
+	}
+
+	/**
+	 * Bean property getter:  <property>name</property>.
+	 *
+	 * <p>
+	 * Replaces the name of the element/attribute used for the described schema property.
+	 *
+	 * <p>
+	 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements
+	 * within the list.
+	 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the
+	 * wrapping element and only if wrapped is <jk>true</jk>.
+	 * <br>If wrapped is <jk>false</jk>, it will be ignored.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Bean property setter:  <property>name</property>.
+	 *
+	 * <p>
+	 * Replaces the name of the element/attribute used for the described schema property.
+	 *
+	 * <p>
+	 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements
+	 * within the list.
+	 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the
+	 * wrapping element and only if wrapped is <jk>true</jk>.
+	 * <br>If wrapped is <jk>false</jk>, it will be ignored.
+	 *
+	 * @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 Xml setName(String value) {
+		name = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setName(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml name(Object value) {
+		return setName(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>namespace</property>.
+	 *
+	 * <p>
+	 * The URL of the namespace definition. Value SHOULD be in the form of a URL.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getNamespace() {
+		return namespace;
+	}
+
+	/**
+	 * Bean property setter:  <property>namespace</property>.
+	 *
+	 * <p>
+	 * The URL of the namespace definition. Value SHOULD be in the form of a URL.
+	 *
+	 * @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 Xml setNamespace(String value) {
+		namespace = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setNamespace(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml namespace(Object value) {
+		return setNamespace(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>prefix</property>.
+	 *
+	 * <p>
+	 * The prefix to be used for the name.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public String getPrefix() {
+		return prefix;
+	}
+
+	/**
+	 * Bean property setter:  <property>prefix</property>.
+	 *
+	 * <p>
+	 * The prefix to be used for the name.
+	 *
+	 * @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 Xml setPrefix(String value) {
+		prefix = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setPrefix(String)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-String values will be converted to String using <code>toString()</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml prefix(Object value) {
+		return setPrefix(toStringVal(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>attribute</property>.
+	 *
+	 * <p>
+	 * Declares whether the property definition translates to an attribute instead of an element.
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getAttribute() {
+		return attribute;
+	}
+
+	/**
+	 * Bean property setter:  <property>attribute</property>.
+	 *
+	 * <p>
+	 * Declares whether the property definition translates to an attribute instead of an element.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Default value is <jk>false</jk>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml setAttribute(Boolean value) {
+		attribute = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setAttribute(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Default value is <jk>false</jk>.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml attribute(Object value) {
+		return setAttribute(toBoolean(value));
+	}
+
+	/**
+	 * Bean property getter:  <property>wrapped</property>.
+	 *
+	 * <p>
+	 * MAY be used only for an array definition.
+	 *
+	 * <p>
+	 * Signifies whether the array is wrapped (for example,
+	 * <code>&lt;books&gt;&lt;book/&gt;&lt;book/&gt;&lt;books&gt;</code>) or unwrapped
+	 * (<code>&lt;book/&gt;&lt;book/&gt;</code>).
+	 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code>
+	 * (outside the <code>items</code>).
+	 *
+	 * @return The property value, or <jk>null</jk> if it is not set.
+	 */
+	public Boolean getWrapped() {
+		return wrapped;
+	}
+
+	/**
+	 * Bean property setter:  <property>wrapped</property>.
+	 *
+	 * <p>
+	 * MAY be used only for an array definition.
+	 *
+	 * <p>
+	 * Signifies whether the array is wrapped (for example,
+	 * <code>&lt;books&gt;&lt;book/&gt;&lt;book/&gt;&lt;books&gt;</code>) or unwrapped
+	 * (<code>&lt;book/&gt;&lt;book/&gt;</code>).
+	 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code>
+	 * (outside the <code>items</code>).
+	 *
+	 * @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 Xml setWrapped(Boolean value) {
+		this.wrapped = value;
+		return this;
+	}
+
+	/**
+	 * Same as {@link #setWrapped(Boolean)}.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
+	 * 	<br>Can be <jk>null</jk> to unset the property.
+	 * @return This object (for method chaining).
+	 */
+	public Xml wrapped(Object value) {
+		return setWrapped(toBoolean(value));
+	}
+
+	@Override /* OpenApiElement */
+	public <T> T get(String property, Class<T> type) {
+		if (property == null)
+			return null;
+		switch (property) {
+			case "name": return toType(getName(), type);
+			case "namespace": return toType(getNamespace(), type);
+			case "prefix": return toType(getPrefix(), type);
+			case "attribute": return toType(getAttribute(), type);
+			case "wrapped": return toType(getWrapped(), type);
+			default: return super.get(property, type);
+		}
+	}
+
+	@Override /* OpenApiElement */
+	public Xml set(String property, Object value) {
+		if (property == null)
+			return this;
+		switch (property) {
+			case "name": return name(value);
+			case "namespace": return namespace(value);
+			case "prefix": return prefix(value);
+			case "attribute": return attribute(value);
+			case "wrapped": return wrapped(value);
+			default:
+				super.set(property, value);
+				return this;
+		}
+	}
+
+	@Override /* OpenApiElement */
+	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/openapi/package-info.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/package-info.java
new file mode 100755
index 000000000..548edf481
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/openapi/package-info.java
@@ -0,0 +1,18 @@
+// ***************************************************************************************************************************
+// * 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.                                              *
+// ***************************************************************************************************************************
+
+/**
+ * Swagger Data Transfer Objects
+ */
+package org.apache.juneau.dto.openapi;
+


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message