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 <jamesbog...@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 > 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 > 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&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 > 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 > 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&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; }