001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.httppart;
018
019import static java.util.Collections.*;
020import static org.apache.juneau.common.utils.StringUtils.*;
021import static org.apache.juneau.common.utils.ThrowableUtils.*;
022import static org.apache.juneau.common.utils.Utils.*;
023import static org.apache.juneau.httppart.HttpPartDataType.*;
024import static org.apache.juneau.httppart.HttpPartFormat.*;
025import static org.apache.juneau.internal.ClassUtils.*;
026import static org.apache.juneau.internal.CollectionUtils.*;
027import static org.apache.juneau.internal.CollectionUtils.map;
028
029import java.lang.annotation.*;
030import java.lang.reflect.*;
031import java.math.*;
032import java.util.*;
033import java.util.concurrent.atomic.*;
034import java.util.function.*;
035import java.util.regex.*;
036
037import org.apache.juneau.*;
038import org.apache.juneau.annotation.*;
039import org.apache.juneau.collections.*;
040import org.apache.juneau.common.utils.*;
041import org.apache.juneau.http.annotation.*;
042import org.apache.juneau.internal.*;
043import org.apache.juneau.parser.*;
044import org.apache.juneau.reflect.*;
045
046/**
047 * Represents an OpenAPI schema definition.
048 *
049 * <p>
050 * The schema definition can be applied to any HTTP parts such as bodies, headers, query/form parameters, and URL path parts.
051 * <br>The API is generic enough to apply to any path part although some attributes may only applicable for certain parts.
052 *
053 * <p>
054 * Schema objects are created via builders instantiated through the {@link #create()} method.
055 *
056 * <h5 class='section'>Notes:</h5><ul>
057 *    <li class='note'>This class is thread safe and reusable.
058 * </ul>
059 *
060 * <h5 class='section'>See Also:</h5><ul>
061 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/OpenApiBasics">OpenApi Basics</a>
062 * </ul>
063 */
064public class HttpPartSchema {
065
066   //-------------------------------------------------------------------------------------------------------------------
067   // Static
068   //-------------------------------------------------------------------------------------------------------------------
069
070   /** Reusable instance of this object, all default settings. */
071   public static final HttpPartSchema DEFAULT = HttpPartSchema.create().allowEmptyValue(true).build();
072
073   /** Boolean type */
074   public static final HttpPartSchema T_BOOLEAN = HttpPartSchema.tBoolean().build();
075
076   /** File type */
077   public static final HttpPartSchema T_FILE = HttpPartSchema.tFile().build();
078
079   /** Integer type */
080   public static final HttpPartSchema T_INTEGER = HttpPartSchema.tInteger().build();
081
082   /** Int32 type */
083   public static final HttpPartSchema T_INT32 = HttpPartSchema.tInt32().build();
084
085   /** Int64 type */
086   public static final HttpPartSchema T_INT64 = HttpPartSchema.tInt64().build();
087
088   /** No type */
089   public static final HttpPartSchema T_NONE = HttpPartSchema.tNone().build();
090
091   /** Number type */
092   public static final HttpPartSchema T_NUMBER = HttpPartSchema.tNumber().build();
093
094   /** Float type */
095   public static final HttpPartSchema T_FLOAT = HttpPartSchema.tFloat().build();
096
097   /** Double type */
098   public static final HttpPartSchema T_DOUBLE = HttpPartSchema.tDouble().build();
099
100   /** String type */
101   public static final HttpPartSchema T_STRING = HttpPartSchema.tString().build();
102
103   /** Byte type */
104   public static final HttpPartSchema T_BYTE = HttpPartSchema.tByte().build();
105
106   /** Binary type */
107   public static final HttpPartSchema T_BINARY = HttpPartSchema.tBinary().build();
108
109   /** Spaced binary type */
110   public static final HttpPartSchema T_BINARY_SPACED = HttpPartSchema.tBinarySpaced().build();
111
112   /** Date type */
113   public static final HttpPartSchema T_DATE = HttpPartSchema.tDate().build();
114
115   /** Date-time type */
116   public static final HttpPartSchema T_DATETIME = HttpPartSchema.tDateTime().build();
117
118   /** UON-formated simple type */
119   public static final HttpPartSchema T_UON = HttpPartSchema.tUon().build();
120
121   /** Array type */
122   public static final HttpPartSchema T_ARRAY = HttpPartSchema.tArray().build();
123
124   /** Comma-delimited array type */
125   public static final HttpPartSchema T_ARRAY_CSV = HttpPartSchema.tArrayCsv().build();
126
127   /** Pipe-delimited array type */
128   public static final HttpPartSchema T_ARRAY_PIPES = HttpPartSchema.tArrayPipes().build();
129
130   /** Space-delimited array type */
131   public static final HttpPartSchema T_ARRAY_SSV = HttpPartSchema.tArraySsv().build();
132
133   /** Tab-delimited array type */
134   public static final HttpPartSchema T_ARRAY_TSV = HttpPartSchema.tArrayTsv().build();
135
136   /** UON-formatted array type */
137   public static final HttpPartSchema T_ARRAY_UON = HttpPartSchema.tArrayUon().build();
138
139   /** Multi-part array type */
140   public static final HttpPartSchema T_ARRAY_MULTI = HttpPartSchema.tArrayMulti().build();
141
142   /** Object type */
143   public static final HttpPartSchema T_OBJECT = HttpPartSchema.tObject().build();
144
145   /** Comma-delimited object type */
146   public static final HttpPartSchema T_OBJECT_CSV = HttpPartSchema.tObjectCsv().build();
147
148   /** Pipe-delimited object type */
149   public static final HttpPartSchema T_OBJECT_PIPES = HttpPartSchema.tObjectPipes().build();
150
151   /** Space-delimited object type */
152   public static final HttpPartSchema T_OBJECT_SSV = HttpPartSchema.tObjectSsv().build();
153
154   /** Tab-delimited object type */
155   public static final HttpPartSchema T_OBJECT_TSV = HttpPartSchema.tObjectTsv().build();
156
157   /** UON-formated object type */
158   public static final HttpPartSchema T_OBJECT_UON = HttpPartSchema.tObjectUon().build();
159
160   /**
161    * Instantiates a new builder for this object.
162    *
163    * @return A new builder for this object.
164    */
165   public static Builder create() {
166      return new Builder();
167   }
168
169   /**
170    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>BOOLEAN</jsf>)</c>.
171    *
172    * @return A new builder for this object.
173    */
174   public static Builder tBoolean() {
175      return create().tBoolean();
176   }
177
178   /**
179    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>FILE</jsf>)</c>.
180    *
181    * @return A new builder for this object.
182    */
183   public static Builder tFile() {
184      return create().tFile();
185   }
186
187   /**
188    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>INTEGER</jsf>)</c>.
189    *
190    * @return A new builder for this object.
191    */
192   public static Builder tInteger() {
193      return create().tInteger();
194   }
195
196   /**
197    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>INTEGER</jsf>).format(HttpPartFormat.<jsf>INT32</jsf>)</c>.
198    *
199    * @return A new builder for this object.
200    */
201   public static Builder tInt32() {
202      return create().tInteger().fInt32();
203   }
204
205   /**
206    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>INTEGER</jsf>).format(HttpPartFormat.<jsf>INT64</jsf>)</c>.
207    *
208    * @return A new builder for this object.
209    */
210   public static Builder tInt64() {
211      return create().tInteger().fInt64();
212   }
213
214   /**
215    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>NONE</jsf>)</c>.
216    *
217    * @return A new builder for this object.
218    */
219   public static Builder tNone() {
220      return create().tNone();
221   }
222
223   /**
224    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>NUMBER</jsf>)</c>.
225    *
226    * @return A new builder for this object.
227    */
228   public static Builder tNumber() {
229      return create().tNumber();
230   }
231
232   /**
233    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>NUMBER</jsf>).format(HttpPartFormat.<jsf>FLOAT</jsf>)</c>.
234    *
235    * @return A new builder for this object.
236    */
237   public static Builder tFloat() {
238      return create().tNumber().fFloat();
239   }
240
241   /**
242    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>NUMBER</jsf>).format(HttpPartFormat.<jsf>DOUBLE</jsf>)</c>.
243    *
244    * @return A new builder for this object.
245    */
246   public static Builder tDouble() {
247      return create().tNumber().fDouble();
248   }
249
250   /**
251    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>)</c>.
252    *
253    * @return A new builder for this object.
254    */
255   public static Builder tString() {
256      return create().tString();
257   }
258
259   /**
260    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>BYTE</jsf>)</c>.
261    *
262    * @return A new builder for this object.
263    */
264   public static Builder tByte() {
265      return create().tString().fByte();
266   }
267
268   /**
269    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>BINARY</jsf>)</c>.
270    *
271    * @return A new builder for this object.
272    */
273   public static Builder tBinary() {
274      return create().tString().fBinary();
275   }
276
277   /**
278    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>BINARY_SPACED</jsf>)</c>.
279    *
280    * @return A new builder for this object.
281    */
282   public static Builder tBinarySpaced() {
283      return create().tString().fBinarySpaced();
284   }
285
286   /**
287    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>DATE</jsf>)</c>.
288    *
289    * @return A new builder for this object.
290    */
291   public static Builder tDate() {
292      return create().tString().fDate();
293   }
294
295   /**
296    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>DATE_TIME</jsf>)</c>.
297    *
298    * @return A new builder for this object.
299    */
300   public static Builder tDateTime() {
301      return create().tString().fDateTime();
302   }
303
304   /**
305    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>STRING</jsf>).format(HttpPartFormat.<jsf>UON</jsf>)</c>.
306    *
307    * @return A new builder for this object.
308    */
309   public static Builder tUon() {
310      return create().tString().fUon();
311   }
312
313   /**
314    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>)</c>.
315    *
316    * @return A new builder for this object.
317    */
318   public static Builder tArray() {
319      return create().tArray();
320   }
321
322   /**
323    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).items(items)</c>.
324    *
325    * @param items The schema of the array items.
326    * @return A new builder for this object.
327    */
328   public static Builder tArray(Builder items) {
329      return create().tArray().items(items);
330   }
331
332   /**
333    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>CSV</jsf>)</c>.
334    *
335    * @return A new builder for this object.
336    */
337   public static Builder tArrayCsv() {
338      return create().tArray().cfCsv();
339   }
340
341   /**
342    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>CSV</jsf>).items(items)</c>.
343    *
344    * @param items The schema of the array items.
345    * @return A new builder for this object.
346    */
347   public static Builder tArrayCsv(Builder items) {
348      return create().tArray().cfCsv().items(items);
349   }
350
351   /**
352    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>PIPES</jsf>)</c>.
353    *
354    * @return A new builder for this object.
355    */
356   public static Builder tArrayPipes() {
357      return create().tArray().cfPipes();
358   }
359
360   /**
361    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>PIPES</jsf>).items(items)</c>.
362    *
363    * @param items The schema of the array items.
364    * @return A new builder for this object.
365    */
366   public static Builder tArrayPipes(Builder items) {
367      return create().tArray().cfPipes().items(items);
368   }
369
370   /**
371    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>SSV</jsf>)</c>.
372    *
373    * @return A new builder for this object.
374    */
375   public static Builder tArraySsv() {
376      return create().tArray().cfSsv();
377   }
378
379   /**
380    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>SSV</jsf>).items(items)</c>.
381    *
382    * @param items The schema of the array items.
383    * @return A new builder for this object.
384    */
385   public static Builder tArraySsv(Builder items) {
386      return create().tArray().cfSsv().items(items);
387   }
388
389   /**
390    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>TSV</jsf>)</c>.
391    *
392    * @return A new builder for this object.
393    */
394   public static Builder tArrayTsv() {
395      return create().tArray().cfTsv();
396   }
397
398   /**
399    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>TSV</jsf>).items(items)</c>.
400    *
401    * @param items The schema of the array items.
402    * @return A new builder for this object.
403    */
404   public static Builder tArrayTsv(Builder items) {
405      return create().tArray().cfTsv().items(items);
406   }
407
408   /**
409    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>UONC</jsf>)</c>.
410    *
411    * @return A new builder for this object.
412    */
413   public static Builder tArrayUon() {
414      return create().tArray().cfUon();
415   }
416
417   /**
418    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>UONC</jsf>).items(items)</c>.
419    *
420    * @param items The schema of the array items.
421    * @return A new builder for this object.
422    */
423   public static Builder tArrayUon(Builder items) {
424      return create().tArray().cfUon().items(items);
425   }
426
427   /**
428    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>MULTI</jsf>)</c>.
429    *
430    * @return A new builder for this object.
431    */
432   public static Builder tArrayMulti() {
433      return create().tArray().cfMulti();
434   }
435
436   /**
437    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>ARRAY</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>MULTI</jsf>).items(items)</c>.
438    *
439    * @param items The schema of the array items.
440    * @return A new builder for this object.
441    */
442   public static Builder tArrayMulti(Builder items) {
443      return create().tArray().cfMulti().items(items);
444   }
445
446   /**
447    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>)</c>.
448    *
449    * @return A new builder for this object.
450    */
451   public static Builder tObject() {
452      return create().tObject();
453   }
454
455   /**
456    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>CSV</jsf>)</c>.
457    *
458    * @return A new builder for this object.
459    */
460   public static Builder tObjectCsv() {
461      return create().tObject().cfCsv();
462   }
463
464   /**
465    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>PIPES</jsf>)</c>.
466    *
467    * @return A new builder for this object.
468    */
469   public static Builder tObjectPipes() {
470      return create().tObject().cfPipes();
471   }
472
473   /**
474    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>SSV</jsf>)</c>.
475    *
476    * @return A new builder for this object.
477    */
478   public static Builder tObjectSsv() {
479      return create().tObject().cfSsv();
480   }
481
482   /**
483    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>TSV</jsf>)</c>.
484    *
485    * @return A new builder for this object.
486    */
487   public static Builder tObjectTsv() {
488      return create().tObject().cfTsv();
489   }
490
491   /**
492    * Shortcut for <c><jsm>create</jsm>().type(HttpPartDataType.<jsf>OBJECT</jsf>).collectionFormat(HttpPartCollectionFormat.<jsf>UON</jsf>)</c>.
493    *
494    * @return A new builder for this object.
495    */
496   public static Builder tObjectUon() {
497      return create().tObject().cfUon();
498   }
499
500   /**
501    * Finds the schema information for the specified method parameter.
502    *
503    * <p>
504    * This method will gather all the schema information from the annotations at the following locations:
505    * <ul>
506    *    <li>The method parameter.
507    *    <li>The method parameter class.
508    *    <li>The method parameter parent classes and interfaces.
509    * </ul>
510    *
511    * @param c
512    *    The annotation to look for.
513    *    <br>Valid values:
514    *    <ul>
515    *       <li>{@link Content}
516    *       <li>{@link Header}
517    *       <li>{@link Query}
518    *       <li>{@link FormData}
519    *       <li>{@link Path}
520    *       <li>{@link Response}
521    *       <li>{@link HasQuery}
522    *       <li>{@link HasFormData}
523    *    </ul>
524    * @param mpi The Java method parameter.
525    * @return The schema information about the parameter.
526    */
527   public static HttpPartSchema create(Class<? extends Annotation> c, ParamInfo mpi) {
528      return create().applyAll(c, mpi).build();
529   }
530
531   /**
532    * Finds the schema information for the specified method return.
533    *
534    * <p>
535    * This method will gather all the schema information from the annotations at the following locations:
536    * <ul>
537    *    <li>The method.
538    *    <li>The method return class.
539    *    <li>The method return parent classes and interfaces.
540    * </ul>
541    *
542    * @param c
543    *    The annotation to look for.
544    *    <br>Valid values:
545    *    <ul>
546    *       <li>{@link Content}
547    *       <li>{@link Header}
548    *       <li>{@link Query}
549    *       <li>{@link FormData}
550    *       <li>{@link Path}
551    *       <li>{@link Response}
552    *       <li>{@link HasQuery}
553    *       <li>{@link HasFormData}
554    *    </ul>
555    * @param m
556    *    The Java method with the return type being checked.
557    * @return The schema information about the parameter.
558    */
559   public static HttpPartSchema create(Class<? extends Annotation> c, Method m) {
560      return create().applyAll(c, m).build();
561   }
562
563   /**
564    * Finds the schema information for the specified class.
565    *
566    * <p>
567    * This method will gather all the schema information from the annotations on the class and all parent classes/interfaces.
568    *
569    * @param c
570    *    The annotation to look for.
571    *    <br>Valid values:
572    *    <ul>
573    *       <li>{@link Content}
574    *       <li>{@link Header}
575    *       <li>{@link Query}
576    *       <li>{@link FormData}
577    *       <li>{@link Path}
578    *       <li>{@link Response}
579    *       <li>{@link HasQuery}
580    *       <li>{@link HasFormData}
581    *    </ul>
582    * @param t
583    *    The class containing the parameter.
584    * @return The schema information about the parameter.
585    */
586   public static HttpPartSchema create(Class<? extends Annotation> c, java.lang.reflect.Type t) {
587      return create().applyAll(c, t).build();
588   }
589
590   /**
591    * Shortcut for calling <c>create().type(type);</c>
592    *
593    * @param type The schema type value.
594    * @return A new builder.
595    */
596   public static Builder create(String type) {
597      return create().type(type);
598   }
599
600   /**
601    * Shortcut for calling <c>create().type(type).format(format);</c>
602    *
603    * @param type The schema type value.
604    * @param format The schema format value.
605    * @return A new builder.
606    */
607   public static Builder create(String type, String format) {
608      return create().type(type).format(format);
609   }
610
611   /**
612    * Finds the schema information on the specified annotation.
613    *
614    * @param a
615    *    The annotation to find the schema information on..
616    * @return The schema information found on the annotation.
617    */
618   public static HttpPartSchema create(Annotation a) {
619      return create().apply(a).build();
620   }
621
622   /**
623    * Finds the schema information on the specified annotation.
624    *
625    * @param a
626    *    The annotation to find the schema information on..
627    * @param defaultName The default part name if not specified on the annotation.
628    * @return The schema information found on the annotation.
629    */
630   public static HttpPartSchema create(Annotation a, String defaultName) {
631      return create().name(defaultName).apply(a).build();
632   }
633
634   //-------------------------------------------------------------------------------------------------------------------
635   // Builder
636   //-------------------------------------------------------------------------------------------------------------------
637
638   /**
639    * Builder class.
640    */
641   public static class Builder {
642      String name, _default;
643      Set<Integer> codes;
644      Set<String> _enum;
645      Boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
646      HttpPartCollectionFormat collectionFormat = HttpPartCollectionFormat.NO_COLLECTION_FORMAT;
647      HttpPartDataType type = HttpPartDataType.NO_TYPE;
648      HttpPartFormat format = HttpPartFormat.NO_FORMAT;
649      Pattern pattern;
650      Number maximum, minimum, multipleOf;
651      Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
652      Map<String,Object> properties;
653      Object items, additionalProperties;
654      boolean noValidate;
655      Class<? extends HttpPartParser> parser;
656      Class<? extends HttpPartSerializer> serializer;
657
658      /**
659       * Instantiates a new {@link HttpPartSchema} object based on the configuration of this builder.
660       *
661       * <p>
662       * This method can be called multiple times to produce new schema objects.
663       *
664       * @return
665       *    A new {@link HttpPartSchema} object.
666       *    <br>Never <jk>null</jk>.
667       */
668      public HttpPartSchema build() {
669         return new HttpPartSchema(this);
670      }
671
672      Builder apply(Class<? extends Annotation> c, ParamInfo mpi) {
673         apply(c, mpi.getParameterType().innerType());
674         mpi.forEachDeclaredAnnotation(c, x -> true, this::apply);
675         return this;
676      }
677
678      Builder applyAll(Class<? extends Annotation> c, ParamInfo mpi) {
679         return apply(Schema.class, mpi).apply(c, mpi);
680      }
681
682      Builder apply(Class<? extends Annotation> c, Method m) {
683         apply(c, m.getGenericReturnType());
684         Annotation a = m.getAnnotation(c);
685         if (a != null)
686            return apply(a);
687         return this;
688      }
689
690      Builder applyAll(Class<? extends Annotation> c, Method m) {
691         return apply(Schema.class, m).apply(c, m);
692      }
693
694      Builder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
695         if (t instanceof Class<?>) {
696            ClassInfo.of((Class<?>)t).forEachAnnotation(c, x -> true, this::apply);
697         } else if (Value.isType(t)) {
698            apply(c, Value.getParameterType(t));
699         }
700         return this;
701      }
702
703      Builder applyAll(Class<? extends Annotation> c, java.lang.reflect.Type t) {
704         return apply(Schema.class, t).apply(c, t);
705      }
706
707      /**
708       * Apply the specified annotation to this schema.
709       *
710       * @param a The annotation to apply.
711       * @return This object.
712       */
713      public Builder apply(Annotation a) {
714         if (a instanceof Content)
715            apply((Content)a);
716         else if (a instanceof Header)
717            apply((Header)a);
718         else if (a instanceof FormData)
719            apply((FormData)a);
720         else if (a instanceof Query)
721            apply((Query)a);
722         else if (a instanceof Path)
723            apply((Path)a);
724         else if (a instanceof Response)
725            apply((Response)a);
726         else if (a instanceof StatusCode)
727            apply((StatusCode)a);
728         else if (a instanceof HasQuery)
729            apply((HasQuery)a);
730         else if (a instanceof HasFormData)
731            apply((HasFormData)a);
732         else if (a instanceof Schema)
733            apply((Schema)a);
734         else
735            throw new BasicRuntimeException("Builder.apply(@{0}) not defined", className(a));
736         return this;
737      }
738
739      Builder apply(Content a) {
740         if (! SchemaAnnotation.empty(a.schema()))
741            apply(a.schema());
742         return this;
743      }
744
745      Builder apply(Header a) {
746         if (! SchemaAnnotation.empty(a.schema()))
747            apply(a.schema());
748         name(firstNonEmpty(a.name(), a.value()));
749         parser(a.parser());
750         serializer(a.serializer());
751         return this;
752      }
753
754      Builder apply(FormData a) {
755         if (! SchemaAnnotation.empty(a.schema()))
756            apply(a.schema());
757         name(firstNonEmpty(a.name(), a.value()));
758         parser(a.parser());
759         serializer(a.serializer());
760         return this;
761      }
762
763      Builder apply(Query a) {
764         if (! SchemaAnnotation.empty(a.schema()))
765            apply(a.schema());
766         name(firstNonEmpty(a.name(), a.value()));
767         parser(a.parser());
768         serializer(a.serializer());
769         return this;
770      }
771
772      Builder apply(Path a) {
773         if (! SchemaAnnotation.empty(a.schema()))
774            apply(a.schema());
775         name(firstNonEmpty(a.name(), a.value()));
776         parser(a.parser());
777         serializer(a.serializer());
778
779         // Path remainder always allows empty value.
780         if (startsWith(name, '/')) {
781            allowEmptyValue();
782            required(false);
783         } else if (required == null) {
784            required(true);
785         }
786
787         return this;
788      }
789
790      Builder apply(Response a) {
791         allowEmptyValue(true);
792         apply(a.schema());
793         parser(a.parser());
794         required(false);
795         serializer(a.serializer());
796         return this;
797      }
798
799      Builder apply(StatusCode a) {
800         codes(a.value());
801         return this;
802      }
803
804      Builder apply(Items a) {
805         _default(joinnlOrNull(a._default(), a.df()));
806         _enum(toSet(a._enum(), a.e()));
807         collectionFormat(firstNonEmpty(a.collectionFormat(), a.cf()));
808         exclusiveMaximum(a.exclusiveMaximum() || a.emax());
809         exclusiveMinimum(a.exclusiveMinimum() || a.emin());
810         format(firstNonEmpty(a.format(), a.f()));
811         items(a.items());
812         maximum(toNumber(a.maximum(), a.max()));
813         maxItems(firstNmo(a.maxItems(), a.maxi()));
814         maxLength(firstNmo(a.maxLength(), a.maxl()));
815         minimum(toNumber(a.minimum(), a.min()));
816         minItems(firstNmo(a.minItems(), a.mini()));
817         minLength(firstNmo(a.minLength(), a.minl()));
818         multipleOf(toNumber(a.multipleOf(), a.mo()));
819         pattern(firstNonEmpty(a.pattern(), a.p()));
820         type(firstNonEmpty(a.type(), a.t()));
821         uniqueItems(a.uniqueItems() || a.ui());         return this;
822      }
823
824      Builder apply(SubItems a) {
825         _default(joinnlOrNull(a._default(), a.df()));
826         _enum(toSet(a._enum(), a.e()));
827         collectionFormat(firstNonEmpty(a.collectionFormat(), a.cf()));
828         exclusiveMaximum(a.exclusiveMaximum() || a.emax());
829         exclusiveMinimum(a.exclusiveMinimum() || a.emin());
830         format(firstNonEmpty(a.format(), a.f()));
831         items(HttpPartSchema.toJsonMap(a.items()));
832         maximum(toNumber(a.maximum(), a.max()));
833         maxItems(firstNmo(a.maxItems(), a.maxi()));
834         maxLength(firstNmo(a.maxLength(), a.maxl()));
835         minimum(toNumber(a.minimum(), a.min()));
836         minItems(firstNmo(a.minItems(), a.mini()));
837         minLength(firstNmo(a.minLength(), a.minl()));
838         multipleOf(toNumber(a.multipleOf(), a.mo()));
839         pattern(firstNonEmpty(a.pattern(), a.p()));
840         type(firstNonEmpty(a.type(), a.t()));
841         uniqueItems(a.uniqueItems() || a.ui());         return this;
842      }
843
844      Builder apply(Schema a) {
845         _default(joinnlOrNull(a._default(), a.df()));
846         _enum(toSet(a._enum(), a.e()));
847         additionalProperties(HttpPartSchema.toJsonMap(a.additionalProperties()));
848         allowEmptyValue(a.allowEmptyValue() || a.aev());
849         collectionFormat(firstNonEmpty(a.collectionFormat(), a.cf()));
850         exclusiveMaximum(a.exclusiveMaximum() || a.emax());
851         exclusiveMinimum(a.exclusiveMinimum() || a.emin());
852         format(firstNonEmpty(a.format(), a.f()));
853         items(a.items());
854         maximum(toNumber(a.maximum(), a.max()));
855         maxItems(firstNmo(a.maxItems(), a.maxi()));
856         maxLength(firstNmo(a.maxLength(), a.maxl()));
857         maxProperties(firstNmo(a.maxProperties(), a.maxp()));
858         minimum(toNumber(a.minimum(), a.min()));
859         minItems(firstNmo(a.minItems(), a.mini()));
860         minLength(firstNmo(a.minLength(), a.minl()));
861         minProperties(firstNmo(a.minProperties(), a.minp()));
862         multipleOf(toNumber(a.multipleOf(), a.mo()));
863         pattern(firstNonEmpty(a.pattern(), a.p()));
864         properties(HttpPartSchema.toJsonMap(a.properties()));
865         required(a.required() || a.r());
866         skipIfEmpty(a.skipIfEmpty() || a.sie());
867         type(firstNonEmpty(a.type(), a.t()));
868         uniqueItems(a.uniqueItems() || a.ui());
869         return this;
870      }
871
872      Builder apply(HasQuery a) {
873         name(firstNonEmpty(a.name(), a.value()));
874         return this;
875      }
876
877      Builder apply(HasFormData a) {
878         name(firstNonEmpty(a.name(), a.value()));
879         return this;
880      }
881
882      Builder apply(JsonMap m) {
883         if (m != null && ! m.isEmpty()) {
884            _default(m.getString("default"));
885            _enum(HttpPartSchema.toSet(m.getString("enum")));
886            allowEmptyValue(m.getBoolean("allowEmptyValue"));
887            exclusiveMaximum(m.getBoolean("exclusiveMaximum"));
888            exclusiveMinimum(m.getBoolean("exclusiveMinimum"));
889            required(m.getBoolean("required"));
890            uniqueItems(m.getBoolean("uniqueItems"));
891            collectionFormat(m.getString("collectionFormat"));
892            type(m.getString("type"));
893            format(m.getString("format"));
894            pattern(m.getString("pattern"));
895            maximum(m.get("maximum", Number.class));
896            minimum(m.get("minimum", Number.class));
897            multipleOf(m.get("multipleOf", Number.class));
898            maxItems(m.get("maxItems", Long.class));
899            maxLength(m.get("maxLength", Long.class));
900            maxProperties(m.get("maxProperties", Long.class));
901            minItems(m.get("minItems", Long.class));
902            minLength(m.get("minLength", Long.class));
903            minProperties(m.get("minProperties", Long.class));
904
905            items(m.getMap("items"));
906            properties(m.getMap("properties"));
907            additionalProperties(m.getMap("additionalProperties"));
908
909            apply(m.getMap("schema", null));
910         }
911         return this;
912      }
913
914      /**
915       * <mk>name</mk> field.
916       *
917       * <p>
918       * Applicable to the following Swagger schema objects:
919       * <ul>
920       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
921       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
922       * </ul>
923       *
924       * @param value
925       *    The new value for this property.
926       * @return This object.
927       */
928      public Builder name(String value) {
929         if (Utils.isNotEmpty(value))
930            name = value;
931         return this;
932      }
933
934      /**
935       * Synonym for {@link #name(String)}.
936       *
937       * @param value
938       *    The new value for this property.
939       * @return This object.
940       */
941      public Builder n(String value) {
942         return name(value);
943      }
944
945      /**
946       * <mk>httpStatusCode</mk> key.
947       *
948       * <p>
949       * Applicable to the following Swagger schema objects:
950       * <ul>
951       *    <li><a class="doclink" href="https://swagger.io/specification/v2#responsesObject">Responses</a>
952       * </ul>
953       *
954       * @param value
955       *    The new value for this property.
956       *    <br>Ignored if <jk>null</jk> or an empty array.
957       * @return This object.
958       */
959      public Builder codes(int[] value) {
960         if (value != null && value.length != 0)
961            for (int v : value)
962               code(v);
963         return this;
964      }
965
966      /**
967       * <mk>httpStatusCode</mk> key.
968       *
969       * <p>
970       * Applicable to the following Swagger schema objects:
971       * <ul>
972       *    <li><a class="doclink" href="https://swagger.io/specification/v2#responsesObject">Responses</a>
973       * </ul>
974       *
975       * @param value
976       *    The new value for this property.
977       *    <br>Ignored if value is <c>0</c>.
978       * @return This object.
979       */
980      public Builder code(int value) {
981         if (value != 0) {
982            if (codes == null)
983               codes = new TreeSet<>();
984            codes.add(value);
985         }
986         return this;
987      }
988
989      /**
990       * <mk>required</mk> field.
991       *
992       * <p>
993       * Determines whether the parameter is mandatory.
994       *
995       * <p>
996       * Applicable to the following Swagger schema objects:
997       * <ul>
998       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
999       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1000       * </ul>
1001       *
1002       * @param value
1003       *    The new value for this property.
1004       *    <br>Ignored if value is <jk>null</jk>.
1005       * @return This object.
1006       */
1007      public Builder required(Boolean value) {
1008         required = resolve(value, required);
1009         return this;
1010      }
1011
1012      /**
1013       * Synonym for {@link #required(Boolean)}.
1014       *
1015       * @param value
1016       *    The new value for this property.
1017       * @return This object.
1018       */
1019      public Builder r(Boolean value) {
1020         return required(value);
1021      }
1022
1023      /**
1024       * <mk>required</mk> field.
1025       *
1026       * <p>
1027       * Determines whether the parameter is mandatory.
1028       *
1029       * <p>
1030       * Same as {@link #required(Boolean)} but takes in a boolean value as a string.
1031       *
1032       * @param value
1033       *    The new value for this property.
1034       *    <br>Ignored if value is <jk>null</jk> or empty.
1035       * @return This object.
1036       */
1037      public Builder required(String value) {
1038         required = resolve(value, required);
1039         return this;
1040      }
1041
1042      /**
1043       * Synonym for {@link #required(String)}.
1044       *
1045       * @param value
1046       *    The new value for this property.
1047       * @return This object.
1048       */
1049      public Builder r(String value) {
1050         return required(value);
1051      }
1052
1053      /**
1054       * <mk>required</mk> field.
1055       *
1056       * <p>
1057       * Shortcut for calling <code>required(<jk>true</jk>);</code>.
1058       *
1059       * @return This object.
1060       */
1061      public Builder required() {
1062         return required(true);
1063      }
1064
1065      /**
1066       * Synonym for {@link #required()}.
1067       *
1068       * @return This object.
1069       */
1070      public Builder r() {
1071         return required();
1072      }
1073
1074      /**
1075       * <mk>type</mk> field.
1076       *
1077       * <p>
1078       * The type of the parameter.
1079       *
1080       * <p>
1081       * If the type is not specified, it will be auto-detected based on the parameter class type.
1082       *
1083       * <p>
1084       * Applicable to the following Swagger schema objects:
1085       * <ul>
1086       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1087       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1088       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1089       *    <li><a class="doclink" href="https://swagger.io/specification/v2#securitySchemeObject">SecurityScheme</a>
1090       * </ul>
1091       *
1092       * <ul class='values'>
1093       *    <li>
1094       *       <js>"string"</js>
1095       *       <br>Parameter must be a string or a POJO convertible from a string.
1096       *    <li>
1097       *       <js>"number"</js>
1098       *       <br>Parameter must be a number primitive or number object.
1099       *       <br>If parameter is <c>Object</c>, creates either a <c>Float</c> or <c>Double</c> depending on the size of the number.
1100       *    <li>
1101       *       <js>"integer"</js>
1102       *       <br>Parameter must be a integer/long primitive or integer/long object.
1103       *       <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.
1104       *    <li>
1105       *       <js>"boolean"</js>
1106       *       <br>Parameter must be a boolean primitive or object.
1107       *    <li>
1108       *       <js>"array"</js>
1109       *       <br>Parameter must be an array or collection.
1110       *       <br>Elements must be strings or POJOs convertible from strings.
1111       *       <br>If parameter is <c>Object</c>, creates an {@link JsonList}.
1112       *    <li>
1113       *       <js>"object"</js>
1114       *       <br>Parameter must be a map or bean.
1115       *       <br>If parameter is <c>Object</c>, creates an {@link JsonMap}.
1116       *       <br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
1117       *    <li>
1118       *       <js>"file"</js>
1119       *       <br>This type is currently not supported.
1120       * </ul>
1121       *
1122       * <h5 class='section'>See Also:</h5><ul>
1123       *    <li class='extlink'><a class="doclink" href="https://swagger.io/specification#dataTypes">Swagger Data Types</a>
1124       * </ul>
1125       *
1126       * @param value
1127       *    The new value for this property.
1128       *    <br>Ignored if value is <jk>null</jk> or empty.
1129       * @return This object.
1130       */
1131      public Builder type(String value) {
1132         try {
1133            if (Utils.isNotEmpty(value))
1134               type = HttpPartDataType.fromString(value);
1135         } catch (Exception e) {
1136            throw new ContextRuntimeException("Invalid value ''{0}'' passed in as type value.  Valid values: {1}", value, HttpPartDataType.values());
1137         }
1138         return this;
1139      }
1140
1141      /**
1142       * Synonym for {@link #type(String)}.
1143       *
1144       * @param value
1145       *    The new value for this property.
1146       * @return This object.
1147       */
1148      public Builder t(String value) {
1149         return type(value);
1150      }
1151
1152      /**
1153       * Shortcut for <c>type(HttpPartDataType.STRING)</c>.
1154       *
1155       * @return This object.
1156       */
1157      public Builder tString() {
1158         type = HttpPartDataType.STRING;
1159         return this;
1160      }
1161
1162      /**
1163       * Shortcut for <c>type(HttpPartDataType.NUMBER)</c>.
1164       *
1165       * @return This object.
1166       */
1167      public Builder tNumber() {
1168         type = HttpPartDataType.NUMBER;
1169         return this;
1170      }
1171
1172      /**
1173       * Shortcut for <c>type(HttpPartDataType.INTEGER)</c>.
1174       *
1175       * @return This object.
1176       */
1177      public Builder tInteger() {
1178         type = HttpPartDataType.INTEGER;
1179         return this;
1180      }
1181
1182      /**
1183       * Shortcut for <c>type(HttpPartDataType.BOOLEAN)</c>.
1184       *
1185       * @return This object.
1186       */
1187      public Builder tBoolean() {
1188         type = HttpPartDataType.BOOLEAN;
1189         return this;
1190      }
1191
1192      /**
1193       * Shortcut for <c>type(HttpPartDataType.ARRAY)</c>.
1194       *
1195       * @return This object.
1196       */
1197      public Builder tArray() {
1198         type = HttpPartDataType.ARRAY;
1199         return this;
1200      }
1201
1202      /**
1203       * Shortcut for <c>type(HttpPartDataType.OBJECT)</c>.
1204       *
1205       * @return This object.
1206       */
1207      public Builder tObject() {
1208         type = HttpPartDataType.OBJECT;
1209         return this;
1210      }
1211
1212      /**
1213       * Shortcut for <c>type(HttpPartDataType.FILE)</c>.
1214       *
1215       * @return This object.
1216       */
1217      public Builder tFile() {
1218         type = HttpPartDataType.FILE;
1219         return this;
1220      }
1221
1222      /**
1223       * Shortcut for <c>type(HttpPartDataType.NO_TYPE)</c>.
1224       *
1225       * @return This object.
1226       */
1227      public Builder tNone() {
1228         type = HttpPartDataType.NO_TYPE;
1229         return this;
1230      }
1231
1232      /**
1233       * <mk>type</mk> field.
1234       *
1235       * <p>
1236       * The type of the parameter.
1237       *
1238       * <p>
1239       * If the type is not specified, it will be auto-detected based on the parameter class type.
1240       *
1241       * <p>
1242       * Applicable to the following Swagger schema objects:
1243       * <ul>
1244       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1245       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1246       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1247       *    <li><a class="doclink" href="https://swagger.io/specification/v2#securitySchemeObject">SecurityScheme</a>
1248       * </ul>
1249       *
1250       * <ul class='values javatree'>
1251       *    <li class='jc'>{@link HttpPartDataType}
1252       *    <ul>
1253       *       <li class='jf'>
1254       *          {@link HttpPartDataType#STRING STRING}
1255       *          <br>Parameter must be a string or a POJO convertible from a string.
1256       *          <li>
1257       *          {@link HttpPartDataType#NUMBER NUMBER}
1258       *          <br>Parameter must be a number primitive or number object.
1259       *          <br>If parameter is <c>Object</c>, creates either a <c>Float</c> or <c>Double</c> depending on the size of the number.
1260       *       <li class='jf'>
1261       *          {@link HttpPartDataType#INTEGER INTEGER}
1262       *          <br>Parameter must be a integer/long primitive or integer/long object.
1263       *          <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.
1264       *       <li class='jf'>
1265       *          {@link HttpPartDataType#BOOLEAN BOOLEAN}
1266       *          <br>Parameter must be a boolean primitive or object.
1267       *       <li class='jf'>
1268       *          {@link HttpPartDataType#ARRAY ARRAY}
1269       *          <br>Parameter must be an array or collection.
1270       *          <br>Elements must be strings or POJOs convertible from strings.
1271       *          <br>If parameter is <c>Object</c>, creates an {@link JsonList}.
1272       *       <li class='jf'>
1273       *          {@link HttpPartDataType#OBJECT OBJECT}
1274       *          <br>Parameter must be a map or bean.
1275       *          <br>If parameter is <c>Object</c>, creates an {@link JsonMap}.
1276       *          <br>Note that this is an extension of the OpenAPI schema as Juneau allows for arbitrarily-complex POJOs to be serialized as HTTP parts.
1277       *       <li class='jf'>
1278       *          {@link HttpPartDataType#FILE FILE}
1279       *          <br>This type is currently not supported.
1280       *    </ul>
1281       * </ul>
1282       *
1283       * <h5 class='section'>See Also:</h5><ul>
1284       *    <li class='extlink'><a class="doclink" href="https://swagger.io/specification#dataTypes">Swagger Data Types</a>
1285       * </ul>
1286       *
1287       * @param value
1288       *    The new value for this property.
1289       * @return This object.
1290       */
1291      public Builder type(HttpPartDataType value) {
1292         this.type = value;
1293         return this;
1294      }
1295
1296      /**
1297       * Synonym for {@link #type(HttpPartDataType)}.
1298       *
1299       * @param value
1300       *    The new value for this property.
1301       * @return This object.
1302       */
1303      public Builder t(HttpPartDataType value) {
1304         return type(value);
1305      }
1306
1307      /**
1308       * <mk>format</mk> field.
1309       *
1310       * <p>
1311       * The extending format for the previously mentioned <a class="doclink" href="https://swagger.io/specification/v2#parameterType">parameter type</a>.
1312       *
1313       * <p>
1314       * Applicable to the following Swagger schema objects:
1315       * <ul>
1316       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1317       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1318       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1319       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1320       * </ul>
1321       *
1322       * <ul class='values'>
1323       *    <li>
1324       *       <js>"int32"</js> - Signed 32 bits.
1325       *       <br>Only valid with type <js>"integer"</js>.
1326       *    <li>
1327       *       <js>"int64"</js> - Signed 64 bits.
1328       *       <br>Only valid with type <js>"integer"</js>.
1329       *    <li>
1330       *       <js>"float"</js> - 32-bit floating point number.
1331       *       <br>Only valid with type <js>"number"</js>.
1332       *    <li>
1333       *       <js>"double"</js> - 64-bit floating point number.
1334       *       <br>Only valid with type <js>"number"</js>.
1335       *    <li>
1336       *       <js>"byte"</js> - BASE-64 encoded characters.
1337       *       <br>Only valid with type <js>"string"</js>.
1338       *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1339       *    <li>
1340       *       <js>"binary"</js> - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
1341       *       <br>Only valid with type <js>"string"</js>.
1342       *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1343       *    <li>
1344       *       <js>"binary-spaced"</js> - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
1345       *       <br>Only valid with type <js>"string"</js>.
1346       *       <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1347       *    <li>
1348       *       <js>"date"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
1349       *       <br>Only valid with type <js>"string"</js>.
1350       *    <li>
1351       *       <js>"date-time"</js> - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
1352       *       <br>Only valid with type <js>"string"</js>.
1353       *    <li>
1354       *       <js>"password"</js> - Used to hint UIs the input needs to be obscured.
1355       *       <br>This format does not affect the serialization or parsing of the parameter.
1356       *    <li>
1357       *       <js>"uon"</js> - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
1358       *       <br>Only valid with type <js>"object"</js>.
1359       *       <br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
1360       * </ul>
1361       *
1362       * <h5 class='section'>See Also:</h5><ul>
1363       *    <li class='extlink'><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Swagger Schema Object</a>
1364       * </ul>
1365       *
1366       * @param value
1367       *    The new value for this property.
1368       *    <br>Ignored if value is <jk>null</jk> or an empty string.
1369       * @return This object.
1370       */
1371      public Builder format(String value) {
1372         try {
1373            if (Utils.isNotEmpty(value))
1374               format = HttpPartFormat.fromString(value);
1375         } catch (Exception e) {
1376            throw new ContextRuntimeException("Invalid value ''{0}'' passed in as format value.  Valid values: {1}", value, HttpPartFormat.values());
1377         }
1378         return this;
1379      }
1380
1381      /**
1382       * Synonym for {@link #format(String)}.
1383       *
1384       * @param value
1385       *    The new value for this property.
1386       * @return This object.
1387       */
1388      public Builder f(String value) {
1389         return format(value);
1390      }
1391
1392      /**
1393       * <mk>format</mk> field.
1394       *
1395       * <p>
1396       * The extending format for the previously mentioned <a class="doclink" href="https://swagger.io/specification/v2#parameterType">parameter type</a>.
1397       *
1398       * <p>
1399       * Applicable to the following Swagger schema objects:
1400       * <ul>
1401       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1402       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1403       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1404       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1405       * </ul>
1406       *
1407       * <ul class='values javatree'>
1408       *    <ul class='jc'>{@link HttpPartFormat}
1409       *    <ul>
1410       *       <li class='jf'>
1411       *          {@link HttpPartFormat#INT32 INT32} - Signed 32 bits.
1412       *          <br>Only valid with type <js>"integer"</js>.
1413       *       <li class='jf'>
1414       *          {@link HttpPartFormat#INT64 INT64} - Signed 64 bits.
1415       *          <br>Only valid with type <js>"integer"</js>.
1416       *       <li class='jf'>
1417       *          {@link HttpPartFormat#FLOAT FLOAT} - 32-bit floating point number.
1418       *          <br>Only valid with type <js>"number"</js>.
1419       *       <li class='jf'>
1420       *          {@link HttpPartFormat#DOUBLE DOUBLE} - 64-bit floating point number.
1421       *          <br>Only valid with type <js>"number"</js>.
1422       *       <li class='jf'>
1423       *          {@link HttpPartFormat#BYTE BYTE} - BASE-64 encoded characters.
1424       *          <br>Only valid with type <js>"string"</js>.
1425       *          <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1426       *       <li class='jf'>
1427       *          {@link HttpPartFormat#BINARY BINARY} - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
1428       *          <br>Only valid with type <js>"string"</js>.
1429       *          <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1430       *       <li class='jf'>
1431       *          {@link HttpPartFormat#BINARY_SPACED BINARY_SPACED} - Hexadecimal encoded octets, spaced (e.g. <js>"00 FF"</js>).
1432       *          <br>Only valid with type <js>"string"</js>.
1433       *          <br>Parameters of type POJO convertible from string are converted after the string has been decoded.
1434       *       <li class='jf'>
1435       *          {@link HttpPartFormat#DATE DATE} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
1436       *          <br>Only valid with type <js>"string"</js>.
1437       *       <li class='jf'>
1438       *          {@link HttpPartFormat#DATE_TIME DATE_TIME} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
1439       *          <br>Only valid with type <js>"string"</js>.
1440       *       <li class='jf'>
1441       *          {@link HttpPartFormat#PASSWORD PASSWORD} - Used to hint UIs the input needs to be obscured.
1442       *          <br>This format does not affect the serialization or parsing of the parameter.
1443       *       <li class='jf'>
1444       *          {@link HttpPartFormat#UON UON} - UON notation (e.g. <js>"(foo=bar,baz=@(qux,123))"</js>).
1445       *          <br>Only valid with type <js>"object"</js>.
1446       *          <br>If not specified, then the input is interpreted as plain-text and is converted to a POJO directly.
1447       *    </ul>
1448       * </ul>
1449       *
1450       * <h5 class='section'>See Also:</h5><ul>
1451       *    <li class='extlink'><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Swagger Schema Object</a>
1452       * </ul>
1453       *
1454       * @param value
1455       *    The new value for this property.
1456       * @return This object.
1457       */
1458      public Builder format(HttpPartFormat value) {
1459         format = value;
1460         return this;
1461      }
1462
1463      /**
1464       * Synonym for {@link #format(HttpPartFormat)}.
1465       *
1466       * @param value
1467       *    The new value for this property.
1468       * @return This object.
1469       */
1470      public Builder f(HttpPartFormat value) {
1471         return format(value);
1472      }
1473
1474      /**
1475       * Shortcut for <c>format(HttpPartFormat.INT32)</c>.
1476       *
1477       * @return This object.
1478       */
1479      public Builder fInt32() {
1480         format = HttpPartFormat.INT32;
1481         return this;
1482      }
1483
1484      /**
1485       * Shortcut for <c>format(HttpPartFormat.INT64)</c>.
1486       *
1487       * @return This object.
1488       */
1489      public Builder fInt64() {
1490         format = HttpPartFormat.INT64;
1491         return this;
1492      }
1493
1494      /**
1495       * Shortcut for <c>format(HttpPartFormat.FLOAT)</c>.
1496       *
1497       * @return This object.
1498       */
1499      public Builder fFloat() {
1500         format = HttpPartFormat.FLOAT;
1501         return this;
1502      }
1503
1504      /**
1505       * Shortcut for <c>format(HttpPartFormat.DOUBLE)</c>.
1506       *
1507       * @return This object.
1508       */
1509      public Builder fDouble() {
1510         format = HttpPartFormat.DOUBLE;
1511         return this;
1512      }
1513
1514      /**
1515       * Shortcut for <c>format(HttpPartFormat.BYTE)</c>.
1516       *
1517       * @return This object.
1518       */
1519      public Builder fByte() {
1520         format = HttpPartFormat.BYTE;
1521         return this;
1522      }
1523
1524      /**
1525       * Shortcut for <c>format(HttpPartFormat.BINARY)</c>.
1526       *
1527       * @return This object.
1528       */
1529      public Builder fBinary() {
1530         format = HttpPartFormat.BINARY;
1531         return this;
1532      }
1533
1534      /**
1535       * Shortcut for <c>format(HttpPartFormat.BINARY_SPACED)</c>.
1536       *
1537       * @return This object.
1538       */
1539      public Builder fBinarySpaced() {
1540         format = HttpPartFormat.BINARY_SPACED;
1541         return this;
1542      }
1543
1544      /**
1545       * Shortcut for <c>format(HttpPartFormat.DATE)</c>.
1546       *
1547       * @return This object.
1548       */
1549      public Builder fDate() {
1550         format = HttpPartFormat.DATE;
1551         return this;
1552      }
1553
1554      /**
1555       * Shortcut for <c>format(HttpPartFormat.DATE_TIME)</c>.
1556       *
1557       * @return This object.
1558       */
1559      public Builder fDateTime() {
1560         format = HttpPartFormat.DATE_TIME;
1561         return this;
1562      }
1563
1564      /**
1565       * Shortcut for <c>format(HttpPartFormat.PASSWORD)</c>.
1566       *
1567       * @return This object.
1568       */
1569      public Builder fPassword() {
1570         format = HttpPartFormat.PASSWORD;
1571         return this;
1572      }
1573
1574      /**
1575       * Shortcut for <c>format(HttpPartFormat.UON)</c>.
1576       *
1577       * @return This object.
1578       */
1579      public Builder fUon() {
1580         format = HttpPartFormat.UON;
1581         return this;
1582      }
1583
1584      /**
1585       * Shortcut for <c>format(HttpPartFormat.NO_FORMAT)</c>.
1586       *
1587       * @return This object.
1588       */
1589      public Builder fNone() {
1590         format = HttpPartFormat.NO_FORMAT;
1591         return this;
1592      }
1593
1594      /**
1595       * <mk>allowEmptyValue</mk> field.
1596       *
1597       * <p>
1598       * Sets the ability to pass empty-valued parameters.
1599       * <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.
1600       * <br>The default value is <jk>false</jk>.
1601       *
1602       * <p>
1603       * Applicable to the following Swagger schema objects:
1604       * <ul>
1605       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1606       * </ul>
1607       *
1608       * @param value
1609       *    The new value for this property.
1610       *    <br>Ignored if value is <jk>null</jk>.
1611       * @return This object.
1612       */
1613      public Builder allowEmptyValue(Boolean value) {
1614         allowEmptyValue = resolve(value, allowEmptyValue);
1615         return this;
1616      }
1617
1618      /**
1619       * Synonym for {@link #allowEmptyValue(Boolean)}.
1620       *
1621       * @param value
1622       *    The new value for this property.
1623       * @return This object.
1624       */
1625      public Builder aev(Boolean value) {
1626         return allowEmptyValue(value);
1627      }
1628
1629      /**
1630       * <mk>allowEmptyValue</mk> field.
1631       *
1632       * <p>
1633       * Same as {@link #allowEmptyValue(Boolean)} but takes in a string boolean value.
1634       *
1635       * @param value
1636       *    The new value for this property.
1637       *    <br>Ignored if value is <jk>null</jk> or empty.
1638       * @return This object.
1639       */
1640      public Builder allowEmptyValue(String value) {
1641         allowEmptyValue = resolve(value, allowEmptyValue);
1642         return this;
1643      }
1644
1645      /**
1646       * Synonym for {@link #allowEmptyValue(String)}.
1647       *
1648       * @param value
1649       *    The new value for this property.
1650       * @return This object.
1651       */
1652      public Builder aev(String value) {
1653         return allowEmptyValue(value);
1654      }
1655
1656      /**
1657       * <mk>allowEmptyValue</mk> field.
1658       *
1659       * <p>
1660       * Shortcut for calling <code>allowEmptyValue(<jk>true</jk>);</code>.
1661       *
1662       * @return This object.
1663       */
1664      public Builder allowEmptyValue() {
1665         return allowEmptyValue(true);
1666      }
1667
1668      /**
1669       * Synonym for {@link #allowEmptyValue()}.
1670       *
1671       * @return This object.
1672       */
1673      public Builder aev() {
1674         return allowEmptyValue(true);
1675      }
1676
1677      /**
1678       * <mk>items</mk> field.
1679       *
1680       * <p>
1681       * Describes the type of items in the array.
1682       * <p>
1683       * Required if <c>type</c> is <js>"array"</js>.
1684       * <br>Can only be used if <c>type</c> is <js>"array"</js>.
1685       *
1686       * <p>
1687       * Applicable to the following Swagger schema objects:
1688       * <ul>
1689       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1690       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1691       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1692       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1693       * </ul>
1694       *
1695       * @param value
1696       *    The new value for this property.
1697       *    <br>Ignored if value is <jk>null</jk> or empty.
1698       * @return This object.
1699       */
1700      public Builder items(Builder value) {
1701         if (value != null)
1702            this.items = value;
1703         return this;
1704      }
1705
1706      /**
1707       * Synonym for {@link #items(HttpPartSchema.Builder)}.
1708       *
1709       * @param value
1710       *    The new value for this property.
1711       * @return This object.
1712       */
1713      public Builder i(Builder value) {
1714         return items(value);
1715      }
1716
1717      /**
1718       * <mk>items</mk> field.
1719       *
1720       * <p>
1721       * Describes the type of items in the array.
1722       * <p>
1723       * Required if <c>type</c> is <js>"array"</js>.
1724       * <br>Can only be used if <c>type</c> is <js>"array"</js>.
1725       *
1726       * <p>
1727       * Applicable to the following Swagger schema objects:
1728       * <ul>
1729       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1730       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1731       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1732       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1733       * </ul>
1734       *
1735       * @param value
1736       *    The new value for this property.
1737       *    <br>Ignored if value is <jk>null</jk> or empty.
1738       * @return This object.
1739       */
1740      public Builder items(HttpPartSchema value) {
1741         if (value != null)
1742            this.items = value;
1743         return this;
1744      }
1745
1746      /**
1747       * Synonym for {@link #items(HttpPartSchema)}.
1748       *
1749       * @param value
1750       *    The new value for this property.
1751       * @return This object.
1752       */
1753      public Builder i(HttpPartSchema value) {
1754         return items(value);
1755      }
1756
1757      Builder items(JsonMap value) {
1758         if (value != null && ! value.isEmpty())
1759            items = HttpPartSchema.create().apply(value);
1760         return this;
1761      }
1762
1763      Builder items(Items value) {
1764         if (! ItemsAnnotation.empty(value))
1765            items = HttpPartSchema.create().apply(value);
1766         return this;
1767      }
1768
1769      Builder items(SubItems value) {
1770         if (! SubItemsAnnotation.empty(value))
1771            items = HttpPartSchema.create().apply(value);
1772         return this;
1773      }
1774
1775
1776      /**
1777       * <mk>collectionFormat</mk> field.
1778       *
1779       * <p>
1780       * Determines the format of the array if <c>type</c> <js>"array"</js> is used.
1781       * <br>Can only be used if <c>type</c> is <js>"array"</js>.
1782       *
1783       * <p>
1784       * Applicable to the following Swagger schema objects:
1785       * <ul>
1786       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1787       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1788       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1789       * </ul>
1790       *
1791       * <p>
1792       * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
1793       *
1794       * <ul class='values'>
1795       *    <li>
1796       *       <js>"csv"</js> (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
1797       *    <li>
1798       *       <js>"ssv"</js> - Space-separated values (e.g. <js>"foo bar"</js>).
1799       *    <li>
1800       *       <js>"tsv"</js> - Tab-separated values (e.g. <js>"foo\tbar"</js>).
1801       *    <li>
1802       *       <js>"pipes</js> - Pipe-separated values (e.g. <js>"foo|bar"</js>).
1803       *    <li>
1804       *       <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>).
1805       *    <li>
1806       *       <js>"uon"</js> - UON notation (e.g. <js>"@(foo,bar)"</js>).
1807       *    <li>
1808       * </ul>
1809       *
1810       * @param value
1811       *    The new value for this property.
1812       *    <br>Ignored if value is <jk>null</jk> or empty.
1813       * @return This object.
1814       */
1815      public Builder collectionFormat(String value) {
1816         try {
1817            if (Utils.isNotEmpty(value))
1818               this.collectionFormat = HttpPartCollectionFormat.fromString(value);
1819         } catch (Exception e) {
1820            throw new ContextRuntimeException("Invalid value ''{0}'' passed in as collectionFormat value.  Valid values: {1}", value, HttpPartCollectionFormat.values());
1821         }
1822         return this;
1823      }
1824
1825      /**
1826       * Synonym for {@link #collectionFormat(String)}.
1827       *
1828       * @param value
1829       *    The new value for this property.
1830       * @return This object.
1831       */
1832      public Builder cf(String value) {
1833         return collectionFormat(value);
1834      }
1835
1836      /**
1837       * <mk>collectionFormat</mk> field.
1838       *
1839       * <p>
1840       * Determines the format of the array if <c>type</c> <js>"array"</js> is used.
1841       * <br>Can only be used if <c>type</c> is <js>"array"</js>.
1842       *
1843       * <p>
1844       * Applicable to the following Swagger schema objects:
1845       * <ul>
1846       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1847       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1848       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1849       * </ul>
1850       *
1851       * <p>
1852       * Note that for collections/arrays parameters with POJO element types, the input is broken into a string array before being converted into POJO elements.
1853       *
1854       * <ul class='values javatree'>
1855       *    <ul class='jc'>{@link HttpPartCollectionFormat}
1856       *    <ul>
1857       *       <li>
1858       *          {@link HttpPartCollectionFormat#CSV CSV} (default) - Comma-separated values (e.g. <js>"foo,bar"</js>).
1859       *       <li>
1860       *          {@link HttpPartCollectionFormat#SSV SSV} - Space-separated values (e.g. <js>"foo bar"</js>).
1861       *       <li>
1862       *          {@link HttpPartCollectionFormat#TSV TSV} - Tab-separated values (e.g. <js>"foo\tbar"</js>).
1863       *       <li>
1864       *          {@link HttpPartCollectionFormat#PIPES PIPES} - Pipe-separated values (e.g. <js>"foo|bar"</js>).
1865       *       <li>
1866       *          {@link HttpPartCollectionFormat#MULTI MULTI} - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
1867       *       <li>
1868       *          {@link HttpPartCollectionFormat#UONC UONC} - UON collection notation (e.g. <js>"@(foo,bar)"</js>).
1869       *    </ul>
1870       * </ul>
1871       *
1872       * @param value
1873       *    The new value for this property.
1874       * @return This object.
1875       */
1876      public Builder collectionFormat(HttpPartCollectionFormat value) {
1877         collectionFormat = value;
1878         return this;
1879      }
1880
1881      /**
1882       * Synonym for {@link #collectionFormat(HttpPartCollectionFormat)}.
1883       *
1884       * @param value
1885       *    The new value for this property.
1886       * @return This object.
1887       */
1888      public Builder cf(HttpPartCollectionFormat value) {
1889         return collectionFormat(value);
1890      }
1891
1892      /**
1893       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.CSV)</c>.
1894       *
1895       * @return This object.
1896       */
1897      public Builder cfCsv() {
1898         return collectionFormat(HttpPartCollectionFormat.CSV);
1899      }
1900
1901      /**
1902       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.SSV)</c>.
1903       *
1904       * @return This object.
1905       */
1906      public Builder cfSsv() {
1907         return collectionFormat(HttpPartCollectionFormat.SSV);
1908      }
1909
1910      /**
1911       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.TSV)</c>.
1912       *
1913       * @return This object.
1914       */
1915      public Builder cfTsv() {
1916         return collectionFormat(HttpPartCollectionFormat.TSV);
1917      }
1918
1919      /**
1920       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.PIPES)</c>.
1921       *
1922       * @return This object.
1923       */
1924      public Builder cfPipes() {
1925         return collectionFormat(HttpPartCollectionFormat.PIPES);
1926      }
1927
1928      /**
1929       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.MULTI)</c>.
1930       *
1931       * @return This object.
1932       */
1933      public Builder cfMulti() {
1934         return collectionFormat(HttpPartCollectionFormat.MULTI);
1935      }
1936
1937      /**
1938       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.UONC)</c>.
1939       *
1940       * @return This object.
1941       */
1942      public Builder cfUon() {
1943         return collectionFormat(HttpPartCollectionFormat.UONC);
1944      }
1945
1946      /**
1947       * Shortcut for <c>collectionFormat(HttpPartCollectionFormat.NO_COLLECTION_FORMAT)</c>.
1948       *
1949       * @return This object.
1950       */
1951      public Builder cfNone() {
1952         return collectionFormat(HttpPartCollectionFormat.NO_COLLECTION_FORMAT);
1953      }
1954
1955      /**
1956       * <mk>default</mk> field.
1957       *
1958       * <p>
1959       * 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.
1960       * <br>(Note: "default" has no meaning for required parameters.)
1961       *
1962       * <p>
1963       * Applicable to the following Swagger schema objects:
1964       * <ul>
1965       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
1966       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
1967       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
1968       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
1969       * </ul>
1970       *
1971       * @param value
1972       *    The new value for this property.
1973       *    <br>Ignored if value is <jk>null</jk>.
1974       * @return This object.
1975       */
1976      public Builder _default(String value) {
1977         if (value != null)
1978            this._default = value;
1979         return this;
1980      }
1981
1982      /**
1983       * Synonym for {@link #_default(String)}.
1984       *
1985       * @param value
1986       *    The new value for this property.
1987       * @return This object.
1988       */
1989      public Builder df(String value) {
1990         return _default(value);
1991      }
1992
1993      /**
1994       * <mk>maximum</mk> field.
1995       *
1996       * <p>
1997       * Defines the maximum value for a parameter of numeric types.
1998       *
1999       * <p>
2000       * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
2001       *
2002       * <p>
2003       * Applicable to the following Swagger schema objects:
2004       * <ul>
2005       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2006       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2007       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2008       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2009       * </ul>
2010       *
2011       * @param value
2012       *    The new value for this property.
2013       *    <br>Ignored if value is <jk>null</jk>.
2014       * @return This object.
2015       */
2016      public Builder maximum(Number value) {
2017         if (value != null)
2018            this.maximum = value;
2019         return this;
2020      }
2021
2022      /**
2023       * Synonym for {@link #maximum(Number)}.
2024       *
2025       * @param value
2026       *    The new value for this property.
2027       * @return This object.
2028       */
2029      public Builder max(Number value) {
2030         return maximum(value);
2031      }
2032
2033      /**
2034       * <mk>exclusiveMaximum</mk> field.
2035       *
2036       * <p>
2037       * Defines whether the maximum is matched exclusively.
2038       *
2039       * <p>
2040       * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
2041       * <br>If <jk>true</jk>, must be accompanied with <c>maximum</c>.
2042       *
2043       * <p>
2044       * Applicable to the following Swagger schema objects:
2045       * <ul>
2046       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2047       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2048       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2049       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2050       * </ul>
2051       *
2052       * @param value
2053       *    The new value for this property.
2054       *    <br>Ignored if value is <jk>null</jk>.
2055       * @return This object.
2056       */
2057      public Builder exclusiveMaximum(Boolean value) {
2058         exclusiveMaximum = resolve(value, exclusiveMaximum);
2059         return this;
2060      }
2061
2062      /**
2063       * Synonym for {@link #exclusiveMaximum(Boolean)}.
2064       *
2065       * @param value
2066       *    The new value for this property.
2067       * @return This object.
2068       */
2069      public Builder emax(Boolean value) {
2070         return exclusiveMaximum(value);
2071      }
2072
2073      /**
2074       * <mk>exclusiveMaximum</mk> field.
2075       *
2076       * <p>
2077       * Same as {@link #exclusiveMaximum(Boolean)} but takes in a string boolean value.
2078       *
2079       * @param value
2080       *    The new value for this property.
2081       *    <br>Ignored if value is <jk>null</jk> or empty.
2082       * @return This object.
2083       */
2084      public Builder exclusiveMaximum(String value) {
2085         exclusiveMaximum = resolve(value, exclusiveMaximum);
2086         return this;
2087      }
2088
2089      /**
2090       * Synonym for {@link #exclusiveMaximum(String)}.
2091       *
2092       * @param value
2093       *    The new value for this property.
2094       * @return This object.
2095       */
2096      public Builder emax(String value) {
2097         return exclusiveMaximum(value);
2098      }
2099
2100      /**
2101       * <mk>exclusiveMaximum</mk> field.
2102       *
2103       * <p>
2104       * Shortcut for calling <code>exclusiveMaximum(<jk>true</jk>);</code>.
2105       *
2106       * @return This object.
2107       */
2108      public Builder exclusiveMaximum() {
2109         return exclusiveMaximum(true);
2110      }
2111
2112      /**
2113       * Synonym for {@link #exclusiveMaximum()}.
2114       *
2115       * @return This object.
2116       */
2117      public Builder emax() {
2118         return exclusiveMaximum();
2119      }
2120
2121      /**
2122       * <mk>minimum</mk> field.
2123       *
2124       * <p>
2125       * Defines the minimum value for a parameter of numeric types.
2126       *
2127       * <p>
2128       * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
2129       *
2130       * <p>
2131       * Applicable to the following Swagger schema objects:
2132       * <ul>
2133       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2134       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2135       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2136       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2137       * </ul>
2138       *
2139       * @param value
2140       *    The new value for this property.
2141       *    <br>Ignored if value is <jk>null</jk>.
2142       * @return This object.
2143       */
2144      public Builder minimum(Number value) {
2145         if (value != null)
2146            this.minimum = value;
2147         return this;
2148      }
2149
2150      /**
2151       * Synonym for {@link #minimum(Number)}.
2152       *
2153       * @param value
2154       *    The new value for this property.
2155       * @return This object.
2156       */
2157      public Builder min(Number value) {
2158         return minimum(value);
2159      }
2160
2161      /**
2162       * <mk>exclusiveMinimum</mk> field.
2163       *
2164       * <p>
2165       * Defines whether the minimum is matched exclusively.
2166       *
2167       * <p>
2168       * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
2169       * <br>If <jk>true</jk>, must be accompanied with <c>minimum</c>.
2170       *
2171       * <p>
2172       * Applicable to the following Swagger schema objects:
2173       * <ul>
2174       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2175       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2176       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2177       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2178       * </ul>
2179       *
2180       * @param value
2181       *    The new value for this property.
2182       *    <br>Ignored if value is <jk>null</jk>.
2183       * @return This object.
2184       */
2185      public Builder exclusiveMinimum(Boolean value) {
2186         exclusiveMinimum = resolve(value, exclusiveMinimum);
2187         return this;
2188      }
2189
2190      /**
2191       * Synonym for {@link #exclusiveMinimum(Boolean)}.
2192       *
2193       * @param value
2194       *    The new value for this property.
2195       * @return This object.
2196       */
2197      public Builder emin(Boolean value) {
2198         return exclusiveMinimum(value);
2199      }
2200
2201      /**
2202       * <mk>exclusiveMinimum</mk> field.
2203       *
2204       * <p>
2205       * Same as {@link #exclusiveMinimum(Boolean)} but takes in a string boolean value.
2206       *
2207       * @param value
2208       *    The new value for this property.
2209       *    <br>Ignored if value is <jk>null</jk> or empty.
2210       * @return This object.
2211       */
2212      public Builder exclusiveMinimum(String value) {
2213         exclusiveMinimum = resolve(value, exclusiveMinimum);
2214         return this;
2215      }
2216
2217      /**
2218       * Synonym for {@link #exclusiveMinimum(String)}.
2219       *
2220       * @param value
2221       *    The new value for this property.
2222       * @return This object.
2223       */
2224      public Builder emin(String value) {
2225         return exclusiveMinimum(value);
2226      }
2227
2228      /**
2229       * <mk>exclusiveMinimum</mk> field.
2230       *
2231       * <p>
2232       * Shortcut for calling <code>exclusiveMinimum(<jk>true</jk>);</code>.
2233       *
2234       * @return This object.
2235       */
2236      public Builder exclusiveMinimum() {
2237         return exclusiveMinimum(true);
2238      }
2239
2240      /**
2241       * Synonym for {@link #exclusiveMinimum()}.
2242       *
2243       * @return This object.
2244       */
2245      public Builder emin() {
2246         return exclusiveMinimum();
2247      }
2248
2249      /**
2250       * <mk>maxLength</mk> field.
2251       *
2252       * <p>
2253       * A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
2254       * <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>.
2255       *
2256       * <p>
2257       * Only allowed for the following types: <js>"string"</js>.
2258       *
2259       * <p>
2260       * Applicable to the following Swagger schema objects:
2261       * <ul>
2262       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2263       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2264       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2265       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2266       * </ul>
2267       *
2268       * @param value
2269       *    The new value for this property.
2270       *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
2271       * @return This object.
2272       */
2273      public Builder maxLength(Long value) {
2274         maxLength = resolve(value, maxLength);
2275         return this;
2276      }
2277
2278      /**
2279       * Synonym for {@link #maxLength(Long)}.
2280       *
2281       * @param value
2282       *    The new value for this property.
2283       * @return This object.
2284       */
2285      public Builder maxl(Long value) {
2286         return maxLength(value);
2287      }
2288
2289      /**
2290       * <mk>maxLength</mk> field.
2291       *
2292       * <p>
2293       * Same as {@link #maxLength(Long)} but takes in a string number.
2294       *
2295       * @param value
2296       *    The new value for this property.
2297       *    <br>Ignored if value is <jk>null</jk> or empty.
2298       * @return This object.
2299       */
2300      public Builder maxLength(String value) {
2301         maxLength = resolve(value, maxLength);
2302         return this;
2303      }
2304
2305      /**
2306       * Synonym for {@link #maxLength(String)}.
2307       *
2308       * @param value
2309       *    The new value for this property.
2310       * @return This object.
2311       */
2312      public Builder maxl(String value) {
2313         return maxLength(value);
2314      }
2315
2316      /**
2317       * <mk>minLength</mk> field.
2318       *
2319       * <p>
2320       * A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword.
2321       * <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>.
2322       *
2323       * <p>
2324       * Only allowed for the following types: <js>"string"</js>.
2325       *
2326       * <p>
2327       * Applicable to the following Swagger schema objects:
2328       * <ul>
2329       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2330       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2331       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2332       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2333       * </ul>
2334       *
2335       * @param value
2336       *    The new value for this property.
2337       *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
2338       * @return This object.
2339       */
2340      public Builder minLength(Long value) {
2341         minLength = resolve(value, minLength);
2342         return this;
2343      }
2344
2345      /**
2346       * Synonym for {@link #minLength(Long)}.
2347       *
2348       * @param value
2349       *    The new value for this property.
2350       * @return This object.
2351       */
2352      public Builder minl(Long value) {
2353         return minLength(value);
2354      }
2355
2356      /**
2357       * <mk>minLength</mk> field.
2358       *
2359       * <p>
2360       * Same as {@link #minLength(Long)} but takes in a string number.
2361       *
2362       * @param value
2363       *    The new value for this property.
2364       *    <br>Ignored if value is <jk>null</jk> or empty.
2365       * @return This object.
2366       */
2367      public Builder minLength(String value) {
2368         minLength = resolve(value, minLength);
2369         return this;
2370      }
2371
2372      /**
2373       * Synonym for {@link #minLength(String)}.
2374       *
2375       * @param value
2376       *    The new value for this property.
2377       * @return This object.
2378       */
2379      public Builder minl(String value) {
2380         return minLength(value);
2381      }
2382
2383      /**
2384       * <mk>pattern</mk> field.
2385       *
2386       * <p>
2387       * A string input is valid if it matches the specified regular expression pattern.
2388       *
2389       * <p>
2390       * Only allowed for the following types: <js>"string"</js>.
2391       *
2392       * <p>
2393       * Applicable to the following Swagger schema objects:
2394       * <ul>
2395       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2396       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2397       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2398       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2399       * </ul>
2400       *
2401       * @param value
2402       *    The new value for this property.
2403       *    <br>Ignored if value is <jk>null</jk> or empty.
2404       * @return This object.
2405       */
2406      public Builder pattern(String value) {
2407         try {
2408            if (Utils.isNotEmpty(value))
2409               this.pattern = Pattern.compile(value);
2410         } catch (Exception e) {
2411            throw new ContextRuntimeException(e, "Invalid value {0} passed in as pattern value.  Must be a valid regular expression.", value);
2412         }
2413         return this;
2414      }
2415
2416      /**
2417       * Synonym for {@link #pattern(String)}.
2418       *
2419       * @param value
2420       *    The new value for this property.
2421       * @return This object.
2422       */
2423      public Builder p(String value) {
2424         return pattern(value);
2425      }
2426
2427      /**
2428       * <mk>maxItems</mk> field.
2429       *
2430       * <p>
2431       * An array or collection is valid if its size is less than, or equal to, the value of this keyword.
2432       *
2433       * <p>
2434       * Only allowed for the following types: <js>"array"</js>.
2435       *
2436       * <p>
2437       * Applicable to the following Swagger schema objects:
2438       * <ul>
2439       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2440       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2441       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2442       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2443       * </ul>
2444       *
2445       * @param value
2446       *    The new value for this property.
2447       *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
2448       * @return This object.
2449       */
2450      public Builder maxItems(Long value) {
2451         maxItems = resolve(value, maxItems);
2452         return this;
2453      }
2454
2455      /**
2456       * Synonym for {@link #maxItems(Long)}.
2457       *
2458       * @param value
2459       *    The new value for this property.
2460       * @return This object.
2461       */
2462      public Builder maxi(Long value) {
2463         return maxItems(value);
2464      }
2465
2466      /**
2467       * <mk>maxItems</mk> field.
2468       *
2469       * <p>
2470       * Same as {@link #maxItems(Long)} but takes in a string number.
2471       *
2472       * @param value
2473       *    The new value for this property.
2474       *    <br>Ignored if value is <jk>null</jk> or empty.
2475       * @return This object.
2476       */
2477      public Builder maxItems(String value) {
2478         maxItems = resolve(value, maxItems);
2479         return this;
2480      }
2481
2482      /**
2483       * Synonym for {@link #maxItems(String)}.
2484       *
2485       * @param value
2486       *    The new value for this property.
2487       * @return This object.
2488       */
2489      public Builder maxi(String value) {
2490         return maxItems(value);
2491      }
2492
2493      /**
2494       * <mk>minItems</mk> field.
2495       *
2496       * <p>
2497       * An array or collection is valid if its size is greater than, or equal to, the value of this keyword.
2498       *
2499       * <p>
2500       * Only allowed for the following types: <js>"array"</js>.
2501       *
2502       * <p>
2503       * Applicable to the following Swagger schema objects:
2504       * <ul>
2505       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2506       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2507       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2508       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2509       * </ul>
2510       *
2511       * @param value
2512       *    The new value for this property.
2513       *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
2514       * @return This object.
2515       */
2516      public Builder minItems(Long value) {
2517         minItems = resolve(value, minItems);
2518         return this;
2519      }
2520
2521      /**
2522       * Synonym for {@link #minItems(Long)}.
2523       *
2524       * @param value
2525       *    The new value for this property.
2526       * @return This object.
2527       */
2528      public Builder mini(Long value) {
2529         return minItems(value);
2530      }
2531
2532      /**
2533       * <mk>minItems</mk> field.
2534       *
2535       * <p>
2536       * Same as {@link #minItems(Long)} but takes in a string number.
2537       *
2538       * @param value
2539       *    The new value for this property.
2540       *    <br>Ignored if value is <jk>null</jk> or empty.
2541       * @return This object.
2542       */
2543      public Builder minItems(String value) {
2544         minItems = resolve(value, minItems);
2545         return this;
2546      }
2547
2548      /**
2549       * Synonym for {@link #minItems(String)}.
2550       *
2551       * @param value
2552       *    The new value for this property.
2553       * @return This object.
2554       */
2555      public Builder mini(String value) {
2556         return minItems(value);
2557      }
2558
2559      /**
2560       * <mk>uniqueItems</mk> field.
2561       *
2562       * <p>
2563       * If <jk>true</jk>, the input validates successfully if all of its elements are unique.
2564       *
2565       * <p>
2566       * <br>If the parameter type is a subclass of {@link Set}, this validation is skipped (since a set can only contain unique items anyway).
2567       * <br>Otherwise, the collection or array is checked for duplicate items.
2568       *
2569       * <p>
2570       * Only allowed for the following types: <js>"array"</js>.
2571       *
2572       * <p>
2573       * Applicable to the following Swagger schema objects:
2574       * <ul>
2575       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2576       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2577       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2578       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2579       * </ul>
2580       *
2581       * @param value
2582       *    The new value for this property.
2583       *    <br>Ignored if value is <jk>null</jk>.
2584       * @return This object.
2585       */
2586      public Builder uniqueItems(Boolean value) {
2587         uniqueItems = resolve(value, uniqueItems);
2588         return this;
2589      }
2590
2591      /**
2592       * Synonym for {@link #uniqueItems(Boolean)}.
2593       *
2594       * @param value
2595       *    The new value for this property.
2596       * @return This object.
2597       */
2598      public Builder ui(Boolean value) {
2599         return uniqueItems(value);
2600      }
2601
2602      /**
2603       * <mk>uniqueItems</mk> field.
2604       *
2605       * <p>
2606       * Same as {@link #uniqueItems(Boolean)} but takes in a string boolean.
2607       *
2608       * @param value
2609       *    The new value for this property.
2610       *    <br>Ignored if value is <jk>null</jk> or empty..
2611       * @return This object.
2612       */
2613      public Builder uniqueItems(String value) {
2614         uniqueItems = resolve(value, uniqueItems);
2615         return this;
2616      }
2617
2618      /**
2619       * Synonym for {@link #uniqueItems(String)}.
2620       *
2621       * @param value
2622       *    The new value for this property.
2623       * @return This object.
2624       */
2625      public Builder ui(String value) {
2626         return uniqueItems(value);
2627      }
2628
2629      /**
2630       * <mk>uniqueItems</mk> field.
2631       *
2632       * <p>
2633       * Shortcut for calling <code>uniqueItems(<jk>true</jk>);</code>.
2634       *
2635       * @return This object.
2636       */
2637      public Builder uniqueItems() {
2638         return uniqueItems(true);
2639      }
2640
2641      /**
2642       * Synonym for {@link #uniqueItems()}.
2643       *
2644       * @return This object.
2645       */
2646      public Builder ui() {
2647         return uniqueItems();
2648      }
2649
2650      /**
2651       * <mk>skipIfEmpty</mk> field.
2652       *
2653       * <p>
2654       * Identifies whether an item should be skipped during serialization if it's empty.
2655       *
2656       * @param value
2657       *    The new value for this property.
2658       *    <br>Ignored if value is <jk>null</jk>.
2659       * @return This object.
2660       */
2661      public Builder skipIfEmpty(Boolean value) {
2662         skipIfEmpty = resolve(value, skipIfEmpty);
2663         return this;
2664      }
2665
2666      /**
2667       * Synonym for {@link #skipIfEmpty(Boolean)}.
2668       *
2669       * @param value
2670       *    The new value for this property.
2671       * @return This object.
2672       */
2673      public Builder sie(Boolean value) {
2674         return skipIfEmpty(value);
2675      }
2676
2677      /**
2678       * <mk>skipIfEmpty</mk> field.
2679       *
2680       * <p>
2681       * Same as {@link #skipIfEmpty(Boolean)} but takes in a string boolean.
2682       *
2683       * @param value
2684       *    The new value for this property.
2685       *    <br>Ignored if value is <jk>null</jk> or empty.
2686       * @return This object.
2687       */
2688      public Builder skipIfEmpty(String value) {
2689         skipIfEmpty = resolve(value, skipIfEmpty);
2690         return this;
2691      }
2692
2693      /**
2694       * Synonym for {@link #skipIfEmpty(String)}.
2695       *
2696       * @param value
2697       *    The new value for this property.
2698       * @return This object.
2699       */
2700      public Builder sie(String value) {
2701         return skipIfEmpty(value);
2702      }
2703
2704      /**
2705       * Identifies whether an item should be skipped if it's empty.
2706       *
2707       * <p>
2708       * Shortcut for calling <code>skipIfEmpty(<jk>true</jk>);</code>.
2709       *
2710       * @return This object.
2711       */
2712      public Builder skipIfEmpty() {
2713         return skipIfEmpty(true);
2714      }
2715
2716      /**
2717       * Synonym for {@link #skipIfEmpty()}.
2718       *
2719       * @return This object.
2720       */
2721      public Builder sie() {
2722         return skipIfEmpty();
2723      }
2724
2725      /**
2726       * <mk>enum</mk> field.
2727       *
2728       * <p>
2729       * If specified, the input validates successfully if it is equal to one of the elements in this array.
2730       *
2731       * <p>
2732       * Applicable to the following Swagger schema objects:
2733       * <ul>
2734       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2735       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2736       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2737       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2738       * </ul>
2739       *
2740       * @param value
2741       *    The new value for this property.
2742       *    <br>Ignored if value is <jk>null</jk> or an empty set.
2743       * @return This object.
2744       */
2745      public Builder _enum(Set<String> value) {
2746         if (value != null && ! value.isEmpty())
2747            this._enum = value;
2748         return this;
2749      }
2750
2751      /**
2752       * Synonym for {@link #_enum(Set)}.
2753       *
2754       * @param value
2755       *    The new value for this property.
2756       * @return This object.
2757       */
2758      public Builder e(Set<String> value) {
2759         return _enum(value);
2760      }
2761
2762      /**
2763       * <mk>_enum</mk> field.
2764       *
2765       * <p>
2766       * Same as {@link #_enum(Set)} but takes in a var-args array.
2767       *
2768       * @param values
2769       *    The new values for this property.
2770       *    <br>Ignored if value is empty.
2771       * @return This object.
2772       */
2773      public Builder _enum(String...values) {
2774         return _enum(Utils.set(values));
2775      }
2776
2777      /**
2778       * Synonym for {@link #_enum(String...)}.
2779       *
2780       * @param values
2781       *    The new values for this property.
2782       * @return This object.
2783       */
2784      public Builder e(String...values) {
2785         return _enum(values);
2786      }
2787
2788      /**
2789       * <mk>multipleOf</mk> field.
2790       *
2791       * <p>
2792       * A numeric instance is valid if the result of the division of the instance by this keyword's value is an integer.
2793       *
2794       * <p>
2795       * Only allowed for the following types: <js>"integer"</js>, <js>"number"</js>.
2796       *
2797       * <p>
2798       * Applicable to the following Swagger schema objects:
2799       * <ul>
2800       *    <li><a class="doclink" href="https://swagger.io/specification/v2#parameterObject">Parameter</a>
2801       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2802       *    <li><a class="doclink" href="https://swagger.io/specification/v2#itemsObject">Items</a>
2803       *    <li><a class="doclink" href="https://swagger.io/specification/v2#headerObject">Header</a>
2804       * </ul>
2805       *
2806       * @param value
2807       *    The new value for this property.
2808       *    <br>Ignored if value is <jk>null</jk>.
2809       * @return This object.
2810       */
2811      public Builder multipleOf(Number value) {
2812         if (value != null)
2813            this.multipleOf = value;
2814         return this;
2815      }
2816
2817      /**
2818       * Synonym for {@link #multipleOf(Number)}.
2819       *
2820       * @param value
2821       *    The new value for this property.
2822       * @return This object.
2823       */
2824      public Builder mo(Number value) {
2825         return multipleOf(value);
2826      }
2827
2828      /**
2829       * <mk>mapProperties</mk> field.
2830       *
2831       * <p>
2832       * Applicable to the following Swagger schema objects:
2833       * <ul>
2834       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2835       * </ul>
2836       *
2837       * @param value
2838       *    The new value for this property.
2839       *    <br>Ignored if value is <jk>null</jk> or <c>-1</c>.
2840       * @return This object.
2841       */
2842      public Builder maxProperties(Long value) {
2843         maxProperties = resolve(value, maxProperties);
2844         return this;
2845      }
2846
2847      /**
2848       * Synonym for {@link #maxProperties(Long)}.
2849       *
2850       * @param value
2851       *    The new value for this property.
2852       * @return This object.
2853       */
2854      public Builder maxp(Long value) {
2855         return maxProperties(value);
2856      }
2857
2858      /**
2859       * <mk>mapProperties</mk> field.
2860       *
2861       * <p>
2862       * Same as {@link #maxProperties(Long)} but takes in a string number.
2863       *
2864       * @param value
2865       *    The new value for this property.
2866       *    <br>Ignored if value is <jk>null</jk> or empty.
2867       * @return This object.
2868       */
2869      public Builder maxProperties(String value) {
2870         maxProperties = resolve(value, maxProperties);
2871         return this;
2872      }
2873
2874      /**
2875       * Synonym for {@link #maxProperties(String)}.
2876       *
2877       * @param value
2878       *    The new value for this property.
2879       * @return This object.
2880       */
2881      public Builder maxp(String value) {
2882         return maxProperties(value);
2883      }
2884
2885      /**
2886       * <mk>minProperties</mk> field.
2887       *
2888       * <p>
2889       * Applicable to the following Swagger schema objects:
2890       * <ul>
2891       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2892       * </ul>
2893       *
2894       * @param value
2895       *    The new value for this property.
2896       *    <br>Ignored if value is <jk>null</jk>.
2897       * @return This object.
2898       */
2899      public Builder minProperties(Long value) {
2900         minProperties = resolve(value, minProperties);
2901         return this;
2902      }
2903
2904      /**
2905       * Synonym for {@link #minProperties(Long)}.
2906       *
2907       * @param value
2908       *    The new value for this property.
2909       * @return This object.
2910       */
2911      public Builder minp(Long value) {
2912         return minProperties(value);
2913      }
2914
2915      /**
2916       * <mk>minProperties</mk> field.
2917       *
2918       * <p>
2919       * Same as {@link #minProperties(Long)} but takes in a string boolean.
2920       *
2921       * @param value
2922       *    The new value for this property.
2923       *    <br>Ignored if value is <jk>null</jk> or empty.
2924       * @return This object.
2925       */
2926      public Builder minProperties(String value) {
2927         minProperties = resolve(value, minProperties);
2928         return this;
2929      }
2930
2931      /**
2932       * Synonym for {@link #minProperties(String)}.
2933       *
2934       * @param value
2935       *    The new value for this property.
2936       * @return This object.
2937       */
2938      public Builder minp(String value) {
2939         return minProperties(value);
2940      }
2941
2942      /**
2943       * <mk>properties</mk> field.
2944       *
2945       * <p>
2946       * Applicable to the following Swagger schema objects:
2947       * <ul>
2948       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2949       * </ul>
2950       *
2951       * @param key
2952       * The property name.
2953       * @param value
2954       *    The new value for this property.
2955       *    <br>Ignored if value is <jk>null</jk>.
2956       * @return This object.
2957       */
2958      public Builder property(String key, Builder value) {
2959         if ( key != null && value != null) {
2960            if (properties == null)
2961               properties = map();
2962            properties.put(key, value);
2963         }
2964         return this;
2965      }
2966
2967      /**
2968       * <mk>properties</mk> field.
2969       *
2970       * <p>
2971       * Applicable to the following Swagger schema objects:
2972       * <ul>
2973       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2974       * </ul>
2975       *
2976       * @param key
2977       * The property name.
2978       * @param value
2979       *    The new value for this property.
2980       *    <br>Ignored if value is <jk>null</jk>.
2981       * @return This object.
2982       */
2983      public Builder property(String key, HttpPartSchema value) {
2984         if ( key != null && value != null) {
2985            if (properties == null)
2986               properties = map();
2987            properties.put(key, value);
2988         }
2989         return this;
2990      }
2991
2992      /**
2993       * Shortcut for <c>property(key, value)</c>.
2994       *
2995       * <p>
2996       * Applicable to the following Swagger schema objects:
2997       * <ul>
2998       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
2999       * </ul>
3000       *
3001       * @param key
3002       * The property name.
3003       * @param value
3004       *    The new value for this property.
3005       *    <br>Ignored if value is <jk>null</jk>.
3006       * @return This object.
3007       */
3008      public Builder p(String key, Builder value) {
3009         return property(key, value);
3010      }
3011
3012      /**
3013       * Shortcut for <c>property(key, value)</c>.
3014       *
3015       * <p>
3016       * Applicable to the following Swagger schema objects:
3017       * <ul>
3018       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
3019       * </ul>
3020       *
3021       * @param key
3022       * The property name.
3023       * @param value
3024       *    The new value for this property.
3025       *    <br>Ignored if value is <jk>null</jk>.
3026       * @return This object.
3027       */
3028      public Builder p(String key, HttpPartSchema value) {
3029         return property(key, value);
3030      }
3031
3032      private Builder properties(JsonMap value) {
3033         if (value != null)
3034            value.forEach((k,v) -> property(k, HttpPartSchema.create().apply((JsonMap)v)));
3035         return this;
3036      }
3037
3038      /**
3039       * <mk>additionalProperties</mk> field.
3040       *
3041       * <p>
3042       * Applicable to the following Swagger schema objects:
3043       * <ul>
3044       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
3045       * </ul>
3046       *
3047       * @param value
3048       *    The new value for this property.
3049       *    <br>Ignored if value is <jk>null</jk> or empty.
3050       * @return This object.
3051       */
3052      public Builder additionalProperties(Builder value) {
3053         if (value != null)
3054            additionalProperties = value;
3055         return this;
3056      }
3057
3058      /**
3059       * <mk>additionalProperties</mk> field.
3060       *
3061       * <p>
3062       * Applicable to the following Swagger schema objects:
3063       * <ul>
3064       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
3065       * </ul>
3066       *
3067       * @param value
3068       *    The new value for this property.
3069       *    <br>Ignored if value is <jk>null</jk> or empty.
3070       * @return This object.
3071       */
3072      public Builder additionalProperties(HttpPartSchema value) {
3073         if (value != null)
3074            additionalProperties = value;
3075         return this;
3076      }
3077
3078      /**
3079       * Shortcut for <c>additionalProperties(value)</c>
3080       *
3081       * <p>
3082       * Applicable to the following Swagger schema objects:
3083       * <ul>
3084       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
3085       * </ul>
3086       *
3087       * @param value
3088       *    The new value for this property.
3089       *    <br>Ignored if value is <jk>null</jk> or empty.
3090       * @return This object.
3091       */
3092      public Builder ap(Builder value) {
3093         return additionalProperties(value);
3094      }
3095
3096      /**
3097       * Shortcut for <c>additionalProperties(value)</c>
3098       *
3099       * <p>
3100       * Applicable to the following Swagger schema objects:
3101       * <ul>
3102       *    <li><a class="doclink" href="https://swagger.io/specification/v2#schemaObject">Schema</a>
3103       * </ul>
3104       *
3105       * @param value
3106       *    The new value for this property.
3107       *    <br>Ignored if value is <jk>null</jk> or empty.
3108       * @return This object.
3109       */
3110      public Builder ap(HttpPartSchema value) {
3111         return additionalProperties(value);
3112      }
3113
3114      private Builder additionalProperties(JsonMap value) {
3115         if (value != null && ! value.isEmpty())
3116            additionalProperties = HttpPartSchema.create().apply(value);
3117         return this;
3118      }
3119
3120      /**
3121       * Identifies the part serializer to use for serializing this part.
3122       *
3123       * @param value
3124       *    The new value for this property.
3125       *    <br>Ignored if value is <jk>null</jk> or {@link HttpPartSerializer.Void}.
3126       * @return This object.
3127       */
3128      public Builder serializer(Class<? extends HttpPartSerializer> value) {
3129         if (isNotVoid(value))
3130            serializer = value;
3131         return this;
3132      }
3133
3134      /**
3135       * Identifies the part parser to use for parsing this part.
3136       *
3137       * @param value
3138       *    The new value for this property.
3139       *    <br>Ignored if value is <jk>null</jk> or {@link HttpPartParser.Void}.
3140       * @return This object.
3141       */
3142      public Builder parser(Class<? extends HttpPartParser> value) {
3143         if (isNotVoid(value))
3144            parser = value;
3145         return this;
3146      }
3147
3148      /**
3149       * Disables Swagger schema usage validation checking.
3150       *
3151       * @param value Specify <jk>true</jk> to prevent {@link ContextRuntimeException} from being thrown if invalid Swagger usage was detected.
3152       * @return This object.
3153       */
3154      public Builder noValidate(Boolean value) {
3155         if (value != null)
3156            this.noValidate = value;
3157         return this;
3158      }
3159
3160      /**
3161       * Disables Swagger schema usage validation checking.
3162       *
3163       * <p>
3164       * Shortcut for calling <code>noValidate(<jk>true</jk>);</code>.
3165       *
3166       * @return This object.
3167       */
3168      public Builder noValidate() {
3169         return noValidate(true);
3170      }
3171
3172      private Boolean resolve(String newValue, Boolean oldValue) {
3173         return Utils.isEmpty(newValue) ? oldValue : Boolean.valueOf(newValue);
3174      }
3175
3176      private Boolean resolve(Boolean newValue, Boolean oldValue) {
3177         return newValue == null ? oldValue : newValue;
3178      }
3179
3180      private Long resolve(String newValue, Long oldValue) {
3181         return Utils.isEmpty(newValue) ? oldValue : Long.parseLong(newValue);
3182      }
3183
3184      private Long resolve(Long newValue, Long oldValue) {
3185         return (newValue == null || newValue == -1) ? oldValue : newValue;
3186      }
3187
3188      private Set<String> toSet(String[]...s) {
3189         return HttpPartSchema.toSet(s);
3190      }
3191
3192      private Number toNumber(String...s) {
3193         return HttpPartSchema.toNumber(s);
3194      }
3195
3196      private Long firstNmo(Long...l) {
3197         for (Long ll : l)
3198            if (ll != null && ll != -1)
3199               return ll;
3200         return null;
3201      }
3202
3203      private String joinnlOrNull(String[]...s) {
3204         for (String[] ss : s)
3205            if (ss.length > 0)
3206               return Utils.joinnl(ss);
3207         return null;
3208      }
3209   }
3210
3211   //-------------------------------------------------------------------------------------------------------------------
3212   // Instance
3213   //-------------------------------------------------------------------------------------------------------------------
3214
3215   final String name;
3216   final String _default;
3217   final Set<String> _enum;
3218   final Map<String,HttpPartSchema> properties;
3219   final boolean allowEmptyValue, exclusiveMaximum, exclusiveMinimum, required, uniqueItems, skipIfEmpty;
3220   final HttpPartCollectionFormat collectionFormat;
3221   final HttpPartDataType type;
3222   final HttpPartFormat format;
3223   final Pattern pattern;
3224   final HttpPartSchema items, additionalProperties;
3225   final Number maximum, minimum, multipleOf;
3226   final Long maxLength, minLength, maxItems, minItems, maxProperties, minProperties;
3227   final Class<? extends HttpPartParser> parser;
3228   final Class<? extends HttpPartSerializer> serializer;
3229   final ClassMeta<?> parsedType;
3230
3231   HttpPartSchema(Builder b) {
3232      this.name = b.name;
3233      this._default = b._default;
3234      this._enum = copy(b._enum);
3235      this.properties = build(b.properties, b.noValidate);
3236      this.allowEmptyValue = resolve(b.allowEmptyValue);
3237      this.exclusiveMaximum = resolve(b.exclusiveMaximum);
3238      this.exclusiveMinimum = resolve(b.exclusiveMinimum);
3239      this.required = resolve(b.required);
3240      this.uniqueItems = resolve(b.uniqueItems);
3241      this.skipIfEmpty = resolve(b.skipIfEmpty);
3242      this.collectionFormat = b.collectionFormat;
3243      this.type = b.type;
3244      this.format = b.format;
3245      this.pattern = b.pattern;
3246      this.items = build(b.items, b.noValidate);
3247      this.additionalProperties = build(b.additionalProperties, b.noValidate);
3248      this.maximum = b.maximum;
3249      this.minimum = b.minimum;
3250      this.multipleOf = b.multipleOf;
3251      this.maxItems = b.maxItems;
3252      this.maxLength = b.maxLength;
3253      this.maxProperties = b.maxProperties;
3254      this.minItems = b.minItems;
3255      this.minLength = b.minLength;
3256      this.minProperties = b.minProperties;
3257      this.parser = b.parser;
3258      this.serializer = b.serializer;
3259
3260      // Calculate parse type
3261      Class<?> parsedType = Object.class;
3262      if (type == ARRAY) {
3263         if (items != null)
3264            parsedType = Array.newInstance(items.parsedType.getInnerClass(), 0).getClass();
3265      } else if (type == BOOLEAN) {
3266         parsedType = Boolean.class;
3267      } else if (type == INTEGER) {
3268         if (format == INT64)
3269            parsedType = Long.class;
3270         else
3271            parsedType = Integer.class;
3272      } else if (type == NUMBER) {
3273         if (format == DOUBLE)
3274            parsedType = Double.class;
3275         else
3276            parsedType = Float.class;
3277      } else if (type == STRING) {
3278         if (format == BYTE || format == BINARY || format == BINARY_SPACED)
3279            parsedType = byte[].class;
3280         else if (format == DATE || format == DATE_TIME)
3281            parsedType = Calendar.class;
3282         else
3283            parsedType = String.class;
3284      }
3285      this.parsedType = BeanContext.DEFAULT.getClassMeta(parsedType);
3286
3287      if (b.noValidate)
3288         return;
3289
3290      // Validation.
3291      List<String> errors = Utils.list();
3292      ListBuilder<String> notAllowed = listBuilder(String.class);
3293      boolean invalidFormat = false;
3294      switch (type) {
3295         case STRING: {
3296            notAllowed
3297               .addIf(properties != null, "properties")
3298               .addIf(additionalProperties != null, "additionalProperties")
3299               .addIf(exclusiveMaximum, "exclusiveMaximum")
3300               .addIf(exclusiveMinimum, "exclusiveMinimum")
3301               .addIf(uniqueItems, "uniqueItems")
3302               .addIf(collectionFormat != HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat")
3303               .addIf(items != null, "items")
3304               .addIf(maximum != null, "maximum")
3305               .addIf(minimum != null, "minimum")
3306               .addIf(multipleOf != null, "multipleOf")
3307               .addIf(maxItems != null, "maxItems")
3308               .addIf(minItems != null, "minItems")
3309               .addIf(minProperties != null, "minProperties");
3310            invalidFormat = ! format.isOneOf(HttpPartFormat.BYTE, HttpPartFormat.BINARY, HttpPartFormat.BINARY_SPACED, HttpPartFormat.DATE, HttpPartFormat.DATE_TIME, HttpPartFormat.PASSWORD, HttpPartFormat.UON, HttpPartFormat.NO_FORMAT);
3311            break;
3312         }
3313         case ARRAY: {
3314            notAllowed.addIf(properties != null, "properties")
3315               .addIf(additionalProperties != null, "additionalProperties")
3316               .addIf(exclusiveMaximum, "exclusiveMaximum")
3317               .addIf(exclusiveMinimum, "exclusiveMinimum")
3318               .addIf(pattern != null, "pattern")
3319               .addIf(maximum != null, "maximum")
3320               .addIf(minimum != null, "minimum")
3321               .addIf(multipleOf != null, "multipleOf")
3322               .addIf(maxLength != null, "maxLength")
3323               .addIf(minLength != null, "minLength")
3324               .addIf(maxProperties != null, "maxProperties")
3325               .addIf(minProperties != null, "minProperties");
3326            invalidFormat = ! format.isOneOf(HttpPartFormat.NO_FORMAT, HttpPartFormat.UON);
3327            break;
3328         }
3329         case BOOLEAN: {
3330            notAllowed.addIf(! _enum.isEmpty(), "_enum")
3331               .addIf(properties != null, "properties")
3332               .addIf(additionalProperties != null, "additionalProperties")
3333               .addIf(exclusiveMaximum, "exclusiveMaximum")
3334               .addIf(exclusiveMinimum, "exclusiveMinimum")
3335               .addIf(uniqueItems, "uniqueItems")
3336               .addIf(collectionFormat != HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat")
3337               .addIf(pattern != null, "pattern")
3338               .addIf(items != null, "items")
3339               .addIf(maximum != null, "maximum")
3340               .addIf(minimum != null, "minimum")
3341               .addIf(multipleOf != null, "multipleOf")
3342               .addIf(maxItems != null, "maxItems")
3343               .addIf(maxLength != null, "maxLength")
3344               .addIf(maxProperties != null, "maxProperties")
3345               .addIf(minItems != null, "minItems")
3346               .addIf(minLength != null, "minLength")
3347               .addIf(minProperties != null, "minProperties");
3348            invalidFormat = ! format.isOneOf(HttpPartFormat.NO_FORMAT, HttpPartFormat.UON);
3349            break;
3350         }
3351         case FILE: {
3352            break;
3353         }
3354         case INTEGER: {
3355            notAllowed.addIf(properties != null, "properties")
3356               .addIf(additionalProperties != null, "additionalProperties")
3357               .addIf(uniqueItems, "uniqueItems")
3358               .addIf(collectionFormat != HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat")
3359               .addIf(pattern != null, "pattern")
3360               .addIf(items != null, "items")
3361               .addIf(maxItems != null, "maxItems")
3362               .addIf(maxLength != null, "maxLength")
3363               .addIf(maxProperties != null, "maxProperties")
3364               .addIf(minItems != null, "minItems")
3365               .addIf(minLength != null, "minLength")
3366               .addIf(minProperties != null, "minProperties");
3367            invalidFormat = ! format.isOneOf(HttpPartFormat.NO_FORMAT, HttpPartFormat.UON, HttpPartFormat.INT32, HttpPartFormat.INT64);
3368            break;
3369         }
3370         case NUMBER: {
3371            notAllowed.addIf(properties != null, "properties")
3372               .addIf(additionalProperties != null, "additionalProperties")
3373               .addIf(uniqueItems, "uniqueItems")
3374               .addIf(collectionFormat != HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat")
3375               .addIf(pattern != null, "pattern")
3376               .addIf(items != null, "items")
3377               .addIf(maxItems != null, "maxItems")
3378               .addIf(maxLength != null, "maxLength")
3379               .addIf(maxProperties != null, "maxProperties")
3380               .addIf(minItems != null, "minItems")
3381               .addIf(minLength != null, "minLength")
3382               .addIf(minProperties != null, "minProperties");
3383            invalidFormat = ! format.isOneOf(HttpPartFormat.NO_FORMAT, HttpPartFormat.UON, HttpPartFormat.FLOAT, HttpPartFormat.DOUBLE);
3384            break;
3385         }
3386         case OBJECT: {
3387            notAllowed.addIf(exclusiveMaximum, "exclusiveMaximum")
3388               .addIf(exclusiveMinimum, "exclusiveMinimum")
3389               .addIf(uniqueItems, "uniqueItems")
3390               .addIf(pattern != null, "pattern")
3391               .addIf(items != null, "items")
3392               .addIf(maximum != null, "maximum")
3393               .addIf(minimum != null, "minimum")
3394               .addIf(multipleOf != null, "multipleOf")
3395               .addIf(maxItems != null, "maxItems")
3396               .addIf(maxLength != null, "maxLength")
3397               .addIf(minItems != null, "minItems")
3398               .addIf(minLength != null, "minLength");
3399            invalidFormat = ! format.isOneOf(HttpPartFormat.NO_FORMAT);
3400            break;
3401         }
3402         default:
3403            break;
3404      }
3405
3406      List<String> notAllowed2 = notAllowed.build();
3407      if (! notAllowed2.isEmpty())
3408         errors.add("Attributes not allow for type='"+type+"': " + Utils.join(notAllowed2, ","));
3409      if (invalidFormat)
3410         errors.add("Invalid format for type='"+type+"': '"+format+"'");
3411      if (exclusiveMaximum && maximum == null)
3412         errors.add("Cannot specify exclusiveMaximum with maximum.");
3413      if (exclusiveMinimum && minimum == null)
3414         errors.add("Cannot specify exclusiveMinimum with minimum.");
3415      if (required && _default != null)
3416         errors.add("Cannot specify a default value on a required value.");
3417      if (minLength != null && maxLength != null && maxLength < minLength)
3418         errors.add("maxLength cannot be less than minLength.");
3419      if (minimum != null && maximum != null && maximum.doubleValue() < minimum.doubleValue())
3420         errors.add("maximum cannot be less than minimum.");
3421      if (minItems != null && maxItems != null && maxItems < minItems)
3422         errors.add("maxItems cannot be less than minItems.");
3423      if (minProperties != null && maxProperties != null && maxProperties < minProperties)
3424         errors.add("maxProperties cannot be less than minProperties.");
3425      if (minLength != null && minLength < 0)
3426         errors.add("minLength cannot be less than zero.");
3427      if (maxLength != null && maxLength < 0)
3428         errors.add("maxLength cannot be less than zero.");
3429      if (minItems != null && minItems < 0)
3430         errors.add("minItems cannot be less than zero.");
3431      if (maxItems != null && maxItems < 0)
3432         errors.add("maxItems cannot be less than zero.");
3433      if (minProperties != null && minProperties < 0)
3434         errors.add("minProperties cannot be less than zero.");
3435      if (maxProperties != null && maxProperties < 0)
3436         errors.add("maxProperties cannot be less than zero.");
3437      if (type == ARRAY && items != null && items.getType() == OBJECT && (format != UON && format != HttpPartFormat.NO_FORMAT))
3438         errors.add("Cannot define an array of objects unless array format is 'uon'.");
3439
3440      if (! errors.isEmpty())
3441         throw new ContextRuntimeException("Schema specification errors: \n\t" + Utils.join(errors, "\n\t"), new Object[0]);
3442   }
3443
3444   /**
3445    * Returns the default parsed type for this schema.
3446    *
3447    * @return The default parsed type for this schema.  Never <jk>null</jk>.
3448    */
3449   public ClassMeta<?> getParsedType() {
3450      return parsedType;
3451   }
3452
3453   /**
3454    * Returns the name of the object described by this schema, for example the query or form parameter name.
3455    *
3456    * @return The name, or <jk>null</jk> if not specified.
3457    * @see HttpPartSchema.Builder#name(String)
3458    */
3459   public String getName() {
3460      return name;
3461   }
3462
3463   /**
3464    * Returns the <c>type</c> field of this schema.
3465    *
3466    * @return The <c>type</c> field of this schema, or <jk>null</jk> if not specified.
3467    * @see HttpPartSchema.Builder#type(String)
3468    */
3469   public HttpPartDataType getType() {
3470      return type;
3471   }
3472
3473   /**
3474    * Returns the <c>type</c> field of this schema.
3475    *
3476    * @param cm
3477    *    The class meta of the object.
3478    *    <br>Used to auto-detect the type if the type was not specified.
3479    * @return The format field of this schema, or <jk>null</jk> if not specified.
3480    * @see HttpPartSchema.Builder#format(String)
3481    */
3482   public HttpPartDataType getType(ClassMeta<?> cm) {
3483      if (type != HttpPartDataType.NO_TYPE)
3484         return type;
3485      if (cm.isTemporal() || cm.isDateOrCalendar())
3486         return HttpPartDataType.STRING;
3487      if (cm.isNumber()) {
3488         if (cm.isDecimal())
3489            return HttpPartDataType.NUMBER;
3490         return HttpPartDataType.INTEGER;
3491      }
3492      if (cm.isBoolean())
3493         return HttpPartDataType.BOOLEAN;
3494      if (cm.isMapOrBean())
3495         return HttpPartDataType.OBJECT;
3496      if (cm.isCollectionOrArray())
3497         return HttpPartDataType.ARRAY;
3498      return HttpPartDataType.STRING;
3499   }
3500
3501   /**
3502    * Returns the <c>default</c> field of this schema.
3503    *
3504    * @return The default value for this schema, or <jk>null</jk> if not specified.
3505    * @see HttpPartSchema.Builder#_default(String)
3506    */
3507   public String getDefault() {
3508      return _default;
3509   }
3510
3511   /**
3512    * Returns the <c>collectionFormat</c> field of this schema.
3513    *
3514    * @return The <c>collectionFormat</c> field of this schema, or <jk>null</jk> if not specified.
3515    * @see HttpPartSchema.Builder#collectionFormat(String)
3516    */
3517   public HttpPartCollectionFormat getCollectionFormat() {
3518      return collectionFormat;
3519   }
3520
3521   /**
3522    * Returns the <c>format</c> field of this schema.
3523    *
3524    * @see HttpPartSchema.Builder#format(String)
3525    * @return The <c>format</c> field of this schema, or <jk>null</jk> if not specified.
3526    */
3527   public HttpPartFormat getFormat() {
3528      return format;
3529   }
3530
3531   /**
3532    * Returns the <c>format</c> field of this schema.
3533    *
3534    * @param cm
3535    *    The class meta of the object.
3536    *    <br>Used to auto-detect the format if the format was not specified.
3537    * @return The <c>format</c> field of this schema, or <jk>null</jk> if not specified.
3538    * @see HttpPartSchema.Builder#format(String)
3539    */
3540   public HttpPartFormat getFormat(ClassMeta<?> cm) {
3541      if (format != HttpPartFormat.NO_FORMAT)
3542         return format;
3543      if (cm.isNumber()) {
3544         if (cm.isDecimal()) {
3545            if (cm.isDouble())
3546               return HttpPartFormat.DOUBLE;
3547            return HttpPartFormat.FLOAT;
3548         }
3549         if (cm.isLong())
3550            return HttpPartFormat.INT64;
3551         return HttpPartFormat.INT32;
3552      }
3553      return format;
3554   }
3555
3556   /**
3557    * Returns the <c>maximum</c> field of this schema.
3558    *
3559    * @return The schema for child items of the object represented by this schema, or <jk>null</jk> if not defined.
3560    * @see HttpPartSchema.Builder#items(HttpPartSchema.Builder)
3561    */
3562   public HttpPartSchema getItems() {
3563      return items;
3564   }
3565
3566   /**
3567    * Returns the <c>maximum</c> field of this schema.
3568    *
3569    * @return The <c>maximum</c> field of this schema, or <jk>null</jk> if not specified.
3570    * @see HttpPartSchema.Builder#maximum(Number)
3571    */
3572   public Number getMaximum() {
3573      return maximum;
3574   }
3575
3576   /**
3577    * Returns the <c>minimum</c> field of this schema.
3578    *
3579    * @return The <c>minimum</c> field of this schema, or <jk>null</jk> if not specified.
3580    * @see HttpPartSchema.Builder#minimum(Number)
3581    */
3582   public Number getMinimum() {
3583      return minimum;
3584   }
3585
3586   /**
3587    * Returns the <c>xxx</c> field of this schema.
3588    *
3589    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3590    * @see HttpPartSchema.Builder#multipleOf(Number)
3591    */
3592   public Number getMultipleOf() {
3593      return multipleOf;
3594   }
3595
3596   /**
3597    * Returns the <c>xxx</c> field of this schema.
3598    *
3599    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3600    * @see HttpPartSchema.Builder#pattern(String)
3601    */
3602   public Pattern getPattern() {
3603      return pattern;
3604   }
3605
3606   /**
3607    * Returns the <c>xxx</c> field of this schema.
3608    *
3609    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3610    * @see HttpPartSchema.Builder#maxLength(Long)
3611    */
3612   public Long getMaxLength() {
3613      return maxLength;
3614   }
3615
3616   /**
3617    * Returns the <c>xxx</c> field of this schema.
3618    *
3619    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3620    * @see HttpPartSchema.Builder#minLength(Long)
3621    */
3622   public Long getMinLength() {
3623      return minLength;
3624   }
3625
3626   /**
3627    * Returns the <c>xxx</c> field of this schema.
3628    *
3629    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3630    * @see HttpPartSchema.Builder#maxItems(Long)
3631    */
3632   public Long getMaxItems() {
3633      return maxItems;
3634   }
3635
3636   /**
3637    * Returns the <c>xxx</c> field of this schema.
3638    *
3639    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3640    * @see HttpPartSchema.Builder#minItems(Long)
3641    */
3642   public Long getMinItems() {
3643      return minItems;
3644   }
3645
3646   /**
3647    * Returns the <c>xxx</c> field of this schema.
3648    *
3649    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3650    * @see HttpPartSchema.Builder#maxProperties(Long)
3651    */
3652   public Long getMaxProperties() {
3653      return maxProperties;
3654   }
3655
3656   /**
3657    * Returns the <c>xxx</c> field of this schema.
3658    *
3659    * @return The <c>xxx</c> field of this schema, or <jk>null</jk> if not specified.
3660    * @see HttpPartSchema.Builder#minProperties(Long)
3661    */
3662   public Long getMinProperties() {
3663      return minProperties;
3664   }
3665
3666   /**
3667    * Returns the <c>exclusiveMaximum</c> field of this schema.
3668    *
3669    * @return The <c>exclusiveMaximum</c> field of this schema.
3670    * @see HttpPartSchema.Builder#exclusiveMaximum(Boolean)
3671    */
3672   public boolean isExclusiveMaximum() {
3673      return exclusiveMaximum;
3674   }
3675
3676   /**
3677    * Returns the <c>exclusiveMinimum</c> field of this schema.
3678    *
3679    * @return The <c>exclusiveMinimum</c> field of this schema.
3680    * @see HttpPartSchema.Builder#exclusiveMinimum(Boolean)
3681    */
3682   public boolean isExclusiveMinimum() {
3683      return exclusiveMinimum;
3684   }
3685
3686   /**
3687    * Returns the <c>uniqueItems</c> field of this schema.
3688    *
3689    * @return The <c>uniqueItems</c> field of this schema.
3690    * @see HttpPartSchema.Builder#uniqueItems(Boolean)
3691    */
3692   public boolean isUniqueItems() {
3693      return uniqueItems;
3694   }
3695
3696   /**
3697    * Returns the <c>required</c> field of this schema.
3698    *
3699    * @return The <c>required</c> field of this schema.
3700    * @see HttpPartSchema.Builder#required(Boolean)
3701    */
3702   public boolean isRequired() {
3703      return required;
3704   }
3705
3706   /**
3707    * Returns the <c>skipIfEmpty</c> field of this schema.
3708    *
3709    * @return The <c>skipIfEmpty</c> field of this schema.
3710    * @see HttpPartSchema.Builder#skipIfEmpty(Boolean)
3711    */
3712   public boolean isSkipIfEmpty() {
3713      return skipIfEmpty;
3714   }
3715
3716   /**
3717    * Returns the <c>allowEmptyValue</c> field of this schema.
3718    *
3719    * @return The <c>skipIfEmpty</c> field of this schema.
3720    * @see HttpPartSchema.Builder#skipIfEmpty(Boolean)
3721    */
3722   public boolean isAllowEmptyValue() {
3723      return allowEmptyValue;
3724   }
3725
3726   /**
3727    * Returns the <c>enum</c> field of this schema.
3728    *
3729    * @return The <c>enum</c> field of this schema, or <jk>null</jk> if not specified.
3730    * @see HttpPartSchema.Builder#_enum(Set)
3731    */
3732   public Set<String> getEnum() {
3733      return _enum;
3734   }
3735
3736   /**
3737    * Returns the <c>parser</c> field of this schema.
3738    *
3739    * @return The <c>parser</c> field of this schema, or <jk>null</jk> if not specified.
3740    * @see HttpPartSchema.Builder#parser(Class)
3741    */
3742   public Class<? extends HttpPartParser> getParser() {
3743      return parser;
3744   }
3745
3746   /**
3747    * Returns the <c>serializer</c> field of this schema.
3748    *
3749    * @return The <c>serializer</c> field of this schema, or <jk>null</jk> if not specified.
3750    * @see HttpPartSchema.Builder#serializer(Class)
3751    */
3752   public Class<? extends HttpPartSerializer> getSerializer() {
3753      return serializer;
3754   }
3755
3756   /**
3757    * Throws a {@link ParseException} if the specified pre-parsed input does not validate against this schema.
3758    *
3759    * @param in The input.
3760    * @return The same object passed in.
3761    * @throws SchemaValidationException if the specified pre-parsed input does not validate against this schema.
3762    */
3763   public String validateInput(String in) throws SchemaValidationException {
3764      if (! isValidRequired(in))
3765         throw new SchemaValidationException("No value specified.");
3766      if (in != null) {
3767         if (! isValidAllowEmpty(in))
3768            throw new SchemaValidationException("Empty value not allowed.");
3769         if (! isValidPattern(in))
3770            throw new SchemaValidationException("Value does not match expected pattern.  Must match pattern: {0}", pattern.pattern());
3771         if (! isValidEnum(in))
3772            throw new SchemaValidationException("Value does not match one of the expected values.  Must be one of the following:  {0}", toCdl(_enum));
3773         if (! isValidMaxLength(in))
3774            throw new SchemaValidationException("Maximum length of value exceeded.");
3775         if (! isValidMinLength(in))
3776            throw new SchemaValidationException("Minimum length of value not met.");
3777      }
3778      return in;
3779   }
3780
3781   /**
3782    * Throws a {@link ParseException} if the specified parsed output does not validate against this schema.
3783    *
3784    * @param <T> The return type.
3785    * @param o The parsed output.
3786    * @param bc The bean context used to detect POJO types.
3787    * @return The same object passed in.
3788    * @throws SchemaValidationException if the specified parsed output does not validate against this schema.
3789    */
3790   public <T> T validateOutput(T o, BeanContext bc) throws SchemaValidationException {
3791      if (o == null) {
3792         if (! isValidRequired(o))
3793            throw new SchemaValidationException("Required value not provided.");
3794         return o;
3795      }
3796      ClassMeta<?> cm = bc.getClassMetaForObject(o);
3797      switch (getType(cm)) {
3798         case ARRAY: {
3799            if (cm.isArray()) {
3800               if (! isValidMinItems(o))
3801                  throw new SchemaValidationException("Minimum number of items not met.");
3802               if (! isValidMaxItems(o))
3803                  throw new SchemaValidationException("Maximum number of items exceeded.");
3804               if (! isValidUniqueItems(o))
3805                  throw new SchemaValidationException("Duplicate items not allowed.");
3806               HttpPartSchema items = getItems();
3807               if (items != null)
3808                  for (int i = 0; i < Array.getLength(o); i++)
3809                     items.validateOutput(Array.get(o, i), bc);
3810            } else if (cm.isCollection()) {
3811               Collection<?> c = (Collection<?>)o;
3812               if (! isValidMinItems(c))
3813                  throw new SchemaValidationException("Minimum number of items not met.");
3814               if (! isValidMaxItems(c))
3815                  throw new SchemaValidationException("Maximum number of items exceeded.");
3816               if (! isValidUniqueItems(c))
3817                  throw new SchemaValidationException("Duplicate items not allowed.");
3818               HttpPartSchema items = getItems();
3819               if (items != null)
3820                  c.forEach(x -> items.validateOutput(x, bc));
3821            }
3822            break;
3823         }
3824         case INTEGER: {
3825            if (cm.isNumber()) {
3826               Number n = (Number)o;
3827               if (! isValidMinimum(n))
3828                  throw new SchemaValidationException("Minimum value not met.");
3829               if (! isValidMaximum(n))
3830                  throw new SchemaValidationException("Maximum value exceeded.");
3831               if (! isValidMultipleOf(n))
3832                  throw new SchemaValidationException("Multiple-of not met.");
3833            }
3834            break;
3835         }
3836         case NUMBER: {
3837            if (cm.isNumber()) {
3838               Number n = (Number)o;
3839               if (! isValidMinimum(n))
3840                  throw new SchemaValidationException("Minimum value not met.");
3841               if (! isValidMaximum(n))
3842                  throw new SchemaValidationException("Maximum value exceeded.");
3843               if (! isValidMultipleOf(n))
3844                  throw new SchemaValidationException("Multiple-of not met.");
3845            }
3846            break;
3847         }
3848         case OBJECT: {
3849            if (cm.isMapOrBean()) {
3850               Map<?,?> m = cm.isMap() ? (Map<?,?>)o : bc.toBeanMap(o);
3851               if (! isValidMinProperties(m))
3852                  throw new SchemaValidationException("Minimum number of properties not met.");
3853               if (! isValidMaxProperties(m))
3854                  throw new SchemaValidationException("Maximum number of properties exceeded.");
3855               m.forEach((k,v) -> {
3856                  String key = k.toString();
3857                  HttpPartSchema s2 = getProperty(key);
3858                  if (s2 != null)
3859                     s2.validateOutput(v, bc);
3860               });
3861            } else if (cm.isBean()) {
3862
3863            }
3864            break;
3865         }
3866         case BOOLEAN:
3867         case FILE:
3868         case STRING:
3869         case NO_TYPE:
3870            break;
3871      }
3872      return o;
3873   }
3874
3875   //-----------------------------------------------------------------------------------------------------------------
3876   // Helper methods.
3877   //-----------------------------------------------------------------------------------------------------------------
3878
3879   private boolean isValidRequired(Object x) {
3880      return x != null || ! required;
3881   }
3882
3883   private boolean isValidMinProperties(Map<?,?> x) {
3884      return minProperties == null || x.size() >= minProperties;
3885   }
3886
3887   private boolean isValidMaxProperties(Map<?,?> x) {
3888      return maxProperties == null || x.size() <= maxProperties;
3889   }
3890
3891   private boolean isValidMinimum(Number x) {
3892      if (x instanceof Integer || x instanceof AtomicInteger)
3893         return minimum == null || x.intValue() > minimum.intValue() || (x.intValue() == minimum.intValue() && (! exclusiveMinimum));
3894      if (x instanceof Short || x instanceof Byte)
3895         return minimum == null || x.shortValue() > minimum.shortValue() || (x.intValue() == minimum.shortValue() && (! exclusiveMinimum));
3896      if (x instanceof Long || x instanceof AtomicLong || x instanceof BigInteger)
3897         return minimum == null || x.longValue() > minimum.longValue() || (x.intValue() == minimum.longValue() && (! exclusiveMinimum));
3898      if (x instanceof Float)
3899         return minimum == null || x.floatValue() > minimum.floatValue() || (x.floatValue() == minimum.floatValue() && (! exclusiveMinimum));
3900      if (x instanceof Double || x instanceof BigDecimal)
3901         return minimum == null || x.doubleValue() > minimum.doubleValue() || (x.doubleValue() == minimum.doubleValue() && (! exclusiveMinimum));
3902      return true;
3903   }
3904
3905   private boolean isValidMaximum(Number x) {
3906      if (x instanceof Integer || x instanceof AtomicInteger)
3907         return maximum == null || x.intValue() < maximum.intValue() || (x.intValue() == maximum.intValue() && (! exclusiveMaximum));
3908      if (x instanceof Short || x instanceof Byte)
3909         return maximum == null || x.shortValue() < maximum.shortValue() || (x.intValue() == maximum.shortValue() && (! exclusiveMaximum));
3910      if (x instanceof Long || x instanceof AtomicLong || x instanceof BigInteger)
3911         return maximum == null || x.longValue() < maximum.longValue() || (x.intValue() == maximum.longValue() && (! exclusiveMaximum));
3912      if (x instanceof Float)
3913         return maximum == null || x.floatValue() < maximum.floatValue() || (x.floatValue() == maximum.floatValue() && (! exclusiveMaximum));
3914      if (x instanceof Double || x instanceof BigDecimal)
3915         return maximum == null || x.doubleValue() < maximum.doubleValue() || (x.doubleValue() == maximum.doubleValue() && (! exclusiveMaximum));
3916      return true;
3917   }
3918
3919   private boolean isValidMultipleOf(Number x) {
3920      if (x instanceof Integer || x instanceof AtomicInteger)
3921         return multipleOf == null || x.intValue() % multipleOf.intValue() == 0;
3922      if (x instanceof Short || x instanceof Byte)
3923         return multipleOf == null || x.shortValue() % multipleOf.shortValue() == 0;
3924      if (x instanceof Long || x instanceof AtomicLong || x instanceof BigInteger)
3925         return multipleOf == null || x.longValue() % multipleOf.longValue() == 0;
3926      if (x instanceof Float)
3927         return multipleOf == null || x.floatValue() % multipleOf.floatValue() == 0;
3928      if (x instanceof Double || x instanceof BigDecimal)
3929         return multipleOf == null || x.doubleValue() % multipleOf.doubleValue() == 0;
3930      return true;
3931   }
3932
3933   private boolean isValidAllowEmpty(String x) {
3934      return allowEmptyValue || Utils.isNotEmpty(x);
3935   }
3936
3937   private boolean isValidPattern(String x) {
3938      return pattern == null || pattern.matcher(x).matches();
3939   }
3940
3941   private boolean isValidEnum(String x) {
3942      return _enum.isEmpty() || _enum.contains(x);
3943   }
3944
3945   private boolean isValidMinLength(String x) {
3946      return minLength == null || x.length() >= minLength;
3947   }
3948
3949   private boolean isValidMaxLength(String x) {
3950      return maxLength == null || x.length() <= maxLength;
3951   }
3952
3953   private boolean isValidMinItems(Object x) {
3954      return minItems == null || Array.getLength(x) >= minItems;
3955   }
3956
3957   private boolean isValidMaxItems(Object x) {
3958      return maxItems == null || Array.getLength(x) <= maxItems;
3959   }
3960
3961   private boolean isValidUniqueItems(Object x) {
3962      if (uniqueItems) {
3963         Set<Object> s = new HashSet<>();
3964         for (int i = 0; i < Array.getLength(x); i++) {
3965            Object o = Array.get(x, i);
3966            if (! s.add(o))
3967               return false;
3968         }
3969      }
3970      return true;
3971   }
3972
3973   private boolean isValidMinItems(Collection<?> x) {
3974      return minItems == null || x.size() >= minItems;
3975   }
3976
3977   private boolean isValidMaxItems(Collection<?> x) {
3978      return maxItems == null || x.size() <= maxItems;
3979   }
3980
3981   private boolean isValidUniqueItems(Collection<?> x) {
3982      if (uniqueItems && ! (x instanceof Set)) {
3983         Set<Object> s = new HashSet<>();
3984         for (Object o : x)
3985            if (! s.add(o))
3986               return false;
3987      }
3988      return true;
3989   }
3990
3991   /**
3992    * Returns the schema information for the specified property.
3993    *
3994    * @param name The property name.
3995    * @return The schema information for the specified property, or <jk>null</jk> if properties are not defined on this schema.
3996    */
3997   public HttpPartSchema getProperty(String name) {
3998      if (properties != null) {
3999         HttpPartSchema schema = properties.get(name);
4000         if (schema != null)
4001            return schema;
4002      }
4003      return additionalProperties;
4004   }
4005
4006   /**
4007    * Returns <jk>true</jk> if this schema has properties associated with it.
4008    *
4009    * @return <jk>true</jk> if this schema has properties associated with it.
4010    */
4011   public boolean hasProperties() {
4012      return properties != null || additionalProperties != null;
4013   }
4014
4015   private static <T> Set<T> copy(Set<T> in) {
4016      return in == null ? emptySet() : u(copyOf(in));
4017   }
4018
4019   private static Map<String,HttpPartSchema> build(Map<String,Object> in, boolean noValidate) {
4020      if (in == null)
4021         return null;
4022      Map<String,HttpPartSchema> m = map();
4023      in.forEach((k,v) -> m.put(k, build(v, noValidate)));
4024      return u(m);
4025   }
4026
4027   private static HttpPartSchema build(Object in, boolean noValidate) {
4028      if (in == null)
4029         return null;
4030      if (in instanceof HttpPartSchema)
4031         return (HttpPartSchema)in;
4032      return ((Builder)in).noValidate(noValidate).build();
4033   }
4034
4035   //-----------------------------------------------------------------------------------------------------------------
4036   // Helper methods.
4037   //-----------------------------------------------------------------------------------------------------------------
4038
4039   private boolean resolve(Boolean b) {
4040      return b == null ? false : b;
4041   }
4042
4043   final static Set<String> toSet(String[]...s) {
4044      boolean isNotEmpty = false;
4045      for (String[] ss : s)
4046         isNotEmpty |= ss.length > 0;
4047      if (! isNotEmpty)
4048         return null;
4049      Set<String> set = Utils.set();
4050      for (String[] ss : s)
4051         if (ss != null)
4052            for (String ss2 : ss)
4053               Utils.split(ss2, x -> set.add(x));
4054      return set.isEmpty() ? null : set;
4055   }
4056
4057   final static Set<String> toSet(String s) {
4058      if (Utils.isEmpty(s))
4059         return null;
4060      Set<String> set = Utils.set();
4061      try {
4062         JsonList.ofJsonOrCdl(s).forEach(x -> set.add(x.toString()));
4063      } catch (ParseException e) {
4064         throw asRuntimeException(e);
4065      }
4066      return set;
4067   }
4068
4069   final static Number toNumber(String...s) {
4070      try {
4071         for (String ss : s)
4072            if (Utils.isNotEmpty(ss))
4073               return parseNumber(ss, Number.class);
4074         return null;
4075      } catch (ParseException e) {
4076         throw asRuntimeException(e);
4077      }
4078   }
4079
4080   final static JsonMap toJsonMap(String[] ss) {
4081      String s = Utils.joinnl(ss);
4082      if (s.isEmpty())
4083         return null;
4084      if (! isJsonObject(s, true))
4085         s = "{" + s + "}";
4086      try {
4087         return JsonMap.ofJson(s);
4088      } catch (ParseException e) {
4089         throw asRuntimeException(e);
4090      }
4091   }
4092
4093   @Override
4094   public String toString() {
4095      try {
4096         Predicate<Object> ne = x -> Utils.isNotEmpty(Utils.s(x));
4097         Predicate<Boolean> nf = Utils::isTrue;
4098         Predicate<Number> nm1 = Utils::isNotMinusOne;
4099         Predicate<Object> nn = Utils::isNotNull;
4100         JsonMap m = new JsonMap()
4101            .appendIf(ne, "name", name)
4102            .appendIf(ne, "type", type)
4103            .appendIf(ne, "format", format)
4104            .appendIf(ne, "default", _default)
4105            .appendIf(ne, "enum", _enum)
4106            .appendIf(ne, "properties", properties)
4107            .appendIf(nf, "allowEmptyValue", allowEmptyValue)
4108            .appendIf(nf, "exclusiveMaximum", exclusiveMaximum)
4109            .appendIf(nf, "exclusiveMinimum", exclusiveMinimum)
4110            .appendIf(nf, "required", required)
4111            .appendIf(nf, "uniqueItems", uniqueItems)
4112            .appendIf(nf, "skipIfEmpty", skipIfEmpty)
4113            .appendIf(x -> x != HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat", collectionFormat)
4114            .appendIf(ne, "pattern", pattern)
4115            .appendIf(nn, "items", items)
4116            .appendIf(nn, "additionalProperties", additionalProperties)
4117            .appendIf(nm1, "maximum", maximum)
4118            .appendIf(nm1, "minimum", minimum)
4119            .appendIf(nm1, "multipleOf", multipleOf)
4120            .appendIf(nm1, "maxLength", maxLength)
4121            .appendIf(nm1, "minLength", minLength)
4122            .appendIf(nm1, "maxItems", maxItems)
4123            .appendIf(nm1, "minItems", minItems)
4124            .appendIf(nm1, "maxProperties", maxProperties)
4125            .appendIf(nm1, "minProperties", minProperties)
4126            .append("parsedType", parsedType)
4127         ;
4128         return m.toString();
4129      } catch (Exception e) {
4130         return "";
4131      }
4132   }
4133}