001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.dto.jsonschema; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.net.*; 018import java.net.URI; 019import java.util.*; 020 021import org.apache.juneau.*; 022import org.apache.juneau.annotation.*; 023import org.apache.juneau.json.*; 024import org.apache.juneau.parser.*; 025import org.apache.juneau.serializer.*; 026import org.apache.juneau.transform.*; 027 028/** 029 * @deprecated Use JsonSchema. 030 */ 031@Deprecated 032@Bean(typeName="schema", 033 properties="id,$schema,$ref, title,description,type,definitions,properties," 034 + "patternProperties,dependencies,items,multipleOf,maximum,exclusiveMaximum," 035 + "minimum,exclusiveMinimum,maxLength,minLength,pattern,additionalItems," 036 + "maxItems,minItems,uniqueItems,maxProperties,minProperties,required," 037 + "additionalProperties,enum,allOf,anyOf,oneOf,not" 038) 039public class Schema { 040 private String name; // Property name. Not serialized. 041 private URI id; 042 private URI schemaVersion; 043 private String title; 044 private String description; 045 private JsonType typeJsonType; // JsonType representation of type 046 private JsonTypeArray typeJsonTypeArray; // JsonTypeArray representation of type 047 private Map<String,Schema> definitions; 048 private Map<String,Schema> properties; 049 private Map<String,Schema> patternProperties; 050 private Map<String,Schema> dependencies; 051 private Schema itemsSchema; // Schema representation of items 052 private SchemaArray itemsSchemaArray; // SchemaArray representation of items 053 private Number multipleOf; 054 private Number maximum; 055 private Boolean exclusiveMaximum; 056 private Number minimum; 057 private Boolean exclusiveMinimum; 058 private Integer maxLength; 059 private Integer minLength; 060 private String pattern; 061 private Boolean additionalItemsBoolean; // Boolean representation of additionalItems 062 private SchemaArray additionalItemsSchemaArray; // SchemaArray representation of additionalItems 063 private Integer maxItems; 064 private Integer minItems; 065 private Boolean uniqueItems; 066 private Integer maxProperties; 067 private Integer minProperties; 068 private List<String> required; 069 private Boolean additionalPropertiesBoolean; // Boolean representation of additionalProperties 070 private Schema additionalPropertiesSchema; // Schema representation of additionalProperties 071 private List<String> _enum; 072 private List<Schema> allOf; 073 private List<Schema> anyOf; 074 private List<Schema> oneOf; 075 private Schema not; 076 private URI ref; 077 private SchemaMap schemaMap; 078 private Schema master = this; 079 080 /** 081 * Default constructor. 082 */ 083 public Schema() {} 084 085 086 //-------------------------------------------------------------------------------- 087 // Bean properties 088 //-------------------------------------------------------------------------------- 089 090 /** 091 * Bean property getter: <property>name</property>. 092 * 093 * @return The value of the <property>name</property> property on this bean, or <jk>null</jk> if it is not set. 094 */ 095 @BeanIgnore 096 public String getName() { 097 return name; 098 } 099 100 /** 101 * Bean property setter: <property>name</property>. 102 * 103 * @param name The new value for the <property>name</property> property on this bean. 104 * @return This object (for method chaining). 105 */ 106 @BeanIgnore 107 public Schema setName(String name) { 108 this.name = name; 109 return this; 110 } 111 112 /** 113 * Bean property getter: <property>id</property>. 114 * 115 * @return The value of the <property>id</property> property on this bean, or <jk>null</jk> if it is not set. 116 */ 117 public URI getId() { 118 return id; 119 } 120 121 /** 122 * Bean property setter: <property>id</property>. 123 * 124 * <p> 125 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 126 * Strings must be valid URIs. 127 * 128 * <p> 129 * URIs defined by {@link UriResolver} can be used for values. 130 * 131 * @param id The new value for the <property>id</property> property on this bean. 132 * @return This object (for method chaining). 133 */ 134 public Schema setId(Object id) { 135 this.id = toURI(id); 136 return this; 137 } 138 139 /** 140 * Bean property getter: <property>$schema</property>. 141 * 142 * @return The value of the <property>$schema</property> property on this bean, or <jk>null</jk> if it is not set. 143 */ 144 @BeanProperty("$schema") 145 public URI getSchemaVersionUri() { 146 return schemaVersion; 147 } 148 149 /** 150 * Bean property setter: <property>$schema</property>. 151 * 152 * <p> 153 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 154 * Strings must be valid URIs. 155 * 156 * <p> 157 * URIs defined by {@link UriResolver} can be used for values. 158 * 159 * @param schemaVersion The new value for the <property>schemaVersion</property> property on this bean. 160 * @return This object (for method chaining). 161 */ 162 @BeanProperty("$schema") 163 public Schema setSchemaVersionUri(Object schemaVersion) { 164 this.schemaVersion = toURI(schemaVersion); 165 return this; 166 } 167 168 /** 169 * Bean property getter: <property>title</property>. 170 * 171 * @return The value of the <property>title</property> property, or <jk>null</jk> if it is not set. 172 */ 173 public String getTitle() { 174 return title; 175 } 176 177 /** 178 * Bean property setter: <property>title</property>. 179 * 180 * @param title The new value for the <property>title</property> property on this bean. 181 * @return This object (for method chaining). 182 */ 183 public Schema setTitle(String title) { 184 this.title = title; 185 return this; 186 } 187 188 /** 189 * Bean property getter: <property>description</property>. 190 * 191 * @return The value of the <property>description</property> property, or <jk>null</jk> if it is not set. 192 */ 193 public String getDescription() { 194 return description; 195 } 196 197 /** 198 * Bean property setter: <property>description</property>. 199 * 200 * @param description The new value for the <property>description</property> property on this bean. 201 * @return This object (for method chaining). 202 */ 203 public Schema setDescription(String description) { 204 this.description = description; 205 return this; 206 } 207 208 /** 209 * Bean property getter: <property>type</property>. 210 * 211 * @return 212 * The value of the <property>type</property> property on this bean, or <jk>null</jk> if it is not set. 213 * Can be either a {@link JsonType} or {@link JsonTypeArray} depending on what value was used to set it. 214 */ 215 @Swap(JsonTypeOrJsonTypeArraySwap.class) 216 public Object getType() { 217 if (typeJsonType != null) 218 return typeJsonType; 219 return typeJsonTypeArray; 220 } 221 222 /** 223 * Bean property getter: <property>type</property>. 224 * 225 * <p> 226 * Convenience method for returning the <property>type</property> property when it is a {@link JsonType} value. 227 * 228 * @return 229 * The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonTypeArray}. 230 */ 231 @BeanIgnore 232 public JsonType getTypeAsJsonType() { 233 return typeJsonType; 234 } 235 236 /** 237 * Bean property getter: <property>type</property>. 238 * 239 * <p> 240 * Convenience method for returning the <property>type</property> property when it is a {@link JsonTypeArray} value. 241 * 242 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonType}. 243 */ 244 @BeanIgnore 245 public JsonTypeArray getTypeAsJsonTypeArray() { 246 return typeJsonTypeArray; 247 } 248 249 /** 250 * Bean property setter: <property>type</property>. 251 * 252 * @param type 253 * The new value for the <property>type</property> property on this bean. 254 * This object must be of type {@link JsonType} or {@link JsonTypeArray}. 255 * @return This object (for method chaining). 256 * @throws BeanRuntimeException If invalid object type passed in. 257 */ 258 public Schema setType(Object type) { 259 this.typeJsonType = null; 260 this.typeJsonTypeArray = null; 261 if (type != null) { 262 if (type instanceof JsonType) 263 this.typeJsonType = (JsonType)type; 264 else if (type instanceof JsonTypeArray) 265 this.typeJsonTypeArray = (JsonTypeArray)type; 266 else 267 throw new BeanRuntimeException(SchemaProperty.class, 268 "Invalid attribute type ''{0}'' passed in. Must be one of the following: SimpleType, SimpleTypeArray", 269 type.getClass().getName()); 270 } 271 return this; 272 } 273 274 /** 275 * Bean property appender: <property>type</property>. 276 * 277 * @param types The list of items to append to the <property>type</property> property on this bean. 278 * @return This object (for method chaining). 279 */ 280 public Schema addTypes(JsonType...types) { 281 if (this.typeJsonTypeArray == null) 282 this.typeJsonTypeArray = new JsonTypeArray(); 283 this.typeJsonTypeArray.addAll(types); 284 return this; 285 } 286 287 /** 288 * Used during parsing to convert the <property>type</property> property to the correct class type. 289 * 290 * <ul class='spaced-list'> 291 * <li> 292 * If parsing a JSON-array, converts to a {@link JsonTypeArray}. 293 * <li> 294 * If parsing a JSON-object, converts to a {@link JsonType}. 295 * </ul> 296 * 297 * <p> 298 * Serialization method is a no-op. 299 */ 300 public static class JsonTypeOrJsonTypeArraySwap extends PojoSwap<Object,Object> { 301 302 @Override /* PojoSwap */ 303 public Object swap(BeanSession session, Object o) throws SerializeException { 304 return o; 305 } 306 307 @Override /* PojoSwap */ 308 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 309 ClassMeta<?> cm = ( 310 o instanceof Collection 311 ? session.getClassMeta(JsonTypeArray.class) 312 : session.getClassMeta(JsonType.class) 313 ); 314 return session.convertToType(o, cm); 315 } 316 } 317 318 /** 319 * Bean property getter: <property>definitions</property>. 320 * 321 * @return 322 * The value of the <property>definitions</property> property on this bean, or <jk>null</jk> if it is not set. 323 */ 324 public Map<String,Schema> getDefinitions() { 325 return definitions; 326 } 327 328 /** 329 * Bean property setter: <property>definitions</property>. 330 * 331 * @param definitions The new value for the <property>definitions</property> property on this bean. 332 * @return This object (for method chaining). 333 */ 334 public Schema setDefinitions(Map<String,Schema> definitions) { 335 this.definitions = definitions; 336 if (definitions != null) 337 setMasterOn(definitions.values()); 338 return this; 339 } 340 341 /** 342 * Bean property appender: <property>definitions</property>. 343 * 344 * @param name The key in the definitions map entry. 345 * @param definition The value in the definitions map entry. 346 * @return This object (for method chaining). 347 */ 348 public Schema addDefinition(String name, Schema definition) { 349 if (this.definitions == null) 350 this.definitions = new LinkedHashMap<>(); 351 this.definitions.put(name, definition); 352 setMasterOn(definition); 353 return this; 354 } 355 356 /** 357 * Bean property getter: <property>properties</property>. 358 * 359 * @return The value of the <property>properties</property> property on this bean, or <jk>null</jk> if it is not set. 360 */ 361 public Map<String,Schema> getProperties() { 362 return properties; 363 } 364 365 /** 366 * Returns the property with the specified name. 367 * 368 * <p> 369 * This is equivalent to calling <property>getProperty(name, <jk>false</jk>)</property>. 370 * 371 * @param name The property name. 372 * @return The property with the specified name, or <jk>null</jk> if no property is specified. 373 */ 374 public Schema getProperty(String name) { 375 return getProperty(name, false); 376 } 377 378 /** 379 * Returns the property with the specified name. 380 * 381 * <p> 382 * If <property>resolve</property> is <jk>true</jk>, the property object will automatically be resolved by calling 383 * {@link #resolve()}. 384 * Therefore, <property>getProperty(name, <jk>true</jk>)</property> is equivalent to calling 385 * <property>getProperty(name).resolve()</property>, except it's safe from a potential 386 * <property>NullPointerException</property>. 387 * 388 * @param name The property name. 389 * @param resolve If <jk>true</jk>, calls {@link #resolve()} on object before returning. 390 * @return The property with the specified name, or <jk>null</jk> if no property is specified. 391 */ 392 public Schema getProperty(String name, boolean resolve) { 393 if (properties == null) 394 return null; 395 Schema s = properties.get(name); 396 if (s == null) 397 return null; 398 if (resolve) 399 s = s.resolve(); 400 return s; 401 } 402 403 /** 404 * Bean property setter: <property>properties</property>. 405 * 406 * @param properties The new value for the <property>properties</property> property on this bean. 407 * @return This object (for method chaining). 408 */ 409 public Schema setProperties(Map<String,Schema> properties) { 410 this.properties = properties; 411 if (properties != null) 412 for (Map.Entry<String,Schema> e : properties.entrySet()) { 413 Schema value = e.getValue(); 414 setMasterOn(value); 415 value.setName(e.getKey()); 416 } 417 return this; 418 } 419 420 /** 421 * Bean property appender: <property>properties</property>. 422 * 423 * <p> 424 * Properties must have their <property>name</property> property set on them when using this method. 425 * 426 * @param properties The list of items to append to the <property>properties</property> property on this bean. 427 * @return This object (for method chaining). 428 * @throws BeanRuntimeException If property is found without a set <property>name</property> property. 429 */ 430 public Schema addProperties(Schema...properties) { 431 if (this.properties == null) 432 this.properties = new LinkedHashMap<>(); 433 for (Schema p : properties) { 434 if (p.getName() == null) 435 throw new BeanRuntimeException(Schema.class, 436 "Invalid property passed to Schema.addProperties(). Property name was null."); 437 setMasterOn(p); 438 this.properties.put(p.getName(), p); 439 } 440 return this; 441 } 442 443 /** 444 * Bean property getter: <property>patternProperties</property>. 445 * 446 * @return 447 * The value of the <property>patternProperties</property> property on this bean, or <jk>null</jk> if it is 448 * not set. 449 */ 450 public Map<String,Schema> getPatternProperties() { 451 return patternProperties; 452 } 453 454 /** 455 * Bean property setter: <property>patternProperties</property>. 456 * 457 * @param patternProperties The new value for the <property>patternProperties</property> property on this bean. 458 * @return This object (for method chaining). 459 */ 460 public Schema setPatternProperties(Map<String,Schema> patternProperties) { 461 this.patternProperties = patternProperties; 462 if (patternProperties != null) 463 for (Map.Entry<String,Schema> e : patternProperties.entrySet()) { 464 Schema s = e.getValue(); 465 setMasterOn(s); 466 s.setName(e.getKey()); 467 } 468 return this; 469 } 470 471 /** 472 * Bean property appender: <property>patternProperties</property>. 473 * 474 * <p> 475 * Properties must have their <property>name</property> property set to the pattern string when using this method. 476 * 477 * @param properties The list of items to append to the <property>patternProperties</property> property on this bean. 478 * @return This object (for method chaining). 479 * @throws BeanRuntimeException If property is found without a set <property>name</property> property. 480 */ 481 public Schema addPatternProperties(SchemaProperty...properties) { 482 if (this.patternProperties == null) 483 this.patternProperties = new LinkedHashMap<>(); 484 for (Schema p : properties) { 485 if (p.getName() == null) 486 throw new BeanRuntimeException(Schema.class, 487 "Invalid property passed to Schema.addProperties(). Property name was null."); 488 setMasterOn(p); 489 this.patternProperties.put(p.getName(), p); 490 } 491 return this; 492 } 493 494 /** 495 * Bean property getter: <property>dependencies</property>. 496 * 497 * @return 498 * The value of the <property>dependencies</property> property on this bean, or <jk>null</jk> if it is not set. 499 */ 500 public Map<String,Schema> getDependencies() { 501 return dependencies; 502 } 503 504 /** 505 * Bean property setter: <property>dependencies</property>. 506 * 507 * @param dependencies The new value for the <property>dependencies</property> property on this bean. 508 * @return This object (for method chaining). 509 */ 510 public Schema setDependencies(Map<String,Schema> dependencies) { 511 this.dependencies = dependencies; 512 if (dependencies != null) 513 setMasterOn(dependencies.values()); 514 return this; 515 } 516 517 /** 518 * Bean property appender: <property>dependencies</property>. 519 * 520 * @param name The key of the entry in the dependencies map. 521 * @param dependency The value of the entry in the dependencies map. 522 * @return This object (for method chaining). 523 */ 524 public Schema addDependency(String name, Schema dependency) { 525 if (this.dependencies == null) 526 this.dependencies = new LinkedHashMap<>(); 527 this.dependencies.put(name, dependency); 528 setMasterOn(dependency); 529 return this; 530 } 531 532 /** 533 * Bean property getter: <property>items</property>. 534 * 535 * @return 536 * The value of the <property>items</property> property on this bean, or <jk>null</jk> if it is not set. 537 * Can be either a {@link Schema} or {@link SchemaArray} depending on what value was used to set it. 538 */ 539 @Swap(SchemaOrSchemaArraySwap.class) 540 public Object getItems() { 541 if (itemsSchema != null) 542 return itemsSchema; 543 return itemsSchemaArray; 544 } 545 546 /** 547 * Bean property getter: <property>items</property>. 548 * 549 * <p> 550 * Convenience method for returning the <property>items</property> property when it is a {@link Schema} value. 551 * 552 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link SchemaArray}. 553 */ 554 @BeanIgnore 555 public Schema getItemsAsSchema() { 556 return itemsSchema; 557 } 558 559 /** 560 * Bean property getter: <property>items</property>. 561 * 562 * <p> 563 * Convenience method for returning the <property>items</property> property when it is a {@link SchemaArray} value. 564 * 565 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Schema}. 566 */ 567 @BeanIgnore 568 public SchemaArray getItemsAsSchemaArray() { 569 return itemsSchemaArray; 570 } 571 572 /** 573 * Used during parsing to convert the <property>items</property> property to the correct class type. 574 * 575 * <ul class='spaced-list'> 576 * <li> 577 * If parsing a JSON-array, converts to a {@link SchemaArray}. 578 * <li> 579 * If parsing a JSON-object, converts to a {@link Schema}. 580 * </ul> 581 * 582 * <p> 583 * Serialization method is a no-op. 584 */ 585 public static class SchemaOrSchemaArraySwap extends PojoSwap<Object,Object> { 586 587 @Override /* PojoSwap */ 588 public Object swap(BeanSession session, Object o) throws SerializeException { 589 return o; 590 } 591 592 @Override /* PojoSwap */ 593 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 594 ClassMeta<?> cm = ( 595 o instanceof Collection 596 ? session.getClassMeta(SchemaArray.class) 597 : session.getClassMeta(Schema.class) 598 ); 599 return session.convertToType(o, cm); 600 } 601 } 602 603 /** 604 * Bean property setter: <property>items</property>. 605 * 606 * @param 607 * items The new value for the <property>items</property> property on this bean. 608 * This object must be of type {@link Schema} or {@link SchemaArray}. 609 * @return This object (for method chaining). 610 * @throws BeanRuntimeException If invalid object type passed in. 611 */ 612 public Schema setItems(Object items) { 613 this.itemsSchema = null; 614 this.itemsSchemaArray = null; 615 if (items != null) { 616 if (items instanceof Schema) { 617 this.itemsSchema = (Schema)items; 618 setMasterOn(this.itemsSchema); 619 } else if (items instanceof SchemaArray) { 620 this.itemsSchemaArray = (SchemaArray)items; 621 setMasterOn(this.itemsSchemaArray); 622 } else 623 throw new BeanRuntimeException(SchemaProperty.class, 624 "Invalid attribute type ''{0}'' passed in. Must be one of the following: Schema, SchemaArray", 625 items.getClass().getName()); 626 } 627 return this; 628 } 629 630 /** 631 * Bean property appender: <property>items</property>. 632 * 633 * @param items The list of items to append to the <property>items</property> property on this bean. 634 * @return This object (for method chaining). 635 */ 636 public Schema addItems(Schema...items) { 637 if (this.itemsSchemaArray == null) 638 this.itemsSchemaArray = new SchemaArray(); 639 this.itemsSchemaArray.addAll(items); 640 setMasterOn(items); 641 return this; 642 } 643 644 /** 645 * Bean property getter: <property>multipleOf</property>. 646 * 647 * @return The value of the <property>multipleOf</property> property on this bean, or <jk>null</jk> if it is not set. 648 */ 649 public Number getMultipleOf() { 650 return multipleOf; 651 } 652 653 /** 654 * Bean property setter: <property>multipleOf</property>. 655 * 656 * @param multipleOf The new value for the <property>multipleOf</property> property on this bean. 657 * @return This object (for method chaining). 658 */ 659 public Schema setMultipleOf(Number multipleOf) { 660 this.multipleOf = multipleOf; 661 return this; 662 } 663 664 /** 665 * Bean property getter: <property>maximum</property>. 666 * 667 * @return The value of the <property>maximum</property> property on this bean, or <jk>null</jk> if it is not set. 668 */ 669 public Number getMaximum() { 670 return maximum; 671 } 672 673 /** 674 * Bean property setter: <property>maximum</property>. 675 * 676 * @param maximum The new value for the <property>maximum</property> property on this bean. 677 * @return This object (for method chaining). 678 */ 679 public Schema setMaximum(Number maximum) { 680 this.maximum = maximum; 681 return this; 682 } 683 684 /** 685 * Bean property getter: <property>exclusiveMaximum</property>. 686 * 687 * @return 688 * The value of the <property>exclusiveMaximum</property> property on this bean, or <jk>null</jk> if it is 689 * not set. 690 */ 691 public Boolean isExclusiveMaximum() { 692 return exclusiveMaximum; 693 } 694 695 /** 696 * Bean property setter: <property>exclusiveMaximum</property>. 697 * 698 * @param exclusiveMaximum The new value for the <property>exclusiveMaximum</property> property on this bean. 699 * @return This object (for method chaining). 700 */ 701 public Schema setExclusiveMaximum(Boolean exclusiveMaximum) { 702 this.exclusiveMaximum = exclusiveMaximum; 703 return this; 704 } 705 706 /** 707 * Bean property getter: <property>minimum</property>. 708 * 709 * @return The value of the <property>minimum</property> property on this bean, or <jk>null</jk> if it is not set. 710 */ 711 public Number getMinimum() { 712 return minimum; 713 } 714 715 /** 716 * Bean property setter: <property>minimum</property>. 717 * 718 * @param minimum The new value for the <property>minimum</property> property on this bean. 719 * @return This object (for method chaining). 720 */ 721 public Schema setMinimum(Number minimum) { 722 this.minimum = minimum; 723 return this; 724 } 725 726 /** 727 * Bean property getter: <property>exclusiveMinimum</property>. 728 * 729 * @return 730 * The value of the <property>exclusiveMinimum</property> property on this bean, or <jk>null</jk> if it is 731 * not set. 732 */ 733 public Boolean isExclusiveMinimum() { 734 return exclusiveMinimum; 735 } 736 737 /** 738 * Bean property setter: <property>exclusiveMinimum</property>. 739 * 740 * @param exclusiveMinimum The new value for the <property>exclusiveMinimum</property> property on this bean. 741 * @return This object (for method chaining). 742 */ 743 public Schema setExclusiveMinimum(Boolean exclusiveMinimum) { 744 this.exclusiveMinimum = exclusiveMinimum; 745 return this; 746 } 747 748 /** 749 * Bean property getter: <property>maxLength</property>. 750 * 751 * @return The value of the <property>maxLength</property> property on this bean, or <jk>null</jk> if it is not set. 752 */ 753 public Integer getMaxLength() { 754 return maxLength; 755 } 756 757 /** 758 * Bean property setter: <property>maxLength</property>. 759 * 760 * @param maxLength The new value for the <property>maxLength</property> property on this bean. 761 * @return This object (for method chaining). 762 */ 763 public Schema setMaxLength(Integer maxLength) { 764 this.maxLength = maxLength; 765 return this; 766 } 767 768 /** 769 * Bean property getter: <property>minLength</property>. 770 * 771 * @return The value of the <property>minLength</property> property on this bean, or <jk>null</jk> if it is not set. 772 */ 773 public Integer getMinLength() { 774 return minLength; 775 } 776 777 /** 778 * Bean property setter: <property>minLength</property>. 779 * 780 * @param minLength The new value for the <property>minLength</property> property on this bean. 781 * @return This object (for method chaining). 782 */ 783 public Schema setMinLength(Integer minLength) { 784 this.minLength = minLength; 785 return this; 786 } 787 788 /** 789 * Bean property getter: <property>pattern</property>. 790 * 791 * @return The value of the <property>pattern</property> property on this bean, or <jk>null</jk> if it is not set. 792 */ 793 public String getPattern() { 794 return pattern; 795 } 796 797 /** 798 * Bean property setter: <property>pattern</property>. 799 * 800 * @param pattern The new value for the <property>pattern</property> property on this bean. 801 * @return This object (for method chaining). 802 */ 803 public Schema setPattern(String pattern) { 804 this.pattern = pattern; 805 return this; 806 } 807 808 /** 809 * Bean property getter: <property>additionalItems</property>. 810 * 811 * @return 812 * The value of the <property>additionalItems</property> property on this bean, or <jk>null</jk> if it is 813 * not set. 814 * Can be either a {@link Boolean} or {@link SchemaArray} depending on what value was used to set it. 815 */ 816 @Swap(BooleanOrSchemaArraySwap.class) 817 public Object getAdditionalItems() { 818 if (additionalItemsBoolean != null) 819 return additionalItemsBoolean; 820 return additionalItemsSchemaArray; 821 } 822 823 /** 824 * Bean property getter: <property>additionalItems</property>. 825 * 826 * <p> 827 * Convenience method for returning the <property>additionalItems</property> property when it is a {@link Boolean} 828 * value. 829 * 830 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link SchemaArray}. 831 */ 832 @BeanIgnore 833 public Boolean getAdditionalItemsAsBoolean() { 834 return additionalItemsBoolean; 835 } 836 837 /** 838 * Bean property getter: <property>additionalItems</property>. 839 * 840 * <p> 841 * Convenience method for returning the <property>additionalItems</property> property when it is a 842 * {@link SchemaArray} value. 843 * 844 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}. 845 */ 846 @BeanIgnore 847 public List<Schema> getAdditionalItemsAsSchemaArray() { 848 return additionalItemsSchemaArray; 849 } 850 851 /** 852 * Bean property setter: <property>additionalItems</property>. 853 * 854 * @param additionalItems 855 * The new value for the <property>additionalItems</property> property on this bean. 856 * This object must be of type {@link Boolean} or {@link SchemaArray}. 857 * @return This object (for method chaining). 858 * @throws BeanRuntimeException If invalid object type passed in. 859 */ 860 public Schema setAdditionalItems(Object additionalItems) { 861 this.additionalItemsBoolean = null; 862 this.additionalItemsSchemaArray = null; 863 if (additionalItems != null) { 864 if (additionalItems instanceof Boolean) 865 this.additionalItemsBoolean = (Boolean)additionalItems; 866 else if (additionalItems instanceof SchemaArray) { 867 this.additionalItemsSchemaArray = (SchemaArray)additionalItems; 868 setMasterOn(this.additionalItemsSchemaArray); 869 } else 870 throw new BeanRuntimeException(SchemaProperty.class, 871 "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, SchemaArray", 872 additionalItems.getClass().getName()); 873 } 874 return this; 875 } 876 877 /** 878 * Bean property appender: <property>additionalItems</property>. 879 * 880 * @param additionalItems 881 * The list of items to append to the <property>additionalItems</property> property on this bean. 882 * @return This object (for method chaining). 883 */ 884 public Schema addAdditionalItems(Schema...additionalItems) { 885 if (this.additionalItemsSchemaArray == null) 886 this.additionalItemsSchemaArray = new SchemaArray(); 887 this.additionalItemsSchemaArray.addAll(additionalItems); 888 setMasterOn(additionalItems); 889 return this; 890 } 891 892 /** 893 * Used during parsing to convert the <property>additionalItems</property> property to the correct class type. 894 * 895 * <ul class='spaced-list'> 896 * <li> 897 * If parsing a JSON-array, converts to a {@link SchemaArray}. 898 * <li> 899 * If parsing a JSON-boolean, converts to a {@link Boolean}. 900 * </ul> 901 * 902 * <p> 903 * Serialization method is a no-op. 904 */ 905 public static class BooleanOrSchemaArraySwap extends PojoSwap<Object,Object> { 906 907 @Override /* PojoSwap */ 908 public Object swap(BeanSession session, Object o) throws SerializeException { 909 return o; 910 } 911 912 @Override /* PojoSwap */ 913 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 914 ClassMeta<?> cm = ( 915 o instanceof Collection 916 ? session.getClassMeta(SchemaArray.class) 917 : session.getClassMeta(Boolean.class) 918 ); 919 return session.convertToType(o, cm); 920 } 921 } 922 923 /** 924 * Bean property getter: <property>maxItems</property>. 925 * 926 * @return The value of the <property>maxItems</property> property on this bean, or <jk>null</jk> if it is not set. 927 */ 928 public Integer getMaxItems() { 929 return maxItems; 930 } 931 932 /** 933 * Bean property setter: <property>maxItems</property>. 934 * 935 * @param maxItems The new value for the <property>maxItems</property> property on this bean. 936 * @return This object (for method chaining). 937 */ 938 public Schema setMaxItems(Integer maxItems) { 939 this.maxItems = maxItems; 940 return this; 941 } 942 943 /** 944 * Bean property getter: <property>minItems</property>. 945 * 946 * @return The value of the <property>minItems</property> property on this bean, or <jk>null</jk> if it is not set. 947 */ 948 public Integer getMinItems() { 949 return minItems; 950 } 951 952 /** 953 * Bean property setter: <property>minItems</property>. 954 * 955 * @param minItems The new value for the <property>minItems</property> property on this bean. 956 * @return This object (for method chaining). 957 */ 958 public Schema setMinItems(Integer minItems) { 959 this.minItems = minItems; 960 return this; 961 } 962 963 /** 964 * Bean property getter: <property>uniqueItems</property>. 965 * 966 * @return 967 * The value of the <property>uniqueItems</property> property on this bean, or <jk>null</jk> if it is not set. 968 */ 969 public Boolean getUniqueItems() { 970 return uniqueItems; 971 } 972 973 /** 974 * Bean property setter: <property>uniqueItems</property>. 975 * 976 * @param uniqueItems The new value for the <property>uniqueItems</property> property on this bean. 977 * @return This object (for method chaining). 978 */ 979 public Schema setUniqueItems(Boolean uniqueItems) { 980 this.uniqueItems = uniqueItems; 981 return this; 982 } 983 984 /** 985 * Bean property getter: <property>maxProperties</property>. 986 * 987 * @return 988 * The value of the <property>maxProperties</property> property on this bean, or <jk>null</jk> if it is not set. 989 */ 990 public Integer getMaxProperties() { 991 return maxProperties; 992 } 993 994 /** 995 * Bean property setter: <property>maxProperties</property>. 996 * 997 * @param maxProperties The new value for the <property>maxProperties</property> property on this bean. 998 * @return This object (for method chaining). 999 */ 1000 public Schema setMaxProperties(Integer maxProperties) { 1001 this.maxProperties = maxProperties; 1002 return this; 1003 } 1004 1005 /** 1006 * Bean property getter: <property>minProperties</property>. 1007 * 1008 * @return 1009 * The value of the <property>minProperties</property> property on this bean, or <jk>null</jk> if it is not set. 1010 */ 1011 public Integer getMinProperties() { 1012 return minProperties; 1013 } 1014 1015 /** 1016 * Bean property setter: <property>minProperties</property>. 1017 * 1018 * @param minProperties The new value for the <property>minProperties</property> property on this bean. 1019 * @return This object (for method chaining). 1020 */ 1021 public Schema setMinProperties(Integer minProperties) { 1022 this.minProperties = minProperties; 1023 return this; 1024 } 1025 1026 /** 1027 * Bean property getter: <property>required</property>. 1028 * 1029 * @return The value of the <property>required</property> property on this bean, or <jk>null</jk> if it is not set. 1030 */ 1031 public List<String> getRequired() { 1032 return required; 1033 } 1034 1035 /** 1036 * Bean property setter: <property>required</property>. 1037 * 1038 * @param required The new value for the <property>required</property> property on this bean. 1039 * @return This object (for method chaining). 1040 */ 1041 public Schema setRequired(List<String> required) { 1042 this.required = required; 1043 return this; 1044 } 1045 1046 /** 1047 * Bean property appender: <property>required</property>. 1048 * 1049 * @param required The list of items to append to the <property>required</property> property on this bean. 1050 * @return This object (for method chaining). 1051 */ 1052 public Schema addRequired(List<String> required) { 1053 if (this.required == null) 1054 this.required = new LinkedList<>(); 1055 for (String r : required) 1056 this.required.add(r); 1057 return this; 1058 } 1059 1060 /** 1061 * Bean property appender: <property>required</property>. 1062 * 1063 * @param required The list of items to append to the <property>required</property> property on this bean. 1064 * @return This object (for method chaining). 1065 */ 1066 public Schema addRequired(String...required) { 1067 if (this.required == null) 1068 this.required = new LinkedList<>(); 1069 for (String r : required) 1070 this.required.add(r); 1071 return this; 1072 } 1073 1074 /** 1075 * Bean property appender: <property>required</property>. 1076 * 1077 * @param properties The list of items to append to the <property>required</property> property on this bean. 1078 * @return This object (for method chaining). 1079 */ 1080 public Schema addRequired(SchemaProperty...properties) { 1081 if (this.required == null) 1082 this.required = new LinkedList<>(); 1083 for (SchemaProperty p : properties) 1084 this.required.add(p.getName()); 1085 return this; 1086 } 1087 1088 /** 1089 * Bean property getter: <property>additionalProperties</property>. 1090 * 1091 * @return 1092 * The value of the <property>additionalProperties</property> property on this bean, or <jk>null</jk> if it 1093 * is not set. 1094 * Can be either a {@link Boolean} or {@link SchemaArray} depending on what value was used to set it. 1095 */ 1096 @Swap(BooleanOrSchemaSwap.class) 1097 public Object getAdditionalProperties() { 1098 if (additionalPropertiesBoolean != null) 1099 return additionalItemsBoolean; 1100 return additionalPropertiesSchema; 1101 } 1102 1103 /** 1104 * Bean property getter: <property>additionalProperties</property>. 1105 * 1106 * <p> 1107 * Convenience method for returning the <property>additionalProperties</property> property when it is a 1108 * {@link Boolean} value. 1109 * 1110 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Schema}. 1111 */ 1112 @BeanIgnore 1113 public Boolean getAdditionalPropertiesAsBoolean() { 1114 return additionalPropertiesBoolean; 1115 } 1116 1117 /** 1118 * Bean property getter: <property>additionalProperties</property>. 1119 * 1120 * <p> 1121 * Convenience method for returning the <property>additionalProperties</property> property when it is a 1122 * {@link Schema} value. 1123 * 1124 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}. 1125 */ 1126 @BeanIgnore 1127 public Schema getAdditionalPropertiesAsSchema() { 1128 return additionalPropertiesSchema; 1129 } 1130 1131 /** 1132 * Bean property setter: <property>additionalProperties</property>. 1133 * 1134 * @param additionalProperties 1135 * The new value for the <property>additionalProperties</property> property on this bean. 1136 * This object must be of type {@link Boolean} or {@link Schema}. 1137 * @return This object (for method chaining). 1138 * @throws BeanRuntimeException If invalid object type passed in. 1139 */ 1140 @BeanProperty(beanDictionary={Schema.class}) 1141 public Schema setAdditionalProperties(Object additionalProperties) { 1142 this.additionalPropertiesBoolean = null; 1143 this.additionalPropertiesSchema = null; 1144 if (additionalProperties != null) { 1145 if (additionalProperties instanceof Boolean) 1146 this.additionalPropertiesBoolean = (Boolean)additionalProperties; 1147 else if (additionalProperties instanceof Schema) { 1148 this.additionalPropertiesSchema = (Schema)additionalProperties; 1149 setMasterOn(this.additionalPropertiesSchema); 1150 } else 1151 throw new BeanRuntimeException(SchemaProperty.class, 1152 "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, Schema", 1153 additionalProperties.getClass().getName()); 1154 } 1155 return this; 1156 } 1157 1158 /** 1159 * Used during parsing to convert the <property>additionalProperties</property> property to the correct class type. 1160 * 1161 * <ul class='spaced-list'> 1162 * <li> 1163 * If parsing a JSON-object, converts to a {@link Schema}. 1164 * <li> 1165 * If parsing a JSON-boolean, converts to a {@link Boolean}. 1166 * </ul> 1167 * 1168 * <p> 1169 * Serialization method is a no-op. 1170 */ 1171 public static class BooleanOrSchemaSwap extends PojoSwap<Object,Object> { 1172 1173 @Override /* PojoSwap */ 1174 public Object swap(BeanSession session, Object o) throws SerializeException { 1175 return o; 1176 } 1177 1178 @Override /* PojoSwap */ 1179 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 1180 ClassMeta<?> cm = ( 1181 o instanceof Boolean 1182 ? session.getClassMeta(Boolean.class) 1183 : session.getClassMeta(Schema.class) 1184 ); 1185 return session.convertToType(o, cm); 1186 } 1187 } 1188 1189 /** 1190 * Bean property getter: <property>enum</property>. 1191 * 1192 * @return The value of the <property>enum</property> property on this bean, or <jk>null</jk> if it is not set. 1193 */ 1194 public List<String> getEnum() { 1195 return _enum; 1196 } 1197 1198 /** 1199 * Bean property setter: <property>enum</property>. 1200 * 1201 * @param _enum The new value for the <property>enum</property> property on this bean. 1202 * @return This object (for method chaining). 1203 */ 1204 public Schema setEnum(List<String> _enum) { 1205 this._enum = _enum; 1206 return this; 1207 } 1208 1209 /** 1210 * Bean property appender: <property>enum</property>. 1211 * 1212 * @param _enum The list of items to append to the <property>enum</property> property on this bean. 1213 * @return This object (for method chaining). 1214 */ 1215 public Schema addEnum(String..._enum) { 1216 if (this._enum == null) 1217 this._enum = new LinkedList<>(); 1218 for (String e : _enum) 1219 this._enum.add(e); 1220 return this; 1221 } 1222 1223 /** 1224 * Bean property getter: <property>allOf</property>. 1225 * 1226 * @return The value of the <property>allOf</property> property on this bean, or <jk>null</jk> if it is not set. 1227 */ 1228 public List<Schema> getAllOf() { 1229 return allOf; 1230 } 1231 1232 /** 1233 * Bean property setter: <property>allOf</property>. 1234 * 1235 * @param allOf The new value for the <property>allOf</property> property on this bean. 1236 * @return This object (for method chaining). 1237 */ 1238 public Schema setAllOf(List<Schema> allOf) { 1239 this.allOf = allOf; 1240 setMasterOn(allOf); 1241 return this; 1242 } 1243 1244 /** 1245 * Bean property appender: <property>allOf</property>. 1246 * 1247 * @param allOf The list of items to append to the <property>allOf</property> property on this bean. 1248 * @return This object (for method chaining). 1249 */ 1250 public Schema addAllOf(Schema...allOf) { 1251 if (this.allOf == null) 1252 this.allOf = new LinkedList<>(); 1253 setMasterOn(allOf); 1254 for (Schema s : allOf) 1255 this.allOf.add(s); 1256 return this; 1257 } 1258 1259 /** 1260 * Bean property getter: <property>anyOf</property>. 1261 * 1262 * @return The value of the <property>anyOf</property> property on this bean, or <jk>null</jk> if it is not set. 1263 */ 1264 public List<Schema> getAnyOf() { 1265 return anyOf; 1266 } 1267 1268 /** 1269 * Bean property setter: <property>anyOf</property>. 1270 * 1271 * @param anyOf The new value of the <property>anyOf</property> property on this bean. 1272 * @return This object (for method chaining). 1273 */ 1274 public Schema setAnyOf(List<Schema> anyOf) { 1275 this.anyOf = anyOf; 1276 setMasterOn(anyOf); 1277 return this; 1278 } 1279 1280 /** 1281 * Bean property appender: <property>anyOf</property>. 1282 * 1283 * @param anyOf The list of items to append to the <property>anyOf</property> property on this bean. 1284 * @return This object (for method chaining). 1285 */ 1286 public Schema addAnyOf(Schema...anyOf) { 1287 if (this.anyOf == null) 1288 this.anyOf = new LinkedList<>(); 1289 setMasterOn(anyOf); 1290 for (Schema s : anyOf) 1291 this.anyOf.add(s); 1292 return this; 1293 } 1294 1295 /** 1296 * Bean property getter: <property>oneOf</property>. 1297 * 1298 * @return The value of the <property>oneOf</property> property on this bean, or <jk>null</jk> if it is not set. 1299 */ 1300 public List<Schema> getOneOf() { 1301 return oneOf; 1302 } 1303 1304 /** 1305 * Bean property setter: <property>oneOf</property>. 1306 * 1307 * @param oneOf The new value for the <property>oneOf</property> property on this bean. 1308 * @return This object (for method chaining). 1309 */ 1310 public Schema setOneOf(List<Schema> oneOf) { 1311 this.oneOf = oneOf; 1312 setMasterOn(oneOf); 1313 return this; 1314 } 1315 1316 /** 1317 * Bean property appender: <property>oneOf</property>. 1318 * 1319 * @param oneOf The list of items to append to the <property>oneOf</property> property on this bean. 1320 * @return This object (for method chaining). 1321 */ 1322 public Schema addOneOf(Schema...oneOf) { 1323 if (this.oneOf == null) 1324 this.oneOf = new LinkedList<>(); 1325 setMasterOn(oneOf); 1326 for (Schema s : oneOf) 1327 this.oneOf.add(s); 1328 return this; 1329 } 1330 1331 /** 1332 * Bean property getter: <property>not</property>. 1333 * 1334 * @return The value of the <property>not</property> property on this bean, or <jk>null</jk> if it is not set. 1335 */ 1336 public Schema getNot() { 1337 return not; 1338 } 1339 1340 /** 1341 * Bean property setter: <property>not</property>. 1342 * 1343 * @param not The new value for the <property>not</property> property on this bean. 1344 * @return This object (for method chaining). 1345 */ 1346 public Schema setNot(Schema not) { 1347 this.not = not; 1348 setMasterOn(not); 1349 return this; 1350 } 1351 1352 /** 1353 * Bean property getter: <property>$ref</property>. 1354 * 1355 * @return The value of the <property>$ref</property> property on this bean, or <jk>null</jk> if it is not set. 1356 */ 1357 @BeanProperty("$ref") 1358 public URI getRef() { 1359 return ref; 1360 } 1361 1362 /** 1363 * Bean property setter: <property>$ref</property>. 1364 * 1365 * <p> 1366 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 1367 * Strings must be valid URIs. 1368 * 1369 * <p> 1370 * URIs defined by {@link UriResolver} can be used for values. 1371 * 1372 * @param ref The new value for the <property>$ref</property> property on this bean. 1373 * @return This object (for method chaining). 1374 */ 1375 @BeanProperty("$ref") 1376 public Schema setRef(Object ref) { 1377 this.ref = toURI(ref); 1378 return this; 1379 } 1380 1381 private void setMasterOn(Schema s) { 1382 if (s != null) 1383 s.setMaster(this); 1384 } 1385 1386 private void setMasterOn(Schema[] ss) { 1387 if (ss != null) 1388 for (Schema s : ss) 1389 setMasterOn(s); 1390 } 1391 1392 private void setMasterOn(Collection<Schema> ss) { 1393 if (ss != null) 1394 for (Schema s : ss) 1395 setMasterOn(s); 1396 } 1397 1398 private void setMasterOn(SchemaArray ss) { 1399 if (ss != null) 1400 for (Schema s : ss) 1401 setMasterOn(s); 1402 } 1403 1404 /** 1405 * Sets the master schema for this schema and all child schema objects. 1406 * 1407 * <p> 1408 * All child elements in a schema should point to a single "master" schema in order to locate registered SchemaMap 1409 * objects for resolving external schemas. 1410 * 1411 * @param master The master schema to associate on this and all children. Can be <jk>null</jk>. 1412 */ 1413 protected void setMaster(Schema master) { 1414 this.master = master; 1415 if (definitions != null) 1416 for (Schema s : definitions.values()) 1417 s.setMaster(master); 1418 if (properties != null) 1419 for (Schema s : properties.values()) 1420 s.setMaster(master); 1421 if (patternProperties != null) 1422 for (Schema s : patternProperties.values()) 1423 s.setMaster(master); 1424 if (dependencies != null) 1425 for (Schema s : dependencies.values()) 1426 s.setMaster(master); 1427 if (itemsSchema != null) 1428 itemsSchema.setMaster(master); 1429 if (itemsSchemaArray != null) 1430 for (Schema s : itemsSchemaArray) 1431 s.setMaster(master); 1432 if (additionalItemsSchemaArray != null) 1433 for (Schema s : additionalItemsSchemaArray) 1434 s.setMaster(master); 1435 if (additionalPropertiesSchema != null) 1436 additionalPropertiesSchema.setMaster(master); 1437 if (allOf != null) 1438 for (Schema s : allOf) 1439 s.setMaster(master); 1440 if (anyOf != null) 1441 for (Schema s : anyOf) 1442 s.setMaster(master); 1443 if (oneOf != null) 1444 for (Schema s : oneOf) 1445 s.setMaster(master); 1446 if (not != null) 1447 not.setMaster(master); 1448 } 1449 /** 1450 * If this schema is a reference to another schema (i.e. has its <property>$ref</property> property set), this 1451 * method will retrieve the referenced schema from the schema map registered with this schema. 1452 * 1453 * <p> 1454 * If this schema is not a reference, or no schema map is registered with this schema, this method is a no-op and 1455 * simply returns this object. 1456 * 1457 * @return The referenced schema, or <jk>null</jk>. 1458 */ 1459 public Schema resolve() { 1460 if (ref == null || master.schemaMap == null) 1461 return this; 1462 return master.schemaMap.get(ref); 1463 } 1464 1465 /** 1466 * Associates a schema map with this schema for resolving other schemas identified through <property>$ref</property> 1467 * properties. 1468 * 1469 * @param schemaMap The schema map to associate with this schema. Can be <jk>null</jk>. 1470 * @return This object (for method chaining). 1471 */ 1472 public Schema setSchemaMap(SchemaMap schemaMap) { 1473 this.schemaMap = schemaMap; 1474 return this; 1475 } 1476 1477 @Override /* Object */ 1478 public String toString() { 1479 return JsonSerializer.DEFAULT.toString(this); 1480 } 1481}