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.jsonschema; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.StringUtils.*; 021import static org.apache.juneau.commons.utils.ThrowableUtils.*; 022import static org.apache.juneau.commons.utils.Utils.*; 023 024import java.net.*; 025import java.util.*; 026 027import org.apache.juneau.*; 028import org.apache.juneau.annotation.*; 029import org.apache.juneau.commons.reflect.*; 030import org.apache.juneau.json.*; 031import org.apache.juneau.parser.*; 032import org.apache.juneau.serializer.*; 033import org.apache.juneau.swap.*; 034 035/** 036 * Represents a top-level schema object bean in the JSON-Schema core specification. 037 * 038 * <p> 039 * This implementation follows the JSON Schema Draft 2020-12 specification. 040 * 041 * <h5 class='section'>Example:</h5> 042 * <p class='bjava'> 043 * <jc>// Create a simple schema for a person object</jc> 044 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 045 * .setIdUri(<js>"https://example.com/person.schema.json"</js>) 046 * .setSchemaVersionUri(<js>"https://json-schema.org/draft/2020-12/schema"</js>) 047 * .setTitle(<js>"Person"</js>) 048 * .setDescription(<js>"A person object"</js>) 049 * .setType(JsonType.<jsf>OBJECT</jsf>) 050 * .addProperties( 051 * <jk>new</jk> JsonSchemaProperty(<js>"firstName"</js>, JsonType.<jsf>STRING</jsf>) 052 * .setMinLength(1) 053 * .setMaxLength(50), 054 * <jk>new</jk> JsonSchemaProperty(<js>"lastName"</js>, JsonType.<jsf>STRING</jsf>) 055 * .setMinLength(1) 056 * .setMaxLength(50), 057 * <jk>new</jk> JsonSchemaProperty(<js>"age"</js>, JsonType.<jsf>INTEGER</jsf>) 058 * .setMinimum(0) 059 * .setExclusiveMaximum(150) 060 * ) 061 * .addRequired(<js>"firstName"</js>, <js>"lastName"</js>); 062 * 063 * <jc>// Serialize to JSON Schema</jc> 064 * String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT_SORTED</jsf>.serialize(<jv>schema</jv>); 065 * </p> 066 * 067 * <p> 068 * Output: 069 * <p class='bjson'> 070 * { 071 * <js>"$id"</js>: <js>"https://example.com/person.schema.json"</js>, 072 * <js>"$schema"</js>: <js>"https://json-schema.org/draft/2020-12/schema"</js>, 073 * <js>"title"</js>: <js>"Person"</js>, 074 * <js>"description"</js>: <js>"A person object"</js>, 075 * <js>"type"</js>: <js>"object"</js>, 076 * <js>"properties"</js>: { 077 * <js>"firstName"</js>: { 078 * <js>"type"</js>: <js>"string"</js>, 079 * <js>"minLength"</js>: 1, 080 * <js>"maxLength"</js>: 50 081 * }, 082 * <js>"lastName"</js>: { 083 * <js>"type"</js>: <js>"string"</js>, 084 * <js>"minLength"</js>: 1, 085 * <js>"maxLength"</js>: 50 086 * }, 087 * <js>"age"</js>: { 088 * <js>"type"</js>: <js>"integer"</js>, 089 * <js>"minimum"</js>: 0, 090 * <js>"exclusiveMaximum"</js>: 150 091 * } 092 * }, 093 * <js>"required"</js>: [<js>"firstName"</js>, <js>"lastName"</js>] 094 * } 095 * </p> 096 * 097 * <h5 class='section'>Key Features:</h5> 098 * <ul class='spaced-list'> 099 * <li><b>Draft 2020-12 Support:</b> Includes all properties from the latest JSON Schema specification 100 * <li><b>Backward Compatibility:</b> Deprecated Draft 04 properties (like <c>id</c> and <c>definitions</c>) are still supported 101 * <li><b>Fluent API:</b> All setter methods return <c>this</c> for method chaining 102 * <li><b>Type Safety:</b> Uses enums and typed collections for validation 103 * <li><b>Serialization:</b> Can be serialized to any format supported by Juneau (JSON, XML, HTML, etc.) 104 * </ul> 105 * 106 * <h5 class='section'>Common Use Cases:</h5> 107 * 108 * <p><b>1. Simple Type Constraints:</b> 109 * <p class='bjava'> 110 * <jc>// String with length constraints</jc> 111 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 112 * .setType(JsonType.<jsf>STRING</jsf>) 113 * .setMinLength(5) 114 * .setMaxLength(100) 115 * .setPattern(<js>"^[A-Za-z]+$"</js>); 116 * </p> 117 * 118 * <p><b>2. Numeric Ranges:</b> 119 * <p class='bjava'> 120 * <jc>// Number between 0 and 100 (exclusive)</jc> 121 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 122 * .setType(JsonType.<jsf>NUMBER</jsf>) 123 * .setExclusiveMinimum(0) 124 * .setExclusiveMaximum(100) 125 * .setMultipleOf(0.5); 126 * </p> 127 * 128 * <p><b>3. Enumerations:</b> 129 * <p class='bjava'> 130 * <jc>// Status field with allowed values</jc> 131 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 132 * .setType(JsonType.<jsf>STRING</jsf>) 133 * .addEnum(<js>"pending"</js>, <js>"active"</js>, <js>"completed"</js>); 134 * </p> 135 * 136 * <p><b>4. Arrays:</b> 137 * <p class='bjava'> 138 * <jc>// Array of strings with constraints</jc> 139 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 140 * .setType(JsonType.<jsf>ARRAY</jsf>) 141 * .setItems(<jk>new</jk> JsonSchema().setType(JsonType.<jsf>STRING</jsf>)) 142 * .setMinItems(1) 143 * .setMaxItems(10) 144 * .setUniqueItems(<jk>true</jk>); 145 * </p> 146 * 147 * <p><b>5. Conditional Schemas (Draft 07+):</b> 148 * <p class='bjava'> 149 * <jc>// Different validation based on country</jc> 150 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 151 * .setType(JsonType.<jsf>OBJECT</jsf>) 152 * .addProperties( 153 * <jk>new</jk> JsonSchemaProperty(<js>"country"</js>, JsonType.<jsf>STRING</jsf>), 154 * <jk>new</jk> JsonSchemaProperty(<js>"postalCode"</js>, JsonType.<jsf>STRING</jsf>) 155 * ) 156 * .setIf(<jk>new</jk> JsonSchema() 157 * .addProperties(<jk>new</jk> JsonSchemaProperty(<js>"country"</js>).setConst(<js>"USA"</js>)) 158 * ) 159 * .setThen(<jk>new</jk> JsonSchema() 160 * .addProperties(<jk>new</jk> JsonSchemaProperty(<js>"postalCode"</js>).setPattern(<js>"^[0-9]{5}$"</js>)) 161 * ); 162 * </p> 163 * 164 * <p><b>6. Reusable Definitions:</b> 165 * <p class='bjava'> 166 * <jc>// Schema with reusable components using $defs</jc> 167 * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema() 168 * .setType(JsonType.<jsf>OBJECT</jsf>) 169 * .addDef(<js>"address"</js>, <jk>new</jk> JsonSchema() 170 * .setType(JsonType.<jsf>OBJECT</jsf>) 171 * .addProperties( 172 * <jk>new</jk> JsonSchemaProperty(<js>"street"</js>, JsonType.<jsf>STRING</jsf>), 173 * <jk>new</jk> JsonSchemaProperty(<js>"city"</js>, JsonType.<jsf>STRING</jsf>) 174 * ) 175 * ) 176 * .addProperties( 177 * <jk>new</jk> JsonSchemaProperty(<js>"billingAddress"</js>) 178 * .setRef(<js>"#/$defs/address"</js>), 179 * <jk>new</jk> JsonSchemaProperty(<js>"shippingAddress"</js>) 180 * .setRef(<js>"#/$defs/address"</js>) 181 * ); 182 * </p> 183 * 184 * <h5 class='section'>Migration from Draft 04:</h5> 185 * <ul class='spaced-list'> 186 * <li>Use {@link #setIdUri(Object)} instead of {@link #setId(Object)} (deprecated) 187 * <li>Use {@link #setDefs(Map)} instead of {@link #setDefinitions(Map)} (deprecated but still works) 188 * <li>Use {@link #setExclusiveMaximum(Number)} with a numeric value instead of a boolean flag 189 * <li>Use {@link #setExclusiveMinimum(Number)} with a numeric value instead of a boolean flag 190 * </ul> 191 * 192 * <h5 class='section'>See Also:</h5><ul> 193 * <li class='link'><a href="https://json-schema.org/draft/2020-12/json-schema-core.html">JSON Schema 2020-12 Core</a> 194 * <li class='link'><a href="https://json-schema.org/draft/2020-12/json-schema-validation.html">JSON Schema 2020-12 Validation</a> 195 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanJsonSchema">juneau-bean-jsonschema</a> 196 * </ul> 197 */ 198@Bean(typeName = "schema") 199public class JsonSchema { 200 /** 201 * Used during parsing to convert the <property>additionalItems</property> property to the correct class type. 202 * 203 * <ul class='spaced-list'> 204 * <li> 205 * If parsing a JSON-array, converts to a {@link JsonSchemaArray}. 206 * <li> 207 * If parsing a JSON-boolean, converts to a {@link Boolean}. 208 * </ul> 209 * 210 * <p> 211 * Serialization method is a no-op. 212 */ 213 public static class BooleanOrSchemaArraySwap extends ObjectSwap<Object,Object> { 214 215 @Override /* Overridden from ObjectSwap */ 216 public Object swap(BeanSession session, Object o) throws SerializeException { 217 return o; 218 } 219 220 @Override /* Overridden from ObjectSwap */ 221 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 222 var cm = (o instanceof Collection ? session.getClassMeta(JsonSchemaArray.class) : session.getClassMeta(Boolean.class)); 223 return session.convertToType(o, cm); 224 } 225 } 226 227 /** 228 * Used during parsing to convert the <property>additionalProperties</property> property to the correct class type. 229 * 230 * <ul class='spaced-list'> 231 * <li> 232 * If parsing a JSON-object, converts to a {@link JsonSchema}. 233 * <li> 234 * If parsing a JSON-boolean, converts to a {@link Boolean}. 235 * </ul> 236 * 237 * <p> 238 * Serialization method is a no-op. 239 */ 240 public static class BooleanOrSchemaSwap extends ObjectSwap<Object,Object> { 241 242 @Override /* Overridden from ObjectSwap */ 243 public Object swap(BeanSession session, Object o) throws SerializeException { 244 return o; 245 } 246 247 @Override /* Overridden from ObjectSwap */ 248 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 249 var cm = (o instanceof Boolean ? session.getClassMeta(Boolean.class) : session.getClassMeta(JsonSchema.class)); 250 return session.convertToType(o, cm); 251 } 252 } 253 254 /** 255 * Used during parsing to convert the <property>items</property> property to the correct class type. 256 * 257 * <ul class='spaced-list'> 258 * <li> 259 * If parsing a JSON-array, converts to a {@link JsonSchemaArray}. 260 * <li> 261 * If parsing a JSON-object, converts to a {@link JsonSchema}. 262 * </ul> 263 * 264 * <p> 265 * Serialization method is a no-op. 266 */ 267 public static class JsonSchemaOrSchemaArraySwap extends ObjectSwap<Object,Object> { 268 269 @Override /* Overridden from ObjectSwap */ 270 public Object swap(BeanSession session, Object o) throws SerializeException { 271 return o; 272 } 273 274 @Override /* Overridden from ObjectSwap */ 275 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 276 var cm = (o instanceof Collection ? session.getClassMeta(JsonSchemaArray.class) : session.getClassMeta(JsonSchema.class)); 277 return session.convertToType(o, cm); 278 } 279 } 280 281 /** 282 * Used during parsing to convert the <property>type</property> property to the correct class type. 283 * 284 * <ul class='spaced-list'> 285 * <li> 286 * If parsing a JSON-array, converts to a {@link JsonTypeArray}. 287 * <li> 288 * If parsing a JSON-object, converts to a {@link JsonType}. 289 * </ul> 290 * 291 * <p> 292 * Serialization method is a no-op. 293 */ 294 public static class JsonTypeOrJsonTypeArraySwap extends ObjectSwap<Object,Object> { 295 296 @Override /* Overridden from ObjectSwap */ 297 public Object swap(BeanSession session, Object o) throws SerializeException { 298 return o; 299 } 300 301 @Override /* Overridden from ObjectSwap */ 302 public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException { 303 var cm = (o instanceof Collection ? session.getClassMeta(JsonTypeArray.class) : session.getClassMeta(JsonType.class)); 304 return session.convertToType(o, cm); 305 } 306 } 307 308 // @formatter:off 309 private String name; // Property name. Not serialized. 310 private URI idUri; // Draft 2020-12: $id 311 private URI id; // Draft 04: id (deprecated but kept for compatibility) 312 private URI schemaVersion; 313 private String title; 314 private String description; 315 private JsonType typeJsonType; // JsonType representation of type 316 private JsonTypeArray typeJsonTypeArray; // JsonTypeArray representation of type 317 private Map<String,JsonSchema> definitions; // Retained for backward compatibility 318 private Map<String,JsonSchema> defs; // Draft 2020-12: $defs 319 private Map<String,JsonSchema> properties; 320 private Map<String,JsonSchema> patternProperties; 321 private Map<String,JsonSchema> dependencies; // Retained for backward compatibility 322 private Map<String,JsonSchema> dependentSchemas; // Draft 2019-09+ 323 private Map<String,List<String>> dependentRequired; // Draft 2019-09+ 324 private JsonSchema itemsSchema; // JsonSchema representation of items 325 private JsonSchemaArray itemsSchemaArray; // JsonSchemaArray representation of items 326 private JsonSchemaArray prefixItems; // Draft 2020-12: replaces tuple validation 327 private Number multipleOf; 328 private Number maximum; 329 private Number exclusiveMaximum; // Draft 06+: changed from Boolean to Number 330 private Number minimum; 331 private Number exclusiveMinimum; // Draft 06+: changed from Boolean to Number 332 private Integer maxLength; 333 private Integer minLength; 334 private String pattern; 335 private Boolean additionalItemsBoolean; // Boolean representation of additionalItems 336 private JsonSchemaArray additionalItemsSchemaArray; // JsonSchemaArray representation of additionalItems 337 private JsonSchema unevaluatedItems; // Draft 2019-09+ 338 private Integer maxItems; 339 private Integer minItems; 340 private Boolean uniqueItems; 341 private Integer maxProperties; 342 private Integer minProperties; 343 private List<String> required; 344 private Boolean additionalPropertiesBoolean; // Boolean representation of additionalProperties 345 private JsonSchema additionalPropertiesSchema; // JsonSchema representation of additionalProperties 346 private JsonSchema unevaluatedProperties; // Draft 2019-09+ 347 private List<Object> enum_; // Changed to Object to support any type 348 private Object const_; // Draft 06+ 349 private List<Object> examples; // Draft 06+ 350 private List<JsonSchema> allOf; 351 private List<JsonSchema> anyOf; 352 private List<JsonSchema> oneOf; 353 private JsonSchema not; 354 private JsonSchema if_; // Draft 07+ 355 private JsonSchema then_; // Draft 07+ 356 private JsonSchema else_; // Draft 07+ 357 private Boolean readOnly; // Draft 07+ 358 private Boolean writeOnly; // Draft 07+ 359 private String contentMediaType; // Draft 07+ 360 361 private String contentEncoding; // Draft 07+ 362 363 private URI ref; 364 365 private JsonSchemaMap schemaMap; 366 367 private JsonSchema master = this; 368 // @formatter:on 369 370 /** 371 * Default constructor. 372 */ 373 public JsonSchema() { /* Empty constructor. */ } 374 375 /** 376 * Bean property appender: <property>additionalItems</property>. 377 * 378 * @param additionalItems 379 * The list of items to append to the <property>additionalItems</property> property on this bean. 380 * @return This object. 381 */ 382 public JsonSchema addAdditionalItems(JsonSchema...additionalItems) { 383 if (this.additionalItemsSchemaArray == null) 384 this.additionalItemsSchemaArray = new JsonSchemaArray(); 385 this.additionalItemsSchemaArray.addAll(additionalItems); 386 setMasterOn(additionalItems); 387 return this; 388 } 389 390 /** 391 * Bean property appender: <property>allOf</property>. 392 * 393 * @param allOf The list of items to append to the <property>allOf</property> property on this bean. 394 * @return This object. 395 */ 396 public JsonSchema addAllOf(JsonSchema...allOf) { 397 setMasterOn(allOf); 398 this.allOf = addAll(this.allOf, allOf); 399 return this; 400 } 401 402 /** 403 * Bean property appender: <property>anyOf</property>. 404 * 405 * @param anyOf The list of items to append to the <property>anyOf</property> property on this bean. 406 * @return This object. 407 */ 408 public JsonSchema addAnyOf(JsonSchema...anyOf) { 409 if (this.anyOf == null) 410 this.anyOf = new LinkedList<>(); 411 setMasterOn(anyOf); 412 for (var s : anyOf) 413 this.anyOf.add(s); 414 return this; 415 } 416 417 /** 418 * Bean property appender: <property>$defs</property>. 419 * 420 * @param name The key in the defs map entry. 421 * @param def The value in the defs map entry. 422 * @return This object. 423 */ 424 public JsonSchema addDef(String name, JsonSchema def) { 425 if (this.defs == null) 426 this.defs = map(); 427 this.defs.put(name, def); 428 setMasterOn(def); 429 return this; 430 } 431 432 /** 433 * Bean property appender: <property>definitions</property>. 434 * 435 * @param name The key in the definitions map entry. 436 * @param definition The value in the definitions map entry. 437 * @return This object. 438 */ 439 public JsonSchema addDefinition(String name, JsonSchema definition) { 440 if (this.definitions == null) 441 this.definitions = map(); 442 this.definitions.put(name, definition); 443 setMasterOn(definition); 444 return this; 445 } 446 447 /** 448 * Bean property appender: <property>dependencies</property>. 449 * 450 * @param name The key of the entry in the dependencies map. 451 * @param dependency The value of the entry in the dependencies map. 452 * @return This object. 453 */ 454 public JsonSchema addDependency(String name, JsonSchema dependency) { 455 if (this.dependencies == null) 456 this.dependencies = map(); 457 this.dependencies.put(name, dependency); 458 setMasterOn(dependency); 459 return this; 460 } 461 462 /** 463 * Bean property appender: <property>dependentRequired</property>. 464 * 465 * @param name The key of the entry in the dependentRequired map. 466 * @param required The value of the entry in the dependentRequired map. 467 * @return This object. 468 */ 469 public JsonSchema addDependentRequired(String name, List<String> required) { 470 if (this.dependentRequired == null) 471 this.dependentRequired = map(); 472 this.dependentRequired.put(name, required); 473 return this; 474 } 475 476 /** 477 * Bean property appender: <property>dependentSchemas</property>. 478 * 479 * @param name The key of the entry in the dependentSchemas map. 480 * @param schema The value of the entry in the dependentSchemas map. 481 * @return This object. 482 */ 483 public JsonSchema addDependentSchema(String name, JsonSchema schema) { 484 if (this.dependentSchemas == null) 485 this.dependentSchemas = map(); 486 this.dependentSchemas.put(name, schema); 487 setMasterOn(schema); 488 return this; 489 } 490 491 /** 492 * Bean property appender: <property>enum</property>. 493 * 494 * @param enum_ The list of items to append to the <property>enum</property> property on this bean. 495 * @return This object. 496 */ 497 public JsonSchema addEnum(Object...enum_) { 498 if (this.enum_ == null) 499 this.enum_ = new LinkedList<>(); 500 for (var e : enum_) 501 this.enum_.add(e); 502 return this; 503 } 504 505 /** 506 * Bean property appender: <property>examples</property>. 507 * 508 * @param examples The list of items to append to the <property>examples</property> property on this bean. 509 * @return This object. 510 */ 511 public JsonSchema addExamples(Object...examples) { 512 if (this.examples == null) 513 this.examples = new LinkedList<>(); 514 for (var e : examples) 515 this.examples.add(e); 516 return this; 517 } 518 519 /** 520 * Bean property appender: <property>items</property>. 521 * 522 * @param items The list of items to append to the <property>items</property> property on this bean. 523 * @return This object. 524 */ 525 public JsonSchema addItems(JsonSchema...items) { 526 if (this.itemsSchemaArray == null) 527 this.itemsSchemaArray = new JsonSchemaArray(); 528 this.itemsSchemaArray.addAll(items); 529 setMasterOn(items); 530 return this; 531 } 532 533 /** 534 * Bean property appender: <property>oneOf</property>. 535 * 536 * @param oneOf The list of items to append to the <property>oneOf</property> property on this bean. 537 * @return This object. 538 */ 539 public JsonSchema addOneOf(JsonSchema...oneOf) { 540 if (this.oneOf == null) 541 this.oneOf = new LinkedList<>(); 542 setMasterOn(oneOf); 543 for (var s : oneOf) 544 this.oneOf.add(s); 545 return this; 546 } 547 548 /** 549 * Bean property appender: <property>patternProperties</property>. 550 * 551 * <p> 552 * Properties must have their <property>name</property> property set to the pattern string when using this method. 553 * 554 * @param properties The list of items to append to the <property>patternProperties</property> property on this bean. 555 * @return This object. 556 * @throws BeanRuntimeException If property is found without a set <property>name</property> property. 557 */ 558 public JsonSchema addPatternProperties(JsonSchemaProperty...properties) { 559 if (this.patternProperties == null) 560 this.patternProperties = map(); 561 for (var p : properties) { 562 if (p.getName() == null) 563 throw bex(JsonSchema.class, "Invalid property passed to JsonSchema.addProperties(). Property name was null."); 564 setMasterOn(p); 565 this.patternProperties.put(p.getName(), p); 566 } 567 return this; 568 } 569 570 /** 571 * Bean property appender: <property>prefixItems</property>. 572 * 573 * @param prefixItems The list of items to append to the <property>prefixItems</property> property on this bean. 574 * @return This object. 575 */ 576 public JsonSchema addPrefixItems(JsonSchema...prefixItems) { 577 if (this.prefixItems == null) 578 this.prefixItems = new JsonSchemaArray(); 579 this.prefixItems.addAll(prefixItems); 580 setMasterOn(prefixItems); 581 return this; 582 } 583 584 /** 585 * Bean property appender: <property>properties</property>. 586 * 587 * <p> 588 * Properties must have their <property>name</property> property set on them when using this method. 589 * 590 * @param properties The list of items to append to the <property>properties</property> property on this bean. 591 * @return This object. 592 * @throws BeanRuntimeException If property is found without a set <property>name</property> property. 593 */ 594 public JsonSchema addProperties(JsonSchema...properties) { 595 if (this.properties == null) 596 this.properties = map(); 597 for (var p : properties) { 598 if (p.getName() == null) 599 throw bex(JsonSchema.class, "Invalid property passed to JsonSchema.addProperties(). Property name was null."); 600 setMasterOn(p); 601 this.properties.put(p.getName(), p); 602 } 603 return this; 604 } 605 606 /** 607 * Bean property appender: <property>required</property>. 608 * 609 * @param properties The list of items to append to the <property>required</property> property on this bean. 610 * @return This object. 611 */ 612 public JsonSchema addRequired(JsonSchemaProperty...properties) { 613 if (this.required == null) 614 this.required = new LinkedList<>(); 615 for (var p : properties) 616 this.required.add(p.getName()); 617 return this; 618 } 619 620 /** 621 * Bean property appender: <property>required</property>. 622 * 623 * @param required The list of items to append to the <property>required</property> property on this bean. 624 * @return This object. 625 */ 626 public JsonSchema addRequired(List<String> required) { 627 if (this.required == null) 628 this.required = new LinkedList<>(); 629 required.forEach(x -> this.required.add(x)); 630 return this; 631 } 632 633 /** 634 * Bean property appender: <property>required</property>. 635 * 636 * @param required The list of items to append to the <property>required</property> property on this bean. 637 * @return This object. 638 */ 639 public JsonSchema addRequired(String...required) { 640 if (this.required == null) 641 this.required = new LinkedList<>(); 642 for (var r : required) 643 this.required.add(r); 644 return this; 645 } 646 647 /** 648 * Bean property appender: <property>type</property>. 649 * 650 * @param types The list of items to append to the <property>type</property> property on this bean. 651 * @return This object. 652 */ 653 public JsonSchema addTypes(JsonType...types) { 654 if (this.typeJsonTypeArray == null) 655 this.typeJsonTypeArray = new JsonTypeArray(); 656 this.typeJsonTypeArray.addAll(types); 657 return this; 658 } 659 660 /** 661 * Bean property getter: <property>additionalItems</property>. 662 * 663 * @return 664 * The value of the <property>additionalItems</property> property on this bean, or <jk>null</jk> if it is 665 * not set. 666 * Can be either a {@link Boolean} or {@link JsonSchemaArray} depending on what value was used to set it. 667 */ 668 @Swap(BooleanOrSchemaArraySwap.class) 669 public Object getAdditionalItems() { 670 if (nn(additionalItemsBoolean)) 671 return additionalItemsBoolean; 672 return additionalItemsSchemaArray; 673 } 674 675 /** 676 * Bean property getter: <property>additionalItems</property>. 677 * 678 * <p> 679 * Convenience method for returning the <property>additionalItems</property> property when it is a {@link Boolean} 680 * value. 681 * 682 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonSchemaArray}. 683 */ 684 @BeanIgnore 685 public Boolean getAdditionalItemsAsBoolean() { return additionalItemsBoolean; } 686 687 /** 688 * Bean property getter: <property>additionalItems</property>. 689 * 690 * <p> 691 * Convenience method for returning the <property>additionalItems</property> property when it is a 692 * {@link JsonSchemaArray} value. 693 * 694 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}. 695 */ 696 @BeanIgnore 697 public List<JsonSchema> getAdditionalItemsAsSchemaArray() { return additionalItemsSchemaArray; } 698 699 /** 700 * Bean property getter: <property>additionalProperties</property>. 701 * 702 * @return 703 * The value of the <property>additionalProperties</property> property on this bean, or <jk>null</jk> if it 704 * is not set. 705 * Can be either a {@link Boolean} or {@link JsonSchemaArray} depending on what value was used to set it. 706 */ 707 @Swap(BooleanOrSchemaSwap.class) 708 public Object getAdditionalProperties() { 709 if (nn(additionalPropertiesBoolean)) 710 return additionalItemsBoolean; 711 return additionalPropertiesSchema; 712 } 713 714 /** 715 * Bean property getter: <property>additionalProperties</property>. 716 * 717 * <p> 718 * Convenience method for returning the <property>additionalProperties</property> property when it is a 719 * {@link Boolean} value. 720 * 721 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonSchema}. 722 */ 723 @BeanIgnore 724 public Boolean getAdditionalPropertiesAsBoolean() { return additionalPropertiesBoolean; } 725 726 /** 727 * Bean property getter: <property>additionalProperties</property>. 728 * 729 * <p> 730 * Convenience method for returning the <property>additionalProperties</property> property when it is a 731 * {@link JsonSchema} value. 732 * 733 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}. 734 */ 735 @BeanIgnore 736 public JsonSchema getAdditionalPropertiesAsSchema() { return additionalPropertiesSchema; } 737 738 /** 739 * Bean property getter: <property>allOf</property>. 740 * 741 * @return The value of the <property>allOf</property> property on this bean, or <jk>null</jk> if it is not set. 742 */ 743 public List<JsonSchema> getAllOf() { return allOf; } 744 745 /** 746 * Bean property getter: <property>anyOf</property>. 747 * 748 * @return The value of the <property>anyOf</property> property on this bean, or <jk>null</jk> if it is not set. 749 */ 750 public List<JsonSchema> getAnyOf() { return anyOf; } 751 752 /** 753 * Bean property getter: <property>const</property>. 754 * 755 * <p> 756 * This property was added in Draft 06. 757 * 758 * @return The value of the <property>const</property> property on this bean, or <jk>null</jk> if it is not set. 759 */ 760 public Object getConst() { return const_; } 761 762 /** 763 * Bean property getter: <property>contentEncoding</property>. 764 * 765 * <p> 766 * This property was added in Draft 07. 767 * 768 * @return The value of the <property>contentEncoding</property> property on this bean, or <jk>null</jk> if it is not set. 769 */ 770 public String getContentEncoding() { return contentEncoding; } 771 772 /** 773 * Bean property getter: <property>contentMediaType</property>. 774 * 775 * <p> 776 * This property was added in Draft 07. 777 * 778 * @return The value of the <property>contentMediaType</property> property on this bean, or <jk>null</jk> if it is not set. 779 */ 780 public String getContentMediaType() { return contentMediaType; } 781 782 /** 783 * Bean property getter: <property>definitions</property>. 784 * 785 * <p> 786 * <b>Deprecated:</b> Use {@link #getDefs()} for Draft 2020-12 compliance. 787 * This property is retained for Draft 04 backward compatibility. 788 * 789 * @return 790 * The value of the <property>definitions</property> property on this bean, or <jk>null</jk> if it is not set. 791 */ 792 public Map<String,JsonSchema> getDefinitions() { 793 return nn(definitions) ? definitions : defs; // Fall back to $defs for compatibility 794 } 795 796 /** 797 * Bean property getter: <property>$defs</property>. 798 * 799 * <p> 800 * This is the Draft 2020-12 replacement for <property>definitions</property>. 801 * Both properties are supported for backward compatibility. 802 * 803 * @return The value of the <property>$defs</property> property on this bean, or <jk>null</jk> if it is not set. 804 */ 805 @Beanp("$defs") 806 public Map<String,JsonSchema> getDefs() { 807 return defs; // Return only defs, not definitions (to avoid double serialization) 808 } 809 810 /** 811 * Bean property getter: <property>dependencies</property>. 812 * 813 * @return 814 * The value of the <property>dependencies</property> property on this bean, or <jk>null</jk> if it is not set. 815 */ 816 public Map<String,JsonSchema> getDependencies() { return dependencies; } 817 818 /** 819 * Bean property getter: <property>dependentRequired</property>. 820 * 821 * <p> 822 * This property was added in Draft 2019-09 as a replacement for the array form of <property>dependencies</property>. 823 * 824 * @return The value of the <property>dependentRequired</property> property on this bean, or <jk>null</jk> if it is not set. 825 */ 826 public Map<String,List<String>> getDependentRequired() { return dependentRequired; } 827 828 /** 829 * Bean property getter: <property>dependentSchemas</property>. 830 * 831 * <p> 832 * This property was added in Draft 2019-09 as a replacement for the schema form of <property>dependencies</property>. 833 * 834 * @return The value of the <property>dependentSchemas</property> property on this bean, or <jk>null</jk> if it is not set. 835 */ 836 public Map<String,JsonSchema> getDependentSchemas() { return dependentSchemas; } 837 838 /** 839 * Bean property getter: <property>description</property>. 840 * 841 * @return The value of the <property>description</property> property, or <jk>null</jk> if it is not set. 842 */ 843 public String getDescription() { return description; } 844 845 /** 846 * Bean property getter: <property>else</property>. 847 * 848 * <p> 849 * This property was added in Draft 07 for conditional schema application. 850 * 851 * @return The value of the <property>else</property> property on this bean, or <jk>null</jk> if it is not set. 852 */ 853 @Beanp("else") 854 public JsonSchema getElse() { return else_; } 855 856 /** 857 * Bean property getter: <property>enum</property>. 858 * 859 * @return The value of the <property>enum</property> property on this bean, or <jk>null</jk> if it is not set. 860 */ 861 public List<Object> getEnum() { return enum_; } 862 863 /** 864 * Bean property getter: <property>examples</property>. 865 * 866 * <p> 867 * This property was added in Draft 06. 868 * 869 * @return The value of the <property>examples</property> property on this bean, or <jk>null</jk> if it is not set. 870 */ 871 public List<Object> getExamples() { return examples; } 872 873 /** 874 * Bean property getter: <property>exclusiveMaximum</property>. 875 * 876 * <p> 877 * In Draft 06+, this is a numeric value representing the exclusive upper bound. 878 * In Draft 04, this was a boolean flag. This implementation uses the Draft 06+ semantics. 879 * 880 * @return 881 * The value of the <property>exclusiveMaximum</property> property on this bean, or <jk>null</jk> if it is 882 * not set. 883 */ 884 public Number getExclusiveMaximum() { return exclusiveMaximum; } 885 886 /** 887 * Bean property getter: <property>exclusiveMinimum</property>. 888 * 889 * <p> 890 * In Draft 06+, this is a numeric value representing the exclusive lower bound. 891 * In Draft 04, this was a boolean flag. This implementation uses the Draft 06+ semantics. 892 * 893 * @return 894 * The value of the <property>exclusiveMinimum</property> property on this bean, or <jk>null</jk> if it is 895 * not set. 896 */ 897 public Number getExclusiveMinimum() { return exclusiveMinimum; } 898 899 /** 900 * Bean property getter: <property>id</property>. 901 * 902 * <p> 903 * <b>Deprecated:</b> Use {@link #getIdUri()} instead. 904 * This property is retained for Draft 04 backward compatibility. 905 * 906 * @return The value of the <property>id</property> property on this bean, or <jk>null</jk> if it is not set. 907 * @deprecated Use {@link #getIdUri()} instead. 908 */ 909 @Deprecated 910 public URI getId() { 911 return nn(id) ? id : idUri; // Fall back to new '$id' for compatibility when reading 912 } 913 914 /** 915 * Bean property getter: <property>$id</property>. 916 * 917 * <p> 918 * This is the Draft 2020-12 property for schema identification. 919 * 920 * @return The value of the <property>$id</property> property on this bean, or <jk>null</jk> if it is not set. 921 */ 922 @Beanp("$id") 923 public URI getIdUri() { 924 return idUri; // Return only idUri, not id (to avoid double serialization) 925 } 926 927 /** 928 * Bean property getter: <property>if</property>. 929 * 930 * <p> 931 * This property was added in Draft 07 for conditional schema application. 932 * 933 * @return The value of the <property>if</property> property on this bean, or <jk>null</jk> if it is not set. 934 */ 935 @Beanp("if") 936 public JsonSchema getIf() { return if_; } 937 938 /** 939 * Bean property getter: <property>items</property>. 940 * 941 * @return 942 * The value of the <property>items</property> property on this bean, or <jk>null</jk> if it is not set. 943 * Can be either a {@link JsonSchema} or {@link JsonSchemaArray} depending on what value was used to set it. 944 */ 945 @Swap(JsonSchemaOrSchemaArraySwap.class) 946 public Object getItems() { 947 if (nn(itemsSchema)) 948 return itemsSchema; 949 return itemsSchemaArray; 950 } 951 952 /** 953 * Bean property getter: <property>items</property>. 954 * 955 * <p> 956 * Convenience method for returning the <property>items</property> property when it is a {@link JsonSchema} value. 957 * 958 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonSchemaArray}. 959 */ 960 @BeanIgnore 961 public JsonSchema getItemsAsSchema() { return itemsSchema; } 962 963 /** 964 * Bean property getter: <property>items</property>. 965 * 966 * <p> 967 * Convenience method for returning the <property>items</property> property when it is a {@link JsonSchemaArray} value. 968 * 969 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonSchema}. 970 */ 971 @BeanIgnore 972 public JsonSchemaArray getItemsAsSchemaArray() { return itemsSchemaArray; } 973 974 /** 975 * Bean property getter: <property>maximum</property>. 976 * 977 * @return The value of the <property>maximum</property> property on this bean, or <jk>null</jk> if it is not set. 978 */ 979 public Number getMaximum() { return maximum; } 980 981 /** 982 * Bean property getter: <property>maxItems</property>. 983 * 984 * @return The value of the <property>maxItems</property> property on this bean, or <jk>null</jk> if it is not set. 985 */ 986 public Integer getMaxItems() { return maxItems; } 987 988 /** 989 * Bean property getter: <property>maxLength</property>. 990 * 991 * @return The value of the <property>maxLength</property> property on this bean, or <jk>null</jk> if it is not set. 992 */ 993 public Integer getMaxLength() { return maxLength; } 994 995 /** 996 * Bean property getter: <property>maxProperties</property>. 997 * 998 * @return 999 * The value of the <property>maxProperties</property> property on this bean, or <jk>null</jk> if it is not set. 1000 */ 1001 public Integer getMaxProperties() { return maxProperties; } 1002 1003 /** 1004 * Bean property getter: <property>minimum</property>. 1005 * 1006 * @return The value of the <property>minimum</property> property on this bean, or <jk>null</jk> if it is not set. 1007 */ 1008 public Number getMinimum() { return minimum; } 1009 1010 /** 1011 * Bean property getter: <property>minItems</property>. 1012 * 1013 * @return The value of the <property>minItems</property> property on this bean, or <jk>null</jk> if it is not set. 1014 */ 1015 public Integer getMinItems() { return minItems; } 1016 1017 /** 1018 * Bean property getter: <property>minLength</property>. 1019 * 1020 * @return The value of the <property>minLength</property> property on this bean, or <jk>null</jk> if it is not set. 1021 */ 1022 public Integer getMinLength() { return minLength; } 1023 1024 /** 1025 * Bean property getter: <property>minProperties</property>. 1026 * 1027 * @return 1028 * The value of the <property>minProperties</property> property on this bean, or <jk>null</jk> if it is not set. 1029 */ 1030 public Integer getMinProperties() { return minProperties; } 1031 1032 /** 1033 * Bean property getter: <property>multipleOf</property>. 1034 * 1035 * @return The value of the <property>multipleOf</property> property on this bean, or <jk>null</jk> if it is not set. 1036 */ 1037 public Number getMultipleOf() { return multipleOf; } 1038 1039 /** 1040 * Bean property getter: <property>name</property>. 1041 * 1042 * <p> 1043 * This is an internal property used for tracking property names and is not part of the JSON Schema specification. 1044 * 1045 * @return The value of the <property>name</property> property on this bean, or <jk>null</jk> if it is not set. 1046 */ 1047 @BeanIgnore 1048 public String getName() { return name; } 1049 1050 /** 1051 * Bean property getter: <property>not</property>. 1052 * 1053 * @return The value of the <property>not</property> property on this bean, or <jk>null</jk> if it is not set. 1054 */ 1055 public JsonSchema getNot() { return not; } 1056 1057 /** 1058 * Bean property getter: <property>oneOf</property>. 1059 * 1060 * @return The value of the <property>oneOf</property> property on this bean, or <jk>null</jk> if it is not set. 1061 */ 1062 public List<JsonSchema> getOneOf() { return oneOf; } 1063 1064 /** 1065 * Bean property getter: <property>pattern</property>. 1066 * 1067 * @return The value of the <property>pattern</property> property on this bean, or <jk>null</jk> if it is not set. 1068 */ 1069 public String getPattern() { return pattern; } 1070 1071 /** 1072 * Bean property getter: <property>patternProperties</property>. 1073 * 1074 * @return 1075 * The value of the <property>patternProperties</property> property on this bean, or <jk>null</jk> if it is 1076 * not set. 1077 */ 1078 public Map<String,JsonSchema> getPatternProperties() { return patternProperties; } 1079 1080 /** 1081 * Bean property getter: <property>prefixItems</property>. 1082 * 1083 * <p> 1084 * This property was added in Draft 2020-12 for tuple validation. 1085 * 1086 * @return The value of the <property>prefixItems</property> property on this bean, or <jk>null</jk> if it is not set. 1087 */ 1088 public JsonSchemaArray getPrefixItems() { return prefixItems; } 1089 1090 /** 1091 * Bean property getter: <property>properties</property>. 1092 * 1093 * @return The value of the <property>properties</property> property on this bean, or <jk>null</jk> if it is not set. 1094 */ 1095 public Map<String,JsonSchema> getProperties() { return properties; } 1096 1097 /** 1098 * Returns the property with the specified name. 1099 * 1100 * <p> 1101 * This is equivalent to calling <property>getProperty(name, <jk>false</jk>)</property>. 1102 * 1103 * @param name The property name. 1104 * @return The property with the specified name, or <jk>null</jk> if no property is specified. 1105 */ 1106 public JsonSchema getProperty(String name) { 1107 return getProperty(name, false); 1108 } 1109 1110 /** 1111 * Returns the property with the specified name. 1112 * 1113 * <p> 1114 * If <property>resolve</property> is <jk>true</jk>, the property object will automatically be resolved by calling 1115 * {@link #resolve()}. 1116 * Therefore, <property>getProperty(name, <jk>true</jk>)</property> is equivalent to calling 1117 * <property>getProperty(name).resolve()</property>, except it's safe from a potential 1118 * <property>NullPointerException</property>. 1119 * 1120 * @param name The property name. 1121 * @param resolve If <jk>true</jk>, calls {@link #resolve()} on object before returning. 1122 * @return The property with the specified name, or <jk>null</jk> if no property is specified. 1123 */ 1124 public JsonSchema getProperty(String name, boolean resolve) { 1125 if (properties == null) 1126 return null; 1127 var s = properties.get(name); 1128 if (s == null) 1129 return null; 1130 if (resolve) 1131 s = s.resolve(); 1132 return s; 1133 } 1134 1135 /** 1136 * Bean property getter: <property>readOnly</property>. 1137 * 1138 * <p> 1139 * This property was added in Draft 07. 1140 * 1141 * @return The value of the <property>readOnly</property> property on this bean, or <jk>null</jk> if it is not set. 1142 */ 1143 public Boolean getReadOnly() { return readOnly; } 1144 1145 /** 1146 * Bean property getter: <property>$ref</property>. 1147 * 1148 * @return The value of the <property>$ref</property> property on this bean, or <jk>null</jk> if it is not set. 1149 */ 1150 @Beanp("$ref") 1151 public URI getRef() { return ref; } 1152 1153 /** 1154 * Bean property getter: <property>required</property>. 1155 * 1156 * @return The value of the <property>required</property> property on this bean, or <jk>null</jk> if it is not set. 1157 */ 1158 public List<String> getRequired() { return required; } 1159 1160 /** 1161 * Bean property getter: <property>$schema</property>. 1162 * 1163 * @return The value of the <property>$schema</property> property on this bean, or <jk>null</jk> if it is not set. 1164 */ 1165 @Beanp("$schema") 1166 public URI getSchemaVersionUri() { return schemaVersion; } 1167 1168 /** 1169 * Bean property getter: <property>then</property>. 1170 * 1171 * <p> 1172 * This property was added in Draft 07 for conditional schema application. 1173 * 1174 * @return The value of the <property>then</property> property on this bean, or <jk>null</jk> if it is not set. 1175 */ 1176 @Beanp("then") 1177 public JsonSchema getThen() { return then_; } 1178 1179 /** 1180 * Bean property getter: <property>title</property>. 1181 * 1182 * @return The value of the <property>title</property> property, or <jk>null</jk> if it is not set. 1183 */ 1184 public String getTitle() { return title; } 1185 1186 /** 1187 * Bean property getter: <property>type</property>. 1188 * 1189 * @return 1190 * The value of the <property>type</property> property on this bean, or <jk>null</jk> if it is not set. 1191 * Can be either a {@link JsonType} or {@link JsonTypeArray} depending on what value was used to set it. 1192 */ 1193 @Swap(JsonTypeOrJsonTypeArraySwap.class) 1194 public Object getType() { 1195 if (nn(typeJsonType)) 1196 return typeJsonType; 1197 return typeJsonTypeArray; 1198 } 1199 1200 /** 1201 * Bean property getter: <property>type</property>. 1202 * 1203 * <p> 1204 * Convenience method for returning the <property>type</property> property when it is a {@link JsonType} value. 1205 * 1206 * @return 1207 * The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonTypeArray}. 1208 */ 1209 @BeanIgnore 1210 public JsonType getTypeAsJsonType() { return typeJsonType; } 1211 1212 /** 1213 * Bean property getter: <property>type</property>. 1214 * 1215 * <p> 1216 * Convenience method for returning the <property>type</property> property when it is a {@link JsonTypeArray} value. 1217 * 1218 * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonType}. 1219 */ 1220 @BeanIgnore 1221 public JsonTypeArray getTypeAsJsonTypeArray() { return typeJsonTypeArray; } 1222 1223 /** 1224 * Bean property getter: <property>unevaluatedItems</property>. 1225 * 1226 * <p> 1227 * This property was added in Draft 2019-09. 1228 * 1229 * @return The value of the <property>unevaluatedItems</property> property on this bean, or <jk>null</jk> if it is not set. 1230 */ 1231 public JsonSchema getUnevaluatedItems() { return unevaluatedItems; } 1232 1233 /** 1234 * Bean property getter: <property>unevaluatedProperties</property>. 1235 * 1236 * <p> 1237 * This property was added in Draft 2019-09. 1238 * 1239 * @return The value of the <property>unevaluatedProperties</property> property on this bean, or <jk>null</jk> if it is not set. 1240 */ 1241 public JsonSchema getUnevaluatedProperties() { return unevaluatedProperties; } 1242 1243 /** 1244 * Bean property getter: <property>uniqueItems</property>. 1245 * 1246 * @return 1247 * The value of the <property>uniqueItems</property> property on this bean, or <jk>null</jk> if it is not set. 1248 */ 1249 public Boolean getUniqueItems() { return uniqueItems; } 1250 1251 /** 1252 * Bean property getter: <property>writeOnly</property>. 1253 * 1254 * <p> 1255 * This property was added in Draft 07. 1256 * 1257 * @return The value of the <property>writeOnly</property> property on this bean, or <jk>null</jk> if it is not set. 1258 */ 1259 public Boolean getWriteOnly() { return writeOnly; } 1260 1261 /** 1262 * Resolve schema if reference. 1263 * 1264 * <p> 1265 * If this schema is a reference to another schema (has its <property>$ref</property> property set), this 1266 * method will retrieve the referenced schema from the schema map registered with this schema. 1267 * 1268 * <p> 1269 * If this schema is not a reference, or no schema map is registered with this schema, this method is a no-op and 1270 * simply returns this object. 1271 * 1272 * @return The referenced schema, or <jk>null</jk>. 1273 */ 1274 public JsonSchema resolve() { 1275 if (ref == null || master.schemaMap == null) 1276 return this; 1277 return master.schemaMap.get(ref); 1278 } 1279 1280 /** 1281 * Bean property setter: <property>additionalItems</property>. 1282 * 1283 * @param additionalItems 1284 * The new value for the <property>additionalItems</property> property on this bean. 1285 * This object must be of type {@link Boolean} or {@link JsonSchemaArray}. 1286 * @return This object. 1287 * @throws BeanRuntimeException If invalid object type passed in. 1288 */ 1289 public JsonSchema setAdditionalItems(Object additionalItems) { 1290 this.additionalItemsBoolean = null; 1291 this.additionalItemsSchemaArray = null; 1292 if (nn(additionalItems)) { 1293 if (additionalItems instanceof Boolean additionalItems2) 1294 this.additionalItemsBoolean = additionalItems2; 1295 else if (additionalItems instanceof JsonSchemaArray additionalItems2) { 1296 this.additionalItemsSchemaArray = additionalItems2; 1297 setMasterOn(this.additionalItemsSchemaArray); 1298 } else { 1299 throw bex(JsonSchemaProperty.class, "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, JsonSchemaArray", cn(additionalItems)); 1300 } 1301 } 1302 return this; 1303 } 1304 1305 /** 1306 * Bean property setter: <property>additionalProperties</property>. 1307 * 1308 * @param additionalProperties 1309 * The new value for the <property>additionalProperties</property> property on this bean. 1310 * This object must be of type {@link Boolean} or {@link JsonSchema}. 1311 * @return This object. 1312 * @throws BeanRuntimeException If invalid object type passed in. 1313 */ 1314 @Beanp(dictionary = { JsonSchema.class }) 1315 public JsonSchema setAdditionalProperties(Object additionalProperties) { 1316 this.additionalPropertiesBoolean = null; 1317 this.additionalPropertiesSchema = null; 1318 if (nn(additionalProperties)) { 1319 if (additionalProperties instanceof Boolean additionalProperties2) 1320 this.additionalPropertiesBoolean = additionalProperties2; 1321 else if (additionalProperties instanceof JsonSchema additionalProperties2) { 1322 this.additionalPropertiesSchema = additionalProperties2; 1323 setMasterOn(this.additionalPropertiesSchema); 1324 } else 1325 throw bex(JsonSchemaProperty.class, "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, JsonSchema", cn(additionalProperties)); 1326 } 1327 return this; 1328 } 1329 1330 /** 1331 * Bean property setter: <property>allOf</property>. 1332 * 1333 * @param allOf The new value for the <property>allOf</property> property on this bean. 1334 * @return This object. 1335 */ 1336 public JsonSchema setAllOf(List<JsonSchema> allOf) { 1337 this.allOf = allOf; 1338 setMasterOn(allOf); 1339 return this; 1340 } 1341 1342 /** 1343 * Bean property setter: <property>anyOf</property>. 1344 * 1345 * @param anyOf The new value of the <property>anyOf</property> property on this bean. 1346 * @return This object. 1347 */ 1348 public JsonSchema setAnyOf(List<JsonSchema> anyOf) { 1349 this.anyOf = anyOf; 1350 setMasterOn(anyOf); 1351 return this; 1352 } 1353 1354 /** 1355 * Bean property setter: <property>const</property>. 1356 * 1357 * <p> 1358 * This property was added in Draft 06. 1359 * 1360 * @param const_ The new value for the <property>const</property> property on this bean. 1361 * @return This object. 1362 */ 1363 public JsonSchema setConst(Object const_) { 1364 this.const_ = const_; 1365 return this; 1366 } 1367 1368 /** 1369 * Bean property setter: <property>contentEncoding</property>. 1370 * 1371 * <p> 1372 * This property was added in Draft 07. 1373 * 1374 * @param contentEncoding The new value for the <property>contentEncoding</property> property on this bean. 1375 * @return This object. 1376 */ 1377 public JsonSchema setContentEncoding(String contentEncoding) { 1378 this.contentEncoding = contentEncoding; 1379 return this; 1380 } 1381 1382 /** 1383 * Bean property setter: <property>contentMediaType</property>. 1384 * 1385 * <p> 1386 * This property was added in Draft 07. 1387 * 1388 * @param contentMediaType The new value for the <property>contentMediaType</property> property on this bean. 1389 * @return This object. 1390 */ 1391 public JsonSchema setContentMediaType(String contentMediaType) { 1392 this.contentMediaType = contentMediaType; 1393 return this; 1394 } 1395 1396 /** 1397 * Bean property setter: <property>definitions</property>. 1398 * 1399 * @param definitions The new value for the <property>definitions</property> property on this bean. 1400 * @return This object. 1401 */ 1402 public JsonSchema setDefinitions(Map<String,JsonSchema> definitions) { 1403 this.definitions = definitions; 1404 if (nn(definitions)) 1405 setMasterOn(definitions.values()); 1406 return this; 1407 } 1408 1409 /** 1410 * Bean property setter: <property>$defs</property>. 1411 * 1412 * <p> 1413 * This is the Draft 2020-12 replacement for <property>definitions</property>. 1414 * Both properties are supported for backward compatibility. 1415 * 1416 * @param defs The new value for the <property>$defs</property> property on this bean. 1417 * @return This object. 1418 */ 1419 @Beanp("$defs") 1420 public JsonSchema setDefs(Map<String,JsonSchema> defs) { 1421 this.defs = defs; 1422 if (nn(defs)) 1423 setMasterOn(defs.values()); 1424 return this; 1425 } 1426 1427 /** 1428 * Bean property setter: <property>dependencies</property>. 1429 * 1430 * @param dependencies The new value for the <property>dependencies</property> property on this bean. 1431 * @return This object. 1432 */ 1433 public JsonSchema setDependencies(Map<String,JsonSchema> dependencies) { 1434 this.dependencies = dependencies; 1435 if (nn(dependencies)) 1436 setMasterOn(dependencies.values()); 1437 return this; 1438 } 1439 1440 /** 1441 * Bean property setter: <property>dependentRequired</property>. 1442 * 1443 * <p> 1444 * This property was added in Draft 2019-09 as a replacement for the array form of <property>dependencies</property>. 1445 * 1446 * @param dependentRequired The new value for the <property>dependentRequired</property> property on this bean. 1447 * @return This object. 1448 */ 1449 public JsonSchema setDependentRequired(Map<String,List<String>> dependentRequired) { 1450 this.dependentRequired = dependentRequired; 1451 return this; 1452 } 1453 1454 /** 1455 * Bean property setter: <property>dependentSchemas</property>. 1456 * 1457 * <p> 1458 * This property was added in Draft 2019-09 as a replacement for the schema form of <property>dependencies</property>. 1459 * 1460 * @param dependentSchemas The new value for the <property>dependentSchemas</property> property on this bean. 1461 * @return This object. 1462 */ 1463 public JsonSchema setDependentSchemas(Map<String,JsonSchema> dependentSchemas) { 1464 this.dependentSchemas = dependentSchemas; 1465 if (nn(dependentSchemas)) 1466 setMasterOn(dependentSchemas.values()); 1467 return this; 1468 } 1469 1470 /** 1471 * Bean property setter: <property>description</property>. 1472 * 1473 * @param description The new value for the <property>description</property> property on this bean. 1474 * @return This object. 1475 */ 1476 public JsonSchema setDescription(String description) { 1477 this.description = description; 1478 return this; 1479 } 1480 1481 /** 1482 * Bean property setter: <property>else</property>. 1483 * 1484 * <p> 1485 * This property was added in Draft 07 for conditional schema application. 1486 * 1487 * @param else_ The new value for the <property>else</property> property on this bean. 1488 * @return This object. 1489 */ 1490 @Beanp("else") 1491 public JsonSchema setElse(JsonSchema else_) { 1492 this.else_ = else_; 1493 setMasterOn(else_); 1494 return this; 1495 } 1496 1497 /** 1498 * Bean property setter: <property>enum</property>. 1499 * 1500 * @param enum_ The new value for the <property>enum</property> property on this bean. 1501 * @return This object. 1502 */ 1503 public JsonSchema setEnum(List<Object> enum_) { 1504 this.enum_ = enum_; 1505 return this; 1506 } 1507 1508 /** 1509 * Bean property setter: <property>examples</property>. 1510 * 1511 * <p> 1512 * This property was added in Draft 06. 1513 * 1514 * @param examples The new value for the <property>examples</property> property on this bean. 1515 * @return This object. 1516 */ 1517 public JsonSchema setExamples(List<Object> examples) { 1518 this.examples = examples; 1519 return this; 1520 } 1521 1522 /** 1523 * Bean property setter: <property>exclusiveMaximum</property>. 1524 * 1525 * <p> 1526 * In Draft 06+, this is a numeric value representing the exclusive upper bound. 1527 * In Draft 04, this was a boolean flag. This implementation uses the Draft 06+ semantics. 1528 * 1529 * @param exclusiveMaximum The new value for the <property>exclusiveMaximum</property> property on this bean. 1530 * @return This object. 1531 */ 1532 public JsonSchema setExclusiveMaximum(Number exclusiveMaximum) { 1533 this.exclusiveMaximum = exclusiveMaximum; 1534 return this; 1535 } 1536 1537 /** 1538 * Bean property setter: <property>exclusiveMinimum</property>. 1539 * 1540 * <p> 1541 * In Draft 06+, this is a numeric value representing the exclusive lower bound. 1542 * In Draft 04, this was a boolean flag. This implementation uses the Draft 06+ semantics. 1543 * 1544 * @param exclusiveMinimum The new value for the <property>exclusiveMinimum</property> property on this bean. 1545 * @return This object. 1546 */ 1547 public JsonSchema setExclusiveMinimum(Number exclusiveMinimum) { 1548 this.exclusiveMinimum = exclusiveMinimum; 1549 return this; 1550 } 1551 1552 /** 1553 * Bean property setter: <property>id</property>. 1554 * 1555 * <p> 1556 * <b>Deprecated:</b> Use {@link #setIdUri(Object)} instead. 1557 * This property is retained for Draft 04 backward compatibility. 1558 * 1559 * <p> 1560 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 1561 * Strings must be valid URIs. 1562 * 1563 * <p> 1564 * URIs defined by {@link UriResolver} can be used for values. 1565 * 1566 * @param id The new value for the <property>id</property> property on this bean. 1567 * @return This object. 1568 * @deprecated Use {@link #setIdUri(Object)} instead. 1569 */ 1570 @Deprecated 1571 public JsonSchema setId(Object id) { 1572 this.id = toUri(id); 1573 return this; 1574 } 1575 1576 /** 1577 * Bean property setter: <property>$id</property>. 1578 * 1579 * <p> 1580 * This is the Draft 2020-12 property for schema identification. 1581 * 1582 * <p> 1583 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 1584 * Strings must be valid URIs. 1585 * 1586 * <p> 1587 * URIs defined by {@link UriResolver} can be used for values. 1588 * 1589 * @param idUri The new value for the <property>$id</property> property on this bean. 1590 * @return This object. 1591 */ 1592 @Beanp("$id") 1593 public JsonSchema setIdUri(Object idUri) { 1594 this.idUri = toUri(idUri); 1595 return this; 1596 } 1597 1598 /** 1599 * Bean property setter: <property>if</property>. 1600 * 1601 * <p> 1602 * This property was added in Draft 07 for conditional schema application. 1603 * 1604 * @param if_ The new value for the <property>if</property> property on this bean. 1605 * @return This object. 1606 */ 1607 @Beanp("if") 1608 public JsonSchema setIf(JsonSchema if_) { 1609 this.if_ = if_; 1610 setMasterOn(if_); 1611 return this; 1612 } 1613 1614 /** 1615 * Bean property setter: <property>items</property>. 1616 * 1617 * @param 1618 * items The new value for the <property>items</property> property on this bean. 1619 * This object must be of type {@link JsonSchema} or {@link JsonSchemaArray}. 1620 * @return This object. 1621 * @throws BeanRuntimeException If invalid object type passed in. 1622 */ 1623 public JsonSchema setItems(Object items) { 1624 this.itemsSchema = null; 1625 this.itemsSchemaArray = null; 1626 if (nn(items)) { 1627 if (items instanceof JsonSchema items2) { 1628 this.itemsSchema = items2; 1629 setMasterOn(this.itemsSchema); 1630 } else if (items instanceof JsonSchemaArray items2) { 1631 this.itemsSchemaArray = items2; 1632 setMasterOn(this.itemsSchemaArray); 1633 } else { 1634 throw bex(JsonSchemaProperty.class, "Invalid attribute type ''{0}'' passed in. Must be one of the following: JsonSchema, JsonSchemaArray", cn(items)); 1635 } 1636 } 1637 return this; 1638 } 1639 1640 /** 1641 * Bean property setter: <property>maximum</property>. 1642 * 1643 * @param maximum The new value for the <property>maximum</property> property on this bean. 1644 * @return This object. 1645 */ 1646 public JsonSchema setMaximum(Number maximum) { 1647 this.maximum = maximum; 1648 return this; 1649 } 1650 1651 /** 1652 * Bean property setter: <property>maxItems</property>. 1653 * 1654 * @param maxItems The new value for the <property>maxItems</property> property on this bean. 1655 * @return This object. 1656 */ 1657 public JsonSchema setMaxItems(Integer maxItems) { 1658 this.maxItems = maxItems; 1659 return this; 1660 } 1661 1662 /** 1663 * Bean property setter: <property>maxLength</property>. 1664 * 1665 * @param maxLength The new value for the <property>maxLength</property> property on this bean. 1666 * @return This object. 1667 */ 1668 public JsonSchema setMaxLength(Integer maxLength) { 1669 this.maxLength = maxLength; 1670 return this; 1671 } 1672 1673 /** 1674 * Bean property setter: <property>maxProperties</property>. 1675 * 1676 * @param maxProperties The new value for the <property>maxProperties</property> property on this bean. 1677 * @return This object. 1678 */ 1679 public JsonSchema setMaxProperties(Integer maxProperties) { 1680 this.maxProperties = maxProperties; 1681 return this; 1682 } 1683 1684 /** 1685 * Bean property setter: <property>minimum</property>. 1686 * 1687 * @param minimum The new value for the <property>minimum</property> property on this bean. 1688 * @return This object. 1689 */ 1690 public JsonSchema setMinimum(Number minimum) { 1691 this.minimum = minimum; 1692 return this; 1693 } 1694 1695 /** 1696 * Bean property setter: <property>minItems</property>. 1697 * 1698 * @param minItems The new value for the <property>minItems</property> property on this bean. 1699 * @return This object. 1700 */ 1701 public JsonSchema setMinItems(Integer minItems) { 1702 this.minItems = minItems; 1703 return this; 1704 } 1705 1706 /** 1707 * Bean property setter: <property>minLength</property>. 1708 * 1709 * @param minLength The new value for the <property>minLength</property> property on this bean. 1710 * @return This object. 1711 */ 1712 public JsonSchema setMinLength(Integer minLength) { 1713 this.minLength = minLength; 1714 return this; 1715 } 1716 1717 /** 1718 * Bean property setter: <property>minProperties</property>. 1719 * 1720 * @param minProperties The new value for the <property>minProperties</property> property on this bean. 1721 * @return This object. 1722 */ 1723 public JsonSchema setMinProperties(Integer minProperties) { 1724 this.minProperties = minProperties; 1725 return this; 1726 } 1727 1728 /** 1729 * Bean property setter: <property>multipleOf</property>. 1730 * 1731 * @param multipleOf The new value for the <property>multipleOf</property> property on this bean. 1732 * @return This object. 1733 */ 1734 public JsonSchema setMultipleOf(Number multipleOf) { 1735 this.multipleOf = multipleOf; 1736 return this; 1737 } 1738 1739 /** 1740 * Bean property setter: <property>name</property>. 1741 * 1742 * <p> 1743 * This is an internal property used for tracking property names and is not part of the JSON Schema specification. 1744 * 1745 * @param name The new value for the <property>name</property> property on this bean. 1746 * @return This object. 1747 */ 1748 @BeanIgnore 1749 public JsonSchema setName(String name) { 1750 this.name = name; 1751 return this; 1752 } 1753 1754 /** 1755 * Bean property setter: <property>not</property>. 1756 * 1757 * @param not The new value for the <property>not</property> property on this bean. 1758 * @return This object. 1759 */ 1760 public JsonSchema setNot(JsonSchema not) { 1761 this.not = not; 1762 setMasterOn(not); 1763 return this; 1764 } 1765 1766 /** 1767 * Bean property setter: <property>oneOf</property>. 1768 * 1769 * @param oneOf The new value for the <property>oneOf</property> property on this bean. 1770 * @return This object. 1771 */ 1772 public JsonSchema setOneOf(List<JsonSchema> oneOf) { 1773 this.oneOf = oneOf; 1774 setMasterOn(oneOf); 1775 return this; 1776 } 1777 1778 /** 1779 * Bean property setter: <property>pattern</property>. 1780 * 1781 * @param pattern The new value for the <property>pattern</property> property on this bean. 1782 * @return This object. 1783 */ 1784 public JsonSchema setPattern(String pattern) { 1785 this.pattern = pattern; 1786 return this; 1787 } 1788 1789 /** 1790 * Bean property setter: <property>patternProperties</property>. 1791 * 1792 * @param patternProperties The new value for the <property>patternProperties</property> property on this bean. 1793 * @return This object. 1794 */ 1795 public JsonSchema setPatternProperties(Map<String,JsonSchema> patternProperties) { 1796 this.patternProperties = patternProperties; 1797 if (nn(patternProperties)) { 1798 patternProperties.entrySet().forEach(x -> { 1799 var s = x.getValue(); 1800 setMasterOn(s); 1801 s.setName(x.getKey()); 1802 }); 1803 } 1804 return this; 1805 } 1806 1807 /** 1808 * Bean property setter: <property>prefixItems</property>. 1809 * 1810 * <p> 1811 * This property was added in Draft 2020-12 for tuple validation. 1812 * 1813 * @param prefixItems The new value for the <property>prefixItems</property> property on this bean. 1814 * @return This object. 1815 */ 1816 public JsonSchema setPrefixItems(JsonSchemaArray prefixItems) { 1817 this.prefixItems = prefixItems; 1818 setMasterOn(prefixItems); 1819 return this; 1820 } 1821 1822 /** 1823 * Bean property setter: <property>properties</property>. 1824 * 1825 * @param properties The new value for the <property>properties</property> property on this bean. 1826 * @return This object. 1827 */ 1828 public JsonSchema setProperties(Map<String,JsonSchema> properties) { 1829 this.properties = properties; 1830 if (nn(properties)) { 1831 properties.entrySet().forEach(x -> { 1832 var value = x.getValue(); 1833 setMasterOn(value); 1834 value.setName(x.getKey()); 1835 }); 1836 } 1837 return this; 1838 } 1839 1840 /** 1841 * Bean property setter: <property>readOnly</property>. 1842 * 1843 * <p> 1844 * This property was added in Draft 07. 1845 * 1846 * @param readOnly The new value for the <property>readOnly</property> property on this bean. 1847 * @return This object. 1848 */ 1849 public JsonSchema setReadOnly(Boolean readOnly) { 1850 this.readOnly = readOnly; 1851 return this; 1852 } 1853 1854 /** 1855 * Bean property setter: <property>$ref</property>. 1856 * 1857 * <p> 1858 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 1859 * Strings must be valid URIs. 1860 * 1861 * <p> 1862 * URIs defined by {@link UriResolver} can be used for values. 1863 * 1864 * @param ref The new value for the <property>$ref</property> property on this bean. 1865 * @return This object. 1866 */ 1867 @Beanp("$ref") 1868 public JsonSchema setRef(Object ref) { 1869 this.ref = toUri(ref); 1870 return this; 1871 } 1872 1873 /** 1874 * Bean property setter: <property>required</property>. 1875 * 1876 * @param required The new value for the <property>required</property> property on this bean. 1877 * @return This object. 1878 */ 1879 public JsonSchema setRequired(List<String> required) { 1880 this.required = required; 1881 return this; 1882 } 1883 1884 /** 1885 * Associates a schema map with this schema for resolving other schemas identified through <property>$ref</property> 1886 * properties. 1887 * 1888 * @param schemaMap The schema map to associate with this schema. Can be <jk>null</jk>. 1889 * @return This object. 1890 */ 1891 @BeanIgnore 1892 public JsonSchema setSchemaMap(JsonSchemaMap schemaMap) { 1893 this.schemaMap = schemaMap; 1894 return this; 1895 } 1896 1897 /** 1898 * Bean property setter: <property>$schema</property>. 1899 * 1900 * <p> 1901 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 1902 * Strings must be valid URIs. 1903 * 1904 * <p> 1905 * URIs defined by {@link UriResolver} can be used for values. 1906 * 1907 * @param schemaVersion The new value for the <property>schemaVersion</property> property on this bean. 1908 * @return This object. 1909 */ 1910 @Beanp("$schema") 1911 public JsonSchema setSchemaVersionUri(Object schemaVersion) { 1912 this.schemaVersion = toUri(schemaVersion); 1913 return this; 1914 } 1915 1916 /** 1917 * Bean property setter: <property>then</property>. 1918 * 1919 * <p> 1920 * This property was added in Draft 07 for conditional schema application. 1921 * 1922 * @param then_ The new value for the <property>then</property> property on this bean. 1923 * @return This object. 1924 */ 1925 @Beanp("then") 1926 public JsonSchema setThen(JsonSchema then_) { 1927 this.then_ = then_; 1928 setMasterOn(then_); 1929 return this; 1930 } 1931 1932 /** 1933 * Bean property setter: <property>title</property>. 1934 * 1935 * @param title The new value for the <property>title</property> property on this bean. 1936 * @return This object. 1937 */ 1938 public JsonSchema setTitle(String title) { 1939 this.title = title; 1940 return this; 1941 } 1942 1943 /** 1944 * Bean property setter: <property>type</property>. 1945 * 1946 * @param type 1947 * The new value for the <property>type</property> property on this bean. 1948 * This object must be of type {@link JsonType} or {@link JsonTypeArray}. 1949 * @return This object. 1950 * @throws BeanRuntimeException If invalid object type passed in. 1951 */ 1952 public JsonSchema setType(Object type) { 1953 this.typeJsonType = null; 1954 this.typeJsonTypeArray = null; 1955 if (nn(type)) { 1956 if (type instanceof JsonType type2) 1957 this.typeJsonType = type2; 1958 else if (type instanceof JsonTypeArray type2) 1959 this.typeJsonTypeArray = type2; 1960 else 1961 throw bex(JsonSchemaProperty.class, "Invalid attribute type ''{0}'' passed in. Must be one of the following: SimpleType, SimpleTypeArray", cn(type)); 1962 } 1963 return this; 1964 } 1965 1966 /** 1967 * Bean property setter: <property>unevaluatedItems</property>. 1968 * 1969 * <p> 1970 * This property was added in Draft 2019-09. 1971 * 1972 * @param unevaluatedItems The new value for the <property>unevaluatedItems</property> property on this bean. 1973 * @return This object. 1974 */ 1975 public JsonSchema setUnevaluatedItems(JsonSchema unevaluatedItems) { 1976 this.unevaluatedItems = unevaluatedItems; 1977 setMasterOn(unevaluatedItems); 1978 return this; 1979 } 1980 1981 /** 1982 * Bean property setter: <property>unevaluatedProperties</property>. 1983 * 1984 * <p> 1985 * This property was added in Draft 2019-09. 1986 * 1987 * @param unevaluatedProperties The new value for the <property>unevaluatedProperties</property> property on this bean. 1988 * @return This object. 1989 */ 1990 public JsonSchema setUnevaluatedProperties(JsonSchema unevaluatedProperties) { 1991 this.unevaluatedProperties = unevaluatedProperties; 1992 setMasterOn(unevaluatedProperties); 1993 return this; 1994 } 1995 1996 /** 1997 * Bean property setter: <property>uniqueItems</property>. 1998 * 1999 * @param uniqueItems The new value for the <property>uniqueItems</property> property on this bean. 2000 * @return This object. 2001 */ 2002 public JsonSchema setUniqueItems(Boolean uniqueItems) { 2003 this.uniqueItems = uniqueItems; 2004 return this; 2005 } 2006 2007 /** 2008 * Bean property setter: <property>writeOnly</property>. 2009 * 2010 * <p> 2011 * This property was added in Draft 07. 2012 * 2013 * @param writeOnly The new value for the <property>writeOnly</property> property on this bean. 2014 * @return This object. 2015 */ 2016 public JsonSchema setWriteOnly(Boolean writeOnly) { 2017 this.writeOnly = writeOnly; 2018 return this; 2019 } 2020 2021 @Override /* Overridden from Object */ 2022 public String toString() { 2023 return JsonSerializer.DEFAULT_SORTED.toString(this); 2024 } 2025 2026 private void setMasterOn(Collection<JsonSchema> ss) { 2027 if (nn(ss)) 2028 ss.forEach(this::setMasterOn); 2029 } 2030 2031 private void setMasterOn(JsonSchema s) { 2032 if (nn(s)) 2033 s.setMaster(this); 2034 } 2035 2036 private void setMasterOn(JsonSchema[] ss) { 2037 if (nn(ss)) 2038 for (var s : ss) 2039 setMasterOn(s); 2040 } 2041 2042 private void setMasterOn(JsonSchemaArray ss) { 2043 if (nn(ss)) 2044 ss.forEach(this::setMasterOn); 2045 } 2046 2047 /** 2048 * Sets the master schema for this schema and all child schema objects. 2049 * 2050 * <p> 2051 * All child elements in a schema should point to a single "master" schema in order to locate registered JsonSchemaMap 2052 * objects for resolving external schemas. 2053 * 2054 * @param master The master schema to associate on this and all children. Can be <jk>null</jk>. 2055 */ 2056 protected void setMaster(JsonSchema master) { 2057 this.master = master; 2058 if (nn(definitions)) 2059 definitions.values().forEach(x -> x.setMaster(master)); 2060 if (nn(defs)) 2061 defs.values().forEach(x -> x.setMaster(master)); 2062 if (nn(properties)) 2063 properties.values().forEach(x -> x.setMaster(master)); 2064 if (nn(patternProperties)) 2065 patternProperties.values().forEach(x -> x.setMaster(master)); 2066 if (nn(dependencies)) 2067 dependencies.values().forEach(x -> x.setMaster(master)); 2068 if (nn(dependentSchemas)) 2069 dependentSchemas.values().forEach(x -> x.setMaster(master)); 2070 if (nn(itemsSchema)) 2071 itemsSchema.setMaster(master); 2072 if (nn(itemsSchemaArray)) 2073 itemsSchemaArray.forEach(x -> x.setMaster(master)); 2074 if (nn(prefixItems)) 2075 prefixItems.forEach(x -> x.setMaster(master)); 2076 if (nn(additionalItemsSchemaArray)) 2077 additionalItemsSchemaArray.forEach(x -> x.setMaster(master)); 2078 if (nn(unevaluatedItems)) 2079 unevaluatedItems.setMaster(master); 2080 if (nn(additionalPropertiesSchema)) 2081 additionalPropertiesSchema.setMaster(master); 2082 if (nn(unevaluatedProperties)) 2083 unevaluatedProperties.setMaster(master); 2084 if (nn(allOf)) 2085 allOf.forEach(x -> x.setMaster(master)); 2086 if (nn(anyOf)) 2087 anyOf.forEach(x -> x.setMaster(master)); 2088 if (nn(oneOf)) 2089 oneOf.forEach(x -> x.setMaster(master)); 2090 if (nn(not)) 2091 not.setMaster(master); 2092 if (nn(if_)) 2093 if_.setMaster(master); 2094 if (nn(then_)) 2095 then_.setMaster(master); 2096 if (nn(else_)) 2097 else_.setMaster(master); 2098 } 2099}