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