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.*;
016
017import java.lang.annotation.*;
018import java.lang.reflect.*;
019import java.util.*;
020import java.util.regex.*;
021
022import org.apache.juneau.*;
023import org.apache.juneau.http.annotation.*;
024import org.apache.juneau.jsonschema.annotation.Schema;
025import org.apache.juneau.jsonschema.annotation.Items;
026import org.apache.juneau.jsonschema.annotation.SubItems;
027import org.apache.juneau.httppart.HttpPartSchema.*;
028import org.apache.juneau.httppart.HttpPartSchema.Type;
029import org.apache.juneau.internal.*;
030import org.apache.juneau.utils.*;
031
032/**
033 * The builder class for creating {@link HttpPartSchema} objects.
034 *
035 */
036public class HttpPartSchemaBuilder {
037   String name, _default;
038   Set<Integer> codes;
039   Set<String> _enum;
040   Boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
041   CollectionFormat collectionFormat = CollectionFormat.NO_COLLECTION_FORMAT;
042   Type type = Type.NO_TYPE;
043   Format format = Format.NO_FORMAT;
044   Pattern pattern;
045   Number maximum, minimum, multipleOf;
046   Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
047   Map<String,HttpPartSchemaBuilder> properties;
048   HttpPartSchemaBuilder items, additionalProperties;
049   boolean noValidate;
050   Class<? extends HttpPartParser> parser;
051   Class<? extends HttpPartSerializer> serializer;
052
053   /**
054    * Instantiates a new {@link HttpPartSchema} object based on the configuration of this builder.
055    *
056    * <p>
057    * This method can be called multiple times to produce new schema objects.
058    *
059    * @return
060    *    A new {@link HttpPartSchema} object.
061    *    <br>Never <jk>null</jk>.
062    */
063   public HttpPartSchema build() {
064      return new HttpPartSchema(this);
065   }
066
067   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, Method m, int index) {
068      apply(c, m.getGenericParameterTypes()[index]);
069      for (Annotation a :  m.getParameterAnnotations()[index])
070         if (c.isInstance(a))
071            apply(a);
072      return this;
073   }
074
075   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, Method m) {
076      apply(c, m.getGenericReturnType());
077      Annotation a = m.getAnnotation(c);
078      if (a != null)
079         return apply(a);
080      return this;
081   }
082
083   HttpPartSchemaBuilder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
084      if (t instanceof Class<?>) {
085         Class<?> tc = (Class<?>)t;
086         for (Annotation a : ClassUtils.getAnnotationsParentFirst(c, tc))
087            apply(a);
088      } else if (Value.isType(t)) {
089         apply(c, Value.getParameterType(t));
090      }
091      return this;
092   }
093
094   /**
095    * Apply the specified annotation to this schema.
096    *
097    * @param a The annotation to apply.
098    * @return This object (for method chaining).
099    */
100   public HttpPartSchemaBuilder apply(Annotation a) {
101      if (a instanceof Body)
102         apply((Body)a);
103      else if (a instanceof Header)
104         apply((Header)a);
105      else if (a instanceof FormData)
106         apply((FormData)a);
107      else if (a instanceof Query)
108         apply((Query)a);
109      else if (a instanceof Path)
110         apply((Path)a);
111      else if (a instanceof Response)
112         apply((Response)a);
113      else if (a instanceof ResponseHeader)
114         apply((ResponseHeader)a);
115      else if (a instanceof HasQuery)
116         apply((HasQuery)a);
117      else if (a instanceof HasFormData)
118         apply((HasFormData)a);
119      else if (a instanceof Schema)
120         apply((Schema)a);
121      else
122         throw new RuntimeException("HttpPartSchemaBuilder.apply(@"+a.getClass().getSimpleName()+") not defined");
123      return this;
124   }
125
126   HttpPartSchemaBuilder apply(Body a) {
127      required(a.required());
128      allowEmptyValue(! a.required());
129      apply(a.schema());
130      return this;
131   }
132
133   HttpPartSchemaBuilder apply(Header a) {
134      name(a.value());
135      name(a.name());
136      required(a.required());
137      type(a.type());
138      format(a.format());
139      allowEmptyValue(a.allowEmptyValue());
140      items(a.items());
141      collectionFormat(a.collectionFormat());
142      _default(a._default().length == 0 ? null : joinnl(a._default()));
143      maximum(HttpPartSchema.toNumber(a.maximum()));
144      exclusiveMaximum(a.exclusiveMaximum());
145      minimum(HttpPartSchema.toNumber(a.minimum()));
146      exclusiveMinimum(a.exclusiveMinimum());
147      maxLength(a.maxLength());
148      minLength(a.minLength());
149      pattern(a.pattern());
150      maxItems(a.maxItems());
151      minItems(a.minItems());
152      uniqueItems(a.uniqueItems());
153      _enum(HttpPartSchema.toSet(a._enum()));
154      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
155      skipIfEmpty(a.skipIfEmpty());
156      parser(a.parser());
157      serializer(a.serializer());
158      return this;
159   }
160
161   HttpPartSchemaBuilder apply(ResponseHeader a) {
162      name(a.value());
163      name(a.name());
164      codes(a.code());
165      type(a.type());
166      format(a.format());
167      items(a.items());
168      collectionFormat(a.collectionFormat());
169      _default(a._default().length == 0 ? null : joinnl(a._default()));
170      maximum(HttpPartSchema.toNumber(a.maximum()));
171      exclusiveMaximum(a.exclusiveMaximum());
172      minimum(HttpPartSchema.toNumber(a.minimum()));
173      exclusiveMinimum(a.exclusiveMinimum());
174      maxLength(a.maxLength());
175      minLength(a.minLength());
176      pattern(a.pattern());
177      maxItems(a.maxItems());
178      minItems(a.minItems());
179      uniqueItems(a.uniqueItems());
180      _enum(HttpPartSchema.toSet(a._enum()));
181      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
182      allowEmptyValue(false);
183      serializer(a.serializer());
184      return this;
185   }
186
187   HttpPartSchemaBuilder apply(FormData a) {
188      name(a.value());
189      name(a.name());
190      required(a.required());
191      type(a.type());
192      format(a.format());
193      allowEmptyValue(a.allowEmptyValue());
194      items(a.items());
195      collectionFormat(a.collectionFormat());
196      _default(a._default().length == 0 ? null : joinnl(a._default()));
197      maximum(HttpPartSchema.toNumber(a.maximum()));
198      exclusiveMaximum(a.exclusiveMaximum());
199      minimum(HttpPartSchema.toNumber(a.minimum()));
200      exclusiveMinimum(a.exclusiveMinimum());
201      maxLength(a.maxLength());
202      minLength(a.minLength());
203      pattern(a.pattern());
204      maxItems(a.maxItems());
205      minItems(a.minItems());
206      uniqueItems(a.uniqueItems());
207      _enum(HttpPartSchema.toSet(a._enum()));
208      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
209      skipIfEmpty(a.skipIfEmpty());
210      parser(a.parser());
211      serializer(a.serializer());
212      return this;
213   }
214
215   HttpPartSchemaBuilder apply(Query a) {
216      name(a.value());
217      name(a.name());
218      required(a.required());
219      type(a.type());
220      format(a.format());
221      allowEmptyValue(a.allowEmptyValue());
222      items(a.items());
223      collectionFormat(a.collectionFormat());
224      _default(a._default().length == 0 ? null : joinnl(a._default()));
225      maximum(HttpPartSchema.toNumber(a.maximum()));
226      exclusiveMaximum(a.exclusiveMaximum());
227      minimum(HttpPartSchema.toNumber(a.minimum()));
228      exclusiveMinimum(a.exclusiveMinimum());
229      maxLength(a.maxLength());
230      minLength(a.minLength());
231      pattern(a.pattern());
232      maxItems(a.maxItems());
233      minItems(a.minItems());
234      uniqueItems(a.uniqueItems());
235      _enum(HttpPartSchema.toSet(a._enum()));
236      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
237      skipIfEmpty(a.skipIfEmpty());
238      parser(a.parser());
239      serializer(a.serializer());
240      return this;
241   }
242
243   HttpPartSchemaBuilder apply(Path a) {
244      name(a.value());
245      name(a.name());
246      type(a.type());
247      format(a.format());
248      items(a.items());
249      allowEmptyValue(a.allowEmptyValue());
250      collectionFormat(a.collectionFormat());
251      maximum(HttpPartSchema.toNumber(a.maximum()));
252      exclusiveMaximum(a.exclusiveMaximum());
253      minimum(HttpPartSchema.toNumber(a.minimum()));
254      exclusiveMinimum(a.exclusiveMinimum());
255      maxLength(a.maxLength());
256      minLength(a.minLength());
257      pattern(a.pattern());
258      maxItems(a.maxItems());
259      minItems(a.minItems());
260      uniqueItems(a.uniqueItems());
261      _enum(HttpPartSchema.toSet(a._enum()));
262      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
263      parser(a.parser());
264      serializer(a.serializer());
265
266      // Path remainder always allows empty value.
267      if (startsWith(name, '/'))
268         allowEmptyValue();
269      else
270         required(true);
271
272      return this;
273   }
274
275   HttpPartSchemaBuilder apply(Response a) {
276      codes(a.value());
277      codes(a.code());
278      required(false);
279      allowEmptyValue(true);
280      serializer(a.partSerializer());
281      parser(a.partParser());
282      apply(a.schema());
283      return this;
284   }
285
286   HttpPartSchemaBuilder apply(Items a) {
287      type(a.type());
288      format(a.format());
289      items(a.items());
290      collectionFormat(a.collectionFormat());
291      _default(a._default().length == 0 ? null : joinnl(a._default()));
292      maximum(HttpPartSchema.toNumber(a.maximum()));
293      exclusiveMaximum(a.exclusiveMaximum());
294      minimum(HttpPartSchema.toNumber(a.minimum()));
295      exclusiveMinimum(a.exclusiveMinimum());
296      maxLength(a.maxLength());
297      minLength(a.minLength());
298      pattern(a.pattern());
299      maxItems(a.maxItems());
300      minItems(a.minItems());
301      uniqueItems(a.uniqueItems());
302      _enum(HttpPartSchema.toSet(a._enum()));
303      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
304      return this;
305   }
306
307   HttpPartSchemaBuilder apply(SubItems a) {
308      type(a.type());
309      format(a.format());
310      items(HttpPartSchema.toObjectMap(a.items()));
311      collectionFormat(a.collectionFormat());
312      _default(a._default().length == 0 ? null : joinnl(a._default()));
313      maximum(HttpPartSchema.toNumber(a.maximum()));
314      exclusiveMaximum(a.exclusiveMaximum());
315      minimum(HttpPartSchema.toNumber(a.minimum()));
316      exclusiveMinimum(a.exclusiveMinimum());
317      maxLength(a.maxLength());
318      minLength(a.minLength());
319      pattern(a.pattern());
320      maxItems(a.maxItems());
321      minItems(a.minItems());
322      uniqueItems(a.uniqueItems());
323      _enum(HttpPartSchema.toSet(a._enum()));
324      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
325      return this;
326   }
327
328   HttpPartSchemaBuilder apply(Schema a) {
329      type(a.type());
330      format(a.format());
331      items(a.items());
332      collectionFormat(a.collectionFormat());
333      _default(a._default().length == 0 ? null : joinnl(a._default()));
334      maximum(HttpPartSchema.toNumber(a.maximum()));
335      exclusiveMaximum(a.exclusiveMaximum());
336      minimum(HttpPartSchema.toNumber(a.minimum()));
337      exclusiveMinimum(a.exclusiveMinimum());
338      maxLength(a.maxLength());
339      minLength(a.minLength());
340      pattern(a.pattern());
341      maxItems(a.maxItems());
342      minItems(a.minItems());
343      uniqueItems(a.uniqueItems());
344      _enum(HttpPartSchema.toSet(a._enum()));
345      multipleOf(HttpPartSchema.toNumber(a.multipleOf()));
346      maxProperties(a.maxProperties());
347      minProperties(a.minProperties());
348      properties(HttpPartSchema.toObjectMap(a.properties()));
349      additionalProperties(HttpPartSchema.toObjectMap(a.additionalProperties()));
350      return this;
351   }
352
353   HttpPartSchemaBuilder apply(HasQuery a) {
354      name(a.value());
355      name(a.name());
356      return this;
357   }
358
359   HttpPartSchemaBuilder apply(HasFormData a) {
360      name(a.value());
361      name(a.name());
362      return this;
363   }
364
365   HttpPartSchemaBuilder apply(ObjectMap m) {
366      if (m != null && ! m.isEmpty()) {
367         _default(m.getString("default"));
368         _enum(HttpPartSchema.toSet(m.getString("enum")));
369         allowEmptyValue(m.getBoolean("allowEmptyValue"));
370         exclusiveMaximum(m.getBoolean("exclusiveMaximum"));
371         exclusiveMinimum(m.getBoolean("exclusiveMinimum"));
372         required(m.getBoolean("required"));
373         uniqueItems(m.getBoolean("uniqueItems"));
374         collectionFormat(m.getString("collectionFormat"));
375         type(m.getString("type"));
376         format(m.getString("format"));
377         pattern(m.getString("pattern"));
378         maximum(m.get("maximum", Number.class));
379         minimum(m.get("minimum", Number.class));
380         multipleOf(m.get("multipleOf", Number.class));
381         maxItems(m.get("maxItems", Long.class));
382         maxLength(m.get("maxLength", Long.class));
383         maxProperties(m.get("maxProperties", Long.class));
384         minItems(m.get("minItems", Long.class));
385         minLength(m.get("minLength", Long.class));
386         minProperties(m.get("minProperties", Long.class));
387
388         items(m.getObjectMap("items"));
389         properties(m.getObjectMap("properties"));
390         additionalProperties(m.getObjectMap("additionalProperties"));
391
392         apply(m.getObjectMap("schema", null));
393      }
394      return this;
395   }
396
397   /**
398    * <mk>name</mk> field.
399    *
400    * <p>
401    * Applicable to the following Swagger schema objects:
402    * <ul>
403    *    <li>{@doc SwaggerParameterObject Parameter}
404    *    <li>{@doc SwaggerHeaderObject Header}
405    * </ul>
406    *
407    * @param value
408    *    The new value for this property.
409    * @return This object (for method chaining).
410    */
411   public HttpPartSchemaBuilder name(String value) {
412      if (isNotEmpty(value))
413         name = value;
414      return this;
415   }
416
417   /**
418    * <mk>httpStatusCode</mk> key.
419    *
420    * <p>
421    * Applicable to the following Swagger schema objects:
422    * <ul>
423    *    <li>{@doc SwaggerResponsesObject Responses}
424    * </ul>
425    *
426    * @param value
427    *    The new value for this property.
428    *    <br>Ignored if <jk>null</jk> or an empty array.
429    * @return This object (for method chaining).
430    */
431   public HttpPartSchemaBuilder codes(int[] value) {
432      if (value != null && value.length != 0)
433         for (int v : value)
434            code(v);
435      return this;
436   }
437
438   /**
439    * <mk>httpStatusCode</mk> key.
440    *
441    * <p>
442    * Applicable to the following Swagger schema objects:
443    * <ul>
444    *    <li>{@doc SwaggerResponsesObject Responses}
445    * </ul>
446    *
447    * @param value
448    *    The new value for this property.
449    *    <br>Ignored if value is <code>0</code>.
450    * @return This object (for method chaining).
451    */
452   public HttpPartSchemaBuilder code(int value) {
453      if (value != 0) {
454         if (codes == null)
455            codes = new TreeSet<>();
456         codes.add(value);
457      }
458      return this;
459   }
460
461   /**
462    * <mk>required</mk> field.
463    *
464    * <p>
465    * Determines whether the parameter is mandatory.
466    *
467    * <p>
468    * Applicable to the following Swagger schema objects:
469    * <ul>
470    *    <li>{@doc SwaggerParameterObject Parameter}
471    *    <li>{@doc SwaggerSchemaObject Schema}
472    * </ul>
473    *
474    * @param value
475    *    The new value for this property.
476    *    <br>Ignored if value is <jk>null</jk>.
477    * @return This object (for method chaining).
478    */
479   public HttpPartSchemaBuilder required(Boolean value) {
480      required = resolve(value, required);
481      return this;
482   }
483
484   /**
485    * <mk>required</mk> field.
486    *
487    * <p>
488    * Determines whether the parameter is mandatory.
489    *
490    * <p>
491    * Same as {@link #required(Boolean)} but takes in a boolean value as a string.
492    *
493    * @param value
494    *    The new value for this property.
495    *    <br>Ignored if value is <jk>null</jk> or empty.
496    * @return This object (for method chaining).
497    */
498   public HttpPartSchemaBuilder required(String value) {
499      required = resolve(value, required);
500      return this;
501   }
502
503   /**
504    * <mk>required</mk> field.
505    *
506    * <p>
507    * Shortcut for calling <code>required(<jk>true</jk>);</code>.
508    *
509    * @return This object (for method chaining).
510    */
511   public HttpPartSchemaBuilder required() {
512      return required(true);
513   }
514
515   /**
516    * <mk>type</mk> field.
517    *
518    * <p>
519    * The type of the parameter.
520    *
521    * <p>
522    * The possible values are:
523    * <ul class='spaced-list'>
524    *    <li>
525    *       <js>"string"</js>
526    *       <br>Parameter must be a string or a POJO convertible from a string.
527    *    <li>
528    *       <js>"number"</js>
529    *       <br>Parameter must be a number primitive or number object.
530    *       <br>If parameter is <code>Object</code>, creates either a <code>Float</code> or <code>Double</code> depending on the size of the number.
531    *    <li>
532    *       <js>"integer"</js>
533    *       <br>Parameter must be a integer/long primitive or integer/long object.
534    *       <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.
535    *    <li>
536    *       <js>"boolean"</js>
537    *       <br>Parameter must be a boolean primitive or object.
538    *    <li>
539    *       <js>"array"</js>
540    *       <br>Parameter must be an array or collection.
541    *       <br>Elements must be strings or POJOs convertible from strings.
542    *       <br>If parameter is <code>Object</code>, creates an {@link ObjectList}.
543    *    <li>
544    *       <js>"object"</js>
545    *       <br>Parameter must be a map or bean.
546    *       <br>If parameter is <code>Object</code>, creates an {@link ObjectMap}.
547    *       <br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
548    *    <li>
549    *       <js>"file"</js>
550    *       <br>This type is currently not supported.
551    * </ul>
552    *
553    * <p>
554    * If the type is not specified, it will be auto-detected based on the parameter class type.
555    *
556    * <p>
557    * Applicable to the following Swagger schema objects:
558    * <ul>
559    *    <li>{@doc SwaggerParameterObject Parameter}
560    *    <li>{@doc SwaggerSchemaObject Schema}
561    *    <li>{@doc SwaggerItemsObject Items}
562    *    <li>{@doc SwaggerSecuritySchemeObject SecurityScheme}
563    * </ul>
564    *
565    * <h5 class='section'>See Also:</h5>
566    * <ul class='doctree'>
567    *    <li class='extlink'>{@doc SwaggerDataTypes}
568    * </ul>
569    *
570    * @param value
571    *    The new value for this property.
572    *    <br>Ignored if value is <jk>null</jk> or empty.
573    * @return This object (for method chaining).
574    */
575   public HttpPartSchemaBuilder type(String value) {
576      try {
577         if (isNotEmpty(value))
578            type = Type.fromString(value);
579      } catch (Exception e) {
580         throw new ContextRuntimeException("Invalid value ''{0}'' passed in as type value.  Valid values: {1}", value, Type.values());
581      }
582      return this;
583   }
584
585   /**
586    * <mk>format</mk> field.
587    *
588    * <p>
589    * The extending format for the previously mentioned {@doc SwaggerParameterTypes parameter type}.
590    *
591    * <p>
592    * The possible values are:
593    * <ul class='spaced-list'>
594    *    <li>
595    *       <js>"int32"</js> - Signed 32 bits.
596    *       <br>Only valid with type <js>"integer"</js>.
597    *    <li>
598    *       <js>"int64"</js> - Signed 64 bits.
599    *       <br>Only valid with type <js>"integer"</js>.
600    *    <li>
601    *       <js>"float"</js> - 32-bit floating point number.
602    *       <br>Only valid with type <js>"number"</js>.
603    *    <li>
604    *       <js>"double"</js> - 64-bit floating point number.
605    *       <br>Only valid with type <js>"number"</js>.
606    *    <li>
607    *       <js>"byte"</js> - BASE-64 encoded characters.
608    *       <br>Only valid with type <js>"string"</js>.
609    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
610    *    <li>
611    *       <js>"binary"</js> - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
612    *       <br>Only valid with type <js>"string"</js>.
613    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
614    *    <li>
615    *       <js>"binary-spaced"</js> - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
616    *       <br>Only valid with type <js>"string"</js>.
617    *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
618    *    <li>
619    *       <js>"date"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
620    *       <br>Only valid with type <js>"string"</js>.
621    *    <li>
622    *       <js>"date-time"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
623    *       <br>Only valid with type <js>"string"</js>.
624    *    <li>
625    *       <js>"password"</js> - Used to hint UIs the input needs to be obscured.
626    *       <br>This format does not affect the serialization or parsing of the parameter.
627    *    <li>
628    *       <js>"uon"</js> - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
629    *       <br>Only valid with type <js>"object"</js>.
630    *       <br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
631    * </ul>
632    *
633    * <p>
634    * Applicable to the following Swagger schema objects:
635    * <ul>
636    *    <li>{@doc SwaggerParameterObject Parameter}
637    *    <li>{@doc SwaggerSchemaObject Schema}
638    *    <li>{@doc SwaggerItemsObject Items}
639    *    <li>{@doc SwaggerHeaderObject Header}
640    * </ul>
641    *
642    * <h5 class='section'>See Also:</h5>
643    * <ul class='doctree'>
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 <code>type</code> is <js>"array"</js>.
721    * <br>Can only be used if <code>type</code> 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 <code>type</code> <js>"array"</js> is used.
767    * <br>Can only be used if <code>type</code> 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 <code>maximum</code>.
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 <code>minimum</code>.
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 <code>-1</code>.
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 <code>-1</code>.
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 <code>-1</code>.
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 <code>-1</code>.
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 <code>-1</code>.
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}