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.bean.openapi3; 018 019import static org.apache.juneau.common.utils.Utils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021import static org.apache.juneau.internal.ConverterUtils.*; 022 023import java.util.*; 024 025import org.apache.juneau.annotation.*; 026import org.apache.juneau.common.utils.*; 027import org.apache.juneau.internal.*; 028 029/** 030 * Allows the definition of input and output data types. 031 * 032 * <p> 033 * The Schema Object allows the definition of input and output data types, including objects, primitives, and arrays. 034 * This object is an extended subset of the JSON Schema Specification Draft 4, with additional extensions provided 035 * by the OpenAPI Specification to allow for more complete documentation. 036 * 037 * <h5 class='section'>OpenAPI Specification:</h5> 038 * <p> 039 * The Schema Object supports all properties from JSON Schema Draft 4, including but not limited to: 040 * <ul class='spaced-list'> 041 * <li><c>type</c> (string) - The data type. Values: <js>"string"</js>, <js>"number"</js>, <js>"integer"</js>, <js>"boolean"</js>, <js>"array"</js>, <js>"object"</js> 042 * <li><c>format</c> (string) - The format modifier (e.g., <js>"int32"</js>, <js>"int64"</js>, <js>"float"</js>, <js>"double"</js>, <js>"date"</js>, <js>"date-time"</js>) 043 * <li><c>title</c> (string) - A short title for the schema 044 * <li><c>description</c> (string) - A description of the schema (CommonMark syntax may be used) 045 * <li><c>default</c> (any) - The default value 046 * <li><c>multipleOf</c> (number) - Must be a multiple of this value 047 * <li><c>maximum</c> (number) - Maximum value (inclusive by default) 048 * <li><c>exclusiveMaximum</c> (boolean) - If true, maximum is exclusive 049 * <li><c>minimum</c> (number) - Minimum value (inclusive by default) 050 * <li><c>exclusiveMinimum</c> (boolean) - If true, minimum is exclusive 051 * <li><c>maxLength</c> (integer) - Maximum string length 052 * <li><c>minLength</c> (integer) - Minimum string length 053 * <li><c>pattern</c> (string) - Regular expression pattern the string must match 054 * <li><c>maxItems</c> (integer) - Maximum array length 055 * <li><c>minItems</c> (integer) - Minimum array length 056 * <li><c>uniqueItems</c> (boolean) - If true, array items must be unique 057 * <li><c>maxProperties</c> (integer) - Maximum number of object properties 058 * <li><c>minProperties</c> (integer) - Minimum number of object properties 059 * <li><c>required</c> (array of string) - Required property names 060 * <li><c>enum</c> (array) - Possible values for this schema 061 * <li><c>properties</c> (map of {@link SchemaInfo}) - Object property definitions 062 * <li><c>items</c> ({@link Items}) - Schema for array items 063 * <li><c>allOf</c> (array of {@link SchemaInfo}) - Must validate against all schemas 064 * <li><c>oneOf</c> (array of {@link SchemaInfo}) - Must validate against exactly one schema 065 * <li><c>anyOf</c> (array of {@link SchemaInfo}) - Must validate against any schema 066 * <li><c>not</c> ({@link SchemaInfo}) - Must not validate against this schema 067 * <li><c>nullable</c> (boolean) - Allows the value to be null (OpenAPI 3.0 extension) 068 * <li><c>discriminator</c> ({@link Discriminator}) - Discriminator for polymorphism (OpenAPI extension) 069 * <li><c>readOnly</c> (boolean) - Relevant only for Schema properties (OpenAPI extension) 070 * <li><c>writeOnly</c> (boolean) - Relevant only for Schema properties (OpenAPI extension) 071 * <li><c>xml</c> ({@link Xml}) - XML representation details (OpenAPI extension) 072 * <li><c>externalDocs</c> ({@link ExternalDocumentation}) - Additional external documentation (OpenAPI extension) 073 * <li><c>example</c> (any) - Example value (OpenAPI extension) 074 * <li><c>deprecated</c> (boolean) - Specifies that the schema is deprecated (OpenAPI extension) 075 * </ul> 076 * 077 * <h5 class='section'>Example:</h5> 078 * <p class='bjava'> 079 * <jc>// Create a schema for a Pet object</jc> 080 * SchemaInfo <jv>schema</jv> = <jk>new</jk> SchemaInfo() 081 * .setType(<js>"object"</js>) 082 * .setRequired(<js>"id"</js>, <js>"name"</js>) 083 * .setProperties( 084 * JsonMap.<jsm>of</jsm>( 085 * <js>"id"</js>, <jk>new</jk> SchemaInfo().setType(<js>"integer"</js>).setFormat(<js>"int64"</js>), 086 * <js>"name"</js>, <jk>new</jk> SchemaInfo().setType(<js>"string"</js>), 087 * <js>"tag"</js>, <jk>new</jk> SchemaInfo().setType(<js>"string"</js>) 088 * ) 089 * ); 090 * </p> 091 * 092 * <h5 class='section'>See Also:</h5><ul> 093 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#schema-object">OpenAPI Specification > Schema Object</a> 094 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/data-models/">OpenAPI Data Models</a> 095 * <li class='link'><a class="doclink" href="https://json-schema.org/">JSON Schema Specification</a> 096 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 097 * </ul> 098 */ 099public class SchemaInfo extends OpenApiElement { 100 101 private String 102 format, 103 title, 104 description, 105 pattern, 106 ref, 107 type; 108 private Number 109 multipleOf, 110 maximum, 111 minimum; 112 private Integer 113 maxLength, 114 minLength, 115 maxItems, 116 minItems, 117 maxProperties, 118 minProperties; 119 private Boolean 120 exclusiveMaximum, 121 exclusiveMinimum, 122 uniqueItems, 123 nullable, 124 writeOnly, 125 readOnly, 126 deprecated; 127 private Object 128 _default, // NOSONAR - Intentional naming. 129 example; 130 private Items items; 131 private Xml xml; 132 private ExternalDocumentation externalDocs; 133 private List<Object> 134 allOf, 135 oneOf, 136 anyOf, 137 _enum; // NOSONAR - Intentional naming. 138 private List<String> 139 required; 140 private Discriminator discriminator; 141 private Map<String, SchemaInfo> properties; 142 private SchemaInfo additionalProperties; 143 private SchemaInfo not; 144 145 /** 146 * Default constructor. 147 */ 148 public SchemaInfo() {} 149 150 /** 151 * Copy constructor. 152 * 153 * @param copyFrom The object to copy. 154 */ 155 public SchemaInfo(SchemaInfo copyFrom) { 156 super(copyFrom); 157 158 this.format = copyFrom.format; 159 this.title = copyFrom.title; 160 this.description = copyFrom.description; 161 this.ref = copyFrom.ref; 162 this.nullable = copyFrom.nullable; 163 this.writeOnly = copyFrom.writeOnly; 164 this.deprecated = copyFrom.deprecated; 165 this.pattern = copyFrom.pattern; 166 this.type = copyFrom.type; 167 this.discriminator = copyFrom.discriminator; 168 this.multipleOf = copyFrom.multipleOf; 169 this.maximum = copyFrom.maximum; 170 this.minimum = copyFrom.minimum; 171 this.maxLength = copyFrom.maxLength; 172 this.minLength = copyFrom.minLength; 173 this.maxItems = copyFrom.maxItems; 174 this.minItems = copyFrom.minItems; 175 this.maxProperties = copyFrom.maxProperties; 176 this.minProperties = copyFrom.minProperties; 177 this.exclusiveMaximum = copyFrom.exclusiveMaximum; 178 this.exclusiveMinimum = copyFrom.exclusiveMinimum; 179 this.uniqueItems = copyFrom.uniqueItems; 180 this.readOnly = copyFrom.readOnly; 181 this._default = copyFrom._default; 182 this.example = copyFrom.example; 183 this.items = copyFrom.items == null ? null : copyFrom.items.copy(); 184 this.xml = copyFrom.xml == null ? null : copyFrom.xml.copy(); 185 this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy(); 186 this._enum = copyOf(copyFrom._enum); 187 this.allOf = copyOf(copyFrom.allOf); 188 this.required = copyOf(copyFrom.required); 189 this.anyOf = copyOf(copyFrom.anyOf); 190 this.oneOf = copyOf(copyFrom.oneOf); 191 this.properties = copyOf(copyFrom.properties, SchemaInfo::copy); 192 this.additionalProperties = copyFrom.additionalProperties == null ? null : copyFrom.additionalProperties.copy(); 193 this.not = copyFrom.not == null ? null : copyFrom.not.copy(); 194 } 195 196 /** 197 * Make a deep copy of this object. 198 * 199 * @return A deep copy of this object. 200 */ 201 public SchemaInfo copy() { 202 return new SchemaInfo(this); 203 } 204 205 /** 206 * Bean property getter: <property>format</property>. 207 * 208 * @return The property value, or <jk>null</jk> if it is not set. 209 */ 210 public String getFormat() { 211 return format; 212 } 213 214 /** 215 * Bean property setter: <property>format</property>. 216 * 217 * @param value 218 * The new value for this property. 219 * <br>Can be <jk>null</jk> to unset the property. 220 * <br>Formats defined by the OAS include: 221 * <ul> 222 * <li><js>"int32"</js> 223 * <li><js>"int64"</js> 224 * <li><js>"float"</js> 225 * <li><js>"double"</js> 226 * <li><js>"byte"</js> 227 * <li><js>"binary"</js> 228 * <li><js>"date"</js> 229 * <li><js>"date-time"</js> 230 * <li><js>"password"</js> 231 * </ul> 232 * @return This object 233 */ 234 public SchemaInfo setFormat(String value) { 235 format = value; 236 return this; 237 } 238 239 /** 240 * Bean property getter: <property>title</property>. 241 * 242 * @return The property value, or <jk>null</jk> if it is not set. 243 */ 244 public String getTitle() { 245 return title; 246 } 247 248 /** 249 * Bean property setter: <property>title</property>. 250 * 251 * @param value 252 * The new value for this property. 253 * <br>Can be <jk>null</jk> to unset the property. 254 * @return This object 255 */ 256 public SchemaInfo setTitle(String value) { 257 title = value; 258 return this; 259 } 260 261 /** 262 * Bean property getter: <property>description</property>. 263 * 264 * @return The property value, or <jk>null</jk> if it is not set. 265 */ 266 public String getDescription() { 267 return description; 268 } 269 270 /** 271 * Bean property setter: <property>description</property>. 272 * 273 * @param value 274 * The new value for this property. 275 * <br>Can be <jk>null</jk> to unset the property. 276 * @return This object 277 */ 278 public SchemaInfo setDescription(String value) { 279 description = value; 280 return this; 281 } 282 283 /** 284 * Bean property getter: <property>default</property>. 285 * 286 * <p> 287 * Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object. 288 * 289 * @return The property value, or <jk>null</jk> if it is not set. 290 */ 291 public Object getDefault() { 292 return _default; 293 } 294 295 /** 296 * Bean property setter: <property>default</property>. 297 * 298 * <p> 299 * Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object. 300 * 301 * @param value 302 * The new value for this property. 303 * <br>Can be <jk>null</jk> to unset the property. 304 * @return This object 305 */ 306 public SchemaInfo setDefault(Object value) { 307 _default = value; 308 return this; 309 } 310 311 /** 312 * Bean property getter: <property>multipleOf</property>. 313 * 314 * @return The property value, or <jk>null</jk> if it is not set. 315 */ 316 public Number getMultipleOf() { 317 return multipleOf; 318 } 319 320 /** 321 * Bean property setter: <property>multipleOf</property>. 322 * 323 * @param value 324 * The new value for this property. 325 * <br>Can be <jk>null</jk> to unset the property. 326 * @return This object 327 */ 328 public SchemaInfo setMultipleOf(Number value) { 329 multipleOf = value; 330 return this; 331 } 332 333 /** 334 * Bean property getter: <property>maximum</property>. 335 * 336 * @return The property value, or <jk>null</jk> if it is not set. 337 */ 338 public Number getMaximum() { 339 return maximum; 340 } 341 342 /** 343 * Bean property setter: <property>maximum</property>. 344 * 345 * @param value 346 * The new value for this property. 347 * <br>Can be <jk>null</jk> to unset the property. 348 * @return This object 349 */ 350 public SchemaInfo setMaximum(Number value) { 351 maximum = value; 352 return this; 353 } 354 355 /** 356 * Bean property getter: <property>exclusiveMaximum</property>. 357 * 358 * @return The property value, or <jk>null</jk> if it is not set. 359 */ 360 public Boolean getExclusiveMaximum() { 361 return exclusiveMaximum; 362 } 363 364 /** 365 * Bean property setter: <property>exclusiveMaximum</property>. 366 * 367 * @param value 368 * The new value for this property. 369 * <br>Can be <jk>null</jk> to unset the property. 370 * @return This object 371 */ 372 public SchemaInfo setExclusiveMaximum(Boolean value) { 373 exclusiveMaximum = value; 374 return this; 375 } 376 377 /** 378 * Bean property getter: <property>minimum</property>. 379 * 380 * @return The property value, or <jk>null</jk> if it is not set. 381 */ 382 public Number getMinimum() { 383 return minimum; 384 } 385 386 /** 387 * Bean property setter: <property>minimum</property>. 388 * 389 * @param value 390 * The new value for this property. 391 * <br>Can be <jk>null</jk> to unset the property. 392 * @return This object 393 */ 394 public SchemaInfo setMinimum(Number value) { 395 minimum = value; 396 return this; 397 } 398 399 /** 400 * Bean property getter: <property>exclusiveMinimum</property>. 401 * 402 * @return The property value, or <jk>null</jk> if it is not set. 403 */ 404 public Boolean getExclusiveMinimum() { 405 return exclusiveMinimum; 406 } 407 408 /** 409 * Bean property setter: <property>exclusiveMinimum</property>. 410 * 411 * @param value 412 * The new value for this property. 413 * <br>Can be <jk>null</jk> to unset the property. 414 * @return This object 415 */ 416 public SchemaInfo setExclusiveMinimum(Boolean value) { 417 exclusiveMinimum = value; 418 return this; 419 } 420 421 /** 422 * Bean property getter: <property>maxLength</property>. 423 * 424 * @return The property value, or <jk>null</jk> if it is not set. 425 */ 426 public Integer getMaxLength() { 427 return maxLength; 428 } 429 430 /** 431 * Bean property setter: <property>maxLength</property>. 432 * 433 * @param value 434 * The new value for this property. 435 * <br>Can be <jk>null</jk> to unset the property. 436 * @return This object 437 */ 438 public SchemaInfo setMaxLength(Integer value) { 439 maxLength = value; 440 return this; 441 } 442 443 /** 444 * Bean property getter: <property>minLength</property>. 445 * 446 * @return The property value, or <jk>null</jk> if it is not set. 447 */ 448 public Integer getMinLength() { 449 return minLength; 450 } 451 452 /** 453 * Bean property setter: <property>minLength</property>. 454 * 455 * @param value 456 * The new value for this property. 457 * <br>Can be <jk>null</jk> to unset the property. 458 * @return This object 459 */ 460 public SchemaInfo setMinLength(Integer value) { 461 minLength = value; 462 return this; 463 } 464 465 /** 466 * Bean property getter: <property>pattern</property>. 467 * 468 * @return The property value, or <jk>null</jk> if it is not set. 469 */ 470 public String getPattern() { 471 return pattern; 472 } 473 474 /** 475 * Bean property setter: <property>pattern</property>. 476 * 477 * <p> 478 * This string SHOULD be a valid regular expression. 479 * 480 * @param value 481 * The new value for this property. 482 * <br>Can be <jk>null</jk> to unset the property. 483 * @return This object 484 */ 485 public SchemaInfo setPattern(String value) { 486 pattern = value; 487 return this; 488 } 489 490 /** 491 * Bean property getter: <property>maxItems</property>. 492 * 493 * @return The property value, or <jk>null</jk> if it is not set. 494 */ 495 public Integer getMaxItems() { 496 return maxItems; 497 } 498 499 /** 500 * Bean property setter: <property>maxItems</property>. 501 * 502 * @param value 503 * The new value for this property. 504 * <br>Can be <jk>null</jk> to unset the property. 505 * @return This object 506 */ 507 public SchemaInfo setMaxItems(Integer value) { 508 maxItems = value; 509 return this; 510 } 511 512 /** 513 * Bean property getter: <property>minItems</property>. 514 * 515 * @return The property value, or <jk>null</jk> if it is not set. 516 */ 517 public Integer getMinItems() { 518 return minItems; 519 } 520 521 /** 522 * Bean property setter: <property>minItems</property>. 523 * 524 * @param value 525 * The new value for this property. 526 * <br>Can be <jk>null</jk> to unset the property. 527 * @return This object 528 */ 529 public SchemaInfo setMinItems(Integer value) { 530 minItems = value; 531 return this; 532 } 533 534 /** 535 * Bean property getter: <property>uniqueItems</property>. 536 * 537 * @return The property value, or <jk>null</jk> if it is not set. 538 */ 539 public Boolean getUniqueItems() { 540 return uniqueItems; 541 } 542 /** 543 * Bean property setter: <property>uniqueItems</property>. 544 * 545 * @param value 546 * The new value for this property. 547 * <br>Can be <jk>null</jk> to unset the property. 548 * @return This object 549 */ 550 public SchemaInfo setUniqueItems(Boolean value) { 551 uniqueItems = value; 552 return this; 553 } 554 555 /** 556 * Bean property getter: <property>uniqueItems</property>. 557 * 558 * @return The property value, or <jk>null</jk> if it is not set. 559 */ 560 public Boolean getNullable() { 561 return nullable; 562 } 563 /** 564 * Bean property setter: <property>nullable</property>. 565 * 566 * @param value 567 * The new value for this property. 568 * <br>Can be <jk>null</jk> to unset the property. 569 * @return This object 570 */ 571 public SchemaInfo setNullable(Boolean value) { 572 nullable = value; 573 return this; 574 } 575 576 /** 577 * Bean property getter: <property>maxProperties</property>. 578 * 579 * @return The property value, or <jk>null</jk> if it is not set. 580 */ 581 public Integer getMaxProperties() { 582 return maxProperties; 583 } 584 585 /** 586 * Bean property setter: <property>maxProperties</property>. 587 * 588 * @param value 589 * The new value for this property. 590 * <br>Can be <jk>null</jk> to unset the property. 591 * @return This object 592 */ 593 public SchemaInfo setMaxProperties(Integer value) { 594 maxProperties = value; 595 return this; 596 } 597 598 /** 599 * Bean property getter: <property>minProperties</property>. 600 * 601 * @return The property value, or <jk>null</jk> if it is not set. 602 */ 603 public Integer getMinProperties() { 604 return minProperties; 605 } 606 607 /** 608 * Bean property setter: <property>minProperties</property>. 609 * 610 * @param value 611 * The new value for this property. 612 * <br>Can be <jk>null</jk> to unset the property. 613 * @return This object 614 */ 615 public SchemaInfo setMinProperties(Integer value) { 616 minProperties = value; 617 return this; 618 } 619 620 /** 621 * Bean property getter: <property>required</property>. 622 * 623 * <p> 624 * The list of required properties. 625 * 626 * @return The property value, or <jk>null</jk> if it is not set. 627 */ 628 public List<String> getRequired() { 629 return required; 630 } 631 632 /** 633 * Bean property setter: <property>required</property>. 634 * 635 * <p> 636 * The list of required properties. 637 * 638 * @param value 639 * The new value for this property. 640 * <br>Valid values: 641 * <ul> 642 * <li><js>"http"</js> 643 * <li><js>"https"</js> 644 * <li><js>"ws"</js> 645 * <li><js>"wss"</js> 646 * </ul> 647 * <br>Can be <jk>null</jk> to unset the property. 648 * @return This object 649 */ 650 public SchemaInfo setRequired(Collection<String> value) { 651 required = listFrom(value); 652 return this; 653 } 654 655 /** 656 * Same as {@link #addRequired(String...)}. 657 * 658 * @param values 659 * The new value for this property. 660 * <br>Valid types: 661 * <ul> 662 * <li><code>Collection<String></code> 663 * <li><code>String</code> - JSON array representation of <code>Collection<String></code> 664 * <h5 class='figure'>Example:</h5> 665 * <p class='bcode'> 666 * schemes(<js>"['scheme1','scheme2']"</js>); 667 * </p> 668 * <li><code>String</code> - Individual values 669 * <h5 class='figure'>Example:</h5> 670 * <p class='bcode'> 671 * schemes(<js>"scheme1</js>, <js>"scheme2"</js>); 672 * </p> 673 * </ul> 674 * @return This object 675 */ 676 public SchemaInfo addRequired(String...values) { 677 required = listBuilder(required).sparse().add(values).build(); 678 return this; 679 } 680 681 /** 682 * Bean property getter: <property>enum</property>. 683 * 684 * @return The property value, or <jk>null</jk> if it is not set. 685 */ 686 public List<Object> getEnum() { 687 return _enum; 688 } 689 690 /** 691 * Bean property setter: <property>enum</property>. 692 * 693 * @param value 694 * The new value for this property. 695 * <br>Can be <jk>null</jk> to unset the property. 696 * @return This object 697 */ 698 public SchemaInfo setEnum(Collection<Object> value) { 699 _enum = listFrom(value); 700 return this; 701 } 702 703 /** 704 * Adds one or more values to the <property>enum</property> property. 705 * 706 * @param values 707 * The values to add to this property. 708 * <br>Valid types: 709 * <ul> 710 * <li><code>Object</code> 711 * <li><code>Collection<Object></code> 712 * <li><code>String</code> - JSON array representation of <code>Collection<Object></code> 713 * <h5 class='figure'>Example:</h5> 714 * <p class='bcode'> 715 * _enum(<js>"['foo','bar']"</js>); 716 * </p> 717 * <li><code>String</code> - Individual values 718 * <h5 class='figure'>Example:</h5> 719 * <p class='bcode'> 720 * _enum(<js>"foo"</js>, <js>"bar"</js>); 721 * </p> 722 * </ul> 723 * <br>Ignored if <jk>null</jk>. 724 * @return This object 725 */ 726 public SchemaInfo addEnum(Object...values) { 727 _enum = listBuilder(_enum).elementType(Object.class).sparse().addAny(values).build(); 728 return this; 729 } 730 731 /** 732 * Bean property getter: <property>type</property>. 733 * 734 * @return The property value, or <jk>null</jk> if it is not set. 735 */ 736 public String getType() { 737 return type; 738 } 739 740 /** 741 * Bean property setter: <property>type</property>. 742 * 743 * @param value 744 * The new value for this property. 745 * <br>Can be <jk>null</jk> to unset the property. 746 * <br>Possible values include: 747 * <ul> 748 * <li><js>"object"</js> 749 * <li><js>"string"</js> 750 * <li><js>"number"</js> 751 * <li><js>"integer"</js> 752 * <li><js>"boolean"</js> 753 * <li><js>"array"</js> 754 * <li><js>"file"</js> 755 * </ul> 756 * @return This object 757 */ 758 public SchemaInfo setType(String value) { 759 type = value; 760 return this; 761 } 762 763 /** 764 * Bean property getter: <property>items</property>. 765 * 766 * @return The property value, or <jk>null</jk> if it is not set. 767 */ 768 public Items getItems() { 769 return items; 770 } 771 772 /** 773 * Bean property setter: <property>items</property>. 774 * 775 * @param value 776 * The new value for this property. 777 * <br>Can be <jk>null</jk> to unset the property. 778 * @return This object 779 */ 780 public SchemaInfo setItems(Items value) { 781 items = value; 782 return this; 783 } 784 785 /** 786 * Bean property getter: <property>allOf</property>. 787 * 788 * @return The property value, or <jk>null</jk> if it is not set. 789 */ 790 public List<Object> getAllOf() { 791 return allOf; 792 } 793 794 /** 795 * Bean property setter: <property>allOf</property>. 796 * 797 * @param value 798 * The new value for this property. 799 * <br>Can be <jk>null</jk> to unset the property. 800 * @return This object 801 */ 802 public SchemaInfo setAllOf(Collection<Object> value) { 803 allOf = listFrom(value); 804 return this; 805 } 806 807 /** 808 * Adds one or more values to the <property>allOf</property> property. 809 * 810 * @param values 811 * The values to add to this property. 812 * <br>Valid types: 813 * <ul> 814 * <li><code>Object</code> 815 * <li><code>Collection<Object></code> 816 * <li><code>String</code> - JSON array representation of <code>Collection<Object></code> 817 * <h5 class='figure'>Example:</h5> 818 * <p class='bcode'> 819 * allOf(<js>"['foo','bar']"</js>); 820 * </p> 821 * <li><code>String</code> - Individual values 822 * <h5 class='figure'>Example:</h5> 823 * <p class='bcode'> 824 * allOf(<js>"foo"</js>, <js>"bar"</js>); 825 * </p> 826 * </ul> 827 * <br>Ignored if <jk>null</jk>. 828 * @return This object 829 */ 830 public SchemaInfo addAllOf(Object...values) { 831 allOf = listBuilder(allOf).elementType(Object.class).sparse().addAny(values).build(); 832 return this; 833 } 834 835 /** 836 * Bean property getter: <property>allOf</property>. 837 * 838 * @return The property value, or <jk>null</jk> if it is not set. 839 */ 840 public List<Object> getAnyOf() { 841 return anyOf; 842 } 843 844 /** 845 * Bean property setter: <property>allOf</property>. 846 * 847 * @param value 848 * The new value for this property. 849 * <br>Can be <jk>null</jk> to unset the property. 850 * @return This object 851 */ 852 public SchemaInfo setAnyOf(Collection<Object> value) { 853 anyOf = listFrom(value); 854 return this; 855 } 856 857 /** 858 * Adds one or more values to the <property>allOf</property> property. 859 * 860 * @param values 861 * The values to add to this property. 862 * <br>Valid types: 863 * <ul> 864 * <li><code>Object</code> 865 * <li><code>Collection<Object></code> 866 * <li><code>String</code> - JSON array representation of <code>Collection<Object></code> 867 * <h5 class='figure'>Example:</h5> 868 * <p class='bcode'> 869 * allOf(<js>"['foo','bar']"</js>); 870 * </p> 871 * <li><code>String</code> - Individual values 872 * <h5 class='figure'>Example:</h5> 873 * <p class='bcode'> 874 * allOf(<js>"foo"</js>, <js>"bar"</js>); 875 * </p> 876 * </ul> 877 * <br>Ignored if <jk>null</jk>. 878 * @return This object 879 */ 880 public SchemaInfo addAnyOf(Object...values) { 881 anyOf = listBuilder(anyOf).elementType(Object.class).sparse().addAny(values).build(); 882 return this; 883 } 884 885 /** 886 * Bean property getter: <property>allOf</property>. 887 * 888 * @return The property value, or <jk>null</jk> if it is not set. 889 */ 890 public List<Object> getOneOf() { 891 return oneOf; 892 } 893 894 /** 895 * Bean property setter: <property>allOf</property>. 896 * 897 * @param value 898 * The new value for this property. 899 * <br>Can be <jk>null</jk> to unset the property. 900 * @return This object 901 */ 902 public SchemaInfo setOneOf(Collection<Object> value) { 903 oneOf = listFrom(value); 904 return this; 905 } 906 907 /** 908 * Adds one or more values to the <property>allOf</property> property. 909 * 910 * @param values 911 * The values to add to this property. 912 * <br>Valid types: 913 * <ul> 914 * <li><code>Object</code> 915 * <li><code>Collection<Object></code> 916 * <li><code>String</code> - JSON array representation of <code>Collection<Object></code> 917 * <h5 class='figure'>Example:</h5> 918 * <p class='bcode'> 919 * allOf(<js>"['foo','bar']"</js>); 920 * </p> 921 * <li><code>String</code> - Individual values 922 * <h5 class='figure'>Example:</h5> 923 * <p class='bcode'> 924 * allOf(<js>"foo"</js>, <js>"bar"</js>); 925 * </p> 926 * </ul> 927 * <br>Ignored if <jk>null</jk>. 928 * @return This object 929 */ 930 public SchemaInfo addOneOf(Object...values) { 931 oneOf = listBuilder(oneOf).elementType(Object.class).sparse().addAny(values).build(); 932 return this; 933 } 934 935 /** 936 * Bean property getter: <property>properties</property>. 937 * 938 * @return The property value, or <jk>null</jk> if it is not set. 939 */ 940 public Map<String, SchemaInfo> getProperties() { 941 return properties; 942 } 943 944 /** 945 * Bean property setter: <property>properties</property>. 946 * 947 * @param value 948 * The new value for this property. 949 * <br>Can be <jk>null</jk> to unset the property. 950 * @return This object 951 */ 952 public SchemaInfo setProperties(Map<String, SchemaInfo> value) { 953 properties = copyOf(value); 954 return this; 955 } 956 957 /** 958 * Bean property getter: <property>additionalProperties</property>. 959 * 960 * @return The property value, or <jk>null</jk> if it is not set. 961 */ 962 public SchemaInfo getAdditionalProperties() { 963 return additionalProperties; 964 } 965 966 /** 967 * Bean property setter: <property>additionalProperties</property>. 968 * 969 * @param value 970 * The new value for this property. 971 * <br>Can be <jk>null</jk> to unset the property. 972 * @return This object 973 */ 974 public SchemaInfo setAdditionalProperties(SchemaInfo value) { 975 additionalProperties = value; 976 return this; 977 } 978 979 /** 980 * Bean property getter: <property>not</property>. 981 * 982 * @return The property value, or <jk>null</jk> if it is not set. 983 */ 984 public SchemaInfo getNot() { 985 return not; 986 } 987 988 /** 989 * Bean property setter: <property>not</property>. 990 * 991 * @param value 992 * The new value for this property. 993 * <br>Can be <jk>null</jk> to unset the property. 994 * @return This object 995 */ 996 public SchemaInfo setNot(SchemaInfo value) { 997 not = value; 998 return this; 999 } 1000 1001 /** 1002 * Bean property getter: <property>discriminator</property>. 1003 * 1004 * @return The property value, or <jk>null</jk> if it is not set. 1005 */ 1006 public Discriminator getDiscriminator() { 1007 return discriminator; 1008 } 1009 1010 /** 1011 * Bean property setter: <property>discriminator</property>. 1012 * 1013 * @param value 1014 * The new value for this property. 1015 * <br>Can be <jk>null</jk> to unset the property. 1016 * @return This object 1017 */ 1018 public SchemaInfo setDiscriminator(Discriminator value) { 1019 discriminator = value; 1020 return this; 1021 } 1022 1023 /** 1024 * Bean property getter: <property>readOnly</property>. 1025 * 1026 * @return The property value, or <jk>null</jk> if it is not set. 1027 */ 1028 public Boolean getReadOnly() { 1029 return readOnly; 1030 } 1031 1032 /** 1033 * Bean property setter: <property>readOnly</property>. 1034 * 1035 * @param value 1036 * The new value for this property. 1037 * <br>Can be <jk>null</jk> to unset the property. 1038 * @return This object 1039 */ 1040 public SchemaInfo setReadOnly(Boolean value) { 1041 readOnly = value; 1042 return this; 1043 } 1044 1045 /** 1046 * Bean property getter: <property>WriteOnly</property>. 1047 * 1048 * @return The property value, or <jk>null</jk> if it is not set. 1049 */ 1050 public Boolean getWriteOnly() { 1051 return writeOnly; 1052 } 1053 1054 /** 1055 * Bean property setter: <property>WriteOnly</property>. 1056 * 1057 * @param value 1058 * The new value for this property. 1059 * <br>Can be <jk>null</jk> to unset the property. 1060 * @return This object 1061 */ 1062 public SchemaInfo setWriteOnly(Boolean value) { 1063 writeOnly = value; 1064 return this; 1065 } 1066 1067 /** 1068 * Bean property getter: <property>deprecated</property>. 1069 * 1070 * @return The property value, or <jk>null</jk> if it is not set. 1071 */ 1072 public Boolean getDeprecated() { 1073 return deprecated; 1074 } 1075 1076 /** 1077 * Bean property setter: <property>deprecated</property>. 1078 * 1079 * @param value 1080 * The new value for this property. 1081 * <br>Can be <jk>null</jk> to unset the property. 1082 * @return This object 1083 */ 1084 public SchemaInfo setDeprecated(Boolean value) { 1085 deprecated = value; 1086 return this; 1087 } 1088 1089 /** 1090 * Bean property getter: <property>xml</property>. 1091 * 1092 * @return The property value, or <jk>null</jk> if it is not set. 1093 */ 1094 public Xml getXml() { 1095 return xml; 1096 } 1097 1098 /** 1099 * Bean property setter: <property>xml</property>. 1100 * 1101 * @param value 1102 * The new value for this property. 1103 * <br>Can be <jk>null</jk> to unset the property. 1104 * @return This object 1105 */ 1106 public SchemaInfo setXml(Xml value) { 1107 xml = value; 1108 return this; 1109 } 1110 1111 /** 1112 * Bean property getter: <property>externalDocs</property>. 1113 * 1114 * @return The property value, or <jk>null</jk> if it is not set. 1115 */ 1116 public ExternalDocumentation getExternalDocs() { 1117 return externalDocs; 1118 } 1119 1120 /** 1121 * Bean property setter: <property>externalDocs</property>. 1122 * 1123 * @param value 1124 * The new value for this property. 1125 * <br>Can be <jk>null</jk> to unset the property. 1126 * @return This object 1127 */ 1128 public SchemaInfo setExternalDocs(ExternalDocumentation value) { 1129 externalDocs = value; 1130 return this; 1131 } 1132 1133 /** 1134 * Bean property getter: <property>example</property>. 1135 * 1136 * @return The property value, or <jk>null</jk> if it is not set. 1137 */ 1138 public Object getExample() { 1139 return example; 1140 } 1141 1142 /** 1143 * Bean property setter: <property>example</property>. 1144 * 1145 * @param value 1146 * The new value for this property. 1147 * <br>Can be <jk>null</jk> to unset the property. 1148 * @return This object 1149 */ 1150 public SchemaInfo setExample(Object value) { 1151 example = value; 1152 return this; 1153 } 1154 1155 /** 1156 * Bean property getter: <property>$ref</property>. 1157 * 1158 * @return The property value, or <jk>null</jk> if it is not set. 1159 */ 1160 @Beanp("$ref") 1161 public String getRef() { 1162 return ref; 1163 } 1164 1165 /** 1166 * Bean property setter: <property>$ref</property>. 1167 * 1168 * @param value 1169 * The new value for this property. 1170 * <br>Can be <jk>null</jk> to unset the property. 1171 * @return This object 1172 */ 1173 @Beanp("$ref") 1174 public SchemaInfo setRef(Object value) { 1175 ref = Utils.s(value); 1176 return this; 1177 } 1178 1179 @Override /* SwaggerElement */ 1180 public <T> T get(String property, Class<T> type) { 1181 assertArgNotNull("property", property); 1182 return switch (property) { // NOSONAR 1183 case "format" -> toType(getFormat(), type); 1184 case "title" -> toType(getTitle(), type); 1185 case "description" -> toType(getDescription(), type); 1186 case "default" -> toType(getDefault(), type); 1187 case "multipleOf" -> toType(getMultipleOf(), type); 1188 case "maximum" -> toType(getMaximum(), type); 1189 case "exclusiveMaximum" -> toType(getExclusiveMaximum(), type); 1190 case "minimum" -> toType(getMinimum(), type); 1191 case "exclusiveMinimum" -> toType(getExclusiveMinimum(), type); 1192 case "maxLength" -> toType(getMaxLength(), type); 1193 case "minLength" -> toType(getMinLength(), type); 1194 case "pattern" -> toType(getPattern(), type); 1195 case "maxItems" -> toType(getMaxItems(), type); 1196 case "minItems" -> toType(getMinItems(), type); 1197 case "uniqueItems" -> toType(getUniqueItems(), type); 1198 case "maxProperties" -> toType(getMaxProperties(), type); 1199 case "minProperties" -> toType(getMinProperties(), type); 1200 case "required" -> toType(getRequired(), type); 1201 case "enum" -> toType(getEnum(), type); 1202 case "type" -> toType(getType(), type); 1203 case "items" -> toType(getItems(), type); 1204 case "allOf" -> toType(getAllOf(), type); 1205 case "oneOf" -> toType(getOneOf(), type); 1206 case "anyOf" -> toType(getAnyOf(), type); 1207 case "properties" -> toType(getProperties(), type); 1208 case "additionalProperties" -> toType(getAdditionalProperties(), type); 1209 case "not" -> toType(getNot(), type); 1210 case "nullable" -> toType(getNullable(), type); 1211 case "deprecated" -> toType(getDeprecated(), type); 1212 case "discriminator" -> toType(getDiscriminator(), type); 1213 case "readOnly" -> toType(getReadOnly(), type); 1214 case "writeOnly" -> toType(getWriteOnly(), type); 1215 case "xml" -> toType(getXml(), type); 1216 case "externalDocs" -> toType(getExternalDocs(), type); 1217 case "example" -> toType(getExample(), type); 1218 case "$ref" -> toType(getRef(), type); 1219 default -> super.get(property, type); 1220 }; 1221 } 1222 1223 @Override /* SwaggerElement */ 1224 public SchemaInfo set(String property, Object value) { 1225 assertArgNotNull("property", property); 1226 return switch (property) { // NOSONAR 1227 case "$ref" -> setRef(value); 1228 case "additionalProperties" -> setAdditionalProperties(toType(value, SchemaInfo.class)); 1229 case "allOf" -> setAllOf(listBuilder(Object.class).sparse().addAny(value).build()); 1230 case "anyOf" -> setAnyOf(listBuilder(Object.class).sparse().addAny(value).build()); 1231 case "default" -> setDefault(value); 1232 case "deprecated" -> setDeprecated(toBoolean(value)); 1233 case "description" -> setDescription(Utils.s(value)); 1234 case "discriminator" -> setDiscriminator(toType(value, Discriminator.class)); 1235 case "enum" -> setEnum(listBuilder(Object.class).sparse().addAny(value).build()); 1236 case "example" -> setExample(value); 1237 case "exclusiveMaximum" -> setExclusiveMaximum(toBoolean(value)); 1238 case "exclusiveMinimum" -> setExclusiveMinimum(toBoolean(value)); 1239 case "externalDocs" -> setExternalDocs(toType(value, ExternalDocumentation.class)); 1240 case "format" -> setFormat(Utils.s(value)); 1241 case "items" -> setItems(toType(value, Items.class)); 1242 case "maxItems" -> setMaxItems(toInteger(value)); 1243 case "maxLength" -> setMaxLength(toInteger(value)); 1244 case "maxProperties" -> setMaxProperties(toInteger(value)); 1245 case "maximum" -> setMaximum(toNumber(value)); 1246 case "minItems" -> setMinItems(toInteger(value)); 1247 case "minLength" -> setMinLength(toInteger(value)); 1248 case "minProperties" -> setMinProperties(toInteger(value)); 1249 case "minimum" -> setMinimum(toNumber(value)); 1250 case "multipleOf" -> setMultipleOf(toNumber(value)); 1251 case "not" -> setNot(toType(value, SchemaInfo.class)); 1252 case "nullable" -> setNullable(toBoolean(value)); 1253 case "oneOf" -> setOneOf(listBuilder(Object.class).sparse().addAny(value).build()); 1254 case "pattern" -> setPattern(Utils.s(value)); 1255 case "properties" -> setProperties(mapBuilder(String.class, SchemaInfo.class).sparse().addAny(value).build()); 1256 case "readOnly" -> setReadOnly(toBoolean(value)); 1257 case "required" -> setRequired(listBuilder(String.class).sparse().addAny(value).build()); 1258 case "title" -> setTitle(Utils.s(value)); 1259 case "type" -> setType(Utils.s(value)); 1260 case "uniqueItems" -> setUniqueItems(toBoolean(value)); 1261 case "writeOnly" -> setWriteOnly(toBoolean(value)); 1262 case "xml" -> setXml(toType(value, Xml.class)); 1263 default -> { 1264 super.set(property, value); 1265 yield this; 1266 } 1267 }; 1268 } 1269 1270 @Override /* SwaggerElement */ 1271 public Set<String> keySet() { 1272 var s = setBuilder(String.class) 1273 .addIf(ref != null, "$ref") 1274 .addIf(additionalProperties != null, "additionalProperties") 1275 .addIf(allOf != null, "allOf") 1276 .addIf(anyOf != null, "anyOf") 1277 .addIf(_default != null, "default") 1278 .addIf(deprecated != null, "deprecated") 1279 .addIf(description != null, "description") 1280 .addIf(discriminator != null, "discriminator") 1281 .addIf(_enum != null, "enum") 1282 .addIf(example != null, "example") 1283 .addIf(exclusiveMaximum != null, "exclusiveMaximum") 1284 .addIf(exclusiveMinimum != null, "exclusiveMinimum") 1285 .addIf(externalDocs != null, "externalDocs") 1286 .addIf(format != null, "format") 1287 .addIf(items != null, "items") 1288 .addIf(maximum != null, "maximum") 1289 .addIf(maxItems != null, "maxItems") 1290 .addIf(maxLength != null, "maxLength") 1291 .addIf(maxProperties != null, "maxProperties") 1292 .addIf(minimum != null, "minimum") 1293 .addIf(minItems != null, "minItems") 1294 .addIf(minLength != null, "minLength") 1295 .addIf(minProperties != null, "minProperties") 1296 .addIf(multipleOf != null, "multipleOf") 1297 .addIf(not != null, "not") 1298 .addIf(nullable != null, "nullable") 1299 .addIf(oneOf != null, "oneOf") 1300 .addIf(pattern != null, "pattern") 1301 .addIf(properties != null, "properties") 1302 .addIf(readOnly != null, "readOnly") 1303 .addIf(required != null, "required") 1304 .addIf(title != null, "title") 1305 .addIf(type != null, "type") 1306 .addIf(uniqueItems != null, "uniqueItems") 1307 .addIf(writeOnly != null, "writeOnly") 1308 .addIf(xml != null, "xml") 1309 .build(); 1310 return new MultiSet<>(s, super.keySet()); 1311 } 1312 1313 /** 1314 * Resolves any <js>"$ref"</js> attributes in this element. 1315 * 1316 * @param openApi The swagger document containing the definitions. 1317 * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops. 1318 * @param maxDepth 1319 * The maximum depth to resolve references. 1320 * <br>After that level is reached, <code>$ref</code> references will be left alone. 1321 * <br>Useful if you have very complex models and you don't want your swagger page to be overly-complex. 1322 * @return 1323 * This object with references resolved. 1324 * <br>May or may not be the same object. 1325 */ 1326 public SchemaInfo resolveRefs(OpenApi openApi, Deque<String> refStack, int maxDepth) { 1327 1328 if (ref != null) { 1329 if (refStack.contains(ref) || refStack.size() >= maxDepth) 1330 return this; 1331 refStack.addLast(ref); 1332 var r = openApi.findRef(ref, SchemaInfo.class); 1333 r = r.resolveRefs(openApi, refStack, maxDepth); 1334 refStack.removeLast(); 1335 return r; 1336 } 1337 1338 if (items != null) 1339 items = items.resolveRefs(openApi, refStack, maxDepth); 1340 1341 if (properties != null) 1342 for (var e : properties.entrySet()) 1343 e.setValue(e.getValue().resolveRefs(openApi, refStack, maxDepth)); 1344 1345 if (additionalProperties != null) 1346 additionalProperties = additionalProperties.resolveRefs(openApi, refStack, maxDepth); 1347 1348 this.example = null; 1349 1350 return this; 1351 } 1352 1353 @Override /* Overridden from OpenApiElement */ 1354 public SchemaInfo strict() { 1355 super.strict(); 1356 return this; 1357 } 1358 1359 @Override /* Overridden from OpenApiElement */ 1360 public SchemaInfo strict(Object value) { 1361 super.strict(value); 1362 return this; 1363 } 1364 1365}