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