You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/07/02 23:33:17 UTC

[juneau] branch master updated: JUnit tests.

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0cb4d22  JUnit tests.
0cb4d22 is described below

commit 0cb4d22952aeac0173994ba5d4c3bf9bb6c9d733
Author: JamesBognar <ja...@apache.org>
AuthorDate: Mon Jul 2 19:33:01 2018 -0400

    JUnit tests.
---
 .../juneau/httppart/OpenApiPartParserTest.java     |  179 ++-
 .../org/apache/juneau/httppart/HttpPartSchema.java | 1400 +-------------------
 .../juneau/httppart/HttpPartSchemaBuilder.java     | 1360 +++++++++++++++++++
 .../apache/juneau/httppart/OpenApiPartParser.java  |   19 +
 .../org/apache/juneau/internal/DelegateList.java   |    2 +-
 5 files changed, 1554 insertions(+), 1406 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/OpenApiPartParserTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/OpenApiPartParserTest.java
index 44d668b..dd9cb14 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/OpenApiPartParserTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/OpenApiPartParserTest.java
@@ -13,10 +13,12 @@
 package org.apache.juneau.httppart;
 
 import static org.junit.Assert.*;
+import static org.apache.juneau.testutils.TestUtils.*;
 
 import java.io.*;
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.internal.*;
 import org.junit.*;
 
@@ -320,48 +322,141 @@ public class OpenApiPartParserTest {
 	// type = array
 	//-----------------------------------------------------------------------------------------------------------------
 
-//	case ARRAY: {
-//	if (type.isObject())
-//		type = (ClassMeta<T>)getClassMeta(ObjectList.class);
-//
-//	ClassMeta<?> eType = type.isObject() ? string() : type.getElementType();
-//	if (eType == null)
-//		throw new ParseException("Value of type ARRAY cannot be converted to type {0}", type);
-//
-//	String[] ss = new String[0];
-//	switch (schema.getCollectionFormat()) {
-//		case MULTI:
-//			ss = new String[]{in};
-//			break;
-//		case CSV:
-//			ss = split(in, ',');
-//			break;
-//		case PIPES:
-//			ss = split(in, '|');
-//			break;
-//		case SSV:
-//			ss = splitQuoted(in);
-//			break;
-//		case TSV:
-//			ss = split(in, '\t');
-//			break;
-//		case UON:
-//			return super.parse(partType, null, in, type);
-//		case NONE:
-//			if (firstNonWhitespaceChar(in) == '@' && lastNonWhitespaceChar(in) == ')')
-//				return super.parse(partType, null, in, type);
-//			ss = split(in, ',');
-//	}
-//	Object[] o = null;
-//	if (schema.getItems() != null) {
-//		o = new Object[ss.length];
-//		for (int i = 0; i < ss.length; i++)
-//			o[i] = parse(partType, schema.getItems(), ss[i], eType);
-//	} else {
-//		o = ss;
-//	}
-//	return toType(o, type);
-//}
+	public static class D {
+		private String f;
+		public D(String in) {
+			this.f = in;
+		}
+		@Override
+		public String toString() {
+			return f;
+		}
+	}
+
+	@Test
+	public void d01_arrayType_collectionFormatCsv() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("csv").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", ObjectList.class));
+	}
+
+	@Test
+	public void d02_arrayType_collectionFormatPipes() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("pipes").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo|bar", ObjectList.class));
+	}
+
+	@Test
+	public void d03_arrayType_collectionFormatSsv() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("ssv").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo bar", ObjectList.class));
+	}
+
+	@Test
+	public void d04_arrayType_collectionFormatTsv() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("tsv").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo\tbar", ObjectList.class));
+	}
+
+	@Test
+	public void d05_arrayType_collectionFormatUon() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("uon").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", ObjectList.class));
+	}
+
+	@Test
+	public void d06a_arrayType_collectionFormatNone() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "foo,bar", Object.class));
+	}
+
+	@Test
+	public void d06b_arrayType_collectionFormatNone_autoDetectUon() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").build();
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", String[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", Object[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", D[].class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, String.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, Object.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", List.class, D.class));
+		assertObjectEquals("['foo','bar']", p.parse(s, "@(foo,bar)", Object.class));
+	}
+
+	@Test
+	public void d07_arrayType_collectionFormatMulti() throws Exception {
+		// collectionFormat=multi should not do any sort of splitting.
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("multi").build();
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", String[].class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", Object[].class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", D[].class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", List.class, String.class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", List.class, Object.class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", List.class, D.class));
+		assertObjectEquals("['foo,bar']", p.parse(s, "foo,bar", Object.class));
+	}
+
+	@Test
+	public void d08_arrayType_collectionFormatCsvAndPipes() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("pipes").items(HttpPartSchema.create().type("array").collectionFormat("csv")).build();
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", String[][].class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", Object[][].class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", D[][].class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", List.class, List.class, String.class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", List.class, List.class, Object.class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", List.class, List.class, D.class));
+		assertObjectEquals("[['foo','bar'],['baz','qux']]", p.parse(s, "foo,bar|baz,qux", Object.class));
+	}
+
+	@Test
+	public void d09_arrayType_itemsInteger() throws Exception {
+		HttpPartSchema s = HttpPartSchema.create().type("array").collectionFormat("csv").items(HttpPartSchema.create().type("integer")).build();
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", int[].class));
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", Integer[].class));
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", Object[].class));
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", List.class, Integer.class));
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", List.class, Object.class));
+		assertObjectEquals("[1,2]", p.parse(s, "1,2", Object.class));
+	}
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// type = boolean
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index 66619c4..94dc878 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -71,8 +71,8 @@ public class HttpPartSchema {
 	 *
 	 * @return A new builder for this object.
 	 */
-	public static Builder create() {
-		return new Builder();
+	public static HttpPartSchemaBuilder create() {
+		return new HttpPartSchemaBuilder();
 	}
 
 	/**
@@ -215,7 +215,7 @@ public class HttpPartSchema {
 		return create().apply(a).build();
 	}
 
-	HttpPartSchema(Builder b) {
+	HttpPartSchema(HttpPartSchemaBuilder b) {
 		this.name = b.name;
 		this.codes = copy(b.codes);
 		this._default = b._default;
@@ -401,1332 +401,6 @@ public class HttpPartSchema {
 	}
 
 	/**
-	 * The builder class for creating {@link HttpPartSchema} objects.
-	 *
-	 */
-	public static class Builder {
-		String name, _default;
-		Set<Integer> codes;
-		Set<String> _enum;
-		Boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
-		CollectionFormat collectionFormat = CollectionFormat.NONE;
-		Type type = Type.NONE;
-		Format format = Format.NONE;
-		Pattern pattern;
-		Number maximum, minimum, multipleOf;
-		Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
-		Map<String,Builder> properties;
-		HttpPartSchema.Builder items, additionalProperties;
-		boolean noValidate;
-		ObjectMap api = new ObjectMap();
-		Class<? extends HttpPartParser> parser;
-		Class<? extends HttpPartSerializer> serializer;
-
-		/**
-		 * Instantiates a new {@link HttpPartSchema} object based on the configuration of this builder.
-		 *
-		 * <p>
-		 * This method can be called multiple times to produce new schema objects.
-		 *
-		 * @return
-		 * 	A new {@link HttpPartSchema} object.
-		 * 	<br>Never <jk>null</jk>.
-		 */
-		public HttpPartSchema build() {
-			return new HttpPartSchema(this);
-		}
-
-		Builder apply(Class<? extends Annotation> c, Method m, int index) {
-			for (Annotation a :  m.getParameterAnnotations()[index])
-				if (c.isInstance(a))
-					return apply(a);
-			apply(c, m.getGenericParameterTypes()[index]);
-			return this;
-		}
-
-		Builder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
-			if (t instanceof Class<?>)
-				for (Annotation a : ReflectionUtils.findAnnotationsParentFirst(c, (Class<?>)t))
-					apply(a);
-			return this;
-		}
-
-		Builder apply(Annotation a) {
-			if (a instanceof Body)
-				apply((Body)a);
-			else if (a instanceof Header)
-				apply((Header)a);
-			else if (a instanceof FormData)
-				apply((FormData)a);
-			else if (a instanceof Query)
-				apply((Query)a);
-			else if (a instanceof Path)
-				apply((Path)a);
-			else if (a instanceof Response)
-				apply((Response)a);
-			else if (a instanceof ResponseHeader)
-				apply((ResponseHeader)a);
-			else if (a instanceof ResponseStatus)
-				apply((ResponseStatus)a);
-			else if (a instanceof HasQuery)
-				apply((HasQuery)a);
-			else if (a instanceof HasFormData)
-				apply((HasFormData)a);
-			return this;
-		}
-
-		Builder apply(Body a) {
-			api = AnnotationUtils.merge(api, a);
-			required(toBoolean(a.required()));
-			allowEmptyValue(toBoolean(! a.required()));
-			parser(a.parser());
-			apply(a.schema());
-			return this;
-		}
-
-		Builder apply(Header a) {
-			api = AnnotationUtils.merge(api, a);
-			name(a.value());
-			name(a.name());
-			required(toBoolean(a.required()));
-			type(a.type());
-			format(a.format());
-			allowEmptyValue(toBoolean(a.allowEmptyValue()));
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			skipIfEmpty(toBoolean(a.skipIfEmpty()));
-			parser(a.parser());
-			serializer(a.serializer());
-			return this;
-		}
-
-		Builder apply(ResponseHeader a) {
-			api = AnnotationUtils.merge(api, a);
-			name(a.value());
-			name(a.name());
-			codes(a.code());
-			type(a.type());
-			format(a.format());
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			allowEmptyValue(false);
-			serializer(a.serializer());
-			return this;
-		}
-
-		Builder apply(ResponseStatus a) {
-			api = AnnotationUtils.merge(api, a);
-			code(a.value());
-			code(a.code());
-			return this;
-		}
-
-		Builder apply(FormData a) {
-			api = AnnotationUtils.merge(api, a);
-			name(a.value());
-			name(a.name());
-			required(toBoolean(a.required()));
-			type(a.type());
-			format(a.format());
-			allowEmptyValue(toBoolean(a.allowEmptyValue()));
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			skipIfEmpty(toBoolean(a.skipIfEmpty()));
-			parser(a.parser());
-			serializer(a.serializer());
-			return this;
-		}
-
-		Builder apply(Query a) {
-			api = AnnotationUtils.merge(api, a);
-			name(a.value());
-			name(a.name());
-			required(toBoolean(a.required()));
-			type(a.type());
-			format(a.format());
-			allowEmptyValue(toBoolean(a.allowEmptyValue()));
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			skipIfEmpty(toBoolean(a.skipIfEmpty()));
-			parser(a.parser());
-			serializer(a.serializer());
-			return this;
-		}
-
-		Builder apply(Path a) {
-			api = AnnotationUtils.merge(api, a);
-			name(a.value());
-			name(a.name());
-			type(a.type());
-			format(a.format());
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			parser(a.parser());
-			serializer(a.serializer());
-			return this;
-		}
-
-		Builder apply(Response a) {
-			api = AnnotationUtils.merge(api, a);
-			codes(a.value());
-			codes(a.code());
-			required(false);
-			allowEmptyValue(true);
-			serializer(a.serializer());
-			apply(a.schema());
-			return this;
-		}
-
-		Builder apply(Items a) {
-			api = AnnotationUtils.merge(api, a);
-			type(a.type());
-			format(a.format());
-			items(a.items());
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			return this;
-		}
-
-		Builder apply(SubItems a) {
-			api = AnnotationUtils.merge(api, a);
-			type(a.type());
-			format(a.format());
-			items(toObjectMap(a.items()));
-			collectionFormat(a.collectionFormat());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			return this;
-		}
-
-		Builder apply(Schema a) {
-			type(a.type());
-			format(a.format());
-			items(a.items());
-			_default(joinnl(a._default()));
-			maximum(toNumber(a.maximum()));
-			exclusiveMaximum(toBoolean(a.exclusiveMaximum()));
-			minimum(toNumber(a.minimum()));
-			exclusiveMinimum(toBoolean(a.exclusiveMinimum()));
-			maxLength(toLong(a.maxLength()));
-			minLength(toLong(a.minLength()));
-			pattern(a.pattern());
-			maxItems(toLong(a.maxItems()));
-			minItems(toLong(a.minItems()));
-			uniqueItems(toBoolean(a.uniqueItems()));
-			_enum(toSet(a._enum()));
-			multipleOf(toNumber(a.multipleOf()));
-			maxProperties(toLong(a.maxProperties()));
-			minProperties(toLong(a.minProperties()));
-			properties(toObjectMap(a.properties()));
-			additionalProperties(toObjectMap(a.additionalProperties()));
-			return this;
-		}
-
-		Builder apply(HasQuery a) {
-			name(a.value());
-			name(a.name());
-			return this;
-		}
-
-		Builder apply(HasFormData a) {
-			name(a.value());
-			name(a.name());
-			return this;
-		}
-
-		Builder apply(ObjectMap m) {
-			if (m != null && ! m.isEmpty()) {
-				_default(m.getString("default"));
-				_enum(toSet(m.getString("enum")));
-				allowEmptyValue(m.getBoolean("allowEmptyValue"));
-				exclusiveMaximum(m.getBoolean("exclusiveMaximum"));
-				exclusiveMinimum(m.getBoolean("exclusiveMinimum"));
-				required(m.getBoolean("required"));
-				uniqueItems(m.getBoolean("uniqueItems"));
-				collectionFormat(m.getString("collectionFormat"));
-				type(m.getString("type"));
-				format(m.getString("format"));
-				pattern(m.getString("pattern"));
-				maximum(m.get("maximum", Number.class));
-				minimum(m.get("minimum", Number.class));
-				multipleOf(m.get("multipleOf", Number.class));
-				maxItems(m.get("maxItems", Long.class));
-				maxLength(m.get("maxLength", Long.class));
-				maxProperties(m.get("maxProperties", Long.class));
-				minItems(m.get("minItems", Long.class));
-				minLength(m.get("minLength", Long.class));
-				minProperties(m.get("minProperties", Long.class));
-
-				items(m.getObjectMap("items"));
-				properties(m.getObjectMap("properties"));
-				additionalProperties(m.getObjectMap("additionalProperties"));
-
-				apply(m.getObjectMap("schema", null));
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>name</mk> field.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * @return This object (for method chaining).
-		 */
-		public Builder name(String value) {
-			if (isNotEmpty(value))
-				name = value;
-			return this;
-		}
-
-		/**
-		 * <mk>httpStatusCode</mk> key.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#responsesObject">Responses</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if <jk>null</jk> or an empty array.
-		 * @return This object (for method chaining).
-		 */
-		public Builder codes(int[] value) {
-			if (value != null && value.length != 0)
-				for (int v : value)
-					code(v);
-			return this;
-		}
-
-		/**
-		 * <mk>httpStatusCode</mk> key.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#responsesObject">Responses</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <code>0</code>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder code(int value) {
-			if (value != 0) {
-				if (codes == null)
-					codes = new TreeSet<>();
-				codes.add(value);
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>required</mk> field.
-		 *
-		 * <p>
-		 * Determines whether the parameter is mandatory.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder required(Boolean value) {
-			if (value != null)
-				required = value;
-			return this;
-		}
-
-		/**
-		 * <mk>required</mk> field.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>required(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder required() {
-			return required(true);
-		}
-
-		/**
-		 * <mk>type</mk> field.
-		 *
-		 * <p>
-		 * The type of the parameter.
-		 *
-		 * <p>
-		 * The possible values are:
-		 * <ul class='spaced-list'>
-		 * 	<li>
-		 * 		<js>"string"</js>
-		 * 		<br>Parameter must be a string or a POJO convertible from a string.
-		 * 	<li>
-		 * 		<js>"number"</js>
-		 * 		<br>Parameter must be a number primitive or number object.
-		 * 		<br>If parameter is <code>Object</code>, creates either a <code>Float</code> or <code>Double</code> depending on the size of the number.
-		 * 	<li>
-		 * 		<js>"integer"</js>
-		 * 		<br>Parameter must be a integer/long primitive or integer/long object.
-		 * 		<br>If parameter is <code>Object</code>, creates either a <code>Short</code>, <code>Integer</code>, or <code>Long</code> depending on the size of the number.
-		 * 	<li>
-		 * 		<js>"boolean"</js>
-		 * 		<br>Parameter must be a boolean primitive or object.
-		 * 	<li>
-		 * 		<js>"array"</js>
-		 * 		<br>Parameter must be an array or collection.
-		 * 		<br>Elements must be strings or POJOs convertible from strings.
-		 * 		<br>If parameter is <code>Object</code>, creates an {@link ObjectList}.
-		 * 	<li>
-		 * 		<js>"object"</js>
-		 * 		<br>Parameter must be a map or bean.
-		 * 		<br>If parameter is <code>Object</code>, creates an {@link ObjectMap}.
-		 * 		<br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
-		 * 	<li>
-		 * 		<js>"file"</js>
-		 * 		<br>This type is currently not supported.
-		 * </ul>
-		 *
-		 * <p>
-		 * If the type is not specified, it will be auto-detected based on the parameter class type.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#securitySchemeObject">Security Scheme</a>
-		 * </ul>
-		 *
-		 * <h5 class='section'>See Also:</h5>
-		 * <ul class='doctree'>
-		 * 	<li class='link'><a class='doclink' href='https://swagger.io/specification/#dataTypes'>Swagger specification &gt; Data Types</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder type(String value) {
-			try {
-				if (isNotEmpty(value))
-					type = Type.fromString(value);
-			} catch (Exception e) {
-				throw new ContextRuntimeException("Invalid value ''{0}'' passed in as type value.  Valid values: {1}", value, Type.values());
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>format</mk> field.
-		 *
-		 * <p>
-		 * The extending format for the previously mentioned <a href='https://swagger.io/specification/v2/#parameterType'>type</a>.
-		 *
-		 * <p>
-		 * The possible values are:
-		 * <ul class='spaced-list'>
-		 * 	<li>
-		 * 		<js>"int32"</js> - Signed 32 bits.
-		 * 		<br>Only valid with type <js>"integer"</js>.
-		 * 	<li>
-		 * 		<js>"int64"</js> - Signed 64 bits.
-		 * 		<br>Only valid with type <js>"integer"</js>.
-		 * 	<li>
-		 * 		<js>"float"</js> - 32-bit floating point number.
-		 * 		<br>Only valid with type <js>"number"</js>.
-		 * 	<li>
-		 * 		<js>"double"</js> - 64-bit floating point number.
-		 * 		<br>Only valid with type <js>"number"</js>.
-		 * 	<li>
-		 * 		<js>"byte"</js> - BASE-64 encoded characters.
-		 * 		<br>Only valid with type <js>"string"</js>.
-		 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
-		 * 	<li>
-		 * 		<js>"binary"</js> - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
-		 * 		<br>Only valid with type <js>"string"</js>.
-		 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
-		 * 	<li>
-		 * 		<js>"binary-spaced"</js> - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
-		 * 		<br>Only valid with type <js>"string"</js>.
-		 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
-		 * 	<li>
-		 * 		<js>"date"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
-		 * 		<br>Only valid with type <js>"string"</js>.
-		 * 	<li>
-		 * 		<js>"date-time"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
-		 * 		<br>Only valid with type <js>"string"</js>.
-		 * 	<li>
-		 * 		<js>"password"</js> - Used to hint UIs the input needs to be obscured.
-		 * 		<br>This format does not affect the serialization or parsing of the parameter.
-		 * 	<li>
-		 * 		<js>"uon"</js> - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
-		 * 		<br>Only valid with type <js>"object"</js>.
-		 * 		<br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
-		 * </ul>
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * <h5 class='section'>See Also:</h5>
-		 * <ul class='doctree'>
-		 * 	<li class='link'><a class='doclink' href='https://swagger.io/specification/v2/#dataTypeFormat'>Swagger specification &gt; Data Type Formats</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder format(String value) {
-			try {
-				if (isNotEmpty(value))
-					format = Format.fromString(value);
-			} catch (Exception e) {
-				throw new ContextRuntimeException("Invalid value ''{0}'' passed in as format value.  Valid values: {1}", value, Format.values());
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>allowEmptyValue</mk> field.
-		 *
-		 * <p>
-		 * Sets the ability to pass empty-valued parameters.
-		 * <br>This is valid only for either query or formData parameters and allows you to send a parameter with a name only or an empty value.
-		 * <br>The default value is <jk>false</jk>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder allowEmptyValue(Boolean value) {
-			if (value != null)
-				allowEmptyValue = value;
-			return this;
-		}
-
-		/**
-		 * <mk>allowEmptyValue</mk> field.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>allowEmptyValue(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder allowEmptyValue() {
-			return allowEmptyValue(true);
-		}
-
-		/**
-		 * <mk>items</mk> field.
-		 *
-		 * <p>
-		 * Describes the type of items in the array.
-		 * <p>
-		 * Required if <code>type</code> is <js>"array"</js>.
-		 * <br>Can only be used if <code>type</code> is <js>"array"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder items(ObjectMap value) {
-			if (value != null && ! value.isEmpty()) {
-				items = HttpPartSchema.create().apply(value);
-				api.put("items", value);
-			}
-			return this;
-		}
-
-		Builder items(Items value) {
-			if (! AnnotationUtils.empty(value)) {
-				items = HttpPartSchema.create().apply(value);
-				api.put("items", items.api);
-			}
-			return this;
-		}
-
-		Builder items(SubItems value) {
-			if (! AnnotationUtils.empty(value)) {
-				items = HttpPartSchema.create().apply(value);
-				api.put("items", items.api);
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>collectionFormat</mk> field.
-		 *
-		 * <p>
-		 * Determines the format of the array if <code>type</code> <js>"array"</js> is used.
-		 * <br>Can only be used if <code>type</code> is <js>"array"</js>.
-		 *
-		 * <br>Possible values are:
-		 * <ul class='spaced-list'>
-		 * 	<li>
-		 * 		<js>"csv"</js> (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
-		 * 	<li>
-		 * 		<js>"ssv"</js> - Space-separated values (e.g. <js>"foo bar"</js>).
-		 * 	<li>
-		 * 		<js>"tsv"</js> - Tab-separated values (e.g. <js>"foo\tbar"</js>).
-		 * 	<li>
-		 * 		<js>"pipes</js> - Pipe-separated values (e.g. <js>"foo|bar"</js>).
-		 * 	<li>
-		 * 		<js>"multi"</js> - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
-		 * 	<li>
-		 * 		<js>"uon"</js> - UON notation (e.g. <js>"@(foo,bar)"</js>).
-		 * 	<li>
-		 * </ul>
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * <p>
-		 * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder collectionFormat(String value) {
-			try {
-				if (isNotEmpty(value))
-					this.collectionFormat = CollectionFormat.fromString(value);
-			} catch (Exception e) {
-				throw new ContextRuntimeException("Invalid value ''{0}'' passed in as collectionFormat value.  Valid values: {1}", value, CollectionFormat.values());
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>default</mk> field.
-		 *
-		 * <p>
-		 * Declares the value of the parameter that the server will use if none is provided, for example a "count" to control the number of results per page might default to 100 if not supplied by the client in the request.
-		 * <br>(Note: "default" has no meaning for required parameters.)
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder _default(String value) {
-			if (isNotEmpty(value))
-				this._default = value;
-			return this;
-		}
-
-		/**
-		 * <mk>maximum</mk> field.
-		 *
-		 * <p>
-		 * Defines the maximum value for a parameter of numeric types.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder maximum(Number value) {
-			if (value != null)
-				this.maximum = value;
-			return this;
-		}
-
-		/**
-		 * <mk>exclusiveMaximum</mk> field.
-		 *
-		 * <p>
-		 * Defines whether the maximum is matched exclusively.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
-		 * <br>If <jk>true</jk>, must be accompanied with <code>maximum</code>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder exclusiveMaximum(Boolean value) {
-			if (value != null)
-				this.exclusiveMaximum = value;
-			return this;
-		}
-
-		/**
-		 * <mk>exclusiveMaximum</mk> field.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>exclusiveMaximum(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder exclusiveMaximum() {
-			return exclusiveMaximum(true);
-		}
-
-		/**
-		 * <mk>minimum</mk> field.
-		 *
-		 * <p>
-		 * Defines the minimum value for a parameter of numeric types.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder minimum(Number value) {
-			if (value != null)
-				this.minimum = value;
-			return this;
-		}
-
-		/**
-		 * <mk>exclusiveMinimum</mk> field.
-		 *
-		 * <p>
-		 * Defines whether the minimum is matched exclusively.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
-		 * <br>If <jk>true</jk>, must be accompanied with <code>minimum</code>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder exclusiveMinimum(Boolean value) {
-			if (value != null)
-				this.exclusiveMinimum = value;
-			return this;
-		}
-
-		/**
-		 * <mk>exclusiveMinimum</mk> field.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>exclusiveMinimum(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder exclusiveMinimum() {
-			return exclusiveMinimum(true);
-		}
-
-		/**
-		 * <mk>maxLength</mk> field.
-		 *
-		 * <p>
-		 * A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
-		 * <br>The length of a string instance is defined as the number of its characters as defined by <a href='https://tools.ietf.org/html/rfc4627'>RFC 4627</a>.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"string"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder maxLength(Long value) {
-			if (value != null)
-				this.maxLength = value;
-			return this;
-		}
-
-		/**
-		 * <mk>minLength</mk> field.
-		 *
-		 * <p>
-		 * A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword.
-		 * <br>The length of a string instance is defined as the number of its characters as defined by <a href='https://tools.ietf.org/html/rfc4627'>RFC 4627</a>.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"string"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder minLength(Long value) {
-			if (value != null)
-				this.minLength = value;
-			return this;
-		}
-
-		/**
-		 * <mk>pattern</mk> field.
-		 *
-		 * <p>
-		 * A string input is valid if it matches the specified regular expression pattern.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"string"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder pattern(String value) {
-			try {
-				if (isNotEmpty(value))
-					this.pattern = Pattern.compile(value);
-			} catch (Exception e) {
-				throw new ContextRuntimeException(e, "Invalid value {0} passed in as pattern value.  Must be a valid regular expression.", value);
-			}
-			return this;
-		}
-
-		/**
-		 * <mk>maxItems</mk> field.
-		 *
-		 * <p>
-		 * An array or collection is valid if its size is less than, or equal to, the value of this keyword.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"array"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder maxItems(Long value) {
-			if (value != null)
-				this.maxItems = value;
-			return this;
-		}
-
-		/**
-		 * <mk>minItems</mk> field.
-		 *
-		 * <p>
-		 * An array or collection is valid if its size is greater than, or equal to, the value of this keyword.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"array"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder minItems(Long value) {
-			if (value != null)
-				this.minItems = value;
-			return this;
-		}
-
-		/**
-		 * <mk>uniqueItems</mk> field.
-		 *
-		 * <p>
-		 * If <jk>true</jk>, the input validates successfully if all of its elements are unique.
-		 *
-		 * <p>
-		 * <br>If the parameter type is a subclass of {@link Set}, this validation is skipped (since a set can only contain unique items anyway).
-		 * <br>Otherwise, the collection or array is checked for duplicate items.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"array"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder uniqueItems(Boolean value) {
-			if (value != null)
-				this.uniqueItems = value;
-			return this;
-		}
-
-		/**
-		 * <mk>uniqueItems</mk> field.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>uniqueItems(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder uniqueItems() {
-			return uniqueItems(true);
-		}
-
-		/**
-		 * Identifies whether an item should be skipped if it's empty.
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder skipIfEmpty(Boolean value) {
-			if (value != null)
-				this.skipIfEmpty = value;
-			return this;
-		}
-
-		/**
-		 * Identifies whether an item should be skipped if it's empty.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>skipIfEmpty(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder skipIfEmpty() {
-			return skipIfEmpty(true);
-		}
-
-		/**
-		 * <mk>enum</mk> field.
-		 *
-		 * <p>
-		 * If specified, the input validates successfully if it is equal to one of the elements in this array.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or an empty set.
-		 * @return This object (for method chaining).
-		 */
-		public Builder _enum(Set<String> value) {
-			if (value != null && ! value.isEmpty())
-				this._enum = value;
-			return this;
-		}
-
-		/**
-		 * <mk>_enum</mk> field.
-		 *
-		 * <p>
-		 * Same as {@link #_enum(Set)} but takes in a var-args array.
-		 *
-		 * @param values
-		 * 	The new values for this property.
-		 * 	<br>Ignored if value is empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder _enum(String...values) {
-			return _enum(new ASet<String>().appendAll(values));
-		}
-
-		/**
-		 * <mk>multipleOf</mk> field.
-		 *
-		 * <p>
-		 * A numeric instance is valid if the result of the division of the instance by this keyword's value is an integer.
-		 *
-		 * <p>
-		 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder multipleOf(Number value) {
-			if (value != null)
-				this.multipleOf = value;
-			return this;
-		}
-
-		/**
-		 * <mk>mapProperties</mk> field.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder maxProperties(Long value) {
-			if (value != null && value != -1)
-				this.maxProperties = value;
-			return this;
-		}
-
-		/**
-		 * <mk>minProperties</mk> field.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder minProperties(Long value) {
-			if (value != null && value != -1)
-				this.minProperties = value;
-			return this;
-		}
-
-		/**
-		 * <mk>properties</mk> field.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk>.
-		 * @return This object (for method chaining).
-		 */
-		public Builder properties(ObjectMap value) {
-			if (value != null && ! value.isEmpty())
-				for (Map.Entry<String,Object> e : value.entrySet())
-					properties.put(e.getKey(), HttpPartSchema.create().apply((ObjectMap)e.getValue()));
-			return this;
-		}
-
-		/**
-		 * <mk>additionalProperties</mk> field.
-		 *
-		 * <p>
-		 * Applicable to the following Swagger schema objects:
-		 * <ul>
-		 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
-		 * </ul>
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or empty.
-		 * @return This object (for method chaining).
-		 */
-		public Builder additionalProperties(ObjectMap value) {
-			if (value != null && ! value.isEmpty())
-				additionalProperties = HttpPartSchema.create().apply(value);
-			return this;
-		}
-
-		/**
-		 * Identifies the part serializer to use for serializing this part.
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or {@link HttpPartSerializer.Null}.
-		 * @return This object (for method chaining).
-		 */
-		public Builder serializer(Class<? extends HttpPartSerializer> value) {
-			if (serializer != null && serializer != HttpPartSerializer.Null.class)
-				serializer = value;
-			return this;
-		}
-
-		/**
-		 * Identifies the part parser to use for parsing this part.
-		 *
-		 * @param value
-		 * 	The new value for this property.
-		 * 	<br>Ignored if value is <jk>null</jk> or {@link HttpPartParser.Null}.
-		 * @return This object (for method chaining).
-		 */
-		public Builder parser(Class<? extends HttpPartParser> value) {
-			if (parser != null && parser != HttpPartParser.Null.class)
-				parser = value;
-			return this;
-		}
-
-		/**
-		 * Disables Swagger schema usage validation checking.
-		 *
-		 * @param value Specify <jk>true</jk> to prevent {@link ContextRuntimeException} from being thrown if invalid Swagger usage was detected.
-		 * @return This object (for method chaining).
-		 */
-		public Builder noValidate(Boolean value) {
-			if (value != null)
-				this.noValidate = value;
-			return this;
-		}
-
-		/**
-		 * Disables Swagger schema usage validation checking.
-		 *
-		 * <p>
-		 * Shortcut for calling <code>noValidate(<jk>true</jk>);</code>.
-		 *
-		 * @return This object (for method chaining).
-		 */
-		public Builder noValidate() {
-			return noValidate(true);
-		}
-	}
-
-	/**
 	 * Valid values for the <code>collectionFormat</code> field.
 	 */
 	public static enum CollectionFormat {
@@ -1926,7 +600,7 @@ public class HttpPartSchema {
 	 * Returns the name of the object described by this schema, for example the query or form parameter name.
 	 *
 	 * @return The name, or <jk>null</jk> if not specified.
-	 * @see Builder#name(String)
+	 * @see HttpPartSchemaBuilder#name(String)
 	 */
 	public String getName() {
 		return name;
@@ -1938,8 +612,8 @@ public class HttpPartSchema {
 	 * @return
 	 * 	The list of HTTP status codes.
 	 * 	<br>Never <jk>null</jk>.
-	 * @see Builder#code(int)
-	 * @see Builder#codes(int[])
+	 * @see HttpPartSchemaBuilder#code(int)
+	 * @see HttpPartSchemaBuilder#codes(int[])
 	 */
 	public Set<Integer> getCodes() {
 		return codes;
@@ -1953,8 +627,8 @@ public class HttpPartSchema {
 	 * 	The list of HTTP status codes.
 	 * 	<br>A singleton set containing the default value if the set is empty.
 	 * 	<br>Never <jk>null</jk>.
-	 * @see Builder#code(int)
-	 * @see Builder#codes(int[])
+	 * @see HttpPartSchemaBuilder#code(int)
+	 * @see HttpPartSchemaBuilder#codes(int[])
 	 */
 	public Set<Integer> getCodes(Integer def) {
 		return codes.isEmpty() ? Collections.singleton(def) : codes;
@@ -1968,8 +642,8 @@ public class HttpPartSchema {
 	 * 	The list of HTTP status codes.
 	 * 	<br>A singleton set containing the default value if the set is empty.
 	 * 	<br>Never <jk>null</jk>.
-	 * @see Builder#code(int)
-	 * @see Builder#codes(int[])
+	 * @see HttpPartSchemaBuilder#code(int)
+	 * @see HttpPartSchemaBuilder#codes(int[])
 	 */
 	public Integer getCode(Integer def) {
 		return codes.isEmpty() ? def : codes.iterator().next();
@@ -1979,7 +653,7 @@ public class HttpPartSchema {
 	 * Returns the <code>type</code> field of this schema.
 	 *
 	 * @return The <code>type</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#type(String)
+	 * @see HttpPartSchemaBuilder#type(String)
 	 */
 	public Type getType() {
 		return type;
@@ -1989,7 +663,7 @@ public class HttpPartSchema {
 	 * Returns the <code>default</code> field of this schema.
 	 *
 	 * @return The default value for this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#_default(String)
+	 * @see HttpPartSchemaBuilder#_default(String)
 	 */
 	public String getDefault() {
 		return _default;
@@ -1999,7 +673,7 @@ public class HttpPartSchema {
 	 * Returns the <code>collectionFormat</code> field of this schema.
 	 *
 	 * @return The <code>collectionFormat</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#collectionFormat(String)
+	 * @see HttpPartSchemaBuilder#collectionFormat(String)
 	 */
 	public CollectionFormat getCollectionFormat() {
 		return collectionFormat;
@@ -2012,7 +686,7 @@ public class HttpPartSchema {
 	 * 	The class meta of the object.
 	 * 	<br>Used to auto-detect the type if the type was not specified.
 	 * @return The format field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#format(String)
+	 * @see HttpPartSchemaBuilder#format(String)
 	 */
 	public Type getType(ClassMeta<?> cm) {
 		if (type != Type.NONE)
@@ -2034,7 +708,7 @@ public class HttpPartSchema {
 	 * Returns the <code>format</code> field of this schema.
 	 *
 	 * @return The <code>format</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#format(String)
+	 * @see HttpPartSchemaBuilder#format(String)
 	 */
 	public Format getFormat() {
 		return format;
@@ -2044,7 +718,7 @@ public class HttpPartSchema {
 	 * Returns the <code>maximum</code> field of this schema.
 	 *
 	 * @return The schema for child items of the object represented by this schema, or <jk>null</jk> if not defined.
-	 * @see Builder#items(ObjectMap)
+	 * @see HttpPartSchemaBuilder#items(HttpPartSchemaBuilder)
 	 */
 	public HttpPartSchema getItems() {
 		return items;
@@ -2054,7 +728,7 @@ public class HttpPartSchema {
 	 * Returns the <code>maximum</code> field of this schema.
 	 *
 	 * @return The <code>maximum</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#maximum(Number)
+	 * @see HttpPartSchemaBuilder#maximum(Number)
 	 */
 	public Number getMaximum() {
 		return maximum;
@@ -2064,7 +738,7 @@ public class HttpPartSchema {
 	 * Returns the <code>minimum</code> field of this schema.
 	 *
 	 * @return The <code>minimum</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#minimum(Number)
+	 * @see HttpPartSchemaBuilder#minimum(Number)
 	 */
 	public Number getMinimum() {
 		return minimum;
@@ -2074,7 +748,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#multipleOf(Number)
+	 * @see HttpPartSchemaBuilder#multipleOf(Number)
 	 */
 	public Number getMultipleOf() {
 		return multipleOf;
@@ -2084,7 +758,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#pattern(String)
+	 * @see HttpPartSchemaBuilder#pattern(String)
 	 */
 	public Pattern getPattern() {
 		return pattern;
@@ -2094,7 +768,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#maxLength(Long)
+	 * @see HttpPartSchemaBuilder#maxLength(Long)
 	 */
 	public Long getMaxLength() {
 		return maxLength;
@@ -2104,7 +778,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#minLength(Long)
+	 * @see HttpPartSchemaBuilder#minLength(Long)
 	 */
 	public Long getMinLength() {
 		return minLength;
@@ -2114,7 +788,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#maxItems(Long)
+	 * @see HttpPartSchemaBuilder#maxItems(Long)
 	 */
 	public Long getMaxItems() {
 		return maxItems;
@@ -2124,7 +798,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#minItems(Long)
+	 * @see HttpPartSchemaBuilder#minItems(Long)
 	 */
 	public Long getMinItems() {
 		return minItems;
@@ -2134,7 +808,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#maxProperties(Long)
+	 * @see HttpPartSchemaBuilder#maxProperties(Long)
 	 */
 	public Long getMaxProperties() {
 		return maxProperties;
@@ -2144,7 +818,7 @@ public class HttpPartSchema {
 	 * Returns the <code>xxx</code> field of this schema.
 	 *
 	 * @return The <code>xxx</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#minProperties(Long)
+	 * @see HttpPartSchemaBuilder#minProperties(Long)
 	 */
 	public Long getMinProperties() {
 		return minProperties;
@@ -2154,7 +828,7 @@ public class HttpPartSchema {
 	 * Returns the <code>exclusiveMaximum</code> field of this schema.
 	 *
 	 * @return The <code>exclusiveMaximum</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#exclusiveMaximum(Boolean)
+	 * @see HttpPartSchemaBuilder#exclusiveMaximum(Boolean)
 	 */
 	public Boolean getExclusiveMaximum() {
 		return exclusiveMaximum;
@@ -2164,7 +838,7 @@ public class HttpPartSchema {
 	 * Returns the <code>exclusiveMinimum</code> field of this schema.
 	 *
 	 * @return The <code>exclusiveMinimum</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#exclusiveMinimum(Boolean)
+	 * @see HttpPartSchemaBuilder#exclusiveMinimum(Boolean)
 	 */
 	public Boolean getExclusiveMinimum() {
 		return exclusiveMinimum;
@@ -2174,7 +848,7 @@ public class HttpPartSchema {
 	 * Returns the <code>uniqueItems</code> field of this schema.
 	 *
 	 * @return The <code>uniqueItems</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#uniqueItems(Boolean)
+	 * @see HttpPartSchemaBuilder#uniqueItems(Boolean)
 	 */
 	public Boolean getUniqueItems() {
 		return uniqueItems;
@@ -2184,7 +858,7 @@ public class HttpPartSchema {
 	 * Returns the <code>required</code> field of this schema.
 	 *
 	 * @return The <code>required</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#required(Boolean)
+	 * @see HttpPartSchemaBuilder#required(Boolean)
 	 */
 	public Boolean getRequired() {
 		return required;
@@ -2194,7 +868,7 @@ public class HttpPartSchema {
 	 * Returns the <code>skipIfEmpty</code> field of this schema.
 	 *
 	 * @return The <code>skipIfEmpty</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#skipIfEmpty(Boolean)
+	 * @see HttpPartSchemaBuilder#skipIfEmpty(Boolean)
 	 */
 	public Boolean getSkipIfEmpty() {
 		return skipIfEmpty;
@@ -2204,7 +878,7 @@ public class HttpPartSchema {
 	 * Returns the <code>enum</code> field of this schema.
 	 *
 	 * @return The <code>enum</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#_enum(Set)
+	 * @see HttpPartSchemaBuilder#_enum(Set)
 	 */
 	public Set<String> getEnum() {
 		return _enum;
@@ -2214,7 +888,7 @@ public class HttpPartSchema {
 	 * Returns the <code>parser</code> field of this schema.
 	 *
 	 * @return The <code>parser</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#parser(Class)
+	 * @see HttpPartSchemaBuilder#parser(Class)
 	 */
 	public Class<? extends HttpPartParser> getParser() {
 		return parser;
@@ -2224,7 +898,7 @@ public class HttpPartSchema {
 	 * Returns the <code>serializer</code> field of this schema.
 	 *
 	 * @return The <code>serializer</code> field of this schema, or <jk>null</jk> if not specified.
-	 * @see Builder#serializer(Class)
+	 * @see HttpPartSchemaBuilder#serializer(Class)
 	 */
 	public Class<? extends HttpPartSerializer> getSerializer() {
 		return serializer;
@@ -2490,16 +1164,16 @@ public class HttpPartSchema {
 		return in == null ? Collections.EMPTY_SET : unmodifiableSet(new LinkedHashSet<>(in));
 	}
 
-	private static Map<String,HttpPartSchema> build(Map<String,Builder> in, boolean noValidate) {
+	private static Map<String,HttpPartSchema> build(Map<String,HttpPartSchemaBuilder> in, boolean noValidate) {
 		if (in == null)
 			return null;
 		Map<String,HttpPartSchema> m = new LinkedHashMap<>();
-		for (Map.Entry<String,Builder> e : in.entrySet())
+		for (Map.Entry<String,HttpPartSchemaBuilder> e : in.entrySet())
 			m.put(e.getKey(), e.getValue().noValidate(noValidate).build());
 		return unmodifiableMap(m);
 	}
 
-	private static HttpPartSchema build(Builder in, boolean noValidate) {
+	private static HttpPartSchema build(HttpPartSchemaBuilder in, boolean noValidate) {
 		return in == null ? null : in.noValidate(noValidate).build();
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
new file mode 100644
index 0000000..37d0a9b
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
@@ -0,0 +1,1360 @@
+// ***************************************************************************************************************************
+// * 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.httppart;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.httppart.HttpPartSchema.*;
+import org.apache.juneau.httppart.HttpPartSchema.Type;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * The builder class for creating {@link HttpPartSchema} objects.
+ *
+ */
+public class HttpPartSchemaBuilder {
+	String name, _default;
+	Set<Integer> codes;
+	Set<String> _enum;
+	Boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
+	CollectionFormat collectionFormat = CollectionFormat.NONE;
+	Type type = Type.NONE;
+	Format format = Format.NONE;
+	Pattern pattern;
+	Number maximum, minimum, multipleOf;
+	Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
+	Map<String,HttpPartSchemaBuilder> properties;
+	HttpPartSchemaBuilder items, additionalProperties;
+	boolean noValidate;
+	ObjectMap api = new ObjectMap();
+	Class<? extends HttpPartParser> parser;
+	Class<? extends HttpPartSerializer> serializer;
+
+	/**
+	 * Instantiates a new {@link HttpPartSchema} object based on the configuration of this builder.
+	 *
+	 * <p>
+	 * This method can be called multiple times to produce new schema objects.
+	 *
+	 * @return
+	 * 	A new {@link HttpPartSchema} object.
+	 * 	<br>Never <jk>null</jk>.
+	 */
+	public HttpPartSchema build() {
+		return new HttpPartSchema(this);
+	}
+
+	HttpPartSchemaBuilder apply(Class<? extends Annotation> c, Method m, int index) {
+		for (Annotation a :  m.getParameterAnnotations()[index])
+			if (c.isInstance(a))
+				return apply(a);
+		apply(c, m.getGenericParameterTypes()[index]);
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
+		if (t instanceof Class<?>)
+			for (Annotation a : ReflectionUtils.findAnnotationsParentFirst(c, (Class<?>)t))
+				apply(a);
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Annotation a) {
+		if (a instanceof Body)
+			apply((Body)a);
+		else if (a instanceof Header)
+			apply((Header)a);
+		else if (a instanceof FormData)
+			apply((FormData)a);
+		else if (a instanceof Query)
+			apply((Query)a);
+		else if (a instanceof Path)
+			apply((Path)a);
+		else if (a instanceof Response)
+			apply((Response)a);
+		else if (a instanceof ResponseHeader)
+			apply((ResponseHeader)a);
+		else if (a instanceof ResponseStatus)
+			apply((ResponseStatus)a);
+		else if (a instanceof HasQuery)
+			apply((HasQuery)a);
+		else if (a instanceof HasFormData)
+			apply((HasFormData)a);
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Body a) {
+		api = AnnotationUtils.merge(api, a);
+		required(HttpPartSchema.toBoolean(a.required()));
+		allowEmptyValue(HttpPartSchema.toBoolean(! a.required()));
+		parser(a.parser());
+		apply(a.schema());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Header a) {
+		api = AnnotationUtils.merge(api, a);
+		name(a.value());
+		name(a.name());
+		required(HttpPartSchema.toBoolean(a.required()));
+		type(a.type());
+		format(a.format());
+		allowEmptyValue(HttpPartSchema.toBoolean(a.allowEmptyValue()));
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		skipIfEmpty(HttpPartSchema.toBoolean(a.skipIfEmpty()));
+		parser(a.parser());
+		serializer(a.serializer());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(ResponseHeader a) {
+		api = AnnotationUtils.merge(api, a);
+		name(a.value());
+		name(a.name());
+		codes(a.code());
+		type(a.type());
+		format(a.format());
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		allowEmptyValue(false);
+		serializer(a.serializer());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(ResponseStatus a) {
+		api = AnnotationUtils.merge(api, a);
+		code(a.value());
+		code(a.code());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(FormData a) {
+		api = AnnotationUtils.merge(api, a);
+		name(a.value());
+		name(a.name());
+		required(HttpPartSchema.toBoolean(a.required()));
+		type(a.type());
+		format(a.format());
+		allowEmptyValue(HttpPartSchema.toBoolean(a.allowEmptyValue()));
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		skipIfEmpty(HttpPartSchema.toBoolean(a.skipIfEmpty()));
+		parser(a.parser());
+		serializer(a.serializer());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Query a) {
+		api = AnnotationUtils.merge(api, a);
+		name(a.value());
+		name(a.name());
+		required(HttpPartSchema.toBoolean(a.required()));
+		type(a.type());
+		format(a.format());
+		allowEmptyValue(HttpPartSchema.toBoolean(a.allowEmptyValue()));
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		skipIfEmpty(HttpPartSchema.toBoolean(a.skipIfEmpty()));
+		parser(a.parser());
+		serializer(a.serializer());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Path a) {
+		api = AnnotationUtils.merge(api, a);
+		name(a.value());
+		name(a.name());
+		type(a.type());
+		format(a.format());
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		parser(a.parser());
+		serializer(a.serializer());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Response a) {
+		api = AnnotationUtils.merge(api, a);
+		codes(a.value());
+		codes(a.code());
+		required(false);
+		allowEmptyValue(true);
+		serializer(a.serializer());
+		apply(a.schema());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Items a) {
+		api = AnnotationUtils.merge(api, a);
+		type(a.type());
+		format(a.format());
+		items(a.items());
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(SubItems a) {
+		api = AnnotationUtils.merge(api, a);
+		type(a.type());
+		format(a.format());
+		items(HttpPartSchema.toObjectMap(a.items()));
+		collectionFormat(a.collectionFormat());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(Schema a) {
+		type(a.type());
+		format(a.format());
+		items(a.items());
+		_default(joinnl(a._default()));
+		maximum(HttpPartSchema.toNumber(a.maximum()));
+		exclusiveMaximum(HttpPartSchema.toBoolean(a.exclusiveMaximum()));
+		minimum(HttpPartSchema.toNumber(a.minimum()));
+		exclusiveMinimum(HttpPartSchema.toBoolean(a.exclusiveMinimum()));
+		maxLength(HttpPartSchema.toLong(a.maxLength()));
+		minLength(HttpPartSchema.toLong(a.minLength()));
+		pattern(a.pattern());
+		maxItems(HttpPartSchema.toLong(a.maxItems()));
+		minItems(HttpPartSchema.toLong(a.minItems()));
+		uniqueItems(HttpPartSchema.toBoolean(a.uniqueItems()));
+		_enum(HttpPartSchema.toSet(a._enum()));
+		multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
+		maxProperties(HttpPartSchema.toLong(a.maxProperties()));
+		minProperties(HttpPartSchema.toLong(a.minProperties()));
+		properties(HttpPartSchema.toObjectMap(a.properties()));
+		additionalProperties(HttpPartSchema.toObjectMap(a.additionalProperties()));
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(HasQuery a) {
+		name(a.value());
+		name(a.name());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(HasFormData a) {
+		name(a.value());
+		name(a.name());
+		return this;
+	}
+
+	HttpPartSchemaBuilder apply(ObjectMap m) {
+		if (m != null && ! m.isEmpty()) {
+			_default(m.getString("default"));
+			_enum(HttpPartSchema.toSet(m.getString("enum")));
+			allowEmptyValue(m.getBoolean("allowEmptyValue"));
+			exclusiveMaximum(m.getBoolean("exclusiveMaximum"));
+			exclusiveMinimum(m.getBoolean("exclusiveMinimum"));
+			required(m.getBoolean("required"));
+			uniqueItems(m.getBoolean("uniqueItems"));
+			collectionFormat(m.getString("collectionFormat"));
+			type(m.getString("type"));
+			format(m.getString("format"));
+			pattern(m.getString("pattern"));
+			maximum(m.get("maximum", Number.class));
+			minimum(m.get("minimum", Number.class));
+			multipleOf(m.get("multipleOf", Number.class));
+			maxItems(m.get("maxItems", Long.class));
+			maxLength(m.get("maxLength", Long.class));
+			maxProperties(m.get("maxProperties", Long.class));
+			minItems(m.get("minItems", Long.class));
+			minLength(m.get("minLength", Long.class));
+			minProperties(m.get("minProperties", Long.class));
+
+			items(m.getObjectMap("items"));
+			properties(m.getObjectMap("properties"));
+			additionalProperties(m.getObjectMap("additionalProperties"));
+
+			apply(m.getObjectMap("schema", null));
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>name</mk> field.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder name(String value) {
+		if (isNotEmpty(value))
+			name = value;
+		return this;
+	}
+
+	/**
+	 * <mk>httpStatusCode</mk> key.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#responsesObject">Responses</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if <jk>null</jk> or an empty array.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder codes(int[] value) {
+		if (value != null && value.length != 0)
+			for (int v : value)
+				code(v);
+		return this;
+	}
+
+	/**
+	 * <mk>httpStatusCode</mk> key.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#responsesObject">Responses</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <code>0</code>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder code(int value) {
+		if (value != 0) {
+			if (codes == null)
+				codes = new TreeSet<>();
+			codes.add(value);
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>required</mk> field.
+	 *
+	 * <p>
+	 * Determines whether the parameter is mandatory.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder required(Boolean value) {
+		if (value != null)
+			required = value;
+		return this;
+	}
+
+	/**
+	 * <mk>required</mk> field.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>required(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder required() {
+		return required(true);
+	}
+
+	/**
+	 * <mk>type</mk> field.
+	 *
+	 * <p>
+	 * The type of the parameter.
+	 *
+	 * <p>
+	 * The possible values are:
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"string"</js>
+	 * 		<br>Parameter must be a string or a POJO convertible from a string.
+	 * 	<li>
+	 * 		<js>"number"</js>
+	 * 		<br>Parameter must be a number primitive or number object.
+	 * 		<br>If parameter is <code>Object</code>, creates either a <code>Float</code> or <code>Double</code> depending on the size of the number.
+	 * 	<li>
+	 * 		<js>"integer"</js>
+	 * 		<br>Parameter must be a integer/long primitive or integer/long object.
+	 * 		<br>If parameter is <code>Object</code>, creates either a <code>Short</code>, <code>Integer</code>, or <code>Long</code> depending on the size of the number.
+	 * 	<li>
+	 * 		<js>"boolean"</js>
+	 * 		<br>Parameter must be a boolean primitive or object.
+	 * 	<li>
+	 * 		<js>"array"</js>
+	 * 		<br>Parameter must be an array or collection.
+	 * 		<br>Elements must be strings or POJOs convertible from strings.
+	 * 		<br>If parameter is <code>Object</code>, creates an {@link ObjectList}.
+	 * 	<li>
+	 * 		<js>"object"</js>
+	 * 		<br>Parameter must be a map or bean.
+	 * 		<br>If parameter is <code>Object</code>, creates an {@link ObjectMap}.
+	 * 		<br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
+	 * 	<li>
+	 * 		<js>"file"</js>
+	 * 		<br>This type is currently not supported.
+	 * </ul>
+	 *
+	 * <p>
+	 * If the type is not specified, it will be auto-detected based on the parameter class type.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#securitySchemeObject">Security Scheme</a>
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='link'><a class='doclink' href='https://swagger.io/specification/#dataTypes'>Swagger specification &gt; Data Types</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder type(String value) {
+		try {
+			if (isNotEmpty(value))
+				type = Type.fromString(value);
+		} catch (Exception e) {
+			throw new ContextRuntimeException("Invalid value ''{0}'' passed in as type value.  Valid values: {1}", value, Type.values());
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>format</mk> field.
+	 *
+	 * <p>
+	 * The extending format for the previously mentioned <a href='https://swagger.io/specification/v2/#parameterType'>type</a>.
+	 *
+	 * <p>
+	 * The possible values are:
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"int32"</js> - Signed 32 bits.
+	 * 		<br>Only valid with type <js>"integer"</js>.
+	 * 	<li>
+	 * 		<js>"int64"</js> - Signed 64 bits.
+	 * 		<br>Only valid with type <js>"integer"</js>.
+	 * 	<li>
+	 * 		<js>"float"</js> - 32-bit floating point number.
+	 * 		<br>Only valid with type <js>"number"</js>.
+	 * 	<li>
+	 * 		<js>"double"</js> - 64-bit floating point number.
+	 * 		<br>Only valid with type <js>"number"</js>.
+	 * 	<li>
+	 * 		<js>"byte"</js> - BASE-64 encoded characters.
+	 * 		<br>Only valid with type <js>"string"</js>.
+	 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
+	 * 	<li>
+	 * 		<js>"binary"</js> - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
+	 * 		<br>Only valid with type <js>"string"</js>.
+	 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
+	 * 	<li>
+	 * 		<js>"binary-spaced"</js> - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
+	 * 		<br>Only valid with type <js>"string"</js>.
+	 * 		<br>Parameters of type POJO convertible from string are converted after the string has been decoded.
+	 * 	<li>
+	 * 		<js>"date"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
+	 * 		<br>Only valid with type <js>"string"</js>.
+	 * 	<li>
+	 * 		<js>"date-time"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
+	 * 		<br>Only valid with type <js>"string"</js>.
+	 * 	<li>
+	 * 		<js>"password"</js> - Used to hint UIs the input needs to be obscured.
+	 * 		<br>This format does not affect the serialization or parsing of the parameter.
+	 * 	<li>
+	 * 		<js>"uon"</js> - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
+	 * 		<br>Only valid with type <js>"object"</js>.
+	 * 		<br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
+	 * </ul>
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul class='doctree'>
+	 * 	<li class='link'><a class='doclink' href='https://swagger.io/specification/v2/#dataTypeFormat'>Swagger specification &gt; Data Type Formats</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder format(String value) {
+		try {
+			if (isNotEmpty(value))
+				format = Format.fromString(value);
+		} catch (Exception e) {
+			throw new ContextRuntimeException("Invalid value ''{0}'' passed in as format value.  Valid values: {1}", value, Format.values());
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>allowEmptyValue</mk> field.
+	 *
+	 * <p>
+	 * Sets the ability to pass empty-valued parameters.
+	 * <br>This is valid only for either query or formData parameters and allows you to send a parameter with a name only or an empty value.
+	 * <br>The default value is <jk>false</jk>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder allowEmptyValue(Boolean value) {
+		if (value != null)
+			allowEmptyValue = value;
+		return this;
+	}
+
+	/**
+	 * <mk>allowEmptyValue</mk> field.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>allowEmptyValue(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder allowEmptyValue() {
+		return allowEmptyValue(true);
+	}
+
+	/**
+	 * <mk>items</mk> field.
+	 *
+	 * <p>
+	 * Describes the type of items in the array.
+	 * <p>
+	 * Required if <code>type</code> is <js>"array"</js>.
+	 * <br>Can only be used if <code>type</code> is <js>"array"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder items(HttpPartSchemaBuilder value) {
+		if (value != null)
+			this.items = value;
+		return this;
+	}
+
+	HttpPartSchemaBuilder items(ObjectMap value) {
+		if (value != null && ! value.isEmpty()) {
+			items = HttpPartSchema.create().apply(value);
+			api.put("items", value);
+		}
+		return this;
+	}
+
+	HttpPartSchemaBuilder items(Items value) {
+		if (! AnnotationUtils.empty(value)) {
+			items = HttpPartSchema.create().apply(value);
+			api.put("items", items.api);
+		}
+		return this;
+	}
+
+	HttpPartSchemaBuilder items(SubItems value) {
+		if (! AnnotationUtils.empty(value)) {
+			items = HttpPartSchema.create().apply(value);
+			api.put("items", items.api);
+		}
+		return this;
+	}
+
+
+	/**
+	 * <mk>collectionFormat</mk> field.
+	 *
+	 * <p>
+	 * Determines the format of the array if <code>type</code> <js>"array"</js> is used.
+	 * <br>Can only be used if <code>type</code> is <js>"array"</js>.
+	 *
+	 * <br>Possible values are:
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"csv"</js> (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
+	 * 	<li>
+	 * 		<js>"ssv"</js> - Space-separated values (e.g. <js>"foo bar"</js>).
+	 * 	<li>
+	 * 		<js>"tsv"</js> - Tab-separated values (e.g. <js>"foo\tbar"</js>).
+	 * 	<li>
+	 * 		<js>"pipes</js> - Pipe-separated values (e.g. <js>"foo|bar"</js>).
+	 * 	<li>
+	 * 		<js>"multi"</js> - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
+	 * 	<li>
+	 * 		<js>"uon"</js> - UON notation (e.g. <js>"@(foo,bar)"</js>).
+	 * 	<li>
+	 * </ul>
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * <p>
+	 * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder collectionFormat(String value) {
+		try {
+			if (isNotEmpty(value))
+				this.collectionFormat = CollectionFormat.fromString(value);
+		} catch (Exception e) {
+			throw new ContextRuntimeException("Invalid value ''{0}'' passed in as collectionFormat value.  Valid values: {1}", value, CollectionFormat.values());
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>default</mk> field.
+	 *
+	 * <p>
+	 * Declares the value of the parameter that the server will use if none is provided, for example a "count" to control the number of results per page might default to 100 if not supplied by the client in the request.
+	 * <br>(Note: "default" has no meaning for required parameters.)
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder _default(String value) {
+		if (isNotEmpty(value))
+			this._default = value;
+		return this;
+	}
+
+	/**
+	 * <mk>maximum</mk> field.
+	 *
+	 * <p>
+	 * Defines the maximum value for a parameter of numeric types.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder maximum(Number value) {
+		if (value != null)
+			this.maximum = value;
+		return this;
+	}
+
+	/**
+	 * <mk>exclusiveMaximum</mk> field.
+	 *
+	 * <p>
+	 * Defines whether the maximum is matched exclusively.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
+	 * <br>If <jk>true</jk>, must be accompanied with <code>maximum</code>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder exclusiveMaximum(Boolean value) {
+		if (value != null)
+			this.exclusiveMaximum = value;
+		return this;
+	}
+
+	/**
+	 * <mk>exclusiveMaximum</mk> field.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>exclusiveMaximum(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder exclusiveMaximum() {
+		return exclusiveMaximum(true);
+	}
+
+	/**
+	 * <mk>minimum</mk> field.
+	 *
+	 * <p>
+	 * Defines the minimum value for a parameter of numeric types.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder minimum(Number value) {
+		if (value != null)
+			this.minimum = value;
+		return this;
+	}
+
+	/**
+	 * <mk>exclusiveMinimum</mk> field.
+	 *
+	 * <p>
+	 * Defines whether the minimum is matched exclusively.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
+	 * <br>If <jk>true</jk>, must be accompanied with <code>minimum</code>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder exclusiveMinimum(Boolean value) {
+		if (value != null)
+			this.exclusiveMinimum = value;
+		return this;
+	}
+
+	/**
+	 * <mk>exclusiveMinimum</mk> field.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>exclusiveMinimum(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder exclusiveMinimum() {
+		return exclusiveMinimum(true);
+	}
+
+	/**
+	 * <mk>maxLength</mk> field.
+	 *
+	 * <p>
+	 * A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
+	 * <br>The length of a string instance is defined as the number of its characters as defined by <a href='https://tools.ietf.org/html/rfc4627'>RFC 4627</a>.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"string"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder maxLength(Long value) {
+		if (value != null)
+			this.maxLength = value;
+		return this;
+	}
+
+	/**
+	 * <mk>minLength</mk> field.
+	 *
+	 * <p>
+	 * A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword.
+	 * <br>The length of a string instance is defined as the number of its characters as defined by <a href='https://tools.ietf.org/html/rfc4627'>RFC 4627</a>.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"string"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder minLength(Long value) {
+		if (value != null)
+			this.minLength = value;
+		return this;
+	}
+
+	/**
+	 * <mk>pattern</mk> field.
+	 *
+	 * <p>
+	 * A string input is valid if it matches the specified regular expression pattern.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"string"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder pattern(String value) {
+		try {
+			if (isNotEmpty(value))
+				this.pattern = Pattern.compile(value);
+		} catch (Exception e) {
+			throw new ContextRuntimeException(e, "Invalid value {0} passed in as pattern value.  Must be a valid regular expression.", value);
+		}
+		return this;
+	}
+
+	/**
+	 * <mk>maxItems</mk> field.
+	 *
+	 * <p>
+	 * An array or collection is valid if its size is less than, or equal to, the value of this keyword.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"array"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder maxItems(Long value) {
+		if (value != null)
+			this.maxItems = value;
+		return this;
+	}
+
+	/**
+	 * <mk>minItems</mk> field.
+	 *
+	 * <p>
+	 * An array or collection is valid if its size is greater than, or equal to, the value of this keyword.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"array"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder minItems(Long value) {
+		if (value != null)
+			this.minItems = value;
+		return this;
+	}
+
+	/**
+	 * <mk>uniqueItems</mk> field.
+	 *
+	 * <p>
+	 * If <jk>true</jk>, the input validates successfully if all of its elements are unique.
+	 *
+	 * <p>
+	 * <br>If the parameter type is a subclass of {@link Set}, this validation is skipped (since a set can only contain unique items anyway).
+	 * <br>Otherwise, the collection or array is checked for duplicate items.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"array"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder uniqueItems(Boolean value) {
+		if (value != null)
+			this.uniqueItems = value;
+		return this;
+	}
+
+	/**
+	 * <mk>uniqueItems</mk> field.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>uniqueItems(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder uniqueItems() {
+		return uniqueItems(true);
+	}
+
+	/**
+	 * Identifies whether an item should be skipped if it's empty.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder skipIfEmpty(Boolean value) {
+		if (value != null)
+			this.skipIfEmpty = value;
+		return this;
+	}
+
+	/**
+	 * Identifies whether an item should be skipped if it's empty.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>skipIfEmpty(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder skipIfEmpty() {
+		return skipIfEmpty(true);
+	}
+
+	/**
+	 * <mk>enum</mk> field.
+	 *
+	 * <p>
+	 * If specified, the input validates successfully if it is equal to one of the elements in this array.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or an empty set.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder _enum(Set<String> value) {
+		if (value != null && ! value.isEmpty())
+			this._enum = value;
+		return this;
+	}
+
+	/**
+	 * <mk>_enum</mk> field.
+	 *
+	 * <p>
+	 * Same as {@link #_enum(Set)} but takes in a var-args array.
+	 *
+	 * @param values
+	 * 	The new values for this property.
+	 * 	<br>Ignored if value is empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder _enum(String...values) {
+		return _enum(new ASet<String>().appendAll(values));
+	}
+
+	/**
+	 * <mk>multipleOf</mk> field.
+	 *
+	 * <p>
+	 * A numeric instance is valid if the result of the division of the instance by this keyword's value is an integer.
+	 *
+	 * <p>
+	 * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#parameterObject">Parameter</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#itemsObject">Items</a>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#headerObject">Header</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder multipleOf(Number value) {
+		if (value != null)
+			this.multipleOf = value;
+		return this;
+	}
+
+	/**
+	 * <mk>mapProperties</mk> field.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder maxProperties(Long value) {
+		if (value != null && value != -1)
+			this.maxProperties = value;
+		return this;
+	}
+
+	/**
+	 * <mk>minProperties</mk> field.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder minProperties(Long value) {
+		if (value != null && value != -1)
+			this.minProperties = value;
+		return this;
+	}
+
+	/**
+	 * <mk>properties</mk> field.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder properties(ObjectMap value) {
+		if (value != null && ! value.isEmpty())
+			for (Map.Entry<String,Object> e : value.entrySet())
+				properties.put(e.getKey(), HttpPartSchema.create().apply((ObjectMap)e.getValue()));
+		return this;
+	}
+
+	/**
+	 * <mk>additionalProperties</mk> field.
+	 *
+	 * <p>
+	 * Applicable to the following Swagger schema objects:
+	 * <ul>
+	 * 	<li><a class="doclink" href="https://swagger.io/specification/v2/#schemaObject">Schema</a>
+	 * </ul>
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or empty.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder additionalProperties(ObjectMap value) {
+		if (value != null && ! value.isEmpty())
+			additionalProperties = HttpPartSchema.create().apply(value);
+		return this;
+	}
+
+	/**
+	 * Identifies the part serializer to use for serializing this part.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or {@link HttpPartSerializer.Null}.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder serializer(Class<? extends HttpPartSerializer> value) {
+		if (serializer != null && serializer != HttpPartSerializer.Null.class)
+			serializer = value;
+		return this;
+	}
+
+	/**
+	 * Identifies the part parser to use for parsing this part.
+	 *
+	 * @param value
+	 * 	The new value for this property.
+	 * 	<br>Ignored if value is <jk>null</jk> or {@link HttpPartParser.Null}.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder parser(Class<? extends HttpPartParser> value) {
+		if (parser != null && parser != HttpPartParser.Null.class)
+			parser = value;
+		return this;
+	}
+
+	/**
+	 * Disables Swagger schema usage validation checking.
+	 *
+	 * @param value Specify <jk>true</jk> to prevent {@link ContextRuntimeException} from being thrown if invalid Swagger usage was detected.
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder noValidate(Boolean value) {
+		if (value != null)
+			this.noValidate = value;
+		return this;
+	}
+
+	/**
+	 * Disables Swagger schema usage validation checking.
+	 *
+	 * <p>
+	 * Shortcut for calling <code>noValidate(<jk>true</jk>);</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpPartSchemaBuilder noValidate() {
+		return noValidate(true);
+	}
+}
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParser.java
index 70e7cc5..8e9bab1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParser.java
@@ -174,6 +174,25 @@ public class OpenApiPartParser extends UonPartParser {
 		return parse(null, schema, in, BeanContext.DEFAULT.getClassMeta(type));
 	}
 
+	/**
+	 * Convenience method for parsing a part to a map or collection.
+	 *
+	 * @param schema
+	 * 	Schema information about the part.
+	 * 	<br>May be <jk>null</jk>.
+	 * 	<br>Not all part parsers use the schema information.
+	 * @param in The input being parsed.
+	 * @param type The category of value being parsed.
+	 * @param args The type arguments of the map or collection.
+	 * @return The parsed value.
+	 * @throws ParseException If a problem occurred while trying to parse the input.
+	 * @throws SchemaValidationParseException If the input or resulting HTTP part object fails schema validation.
+	 */
+	@SuppressWarnings("unchecked")
+	public <T> T parse(HttpPartSchema schema, String in, java.lang.reflect.Type type, java.lang.reflect.Type...args) throws ParseException, SchemaValidationParseException {
+		return (T)parse(null, schema, in, BeanContext.DEFAULT.getClassMeta(type, args));
+	}
+
 	@Override /* HttpPartParser */
 	public <T> T parse(HttpPartType partType, HttpPartSchema schema, String in, ClassMeta<T> type) throws ParseException, SchemaValidationParseException {
 		schema = ObjectUtils.firstNonNull(schema, this.schema, HttpPartSchema.DEFAULT);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateList.java
index e04da5f..7539c94 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateList.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateList.java
@@ -34,7 +34,7 @@ public class DelegateList<T extends Collection<?>> extends ObjectList implements
 	 */
 	public DelegateList(ClassMeta<T> classMeta) {
 		if (classMeta.isArray())
-			classMeta = classMeta.getBeanContext().getClassMeta(List.class, classMeta.getElementType());
+			classMeta = classMeta.getBeanContext().<T>getClassMeta(List.class, classMeta.getElementType());
 		this.classMeta = classMeta;
 	}