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.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.bean.openapi3.OpenApiCopyUtils.*; 021import static org.apache.juneau.commons.utils.CollectionUtils.contains; 022import static org.apache.juneau.commons.utils.Shorts.*; 023import static org.apache.juneau.commons.utils.StringUtils.*; 024import static org.apache.juneau.marshall.internal.ConverterUtils.*; 025 026import java.util.*; 027 028import org.apache.juneau.commons.bean.*; 029import org.apache.juneau.commons.collections.*; 030import org.apache.juneau.marshall.collections.*; 031import org.apache.juneau.marshall.marshaller.*; 032 033/** 034 * A limited subset of JSON-Schema's items object. 035 * 036 * <p> 037 * The Items Object is a limited subset of JSON-Schema's items object. It is used by parameter definitions that are 038 * not located in "body" to describe the type of items in an array. This is particularly useful for query parameters, 039 * path parameters, and header parameters that accept arrays. 040 * 041 * <h5 class='section'>OpenAPI Specification:</h5> 042 * <p> 043 * The Items Object supports the following fields from JSON Schema: 044 * <ul class='spaced-list'> 045 * <li><c>type</c> (string, REQUIRED) - The data type. Values: <js>"string"</js>, <js>"number"</js>, <js>"integer"</js>, <js>"boolean"</js>, <js>"array"</js> 046 * <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>) 047 * <li><c>items</c> ({@link Items}) - Required if type is <js>"array"</js>. Describes the type of items in the array 048 * <li><c>collectionFormat</c> (string) - How multiple values are formatted. Values: <js>"csv"</js>, <js>"ssv"</js>, <js>"tsv"</js>, <js>"pipes"</js>, <js>"multi"</js> 049 * <li><c>default</c> (any) - The default value 050 * <li><c>maximum</c> (number), <c>exclusiveMaximum</c> (boolean), <c>minimum</c> (number), <c>exclusiveMinimum</c> (boolean) - Numeric constraints 051 * <li><c>maxLength</c> (integer), <c>minLength</c> (integer), <c>pattern</c> (string) - String constraints 052 * <li><c>maxItems</c> (integer), <c>minItems</c> (integer), <c>uniqueItems</c> (boolean) - Array constraints 053 * <li><c>enum</c> (array) - Possible values for this item 054 * <li><c>multipleOf</c> (number) - Must be a multiple of this value 055 * </ul> 056 * 057 * <h5 class='section'>Example:</h5> 058 * <p class='bcode'> 059 * <jc>// Construct using SwaggerBuilder.</jc> 060 * Items <jv>x</jv> = <jsm>items</jsm>(<js>"string"</js>).minLength(2); 061 * 062 * <jc>// Serialize using JsonSerializer.</jc> 063 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>); 064 * 065 * <jc>// Or just use toString() which does the same as above.</jc> 066 * String <jv>json</jv> = <jv>x</jv>.toString(); 067 * </p> 068 * <p class='bcode'> 069 * <jc>// Output</jc> 070 * { 071 * <js>"type"</js>: <js>"string"</js>, 072 * <js>"minLength"</js>: 2 073 * } 074 * </p> 075 * 076 * <h5 class='section'>See Also:</h5><ul> 077 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#items-object">OpenAPI Specification > Items Object</a> 078 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/describing-parameters/">OpenAPI Describing Parameters</a> 079 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 080 * </ul> 081 */ 082@SuppressWarnings({ 083 "java:S116", // Field name uses trailing underscore (default_) to avoid Java keyword conflict 084 "java:S1192" // Duplicated literals (property names) read more clearly inline than as constants 085}) 086public class Items extends OpenApiElement { 087 088 private static final String[] VALID_TYPES = { "string", "number", "integer", "boolean", "array" }; 089 private static final String[] VALID_COLLECTION_FORMATS = { "csv", "ssv", "tsv", "pipes", "multi" }; 090 091 private String type; 092 private String format; 093 private String collectionFormat; 094 private String pattern; 095 private String ref; 096 private Number maximum; 097 private Number minimum; 098 private Number multipleOf; 099 private Integer maxLength; 100 private Integer minLength; 101 private Integer maxItems; 102 private Integer minItems; 103 private Boolean exclusiveMaximum; 104 private Boolean exclusiveMinimum; 105 private Boolean uniqueItems; 106 @SuppressWarnings({ 107 "java:S1700" // Field duplicates class name per OpenAPI spec 108 }) 109 private Items items; 110 private Object default_; 111 private List<Object> enum_ = list(); 112 113 /** 114 * Default constructor. 115 */ 116 public Items() {} 117 118 /** 119 * Copy constructor. 120 * 121 * @param copyFrom The object to copy. 122 */ 123 public Items(Items copyFrom) { 124 super(copyFrom); 125 126 this.type = copyFrom.type; 127 this.format = copyFrom.format; 128 this.collectionFormat = copyFrom.collectionFormat; 129 this.pattern = copyFrom.pattern; 130 this.maximum = copyFrom.maximum; 131 this.minimum = copyFrom.minimum; 132 this.multipleOf = copyFrom.multipleOf; 133 this.maxLength = copyFrom.maxLength; 134 this.minLength = copyFrom.minLength; 135 this.maxItems = copyFrom.maxItems; 136 this.minItems = copyFrom.minItems; 137 this.exclusiveMaximum = copyFrom.exclusiveMaximum; 138 this.exclusiveMinimum = copyFrom.exclusiveMinimum; 139 this.uniqueItems = copyFrom.uniqueItems; 140 this.items = copyOf(copyFrom.items); 141 this.default_ = copyFrom.default_; 142 this.enum_.addAll(copyOf(copyFrom.enum_)); 143 this.ref = copyFrom.ref; 144 } 145 146 /** 147 * Adds one or more values to the <property>enum</property> property. 148 * 149 * @param values 150 * The values to add to this property. 151 * <br>Ignored if <jk>null</jk>. 152 * @return This object 153 */ 154 public Items addEnum(Object...values) { 155 addAllNn(enum_, values); 156 return this; 157 } 158 159 /** 160 * Make a deep copy of this object. 161 * 162 * @return A deep copy of this object. 163 */ 164 public Items copy() { 165 return new Items(this); 166 } 167 168 @Override /* Overridden from SwaggerElement */ 169 public <T> T get(String property, Class<T> type) { 170 reqnn("property", property); 171 return switch (property) { 172 case "type" -> toType(getType(), type); 173 case "format" -> toType(getFormat(), type); 174 case "items" -> toType(getItems(), type); 175 case "collectionFormat" -> toType(getCollectionFormat(), type); 176 case "default" -> toType(getDefault(), type); 177 case "maximum" -> toType(getMaximum(), type); 178 case "exclusiveMaximum" -> toType(getExclusiveMaximum(), type); 179 case "minimum" -> toType(getMinimum(), type); 180 case "exclusiveMinimum" -> toType(getExclusiveMinimum(), type); 181 case "maxLength" -> toType(getMaxLength(), type); 182 case "minLength" -> toType(getMinLength(), type); 183 case "pattern" -> toType(getPattern(), type); 184 case "maxItems" -> toType(getMaxItems(), type); 185 case "minItems" -> toType(getMinItems(), type); 186 case "uniqueItems" -> toType(getUniqueItems(), type); 187 case "enum" -> toType(getEnum(), type); 188 case "multipleOf" -> toType(getMultipleOf(), type); 189 case "$ref" -> toType(getRef(), type); 190 default -> super.get(property, type); 191 }; 192 } 193 194 /** 195 * Bean property getter: <property>collectionFormat</property>. 196 * 197 * <p> 198 * Determines the format of the array if type array is used. 199 * 200 * @return The property value, or <jk>null</jk> if it is not set. 201 */ 202 public String getCollectionFormat() { return collectionFormat; } 203 204 /** 205 * Bean property getter: <property>default</property>. 206 * 207 * <p> 208 * Declares the value of the item that the server will use if none is provided. 209 * 210 * <h5 class='section'>Notes:</h5> 211 * <ul class='spaced-list'> 212 * <li> 213 * <js>"default"</js> has no meaning for required items. 214 * <li> 215 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type. 216 * </ul> 217 * 218 * @return The property value, or <jk>null</jk> if it is not set. 219 */ 220 public Object getDefault() { return default_; } 221 222 /** 223 * Bean property getter: <property>enum</property>. 224 * 225 * @return The property value, or <jk>null</jk> if it is not set. 226 */ 227 public List<Object> getEnum() { return nie(enum_); } 228 229 /** 230 * Bean property getter: <property>exclusiveMaximum</property>. 231 * 232 * @return The property value, or <jk>null</jk> if it is not set. 233 */ 234 public Boolean getExclusiveMaximum() { return exclusiveMaximum; } 235 236 /** 237 * Bean property getter: <property>exclusiveMinimum</property>. 238 * 239 * @return The property value, or <jk>null</jk> if it is not set. 240 */ 241 public Boolean getExclusiveMinimum() { return exclusiveMinimum; } 242 243 /** 244 * Bean property getter: <property>format</property>. 245 * 246 * <p> 247 * The extending format for the previously mentioned <code>type</code>. 248 * 249 * @return The property value, or <jk>null</jk> if it is not set. 250 */ 251 public String getFormat() { return format; } 252 253 /** 254 * Bean property getter: <property>items</property>. 255 * 256 * <p> 257 * Describes the type of items in the array. 258 * 259 * @return The property value, or <jk>null</jk> if it is not set. 260 */ 261 public Items getItems() { return items; } 262 263 /** 264 * Bean property getter: <property>maximum</property>. 265 * 266 * @return The property value, or <jk>null</jk> if it is not set. 267 */ 268 public Number getMaximum() { return maximum; } 269 270 /** 271 * Bean property getter: <property>maxItems</property>. 272 * 273 * @return The property value, or <jk>null</jk> if it is not set. 274 */ 275 public Integer getMaxItems() { return maxItems; } 276 277 /** 278 * Bean property getter: <property>maxLength</property>. 279 * 280 * @return The property value, or <jk>null</jk> if it is not set. 281 */ 282 public Integer getMaxLength() { return maxLength; } 283 284 /** 285 * Bean property getter: <property>minimum</property>. 286 * 287 * @return The property value, or <jk>null</jk> if it is not set. 288 */ 289 public Number getMinimum() { return minimum; } 290 291 /** 292 * Bean property getter: <property>minItems</property>. 293 * 294 * @return The property value, or <jk>null</jk> if it is not set. 295 */ 296 public Integer getMinItems() { return minItems; } 297 298 /** 299 * Bean property getter: <property>minLength</property>. 300 * 301 * @return The property value, or <jk>null</jk> if it is not set. 302 */ 303 public Integer getMinLength() { return minLength; } 304 305 /** 306 * Bean property getter: <property>multipleOf</property>. 307 * 308 * @return The property value, or <jk>null</jk> if it is not set. 309 */ 310 public Number getMultipleOf() { return multipleOf; } 311 312 /** 313 * Bean property getter: <property>pattern</property>. 314 * 315 * @return The property value, or <jk>null</jk> if it is not set. 316 */ 317 public String getPattern() { return pattern; } 318 319 /** 320 * Bean property getter: <property>$ref</property>. 321 * 322 * @return The property value, or <jk>null</jk> if it is not set. 323 */ 324 @BeanProp("$ref") 325 public String getRef() { return ref; } 326 327 /** 328 * Bean property getter: <property>type</property>. 329 * 330 * <p> 331 * The internal type of the array. 332 * 333 * @return The property value, or <jk>null</jk> if it is not set. 334 */ 335 public String getType() { return type; } 336 337 /** 338 * Bean property getter: <property>uniqueItems</property>. 339 * 340 * @return The property value, or <jk>null</jk> if it is not set. 341 */ 342 public Boolean getUniqueItems() { return uniqueItems; } 343 344 @Override /* Overridden from SwaggerElement */ 345 public Set<String> keySet() { 346 // @formatter:off 347 var s = stb(String.class) 348 .addIf(nn(ref), "$ref") 349 .addIf(nn(collectionFormat), "collectionFormat") 350 .addIf(nn(default_), "default") 351 .addIf(ine(enum_), "enum") 352 .addIf(nn(exclusiveMaximum), "exclusiveMaximum") 353 .addIf(nn(exclusiveMinimum), "exclusiveMinimum") 354 .addIf(nn(format), "format") 355 .addIf(nn(items), "items") 356 .addIf(nn(maxItems), "maxItems") 357 .addIf(nn(maxLength), "maxLength") 358 .addIf(nn(maximum), "maximum") 359 .addIf(nn(minItems), "minItems") 360 .addIf(nn(minLength), "minLength") 361 .addIf(nn(minimum), "minimum") 362 .addIf(nn(multipleOf), "multipleOf") 363 .addIf(nn(pattern), "pattern") 364 .addIf(nn(type), "type") 365 .addIf(nn(uniqueItems), "uniqueItems") 366 .build(); 367 // @formatter:on 368 return new MultiSet<>(s, super.keySet()); 369 } 370 371 /** 372 * Resolves any <js>"$ref"</js> attributes in this element. 373 * 374 * @param openApi The swagger document containing the definitions. 375 * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops. 376 * @param maxDepth 377 * The maximum depth to resolve references. 378 * <br>After that level is reached, <code>$ref</code> references will be left alone. 379 * <br>Useful if you have very complex models and you don't want your swagger page to be overly-complex. 380 * @return 381 * This object with references resolved. 382 * <br>May or may not be the same object. 383 */ 384 public Items resolveRefs(OpenApi openApi, Deque<String> refStack, int maxDepth) { 385 386 if (nn(ref)) { 387 if (refStack.contains(ref) || refStack.size() >= maxDepth) 388 return this; 389 refStack.addLast(ref); 390 var r = openApi.findRef(ref, Items.class); 391 r = r.resolveRefs(openApi, refStack, maxDepth); 392 refStack.removeLast(); 393 return r; 394 } 395 396 set("properties", resolveRefs(get("properties"), openApi, refStack, maxDepth)); 397 398 if (nn(items)) 399 items = items.resolveRefs(openApi, refStack, maxDepth); 400 401 set("example", null); 402 403 return this; 404 } 405 406 @Override /* Overridden from SwaggerElement */ 407 public Items set(String property, Object value) { 408 reqnn("property", property); 409 return switch (property) { 410 case "$ref" -> setRef(value); 411 case "collectionFormat" -> setCollectionFormat(s(value)); 412 case "default" -> setDefault(value); 413 case "enum" -> setEnum(value); 414 case "exclusiveMaximum" -> setExclusiveMaximum(toBoolean(value)); 415 case "exclusiveMinimum" -> setExclusiveMinimum(toBoolean(value)); 416 case "format" -> setFormat(s(value)); 417 case "items" -> setItems(toType(value, Items.class)); 418 case "maxItems" -> setMaxItems(toInteger(value)); 419 case "maxLength" -> setMaxLength(toInteger(value)); 420 case "maximum" -> setMaximum(toNumber(value)); 421 case "minItems" -> setMinItems(toInteger(value)); 422 case "minLength" -> setMinLength(toInteger(value)); 423 case "minimum" -> setMinimum(toNumber(value)); 424 case "multipleOf" -> setMultipleOf(toNumber(value)); 425 case "pattern" -> setPattern(s(value)); 426 case "type" -> setType(s(value)); 427 case "uniqueItems" -> setUniqueItems(toBoolean(value)); 428 default -> { 429 super.set(property, value); 430 yield this; 431 } 432 }; 433 } 434 435 /** 436 * Bean property setter: <property>collectionFormat</property>. 437 * 438 * <p> 439 * Determines the format of the array if type array is used. 440 * 441 * @param value 442 * The new value for this property. 443 * <br>Valid values: 444 * <ul> 445 * <li><js>"csv"</js> (default) - comma separated values <code>foo,bar</code>. 446 * <li><js>"ssv"</js> - space separated values <code>foo bar</code>. 447 * <li><js>"tsv"</js> - tab separated values <code>foo\tbar</code>. 448 * <li><js>"pipes"</js> - pipe separated values <code>foo|bar</code>. 449 * </ul> 450 * <br>Can be <jk>null</jk> to unset the property. 451 * @return This object 452 */ 453 public Items setCollectionFormat(String value) { 454 if (isStrict() && ! contains(value, VALID_COLLECTION_FORMATS)) 455 throw rex("Invalid value passed in to setCollectionFormat(String). Value='%s', valid values=[%s]", value, toCdl(VALID_COLLECTION_FORMATS)); 456 collectionFormat = value; 457 return this; 458 } 459 460 /** 461 * Bean property setter: <property>default</property>. 462 * 463 * <p> 464 * Declares the value of the item that the server will use if none is provided. 465 * 466 * <h5 class='section'>Notes:</h5> 467 * <ul class='spaced-list'> 468 * <li> 469 * <js>"default"</js> has no meaning for required items. 470 * <li> 471 * Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type. 472 * </ul> 473 * 474 * @param value 475 * The new value for this property. 476 * <br>Can be <jk>null</jk> to unset the property. 477 * @return This object 478 */ 479 public Items setDefault(Object value) { 480 default_ = value; 481 return this; 482 } 483 484 /** 485 * Bean property setter: <property>enum</property>. 486 * 487 * @param value 488 * The new value for this property. 489 * <br>Can be <jk>null</jk> to unset the property. 490 * @return This object 491 */ 492 public Items setEnum(Collection<Object> value) { 493 enum_.clear(); 494 if (nn(value)) 495 enum_.addAll(value); 496 return this; 497 } 498 499 /** 500 * Adds one or more values to the <property>enum</property> property. 501 * 502 * @param values 503 * The values to add to this property. 504 * <br>Valid types: 505 * <ul> 506 * <li><code>Object</code> 507 * <li><code>Collection<Object></code> 508 * <li><code>String</code> - JSON array representation of <code>Collection<Object></code> 509 * <h5 class='figure'>Example:</h5> 510 * <p class='bcode'> 511 * enum_(<js>"['foo','bar']"</js>); 512 * </p> 513 * <li><code>String</code> - Individual values 514 * <h5 class='figure'>Example:</h5> 515 * <p class='bcode'> 516 * enum_(<js>"foo"</js>, <js>"bar"</js>); 517 * </p> 518 * </ul> 519 * <br>Ignored if <jk>null</jk>. 520 * @return This object 521 */ 522 public Items setEnum(Object...values) { 523 enum_ = lb(Object.class).sparse().addAny(enum_, values).build(); 524 return this; 525 } 526 527 /** 528 * Bean property setter: <property>exclusiveMaximum</property>. 529 * 530 * @param value 531 * The new value for this property. 532 * <br>Can be <jk>null</jk> to unset the property. 533 * @return This object 534 */ 535 public Items setExclusiveMaximum(Boolean value) { 536 exclusiveMaximum = value; 537 return this; 538 } 539 540 /** 541 * Bean property setter: <property>exclusiveMinimum</property>. 542 * 543 * @param value 544 * The new value for this property. 545 * <br>Can be <jk>null</jk> to unset the property. 546 * @return This object 547 */ 548 public Items setExclusiveMinimum(Boolean value) { 549 exclusiveMinimum = value; 550 return this; 551 } 552 553 /** 554 * Bean property setter: <property>format</property>. 555 * 556 * <p> 557 * The extending format for the previously mentioned <code>type</code>. 558 * 559 * @param value 560 * The new value for this property. 561 * <br>Can be <jk>null</jk> to unset the property. 562 * @return This object 563 */ 564 public Items setFormat(String value) { 565 format = value; 566 return this; 567 } 568 569 /** 570 * Bean property setter: <property>items</property>. 571 * 572 * <p> 573 * Describes the type of items in the array. 574 * 575 * @param value 576 * The new value for this property. 577 * <br>Property value is required if <code>type</code> is <js>"array"</js>. 578 * <br>Can be <jk>null</jk> to unset the property. 579 * @return This object 580 */ 581 public Items setItems(Items value) { 582 items = value; 583 return this; 584 } 585 586 /** 587 * Bean property setter: <property>maximum</property>. 588 * 589 * @param value 590 * The new value for this property. 591 * <br>Can be <jk>null</jk> to unset the property. 592 * @return This object 593 */ 594 public Items setMaximum(Number value) { 595 maximum = value; 596 return this; 597 } 598 599 /** 600 * Bean property setter: <property>maxItems</property>. 601 * 602 * @param value 603 * The new value for this property. 604 * <br>Can be <jk>null</jk> to unset the property. 605 * @return This object 606 */ 607 public Items setMaxItems(Integer value) { 608 maxItems = value; 609 return this; 610 } 611 612 /** 613 * Bean property setter: <property>maxLength</property>. 614 * 615 * @param value 616 * The new value for this property. 617 * <br>Can be <jk>null</jk> to unset the property. 618 * @return This object 619 */ 620 public Items setMaxLength(Integer value) { 621 maxLength = value; 622 return this; 623 } 624 625 /** 626 * Bean property setter: <property>minimum</property>. 627 * 628 * @param value 629 * The new value for this property. 630 * <br>Can be <jk>null</jk> to unset the property. 631 * @return This object 632 */ 633 public Items setMinimum(Number value) { 634 minimum = value; 635 return this; 636 } 637 638 /** 639 * Bean property setter: <property>minItems</property>. 640 * 641 * @param value 642 * The new value for this property. 643 * <br>Can be <jk>null</jk> to unset the property. 644 * @return This object 645 */ 646 public Items setMinItems(Integer value) { 647 minItems = value; 648 return this; 649 } 650 651 /** 652 * Bean property setter: <property>minLength</property>. 653 * 654 * @param value 655 * The new value for this property. 656 * <br>Can be <jk>null</jk> to unset the property. 657 * @return This object 658 */ 659 public Items setMinLength(Integer value) { 660 minLength = value; 661 return this; 662 } 663 664 /** 665 * Bean property setter: <property>multipleOf</property>. 666 * 667 * @param value 668 * The new value for this property. 669 * <br>Can be <jk>null</jk> to unset the property. 670 * @return This object 671 */ 672 public Items setMultipleOf(Number value) { 673 multipleOf = value; 674 return this; 675 } 676 677 /** 678 * Bean property setter: <property>pattern</property>. 679 * 680 * <p> 681 * This string SHOULD be a valid regular expression. 682 * 683 * @param value 684 * The new value for this property. 685 * <br>Can be <jk>null</jk> to unset the property. 686 * @return This object 687 */ 688 public Items setPattern(String value) { 689 pattern = value; 690 return this; 691 } 692 693 /** 694 * Bean property setter: <property>$ref</property>. 695 * 696 * @param value 697 * The new value for this property. 698 * <br>Can be <jk>null</jk> to unset the property. 699 * @return This object 700 */ 701 @BeanProp("$ref") 702 public Items setRef(Object value) { 703 ref = s(value); 704 return this; 705 } 706 707 /** 708 * Bean property setter: <property>type</property>. 709 * 710 * <p> 711 * The internal type of the array. 712 * 713 * @param value 714 * The new value for this property. 715 * <br>Valid values: 716 * <ul> 717 * <li><js>"string"</js> 718 * <li><js>"number"</js> 719 * <li><js>"integer"</js> 720 * <li><js>"boolean"</js> 721 * <li><js>"array"</js> 722 * </ul> 723 * <br>Property value is required. 724 * <br>Can be <jk>null</jk> to unset the property. 725 * @return This object 726 */ 727 public Items setType(String value) { 728 if (isStrict() && ! contains(value, VALID_TYPES)) 729 throw iaex("Invalid value passed in to setType(String). Value='%s', valid values=%s", value, Json5.of(VALID_TYPES)); 730 type = value; 731 return this; 732 } 733 734 /** 735 * Bean property setter: <property>uniqueItems</property>. 736 * 737 * @param value 738 * The new value for this property. 739 * <br>Can be <jk>null</jk> to unset the property. 740 * @return This object 741 */ 742 public Items setUniqueItems(Boolean value) { 743 uniqueItems = value; 744 return this; 745 } 746 747 @Override /* Overridden from OpenApiElement */ 748 public Items strict(Object value) { 749 super.strict(value); 750 return this; 751 } 752 753 /* Resolve references in extra attributes */ 754 private Object resolveRefs(Object o, OpenApi openApi, Deque<String> refStack, int maxDepth) { 755 if (o instanceof MarshalledMap o2) { 756 var ref2 = o2.get("$ref"); 757 if (ref2 instanceof CharSequence) { 758 var sref = ref2.toString(); 759 if (refStack.contains(sref) || refStack.size() >= maxDepth) 760 return o; 761 refStack.addLast(sref); 762 var o3 = openApi.findRef(sref, Object.class); 763 o3 = resolveRefs(o3, openApi, refStack, maxDepth); 764 refStack.removeLast(); 765 return o3; 766 } 767 for (var e : o2.entrySet()) 768 e.setValue(resolveRefs(e.getValue(), openApi, refStack, maxDepth)); 769 } 770 if (o instanceof MarshalledList o2) 771 for (var li = o2.listIterator(); li.hasNext();) 772 li.set(resolveRefs(li.next(), openApi, refStack, maxDepth)); 773 return o; 774 } 775 776 @Override /* Overridden from SwaggerElement */ 777 protected Items strict() { 778 super.strict(); 779 return this; 780 } 781}