001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.httppart;
014
015import static org.apache.juneau.internal.StringUtils.*;
016import static org.apache.juneau.internal.ClassUtils.*;
017
018import java.lang.annotation.*;
019import java.lang.reflect.*;
020import java.util.*;
021import java.util.regex.*;
022
023import org.apache.juneau.*;
024import org.apache.juneau.http.annotation.*;
025import org.apache.juneau.jsonschema.annotation.Schema;
026import org.apache.juneau.jsonschema.annotation.Items;
027import org.apache.juneau.jsonschema.annotation.SubItems;
028import org.apache.juneau.reflect.*;
029import org.apache.juneau.httppart.HttpPartSchema.*;
030import org.apache.juneau.httppart.HttpPartSchema.Type;
031import org.apache.juneau.utils.*;
032
033/**
034 * The builder class for creating {@link HttpPartSchema} objects.
035 *
036 */
037public class HttpPartSchemaBuilder {
038   String name, _default;
039   Set<Integer> codes;
040   Set<String> _enum;
041   Boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
042   CollectionFormat collectionFormat = CollectionFormat.NO_COLLECTION_FORMAT;
043   Type type = Type.NO_TYPE;
044   Format format = Format.NO_FORMAT;
045   Pattern pattern;
046   Number maximum, minimum, multipleOf;
047   Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
048   Map<String,HttpPartSchemaBuilder> properties;
049   HttpPartSchemaBuilder items, additionalProperties;
050   boolean noValidate;
051   Class<? extends HttpPartParser> parser;
052   Class<? extends HttpPartSerializer> serializer;
053
054   /**
055    * Instantiates a new {@link HttpPartSchema} object based on the configuration of this builder.
056    *
057    * <p>
058    * This method can be called multiple times to produce new schema objects.
059    *
060    * @return
061    *    A new {@link HttpPartSchema} object.
062    *    <br>Never <jk>null</jk>.
063    */
064   public HttpPartSchema build() {
065      return new HttpPartSchema(this);
066   }
067
068   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, ParamInfo mpi) {
069      apply(c, mpi.getParameterType().innerType());
070      for (Annotation a : mpi.getDeclaredAnnotations())
071         if (c.isInstance(a))
072            apply(a);
073      return this;
074   }
075
076   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, Method m) {
077      apply(c, m.getGenericReturnType());
078      Annotation a = m.getAnnotation(c);
079      if (a != null)
080         return apply(a);
081      return this;
082   }
083
084   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
085      if (t instanceof Class<?>) {
086         Class<?> tc = (Class<?>)t;
087         ClassInfo ci = getClassInfo(tc);
088         for (Annotation a : ci.getAnnotationsParentFirst(c))
089            apply(a);
090      } else if (Value.isType(t)) {
091         apply(c, Value.getParameterType(t));
092      }
093      return this;
094   }
095
096   /**
097    * Apply the specified annotation to this schema.
098    *
099    * @param a The annotation to apply.
100    * @return This object (for method chaining).
101    */
102   public HttpPartSchemaBuilder apply(Annotation a) {
103      if (a instanceof Body)
104         apply((Body)a);
105      else if (a instanceof Header)
106         apply((Header)a);
107      else if (a instanceof FormData)
108         apply((FormData)a);
109      else if (a instanceof Query)
110         apply((Query)a);
111      else if (a instanceof Path)
112         apply((Path)a);
113      else if (a instanceof Response)
114         apply((Response)a);
115      else if (a instanceof ResponseHeader)
116         apply((ResponseHeader)a);
117      else if (a instanceof HasQuery)
118         apply((HasQuery)a);
119      else if (a instanceof HasFormData)
120         apply((HasFormData)a);
121      else if (a instanceof Schema)
122         apply((Schema)a);
123      else
124         throw new RuntimeException("HttpPartSchemaBuilder.apply(@"+a.getClass().getSimpleName()+") not defined");
125      return this;
126   }
127
128   HttpPartSchemaBuilder apply(Body a) {
129      required(a.required());
130      allowEmptyValue(! a.required());
131      apply(a.schema());
132      return this;
133   }
134
135   HttpPartSchemaBuilder apply(Header a) {
136      name(a.value());
137      name(a.name());
138      required(a.required());
139      type(a.type());
140      format(a.format());
141      allowEmptyValue(a.allowEmptyValue());
142      items(a.items());
143      collectionFormat(a.collectionFormat());
144      _default(a._default().length == 0 ? null : joinnl(a._default()));
145      maximum(HttpPartSchema.toNumber(a.maximum()));
146      exclusiveMaximum(a.exclusiveMaximum());
147      minimum(HttpPartSchema.toNumber(a.minimum()));
148      exclusiveMinimum(a.exclusiveMinimum());
149      maxLength(a.maxLength());
150      minLength(a.minLength());
151      pattern(a.pattern());
152      maxItems(a.maxItems());
153      minItems(a.minItems());
154      uniqueItems(a.uniqueItems());
155      _enum(HttpPartSchema.toSet(a._enum()));
156      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
157      skipIfEmpty(a.skipIfEmpty());
158      parser(a.parser());
159      serializer(a.serializer());
160      return this;
161   }
162
163   HttpPartSchemaBuilder apply(ResponseHeader a) {
164      name(a.value());
165      name(a.name());
166      codes(a.code());
167      type(a.type());
168      format(a.format());
169      items(a.items());
170      collectionFormat(a.collectionFormat());
171      _default(a._default().length == 0 ? null : joinnl(a._default()));
172      maximum(HttpPartSchema.toNumber(a.maximum()));
173      exclusiveMaximum(a.exclusiveMaximum());
174      minimum(HttpPartSchema.toNumber(a.minimum()));
175      exclusiveMinimum(a.exclusiveMinimum());
176      maxLength(a.maxLength());
177      minLength(a.minLength());
178      pattern(a.pattern());
179      maxItems(a.maxItems());
180      minItems(a.minItems());
181      uniqueItems(a.uniqueItems());
182      _enum(HttpPartSchema.toSet(a._enum()));
183      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
184      allowEmptyValue(false);
185      serializer(a.serializer());
186      return this;
187   }
188
189   HttpPartSchemaBuilder apply(FormData a) {
190      name(a.value());
191      name(a.name());
192      required(a.required());
193      type(a.type());
194      format(a.format());
195      allowEmptyValue(a.allowEmptyValue());
196      items(a.items());
197      collectionFormat(a.collectionFormat());
198      _default(a._default().length == 0 ? null : joinnl(a._default()));
199      maximum(HttpPartSchema.toNumber(a.maximum()));
200      exclusiveMaximum(a.exclusiveMaximum());
201      minimum(HttpPartSchema.toNumber(a.minimum()));
202      exclusiveMinimum(a.exclusiveMinimum());
203      maxLength(a.maxLength());
204      minLength(a.minLength());
205      pattern(a.pattern());
206      maxItems(a.maxItems());
207      minItems(a.minItems());
208      uniqueItems(a.uniqueItems());
209      _enum(HttpPartSchema.toSet(a._enum()));
210      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
211      skipIfEmpty(a.skipIfEmpty());
212      parser(a.parser());
213      serializer(a.serializer());
214      return this;
215   }
216
217   HttpPartSchemaBuilder apply(Query a) {
218      name(a.value());
219      name(a.name());
220      required(a.required());
221      type(a.type());
222      format(a.format());
223      allowEmptyValue(a.allowEmptyValue());
224      items(a.items());
225      collectionFormat(a.collectionFormat());
226      _default(a._default().length == 0 ? null : joinnl(a._default()));
227      maximum(HttpPartSchema.toNumber(a.maximum()));
228      exclusiveMaximum(a.exclusiveMaximum());
229      minimum(HttpPartSchema.toNumber(a.minimum()));
230      exclusiveMinimum(a.exclusiveMinimum());
231      maxLength(a.maxLength());
232      minLength(a.minLength());
233      pattern(a.pattern());
234      maxItems(a.maxItems());
235      minItems(a.minItems());
236      uniqueItems(a.uniqueItems());
237      _enum(HttpPartSchema.toSet(a._enum()));
238      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
239      skipIfEmpty(a.skipIfEmpty());
240      parser(a.parser());
241      serializer(a.serializer());
242      return this;
243   }
244
245   HttpPartSchemaBuilder apply(Path a) {
246      name(a.value());
247      name(a.name());
248      type(a.type());
249      format(a.format());
250      items(a.items());
251      allowEmptyValue(a.allowEmptyValue());
252      collectionFormat(a.collectionFormat());
253      maximum(HttpPartSchema.toNumber(a.maximum()));
254      exclusiveMaximum(a.exclusiveMaximum());
255      minimum(HttpPartSchema.toNumber(a.minimum()));
256      exclusiveMinimum(a.exclusiveMinimum());
257      maxLength(a.maxLength());
258      minLength(a.minLength());
259      pattern(a.pattern());
260      maxItems(a.maxItems());
261      minItems(a.minItems());
262      uniqueItems(a.uniqueItems());
263      _enum(HttpPartSchema.toSet(a._enum()));
264      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
265      parser(a.parser());
266      serializer(a.serializer());
267
268      // Path remainder always allows empty value.
269      if (startsWith(name, '/'))
270         allowEmptyValue();
271      else
272         required(true);
273
274      return this;
275   }
276
277   HttpPartSchemaBuilder apply(Response a) {
278      codes(a.value());
279      codes(a.code());
280      required(false);
281      allowEmptyValue(true);
282      serializer(a.partSerializer());
283      parser(a.partParser());
284      apply(a.schema());
285      return this;
286   }
287
288   HttpPartSchemaBuilder apply(Items a) {
289      type(a.type());
290      format(a.format());
291      items(a.items());
292      collectionFormat(a.collectionFormat());
293      _default(a._default().length == 0 ? null : joinnl(a._default()));
294      maximum(HttpPartSchema.toNumber(a.maximum()));
295      exclusiveMaximum(a.exclusiveMaximum());
296      minimum(HttpPartSchema.toNumber(a.minimum()));
297      exclusiveMinimum(a.exclusiveMinimum());
298      maxLength(a.maxLength());
299      minLength(a.minLength());
300      pattern(a.pattern());
301      maxItems(a.maxItems());
302      minItems(a.minItems());
303      uniqueItems(a.uniqueItems());
304      _enum(HttpPartSchema.toSet(a._enum()));
305      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
306      return this;
307   }
308
309   HttpPartSchemaBuilder apply(SubItems a) {
310      type(a.type());
311      format(a.format());
312      items(HttpPartSchema.toObjectMap(a.items()));
313      collectionFormat(a.collectionFormat());
314      _default(a._default().length == 0 ? null : joinnl(a._default()));
315      maximum(HttpPartSchema.toNumber(a.maximum()));
316      exclusiveMaximum(a.exclusiveMaximum());
317      minimum(HttpPartSchema.toNumber(a.minimum()));
318      exclusiveMinimum(a.exclusiveMinimum());
319      maxLength(a.maxLength());
320      minLength(a.minLength());
321      pattern(a.pattern());
322      maxItems(a.maxItems());
323      minItems(a.minItems());
324      uniqueItems(a.uniqueItems());
325      _enum(HttpPartSchema.toSet(a._enum()));
326      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
327      return this;
328   }
329
330   HttpPartSchemaBuilder apply(Schema a) {
331      type(a.type());
332      format(a.format());
333      items(a.items());
334      collectionFormat(a.collectionFormat());
335      _default(a._default().length == 0 ? null : joinnl(a._default()));
336      maximum(HttpPartSchema.toNumber(a.maximum()));
337      exclusiveMaximum(a.exclusiveMaximum());
338      minimum(HttpPartSchema.toNumber(a.minimum()));
339      exclusiveMinimum(a.exclusiveMinimum());
340      maxLength(a.maxLength());
341      minLength(a.minLength());
342      pattern(a.pattern());
343      maxItems(a.maxItems());
344      minItems(a.minItems());
345      uniqueItems(a.uniqueItems());
346      _enum(HttpPartSchema.toSet(a._enum()));
347      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
348      maxProperties(a.maxProperties());
349      minProperties(a.minProperties());
350      properties(HttpPartSchema.toObjectMap(a.properties()));
351      additionalProperties(HttpPartSchema.toObjectMap(a.additionalProperties()));
352      return this;
353   }
354
355   HttpPartSchemaBuilder apply(HasQuery a) {
356      name(a.value());
357      name(a.name());
358      return this;
359   }
360
361   HttpPartSchemaBuilder apply(HasFormData a) {
362      name(a.value());
363      name(a.name());
364      return this;
365   }
366
367   HttpPartSchemaBuilder apply(ObjectMap m) {
368      if (m != null && ! m.isEmpty()) {
369         _default(m.getString("default"));
370         _enum(HttpPartSchema.toSet(m.getString("enum")));
371         allowEmptyValue(m.getBoolean("allowEmptyValue"));
372         exclusiveMaximum(m.getBoolean("exclusiveMaximum"));
373         exclusiveMinimum(m.getBoolean("exclusiveMinimum"));
374         required(m.getBoolean("required"));
375         uniqueItems(m.getBoolean("uniqueItems"));
376         collectionFormat(m.getString("collectionFormat"));
377         type(m.getString("type"));
378         format(m.getString("format"));
379         pattern(m.getString("pattern"));
380         maximum(m.get("maximum", Number.class));
381         minimum(m.get("minimum", Number.class));
382         multipleOf(m.get("multipleOf", Number.class));
383         maxItems(m.get("maxItems", Long.class));
384         maxLength(m.get("maxLength", Long.class));
385         maxProperties(m.get("maxProperties", Long.class));
386         minItems(m.get("minItems", Long.class));
387         minLength(m.get("minLength", Long.class));
388         minProperties(m.get("minProperties", Long.class));
389
390         items(m.getObjectMap("items"));
391         properties(m.getObjectMap("properties"));
392         additionalProperties(m.getObjectMap("additionalProperties"));
393
394         apply(m.getObjectMap("schema", null));
395      }
396      return this;
397   }
398
399   /**
400    * <mk>name</mk> field.
401    *
402    * <p>
403    * Applicable to the following Swagger schema objects:
404    * <ul>
405    *    <li>{@doc SwaggerParameterObject Parameter}
406    *    <li>{@doc SwaggerHeaderObject Header}
407    * </ul>
408    *
409    * @param value
410    *    The new value for this property.
411    * @return This object (for method chaining).
412    */
413   public HttpPartSchemaBuilder name(String value) {
414      if (isNotEmpty(value))
415         name = value;
416      return this;
417   }
418
419   /**
420    * <mk>httpStatusCode</mk> key.
421    *
422    * <p>
423    * Applicable to the following Swagger schema objects:
424    * <ul>
425    *    <li>{@doc SwaggerResponsesObject Responses}
426    * </ul>
427    *
428    * @param value
429    *    The new value for this property.
430    *    <br>Ignored if <jk>null</jk> or an empty array.
431    * @return This object (for method chaining).
432    */
433   public HttpPartSchemaBuilder codes(int[] value) {
434      if (value != null && value.length != 0)
435         for (int v : value)
436            code(v);
437      return this;
438   }
439
440   /**
441    * <mk>httpStatusCode</mk> key.
442    *
443    * <p>
444    * Applicable to the following Swagger schema objects:
445    * <ul>
446    *    <li>{@doc SwaggerResponsesObject Responses}
447    * </ul>
448    *
449    * @param value
450    *    The new value for this property.
451    *    <br>Ignored if value is <c>0</c>.
452    * @return This object (for method chaining).
453    */
454   public HttpPartSchemaBuilder code(int value) {
455      if (value != 0) {
456         if (codes == null)
457            codes = new TreeSet<>();
458         codes.add(value);
459      }
460      return this;
461   }
462
463   /**
464    * <mk>required</mk> field.
465    *
466    * <p>
467    * Determines whether the parameter is mandatory.
468    *
469    * <p>
470    * Applicable to the following Swagger schema objects:
471    * <ul>
472    *    <li>{@doc SwaggerParameterObject Parameter}
473    *    <li>{@doc SwaggerSchemaObject Schema}
474    * </ul>
475    *
476    * @param value
477    *    The new value for this property.
478    *    <br>Ignored if value is <jk>null</jk>.
479    * @return This object (for method chaining).
480    */
481   public HttpPartSchemaBuilder required(Boolean value) {
482      required = resolve(value, required);
483      return this;
484   }
485
486   /**
487    * <mk>required</mk> field.
488    *
489    * <p>
490    * Determines whether the parameter is mandatory.
491    *
492    * <p>
493    * Same as {@link #required(Boolean)} but takes in a boolean value as a string.
494    *
495    * @param value
496    *    The new value for this property.
497    *    <br>Ignored if value is <jk>null</jk> or empty.
498    * @return This object (for method chaining).
499    */
500   public HttpPartSchemaBuilder required(String value) {
501      required = resolve(value, required);
502      return this;
503   }
504
505   /**
506    * <mk>required</mk> field.
507    *
508    * <p>
509    * Shortcut for calling <code>required(<jk>true</jk>);</code>.
510    *
511    * @return This object (for method chaining).
512    */
513   public HttpPartSchemaBuilder required() {
514      return required(true);
515   }
516
517   /**
518    * <mk>type</mk> field.
519    *
520    * <p>
521    * The type of the parameter.
522    *
523    * <p>
524    * The possible values are:
525    * <ul class='spaced-list'>
526    *    <li>
527    *       <js>"string"</js>
528    *       <br>Parameter must be a string or a POJO convertible from a string.
529    *    <li>
530    *       <js>"number"</js>
531    *       <br>Parameter must be a number primitive or number object.
532    *       <br>If parameter is <c>Object</c>, creates either a <c>Float</c> or <c>Double</c> depending on the size of the number.
533    *    <li>
534    *       <js>"integer"</js>
535    *       <br>Parameter must be a integer/long primitive or integer/long object.
536    *       <br>If parameter is <c>Object</c>, creates either a <c>Short</c>, <c>Integer</c>, or <c>Long</c> depending on the size of the number.
537    *    <li>
538    *       <js>"boolean"</js>
539    *       <br>Parameter must be a boolean primitive or object.
540    *    <li>
541    *       <js>"array"</js>
542    *       <br>Parameter must be an array or collection.
543    *       <br>Elements must be strings or POJOs convertible from strings.
544    *       <br>If parameter is <c>Object</c>, creates an {@link ObjectList}.
545    *    <li>
546    *       <js>"object"</js>
547    *       <br>Parameter must be a map or bean.
548    *       <br>If parameter is <c>Object</c>, creates an {@link ObjectMap}.
549    *       <br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
550    *    <li>
551    *       <js>"file"</js>
552    *       <br>This type is currently not supported.
553    * </ul>
554    *
555    * <p>
556    * If the type is not specified, it will be auto-detected based on the parameter class type.
557    *
558    * <p>
559    * Applicable to the following Swagger schema objects:
560    * <ul>
561    *    <li>{@doc SwaggerParameterObject Parameter}
562    *    <li>{@doc SwaggerSchemaObject Schema}
563    *    <li>{@doc SwaggerItemsObject Items}
564    *    <li>{@doc SwaggerSecuritySchemeObject SecurityScheme}
565    * </ul>
566    *
567    * <ul class='seealso'>
568    *    <li class='extlink'>{@doc SwaggerDataTypes}
569    * </ul>
570    *
571    * @param value
572    *    The new value for this property.
573    *    <br>Ignored if value is <jk>null</jk> or empty.
574    * @return This object (for method chaining).
575    */
576   public HttpPartSchemaBuilder type(String value) {
577      try {
578         if (isNotEmpty(value))
579            type = Type.fromString(value);
580      } catch (Exception e) {
581         throw new ContextRuntimeException("Invalid value ''{0}'' passed in as type value.  Valid values: {1}", value, Type.values());
582      }
583      return this;
584   }
585
586   /**
587    * <mk>format</mk> field.
588    *
589    * <p>
590    * The extending format for the previously mentioned {@doc SwaggerParameterTypes parameter type}.
591    *
592    * <p>
593    * The possible values are:
594    * <ul class='spaced-list'>
595    *    <li>
596    *       <js>"int32"</js> - Signed 32 bits.
597    *       <br>Only valid with type <js>"integer"</js>.
598    *    <li>
599    *       <js>"int64"</js> - Signed 64 bits.
600    *       <br>Only valid with type <js>"integer"</js>.
601    *    <li>
602    *       <js>"float"</js> - 32-bit floating point number.
603    *       <br>Only valid with type <js>"number"</js>.
604    *    <li>
605    *       <js>"double"</js> - 64-bit floating point number.
606    *       <br>Only valid with type <js>"number"</js>.
607    *    <li>
608    *       <js>"byte"</js> - BASE-64 encoded characters.
609    *       <br>Only valid with type <js>"string"</js>.
610    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
611    *    <li>
612    *       <js>"binary"</js> - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
613    *       <br>Only valid with type <js>"string"</js>.
614    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
615    *    <li>
616    *       <js>"binary-spaced"</js> - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
617    *       <br>Only valid with type <js>"string"</js>.
618    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
619    *    <li>
620    *       <js>"date"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
621    *       <br>Only valid with type <js>"string"</js>.
622    *    <li>
623    *       <js>"date-time"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
624    *       <br>Only valid with type <js>"string"</js>.
625    *    <li>
626    *       <js>"password"</js> - Used to hint UIs the input needs to be obscured.
627    *       <br>This format does not affect the serialization or parsing of the parameter.
628    *    <li>
629    *       <js>"uon"</js> - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
630    *       <br>Only valid with type <js>"object"</js>.
631    *       <br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
632    * </ul>
633    *
634    * <p>
635    * Applicable to the following Swagger schema objects:
636    * <ul>
637    *    <li>{@doc SwaggerParameterObject Parameter}
638    *    <li>{@doc SwaggerSchemaObject Schema}
639    *    <li>{@doc SwaggerItemsObject Items}
640    *    <li>{@doc SwaggerHeaderObject Header}
641    * </ul>
642    *
643    * <ul class='seealso'>
644    *    <li class='extlink'>{@doc SwaggerDataTypeFormats}
645    * </ul>
646    *
647    * @param value
648    *    The new value for this property.
649    *    <br>Ignored if value is <jk>null</jk> or empty.
650    * @return This object (for method chaining).
651    */
652   public HttpPartSchemaBuilder format(String value) {
653      try {
654         if (isNotEmpty(value))
655            format = Format.fromString(value);
656      } catch (Exception e) {
657         throw new ContextRuntimeException("Invalid value ''{0}'' passed in as format value.  Valid values: {1}", value, Format.values());
658      }
659      return this;
660   }
661
662   /**
663    * <mk>allowEmptyValue</mk> field.
664    *
665    * <p>
666    * Sets the ability to pass empty-valued parameters.
667    * <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.
668    * <br>The default value is <jk>false</jk>.
669    *
670    * <p>
671    * Applicable to the following Swagger schema objects:
672    * <ul>
673    *    <li>{@doc SwaggerParameterObject Parameter}
674    * </ul>
675    *
676    * @param value
677    *    The new value for this property.
678    *    <br>Ignored if value is <jk>null</jk>.
679    * @return This object (for method chaining).
680    */
681   public HttpPartSchemaBuilder allowEmptyValue(Boolean value) {
682      allowEmptyValue = resolve(value, allowEmptyValue);
683      return this;
684   }
685
686   /**
687    * <mk>allowEmptyValue</mk> field.
688    *
689    * <p>
690    * Same as {@link #allowEmptyValue(Boolean)} but takes in a string boolean value.
691    *
692    * @param value
693    *    The new value for this property.
694    *    <br>Ignored if value is <jk>null</jk> or empty.
695    * @return This object (for method chaining).
696    */
697   public HttpPartSchemaBuilder allowEmptyValue(String value) {
698      allowEmptyValue = resolve(value, allowEmptyValue);
699      return this;
700   }
701
702   /**
703    * <mk>allowEmptyValue</mk> field.
704    *
705    * <p>
706    * Shortcut for calling <code>allowEmptyValue(<jk>true</jk>);</code>.
707    *
708    * @return This object (for method chaining).
709    */
710   public HttpPartSchemaBuilder allowEmptyValue() {
711      return allowEmptyValue(true);
712   }
713
714   /**
715    * <mk>items</mk> field.
716    *
717    * <p>
718    * Describes the type of items in the array.
719    * <p>
720    * Required if <c>type</c> is <js>"array"</js>.
721    * <br>Can only be used if <c>type</c> is <js>"array"</js>.
722    *
723    * <p>
724    * Applicable to the following Swagger schema objects:
725    * <ul>
726    *    <li>{@doc SwaggerParameterObject Parameter}
727    *    <li>{@doc SwaggerSchemaObject Schema}
728    *    <li>{@doc SwaggerItemsObject Items}
729    *    <li>{@doc SwaggerHeaderObject Header}
730    * </ul>
731    *
732    * @param value
733    *    The new value for this property.
734    *    <br>Ignored if value is <jk>null</jk> or empty.
735    * @return This object (for method chaining).
736    */
737   public HttpPartSchemaBuilder items(HttpPartSchemaBuilder value) {
738      if (value != null)
739         this.items = value;
740      return this;
741   }
742
743   HttpPartSchemaBuilder items(ObjectMap value) {
744      if (value != null && ! value.isEmpty())
745         items = HttpPartSchema.create().apply(value);
746      return this;
747   }
748
749   HttpPartSchemaBuilder items(Items value) {
750      if (! AnnotationUtils.empty(value))
751         items = HttpPartSchema.create().apply(value);
752      return this;
753   }
754
755   HttpPartSchemaBuilder items(SubItems value) {
756      if (! AnnotationUtils.empty(value))
757         items = HttpPartSchema.create().apply(value);
758      return this;
759   }
760
761
762   /**
763    * <mk>collectionFormat</mk> field.
764    *
765    * <p>
766    * Determines the format of the array if <c>type</c> <js>"array"</js> is used.
767    * <br>Can only be used if <c>type</c> is <js>"array"</js>.
768    *
769    * <br>Possible values are:
770    * <ul class='spaced-list'>
771    *    <li>
772    *       <js>"csv"</js> (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
773    *    <li>
774    *       <js>"ssv"</js> - Space-separated values (e.g. <js>"foo bar"</js>).
775    *    <li>
776    *       <js>"tsv"</js> - Tab-separated values (e.g. <js>"foo\tbar"</js>).
777    *    <li>
778    *       <js>"pipes</js> - Pipe-separated values (e.g. <js>"foo|bar"</js>).
779    *    <li>
780    *       <js>"multi"</js> - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
781    *    <li>
782    *       <js>"uon"</js> - UON notation (e.g. <js>"@(foo,bar)"</js>).
783    *    <li>
784    * </ul>
785    *
786    * <p>
787    * Applicable to the following Swagger schema objects:
788    * <ul>
789    *    <li>{@doc SwaggerParameterObject Parameter}
790    *    <li>{@doc SwaggerItemsObject Items}
791    *    <li>{@doc SwaggerHeaderObject Header}
792    * </ul>
793    *
794    * <p>
795    * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
796    *
797    * @param value
798    *    The new value for this property.
799    *    <br>Ignored if value is <jk>null</jk> or empty.
800    * @return This object (for method chaining).
801    */
802   public HttpPartSchemaBuilder collectionFormat(String value) {
803      try {
804         if (isNotEmpty(value))
805            this.collectionFormat = CollectionFormat.fromString(value);
806      } catch (Exception e) {
807         throw new ContextRuntimeException("Invalid value ''{0}'' passed in as collectionFormat value.  Valid values: {1}", value, CollectionFormat.values());
808      }
809      return this;
810   }
811
812   /**
813    * <mk>default</mk> field.
814    *
815    * <p>
816    * 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.
817    * <br>(Note: "default" has no meaning for required parameters.)
818    *
819    * <p>
820    * Applicable to the following Swagger schema objects:
821    * <ul>
822    *    <li>{@doc SwaggerParameterObject Parameter}
823    *    <li>{@doc SwaggerSchemaObject Schema}
824    *    <li>{@doc SwaggerItemsObject Items}
825    *    <li>{@doc SwaggerHeaderObject Header}
826    * </ul>
827    *
828    * @param value
829    *    The new value for this property.
830    *    <br>Ignored if value is <jk>null</jk>.
831    * @return This object (for method chaining).
832    */
833   public HttpPartSchemaBuilder _default(String value) {
834      if (value != null)
835         this._default = value;
836      return this;
837   }
838
839   /**
840    * <mk>maximum</mk> field.
841    *
842    * <p>
843    * Defines the maximum value for a parameter of numeric types.
844    *
845    * <p>
846    * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
847    *
848    * <p>
849    * Applicable to the following Swagger schema objects:
850    * <ul>
851    *    <li>{@doc SwaggerParameterObject Parameter}
852    *    <li>{@doc SwaggerSchemaObject Schema}
853    *    <li>{@doc SwaggerItemsObject Items}
854    *    <li>{@doc SwaggerHeaderObject Header}
855    * </ul>
856    *
857    * @param value
858    *    The new value for this property.
859    *    <br>Ignored if value is <jk>null</jk>.
860    * @return This object (for method chaining).
861    */
862   public HttpPartSchemaBuilder maximum(Number value) {
863      if (value != null)
864         this.maximum = value;
865      return this;
866   }
867
868   /**
869    * <mk>exclusiveMaximum</mk> field.
870    *
871    * <p>
872    * Defines whether the maximum is matched exclusively.
873    *
874    * <p>
875    * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
876    * <br>If <jk>true</jk>, must be accompanied with <c>maximum</c>.
877    *
878    * <p>
879    * Applicable to the following Swagger schema objects:
880    * <ul>
881    *    <li>{@doc SwaggerParameterObject Parameter}
882    *    <li>{@doc SwaggerSchemaObject Schema}
883    *    <li>{@doc SwaggerItemsObject Items}
884    *    <li>{@doc SwaggerHeaderObject Header}
885    * </ul>
886    *
887    * @param value
888    *    The new value for this property.
889    *    <br>Ignored if value is <jk>null</jk>.
890    * @return This object (for method chaining).
891    */
892   public HttpPartSchemaBuilder exclusiveMaximum(Boolean value) {
893      exclusiveMaximum = resolve(value, exclusiveMaximum);
894      return this;
895   }
896
897   /**
898    * <mk>exclusiveMaximum</mk> field.
899    *
900    * <p>
901    * Same as {@link #exclusiveMaximum(Boolean)} but takes in a string boolean value.
902    *
903    * @param value
904    *    The new value for this property.
905    *    <br>Ignored if value is <jk>null</jk> or empty.
906    * @return This object (for method chaining).
907    */
908   public HttpPartSchemaBuilder exclusiveMaximum(String value) {
909      exclusiveMaximum = resolve(value, exclusiveMaximum);
910      return this;
911   }
912
913   /**
914    * <mk>exclusiveMaximum</mk> field.
915    *
916    * <p>
917    * Shortcut for calling <code>exclusiveMaximum(<jk>true</jk>);</code>.
918    *
919    * @return This object (for method chaining).
920    */
921   public HttpPartSchemaBuilder exclusiveMaximum() {
922      return exclusiveMaximum(true);
923   }
924
925   /**
926    * <mk>minimum</mk> field.
927    *
928    * <p>
929    * Defines the minimum value for a parameter of numeric types.
930    *
931    * <p>
932    * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
933    *
934    * <p>
935    * Applicable to the following Swagger schema objects:
936    * <ul>
937    *    <li>{@doc SwaggerParameterObject Parameter}
938    *    <li>{@doc SwaggerSchemaObject Schema}
939    *    <li>{@doc SwaggerItemsObject Items}
940    *    <li>{@doc SwaggerHeaderObject Header}
941    * </ul>
942    *
943    * @param value
944    *    The new value for this property.
945    *    <br>Ignored if value is <jk>null</jk>.
946    * @return This object (for method chaining).
947    */
948   public HttpPartSchemaBuilder minimum(Number value) {
949      if (value != null)
950         this.minimum = value;
951      return this;
952   }
953
954   /**
955    * <mk>exclusiveMinimum</mk> field.
956    *
957    * <p>
958    * Defines whether the minimum is matched exclusively.
959    *
960    * <p>
961    * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
962    * <br>If <jk>true</jk>, must be accompanied with <c>minimum</c>.
963    *
964    * <p>
965    * Applicable to the following Swagger schema objects:
966    * <ul>
967    *    <li>{@doc SwaggerParameterObject Parameter}
968    *    <li>{@doc SwaggerSchemaObject Schema}
969    *    <li>{@doc SwaggerItemsObject Items}
970    *    <li>{@doc SwaggerHeaderObject Header}
971    * </ul>
972    *
973    * @param value
974    *    The new value for this property.
975    *    <br>Ignored if value is <jk>null</jk>.
976    * @return This object (for method chaining).
977    */
978   public HttpPartSchemaBuilder exclusiveMinimum(Boolean value) {
979      exclusiveMinimum = resolve(value, exclusiveMinimum);
980      return this;
981   }
982
983   /**
984    * <mk>exclusiveMinimum</mk> field.
985    *
986    * <p>
987    * Same as {@link #exclusiveMinimum(Boolean)} but takes in a string boolean value.
988    *
989    * @param value
990    *    The new value for this property.
991    *    <br>Ignored if value is <jk>null</jk> or empty.
992    * @return This object (for method chaining).
993    */
994   public HttpPartSchemaBuilder exclusiveMinimum(String value) {
995      exclusiveMinimum = resolve(value, exclusiveMinimum);
996      return this;
997   }
998
999   /**
1000    * <mk>exclusiveMinimum</mk> field.
1001    *
1002    * <p>
1003    * Shortcut for calling <code>exclusiveMinimum(<jk>true</jk>);</code>.
1004    *
1005    * @return This object (for method chaining).
1006    */
1007   public HttpPartSchemaBuilder exclusiveMinimum() {
1008      return exclusiveMinimum(true);
1009   }
1010
1011   /**
1012    * <mk>maxLength</mk> field.
1013    *
1014    * <p>
1015    * A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
1016    * <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>.
1017    *
1018    * <p>
1019    * Only allowed for the following types: <js>"string"</js>.
1020    *
1021    * <p>
1022    * Applicable to the following Swagger schema objects:
1023    * <ul>
1024    *    <li>{@doc SwaggerParameterObject Parameter}
1025    *    <li>{@doc SwaggerSchemaObject Schema}
1026    *    <li>{@doc SwaggerItemsObject Items}
1027    *    <li>{@doc SwaggerHeaderObject Header}
1028    * </ul>
1029    *
1030    * @param value
1031    *    The new value for this property.
1032    *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
1033    * @return This object (for method chaining).
1034    */
1035   public HttpPartSchemaBuilder maxLength(Long value) {
1036      maxLength = resolve(value, maxLength);
1037      return this;
1038   }
1039
1040   /**
1041    * <mk>maxLength</mk> field.
1042    *
1043    * <p>
1044    * Same as {@link #maxLength(Long)} but takes in a string number.
1045    *
1046    * @param value
1047    *    The new value for this property.
1048    *    <br>Ignored if value is <jk>null</jk> or empty.
1049    * @return This object (for method chaining).
1050    */
1051   public HttpPartSchemaBuilder maxLength(String value) {
1052      maxLength = resolve(value, maxLength);
1053      return this;
1054   }
1055
1056   /**
1057    * <mk>minLength</mk> field.
1058    *
1059    * <p>
1060    * A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword.
1061    * <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>.
1062    *
1063    * <p>
1064    * Only allowed for the following types: <js>"string"</js>.
1065    *
1066    * <p>
1067    * Applicable to the following Swagger schema objects:
1068    * <ul>
1069    *    <li>{@doc SwaggerParameterObject Parameter}
1070    *    <li>{@doc SwaggerSchemaObject Schema}
1071    *    <li>{@doc SwaggerItemsObject Items}
1072    *    <li>{@doc SwaggerHeaderObject Header}
1073    * </ul>
1074    *
1075    * @param value
1076    *    The new value for this property.
1077    *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
1078    * @return This object (for method chaining).
1079    */
1080   public HttpPartSchemaBuilder minLength(Long value) {
1081      minLength = resolve(value, minLength);
1082      return this;
1083   }
1084
1085   /**
1086    * <mk>minLength</mk> field.
1087    *
1088    * <p>
1089    * Same as {@link #minLength(Long)} but takes in a string number.
1090    *
1091    * @param value
1092    *    The new value for this property.
1093    *    <br>Ignored if value is <jk>null</jk> or empty.
1094    * @return This object (for method chaining).
1095    */
1096   public HttpPartSchemaBuilder minLength(String value) {
1097      minLength = resolve(value, minLength);
1098      return this;
1099   }
1100
1101   /**
1102    * <mk>pattern</mk> field.
1103    *
1104    * <p>
1105    * A string input is valid if it matches the specified regular expression pattern.
1106    *
1107    * <p>
1108    * Only allowed for the following types: <js>"string"</js>.
1109    *
1110    * <p>
1111    * Applicable to the following Swagger schema objects:
1112    * <ul>
1113    *    <li>{@doc SwaggerParameterObject Parameter}
1114    *    <li>{@doc SwaggerSchemaObject Schema}
1115    *    <li>{@doc SwaggerItemsObject Items}
1116    *    <li>{@doc SwaggerHeaderObject Header}
1117    * </ul>
1118    *
1119    * @param value
1120    *    The new value for this property.
1121    *    <br>Ignored if value is <jk>null</jk> or empty.
1122    * @return This object (for method chaining).
1123    */
1124   public HttpPartSchemaBuilder pattern(String value) {
1125      try {
1126         if (isNotEmpty(value))
1127            this.pattern = Pattern.compile(value);
1128      } catch (Exception e) {
1129         throw new ContextRuntimeException(e, "Invalid value {0} passed in as pattern value.  Must be a valid regular expression.", value);
1130      }
1131      return this;
1132   }
1133
1134   /**
1135    * <mk>maxItems</mk> field.
1136    *
1137    * <p>
1138    * An array or collection is valid if its size is less than, or equal to, the value of this keyword.
1139    *
1140    * <p>
1141    * Only allowed for the following types: <js>"array"</js>.
1142    *
1143    * <p>
1144    * Applicable to the following Swagger schema objects:
1145    * <ul>
1146    *    <li>{@doc SwaggerParameterObject Parameter}
1147    *    <li>{@doc SwaggerSchemaObject Schema}
1148    *    <li>{@doc SwaggerItemsObject Items}
1149    *    <li>{@doc SwaggerHeaderObject Header}
1150    * </ul>
1151    *
1152    * @param value
1153    *    The new value for this property.
1154    *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
1155    * @return This object (for method chaining).
1156    */
1157   public HttpPartSchemaBuilder maxItems(Long value) {
1158      maxItems = resolve(value, maxItems);
1159      return this;
1160   }
1161
1162   /**
1163    * <mk>maxItems</mk> field.
1164    *
1165    * <p>
1166    * Same as {@link #maxItems(Long)} but takes in a string number.
1167    *
1168    * @param value
1169    *    The new value for this property.
1170    *    <br>Ignored if value is <jk>null</jk> or empty.
1171    * @return This object (for method chaining).
1172    */
1173   public HttpPartSchemaBuilder maxItems(String value) {
1174      maxItems = resolve(value, maxItems);
1175      return this;
1176   }
1177
1178   /**
1179    * <mk>minItems</mk> field.
1180    *
1181    * <p>
1182    * An array or collection is valid if its size is greater than, or equal to, the value of this keyword.
1183    *
1184    * <p>
1185    * Only allowed for the following types: <js>"array"</js>.
1186    *
1187    * <p>
1188    * Applicable to the following Swagger schema objects:
1189    * <ul>
1190    *    <li>{@doc SwaggerParameterObject Parameter}
1191    *    <li>{@doc SwaggerSchemaObject Schema}
1192    *    <li>{@doc SwaggerItemsObject Items}
1193    *    <li>{@doc SwaggerHeaderObject Header}
1194    * </ul>
1195    *
1196    * @param value
1197    *    The new value for this property.
1198    *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
1199    * @return This object (for method chaining).
1200    */
1201   public HttpPartSchemaBuilder minItems(Long value) {
1202      minItems = resolve(value, minItems);
1203      return this;
1204   }
1205
1206   /**
1207    * <mk>minItems</mk> field.
1208    *
1209    * <p>
1210    * Same as {@link #minItems(Long)} but takes in a string number.
1211    *
1212    * @param value
1213    *    The new value for this property.
1214    *    <br>Ignored if value is <jk>null</jk> or empty.
1215    * @return This object (for method chaining).
1216    */
1217   public HttpPartSchemaBuilder minItems(String value) {
1218      minItems = resolve(value, minItems);
1219      return this;
1220   }
1221
1222   /**
1223    * <mk>uniqueItems</mk> field.
1224    *
1225    * <p>
1226    * If <jk>true</jk>, the input validates successfully if all of its elements are unique.
1227    *
1228    * <p>
1229    * <br>If the parameter type is a subclass of {@link Set}, this validation is skipped (since a set can only contain unique items anyway).
1230    * <br>Otherwise, the collection or array is checked for duplicate items.
1231    *
1232    * <p>
1233    * Only allowed for the following types: <js>"array"</js>.
1234    *
1235    * <p>
1236    * Applicable to the following Swagger schema objects:
1237    * <ul>
1238    *    <li>{@doc SwaggerParameterObject Parameter}
1239    *    <li>{@doc SwaggerSchemaObject Schema}
1240    *    <li>{@doc SwaggerItemsObject Items}
1241    *    <li>{@doc SwaggerHeaderObject Header}
1242    * </ul>
1243    *
1244    * @param value
1245    *    The new value for this property.
1246    *    <br>Ignored if value is <jk>null</jk>.
1247    * @return This object (for method chaining).
1248    */
1249   public HttpPartSchemaBuilder uniqueItems(Boolean value) {
1250      uniqueItems = resolve(value, uniqueItems);
1251      return this;
1252   }
1253
1254   /**
1255    * <mk>uniqueItems</mk> field.
1256    *
1257    * <p>
1258    * Same as {@link #uniqueItems(Boolean)} but takes in a string boolean.
1259    *
1260    * @param value
1261    *    The new value for this property.
1262    *    <br>Ignored if value is <jk>null</jk> or empty..
1263    * @return This object (for method chaining).
1264    */
1265   public HttpPartSchemaBuilder uniqueItems(String value) {
1266      uniqueItems = resolve(value, uniqueItems);
1267      return this;
1268   }
1269
1270   /**
1271    * <mk>uniqueItems</mk> field.
1272    *
1273    * <p>
1274    * Shortcut for calling <code>uniqueItems(<jk>true</jk>);</code>.
1275    *
1276    * @return This object (for method chaining).
1277    */
1278   public HttpPartSchemaBuilder uniqueItems() {
1279      return uniqueItems(true);
1280   }
1281
1282   /**
1283    * <mk>skipIfEmpty</mk> field.
1284    *
1285    * <p>
1286    * Identifies whether an item should be skipped during serialization if it's empty.
1287    *
1288    * @param value
1289    *    The new value for this property.
1290    *    <br>Ignored if value is <jk>null</jk>.
1291    * @return This object (for method chaining).
1292    */
1293   public HttpPartSchemaBuilder skipIfEmpty(Boolean value) {
1294      skipIfEmpty = resolve(value, skipIfEmpty);
1295      return this;
1296   }
1297
1298   /**
1299    * <mk>skipIfEmpty</mk> field.
1300    *
1301    * <p>
1302    * Same as {@link #skipIfEmpty(Boolean)} but takes in a string boolean.
1303    *
1304    * @param value
1305    *    The new value for this property.
1306    *    <br>Ignored if value is <jk>null</jk> or empty.
1307    * @return This object (for method chaining).
1308    */
1309   public HttpPartSchemaBuilder skipIfEmpty(String value) {
1310      skipIfEmpty = resolve(value, skipIfEmpty);
1311      return this;
1312   }
1313
1314   /**
1315    * Identifies whether an item should be skipped if it's empty.
1316    *
1317    * <p>
1318    * Shortcut for calling <code>skipIfEmpty(<jk>true</jk>);</code>.
1319    *
1320    * @return This object (for method chaining).
1321    */
1322   public HttpPartSchemaBuilder skipIfEmpty() {
1323      return skipIfEmpty(true);
1324   }
1325
1326   /**
1327    * <mk>enum</mk> field.
1328    *
1329    * <p>
1330    * If specified, the input validates successfully if it is equal to one of the elements in this array.
1331    *
1332    * <p>
1333    * Applicable to the following Swagger schema objects:
1334    * <ul>
1335    *    <li>{@doc SwaggerParameterObject Parameter}
1336    *    <li>{@doc SwaggerSchemaObject Schema}
1337    *    <li>{@doc SwaggerItemsObject Items}
1338    *    <li>{@doc SwaggerHeaderObject Header}
1339    * </ul>
1340    *
1341    * @param value
1342    *    The new value for this property.
1343    *    <br>Ignored if value is <jk>null</jk> or an empty set.
1344    * @return This object (for method chaining).
1345    */
1346   public HttpPartSchemaBuilder _enum(Set<String> value) {
1347      if (value != null && ! value.isEmpty())
1348         this._enum = value;
1349      return this;
1350   }
1351
1352   /**
1353    * <mk>_enum</mk> field.
1354    *
1355    * <p>
1356    * Same as {@link #_enum(Set)} but takes in a var-args array.
1357    *
1358    * @param values
1359    *    The new values for this property.
1360    *    <br>Ignored if value is empty.
1361    * @return This object (for method chaining).
1362    */
1363   public HttpPartSchemaBuilder _enum(String...values) {
1364      return _enum(new ASet<String>().appendAll(values));
1365   }
1366
1367   /**
1368    * <mk>multipleOf</mk> field.
1369    *
1370    * <p>
1371    * A numeric instance is valid if the result of the division of the instance by this keyword's value is an integer.
1372    *
1373    * <p>
1374    * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
1375    *
1376    * <p>
1377    * Applicable to the following Swagger schema objects:
1378    * <ul>
1379    *    <li>{@doc SwaggerParameterObject Parameter}
1380    *    <li>{@doc SwaggerSchemaObject Schema}
1381    *    <li>{@doc SwaggerItemsObject Items}
1382    *    <li>{@doc SwaggerHeaderObject Header}
1383    * </ul>
1384    *
1385    * @param value
1386    *    The new value for this property.
1387    *    <br>Ignored if value is <jk>null</jk>.
1388    * @return This object (for method chaining).
1389    */
1390   public HttpPartSchemaBuilder multipleOf(Number value) {
1391      if (value != null)
1392         this.multipleOf = value;
1393      return this;
1394   }
1395
1396   /**
1397    * <mk>mapProperties</mk> field.
1398    *
1399    * <p>
1400    * Applicable to the following Swagger schema objects:
1401    * <ul>
1402    *    <li>{@doc SwaggerSchemaObject Schema}
1403    * </ul>
1404    *
1405    * @param value
1406    *    The new value for this property.
1407    *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
1408    * @return This object (for method chaining).
1409    */
1410   public HttpPartSchemaBuilder maxProperties(Long value) {
1411      maxProperties = resolve(value, maxProperties);
1412      return this;
1413   }
1414
1415   /**
1416    * <mk>mapProperties</mk> field.
1417    *
1418    * <p>
1419    * Same as {@link #maxProperties(Long)} but takes in a string number.
1420    *
1421    * @param value
1422    *    The new value for this property.
1423    *    <br>Ignored if value is <jk>null</jk> or empty.
1424    * @return This object (for method chaining).
1425    */
1426   public HttpPartSchemaBuilder maxProperties(String value) {
1427      maxProperties = resolve(value, maxProperties);
1428      return this;
1429   }
1430
1431   /**
1432    * <mk>minProperties</mk> field.
1433    *
1434    * <p>
1435    * Applicable to the following Swagger schema objects:
1436    * <ul>
1437    *    <li>{@doc SwaggerSchemaObject Schema}
1438    * </ul>
1439    *
1440    * @param value
1441    *    The new value for this property.
1442    *    <br>Ignored if value is <jk>null</jk>.
1443    * @return This object (for method chaining).
1444    */
1445   public HttpPartSchemaBuilder minProperties(Long value) {
1446      minProperties = resolve(value, minProperties);
1447      return this;
1448   }
1449
1450   /**
1451    * <mk>minProperties</mk> field.
1452    *
1453    * <p>
1454    * Same as {@link #minProperties(Long)} but takes in a string boolean.
1455    *
1456    * @param value
1457    *    The new value for this property.
1458    *    <br>Ignored if value is <jk>null</jk> or empty.
1459    * @return This object (for method chaining).
1460    */
1461   public HttpPartSchemaBuilder minProperties(String value) {
1462      minProperties = resolve(value, minProperties);
1463      return this;
1464   }
1465
1466   /**
1467    * <mk>properties</mk> field.
1468    *
1469    * <p>
1470    * Applicable to the following Swagger schema objects:
1471    * <ul>
1472    *    <li>{@doc SwaggerSchemaObject Schema}
1473    * </ul>
1474    *
1475    * @param key
1476    * The property name.
1477    * @param value
1478    *    The new value for this property.
1479    *    <br>Ignored if value is <jk>null</jk>.
1480    * @return This object (for method chaining).
1481    */
1482   public HttpPartSchemaBuilder property(String key, HttpPartSchemaBuilder value) {
1483      if ( key != null && value != null) {
1484         if (properties == null)
1485            properties = new LinkedHashMap<>();
1486         properties.put(key, value);
1487      }
1488      return this;
1489   }
1490
1491   private HttpPartSchemaBuilder properties(ObjectMap value) {
1492      if (value != null && ! value.isEmpty())
1493      for (Map.Entry<String,Object> e : value.entrySet())
1494         property(e.getKey(), HttpPartSchema.create().apply((ObjectMap)e.getValue()));
1495      return this;
1496   }
1497
1498   /**
1499    * <mk>additionalProperties</mk> field.
1500    *
1501    * <p>
1502    * Applicable to the following Swagger schema objects:
1503    * <ul>
1504    *    <li>{@doc SwaggerSchemaObject Schema}
1505    * </ul>
1506    *
1507    * @param value
1508    *    The new value for this property.
1509    *    <br>Ignored if value is <jk>null</jk> or empty.
1510    * @return This object (for method chaining).
1511    */
1512   public HttpPartSchemaBuilder additionalProperties(HttpPartSchemaBuilder value) {
1513      if (value != null)
1514         additionalProperties = value;
1515      return this;
1516   }
1517
1518   private HttpPartSchemaBuilder additionalProperties(ObjectMap value) {
1519      if (value != null && ! value.isEmpty())
1520         additionalProperties = HttpPartSchema.create().apply(value);
1521      return this;
1522   }
1523
1524   /**
1525    * Identifies the part serializer to use for serializing this part.
1526    *
1527    * @param value
1528    *    The new value for this property.
1529    *    <br>Ignored if value is <jk>null</jk> or {@link HttpPartSerializer.Null}.
1530    * @return This object (for method chaining).
1531    */
1532   public HttpPartSchemaBuilder serializer(Class<? extends HttpPartSerializer> value) {
1533      if (value != null && value != HttpPartSerializer.Null.class)
1534         serializer = value;
1535      return this;
1536   }
1537
1538   /**
1539    * Identifies the part parser to use for parsing this part.
1540    *
1541    * @param value
1542    *    The new value for this property.
1543    *    <br>Ignored if value is <jk>null</jk> or {@link HttpPartParser.Null}.
1544    * @return This object (for method chaining).
1545    */
1546   public HttpPartSchemaBuilder parser(Class<? extends HttpPartParser> value) {
1547      if (value != null && value != HttpPartParser.Null.class)
1548         parser = value;
1549      return this;
1550   }
1551
1552   /**
1553    * Disables Swagger schema usage validation checking.
1554    *
1555    * @param value Specify <jk>true</jk> to prevent {@link ContextRuntimeException} from being thrown if invalid Swagger usage was detected.
1556    * @return This object (for method chaining).
1557    */
1558   public HttpPartSchemaBuilder noValidate(Boolean value) {
1559      if (value != null)
1560         this.noValidate = value;
1561      return this;
1562   }
1563
1564   /**
1565    * Disables Swagger schema usage validation checking.
1566    *
1567    * <p>
1568    * Shortcut for calling <code>noValidate(<jk>true</jk>);</code>.
1569    *
1570    * @return This object (for method chaining).
1571    */
1572   public HttpPartSchemaBuilder noValidate() {
1573      return noValidate(true);
1574   }
1575
1576   private Boolean resolve(String newValue, Boolean oldValue) {
1577      return isEmpty(newValue) ? oldValue : Boolean.valueOf(newValue);
1578   }
1579
1580   private Boolean resolve(Boolean newValue, Boolean oldValue) {
1581      return newValue == null ? oldValue : newValue;
1582   }
1583
1584   private Long resolve(String newValue, Long oldValue) {
1585      return isEmpty(newValue) ? oldValue : Long.parseLong(newValue);
1586   }
1587
1588   private Long resolve(Long newValue, Long oldValue) {
1589      return (newValue == null || newValue == -1) ? oldValue : newValue;
1590   }
1591}