From 2a561d871e70011d6ecf3b6ca61227af95b22aed Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sat, 20 Jan 2024 14:27:59 -0800 Subject: [PATCH 1/2] Adds unevaluatedItems handling --- .../java/.openapi-generator/FILES | 1 + .../client/schemas/validation/JsonSchema.java | 12 ++++- .../schemas/validation/JsonSchemaInfo.java | 5 ++ .../validation/UnevaluatedItemsValidator.java | 51 +++++++++++++++++++ .../schemas/validation/ValidationData.java | 3 +- .../generators/JavaClientGenerator.java | 3 +- .../schemas/SchemaClass/_unevaluatedItems.hbs | 17 +++++++ .../schemas/validation/JsonSchema.hbs | 12 ++++- .../schemas/validation/JsonSchemaInfo.hbs | 5 ++ .../validation/UnevaluatedItemsValidator.hbs | 51 +++++++++++++++++++ .../schemas/validation/ValidationData.hbs | 3 +- 11 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java create mode 100644 src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems.hbs create mode 100644 src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs diff --git a/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES b/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES index 89259247726..f8042362493 100644 --- a/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES +++ b/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES @@ -373,6 +373,7 @@ src/main/java/org/openapijsonschematools/client/schemas/validation/StringSchemaV src/main/java/org/openapijsonschematools/client/schemas/validation/StringValueMethod.java src/main/java/org/openapijsonschematools/client/schemas/validation/ThenValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/TypeValidator.java +src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UniqueItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UnsetAnyTypeJsonSchema.java src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java index 1925008547c..89ac9daedff 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java @@ -57,6 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; + public final @Nullable Class unevaluatedItems = null; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -208,6 +209,10 @@ protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { if (this.elseSchema != null) { keywordToValidator.put("else", new ElseValidator()); } + this.unevaluatedItems = jsonSchemaInfo.unevaluatedItems; + if (this.unevaluatedItems != null) { + keywordToValidator.put("unevaluatedItems", new UnevaluatedItemsValidator()); + } this.keywordToValidator = keywordToValidator; } @@ -321,6 +326,7 @@ public static PathToSchemasMap validate( if (thisKeywordToValidator.containsKey("if")) { ifPathToSchemas = jsonSchema.getIfPathToSchemas(arg, validationMetadata); } + @Nullable PathToSchemasMap knownPathToSchemas = null; for (Map.Entry entry: thisKeywordToValidator.entrySet()) { String jsonKeyword = entry.getKey(); if (disabledKeywords.contains(jsonKeyword)) { @@ -329,6 +335,9 @@ public static PathToSchemasMap validate( continue; } } + if ("unevaluatedItems".equals(jsonKeyword)) { + knownPathToSchemas = pathToSchemas; + } KeywordValidator validator = entry.getValue(); ValidationData data = new ValidationData( jsonSchema, @@ -336,7 +345,8 @@ public static PathToSchemasMap validate( validationMetadata, containsPathToSchemas, patternPropertiesPathToSchemas, - ifPathToSchemas + ifPathToSchemas, + knownPathToSchemas ); @Nullable PathToSchemasMap otherPathToSchemas = validator.validate(data); if (otherPathToSchemas == null) { diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java index e423d151a5e..a9d63bf0c95 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java @@ -197,4 +197,9 @@ public JsonSchemaInfo elseSchema(Class elseSchema) { this.elseSchema = elseSchema; return this; } + public @Nullable Class unevaluatedItems = null; + public JsonSchemaInfo unevaluatedItems(Class unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + return this; + } } \ No newline at end of file diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java new file mode 100644 index 00000000000..336ea7b7025 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java @@ -0,0 +1,51 @@ +package org.openapijsonschematools.client.schemas.validation; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class UnevaluatedItemsValidator implements KeywordValidator { + @Override + public @Nullable PathToSchemasMap validate( + ValidationData data + ) { + var unevaluatedItems = data.schema().unevaluatedItems; + if (unevaluatedItems == null) { + return null; + } + var knownPathToSchemas = data.knownPathToSchemas(); + if (knownPathToSchemas == null) { + return null; + } + if (!(data.arg() instanceof List listArg)) { + return null; + } + if (listArg.isEmpty()) { + return null; + } + PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + int minIndex = data.schema().prefixItems != null ? data.schema().prefixItems.size() : 0; + JsonSchema unevaluatedItemsSchema = JsonSchemaFactory.getInstance(unevaluatedItems); + for(int i = minIndex; i < listArg.size(); i++) { + List itemPathToItem = new ArrayList<>(data.validationMetadata().pathToItem()); + itemPathToItem.add(i); + if (knownPathToSchemas.containsKey(itemPathToItem)) { + continue; + } + ValidationMetadata itemValidationMetadata = new ValidationMetadata( + itemPathToItem, + data.validationMetadata().configuration(), + data.validationMetadata().validatedPathToSchemas(), + data.validationMetadata().seenClasses() + ); + if (itemValidationMetadata.validationRanEarlier(itemsSchema)) { + // todo add_deeper_validated_schemas + continue; + } + PathToSchemasMap otherPathToSchemas = JsonSchema.validate(unevaluatedItemsSchema, listArg.get(i), itemValidationMetadata); + pathToSchemas.update(otherPathToSchemas); + } + return pathToSchemas; + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java index 55cb65fe9ef..951ba3f9f0e 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java @@ -11,12 +11,13 @@ public record ValidationData( @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( JsonSchema schema, @Nullable Object arg, ValidationMetadata validationMetadata ) { - this(schema, arg, validationMetadata, null, null, null); + this(schema, arg, validationMetadata, null, null, null, null); } } \ No newline at end of file diff --git a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java index 41bc0d864d1..1d3968972d3 100644 --- a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java +++ b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java @@ -291,7 +291,7 @@ public JavaClientGenerator() { SchemaFeature.Required, SchemaFeature.Then, SchemaFeature.Type, - // SchemaFeature.UnevaluatedItems, + SchemaFeature.UnevaluatedItems, // SchemaFeature.UnevaluatedProperties, SchemaFeature.UniqueItems ) @@ -625,6 +625,7 @@ public void processOpts() { keywordValidatorFiles.add("StringValueMethod"); keywordValidatorFiles.add("ThenValidator"); keywordValidatorFiles.add("TypeValidator"); + keywordValidatorFiles.add("UnevaluatedItemsValidator"); keywordValidatorFiles.add("UniqueItemsValidator"); keywordValidatorFiles.add("UnsetAnyTypeJsonSchema"); keywordValidatorFiles.add("ValidationData"); diff --git a/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems.hbs b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems.hbs new file mode 100644 index 00000000000..77b04ff5678 --- /dev/null +++ b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems.hbs @@ -0,0 +1,17 @@ +{{#if forDocs}} + {{#with unevaluatedItems}} + {{#if refInfo.refClass}} + {{#if refInfo.refModule}} +unevaluatedItems = [{{refInfo.refModule}}.{{refInfo.refClass}}.class]({{docRoot}}{{refInfo.ref.pathFromDocRoot}}.md#{{refInfo.ref.jsonPathPiece.kebabCase}}) + {{~else}} +unevaluatedItems = [{{refInfo.refClass}}.class](#{{refInfo.ref.jsonPathPiece.kebabCase}}) + {{~/if}} + {{else}} +unevaluatedItems = [{{jsonPathPiece.pascalCase}}.class](#{{jsonPathPiece.kebabCase}}) + {{~/if}} + {{/with}} +{{else}} + {{#with unevaluatedItems}} +.unevaluatedItems({{#if refInfo.refClass}}{{#if refInfo.refModule}}{{refInfo.refModule}}.{{/if}}{{refInfo.refClass}}{{else}}{{jsonPathPiece.pascalCase}}{{/if}}.class) + {{/with}} +{{/if}} \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs index d45b175eb61..48121e68747 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs @@ -57,6 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; + public final @Nullable Class unevaluatedItems = null; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -208,6 +209,10 @@ public abstract class JsonSchema { if (this.elseSchema != null) { keywordToValidator.put("else", new ElseValidator()); } + this.unevaluatedItems = jsonSchemaInfo.unevaluatedItems; + if (this.unevaluatedItems != null) { + keywordToValidator.put("unevaluatedItems", new UnevaluatedItemsValidator()); + } this.keywordToValidator = keywordToValidator; } @@ -321,6 +326,7 @@ public abstract class JsonSchema { if (thisKeywordToValidator.containsKey("if")) { ifPathToSchemas = jsonSchema.getIfPathToSchemas(arg, validationMetadata); } + @Nullable PathToSchemasMap knownPathToSchemas = null; for (Map.Entry entry: thisKeywordToValidator.entrySet()) { String jsonKeyword = entry.getKey(); if (disabledKeywords.contains(jsonKeyword)) { @@ -329,6 +335,9 @@ public abstract class JsonSchema { continue; } } + if ("unevaluatedItems".equals(jsonKeyword)) { + knownPathToSchemas = pathToSchemas; + } KeywordValidator validator = entry.getValue(); ValidationData data = new ValidationData( jsonSchema, @@ -336,7 +345,8 @@ public abstract class JsonSchema { validationMetadata, containsPathToSchemas, patternPropertiesPathToSchemas, - ifPathToSchemas + ifPathToSchemas, + knownPathToSchemas ); @Nullable PathToSchemasMap otherPathToSchemas = validator.validate(data); if (otherPathToSchemas == null) { diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchemaInfo.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchemaInfo.hbs index 948ef3a57be..47aa71dd34e 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchemaInfo.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchemaInfo.hbs @@ -197,4 +197,9 @@ public class JsonSchemaInfo { this.elseSchema = elseSchema; return this; } + public @Nullable Class unevaluatedItems = null; + public JsonSchemaInfo unevaluatedItems(Class unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + return this; + } } \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs new file mode 100644 index 00000000000..9caa79a6a09 --- /dev/null +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs @@ -0,0 +1,51 @@ +package {{{packageName}}}.schemas.validation; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class UnevaluatedItemsValidator implements KeywordValidator { + @Override + public @Nullable PathToSchemasMap validate( + ValidationData data + ) { + var unevaluatedItems = data.schema().unevaluatedItems; + if (unevaluatedItems == null) { + return null; + } + var knownPathToSchemas = data.knownPathToSchemas(); + if (knownPathToSchemas == null) { + return null; + } + if (!(data.arg() instanceof List listArg)) { + return null; + } + if (listArg.isEmpty()) { + return null; + } + PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + int minIndex = data.schema().prefixItems != null ? data.schema().prefixItems.size() : 0; + JsonSchema unevaluatedItemsSchema = JsonSchemaFactory.getInstance(unevaluatedItems); + for(int i = minIndex; i < listArg.size(); i++) { + List itemPathToItem = new ArrayList<>(data.validationMetadata().pathToItem()); + itemPathToItem.add(i); + if (knownPathToSchemas.containsKey(itemPathToItem)) { + continue; + } + ValidationMetadata itemValidationMetadata = new ValidationMetadata( + itemPathToItem, + data.validationMetadata().configuration(), + data.validationMetadata().validatedPathToSchemas(), + data.validationMetadata().seenClasses() + ); + if (itemValidationMetadata.validationRanEarlier(itemsSchema)) { + // todo add_deeper_validated_schemas + continue; + } + PathToSchemasMap otherPathToSchemas = JsonSchema.validate(unevaluatedItemsSchema, listArg.get(i), itemValidationMetadata); + pathToSchemas.update(otherPathToSchemas); + } + return pathToSchemas; + } +} diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs index 55cb65fe9ef..951ba3f9f0e 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs @@ -11,12 +11,13 @@ public record ValidationData( @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( JsonSchema schema, @Nullable Object arg, ValidationMetadata validationMetadata ) { - this(schema, arg, validationMetadata, null, null, null); + this(schema, arg, validationMetadata, null, null, null, null); } } \ No newline at end of file From 12b56c24bd028c4e4928a9d2e0778cd38c767fdb Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 21 Jan 2024 11:58:56 -0800 Subject: [PATCH 2/2] Samples regen --- docs/generators/java.md | 2 +- .../java/.openapi-generator/FILES | 1 + .../client/schemas/validation/JsonSchema.java | 18 +- .../schemas/validation/JsonSchemaInfo.java | 5 + .../validation/UnevaluatedItemsValidator.java | 51 + .../schemas/validation/ValidationData.java | 5 +- .../java/.openapi-generator/FILES | 6 + samples/client/3_1_0_unit_test/java/README.md | 3 + .../schemas/UnevaluateditemsAsSchema.md | 48 + ...teditemsDependsOnMultipleNestedContains.md | 163 +++ .../schemas/UnevaluateditemsWithItems.md | 1 + ...nevaluateditemsWithNullInstanceElements.md | 48 + .../schemas/UnevaluateditemsAsSchema.java | 250 ++++ ...ditemsDependsOnMultipleNestedContains.java | 1218 +++++++++++++++++ .../schemas/UnevaluateditemsWithItems.java | 1 + ...valuateditemsWithNullInstanceElements.java | 250 ++++ .../client/schemas/validation/JsonSchema.java | 8 +- .../validation/UnevaluatedItemsValidator.java | 2 +- .../schemas/validation/ValidationData.java | 2 +- .../schemas/UnevaluateditemsAsSchemaTest.java | 59 + ...msDependsOnMultipleNestedContainsTest.java | 56 + ...ateditemsWithNullInstanceElementsTest.java | 31 + .../petstore/java/.openapi-generator/FILES | 1 + .../client/schemas/validation/JsonSchema.java | 18 +- .../schemas/validation/JsonSchemaInfo.java | 5 + .../validation/UnevaluatedItemsValidator.java | 51 + .../schemas/validation/ValidationData.java | 5 +- .../_Schema_anytypeOrMultitype.hbs | 6 +- .../schemas/SchemaClass/_Schema_list.hbs | 6 +- .../schemas/docschema_fields_field.hbs | 3 + .../schemas/validation/JsonSchema.hbs | 8 +- .../validation/UnevaluatedItemsValidator.hbs | 2 +- .../schemas/validation/ValidationData.hbs | 2 +- .../3_1_0_unit_test_spec_nopaths.yaml | 63 + .../3_1/unit_test_spec/spec_writer.py | 3 - 35 files changed, 2363 insertions(+), 38 deletions(-) create mode 100644 samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java create mode 100644 samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsAsSchema.md create mode 100644 samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md create mode 100644 samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md create mode 100644 samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchema.java create mode 100644 samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.java create mode 100644 samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElements.java create mode 100644 samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchemaTest.java create mode 100644 samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContainsTest.java create mode 100644 samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElementsTest.java create mode 100644 samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java diff --git a/docs/generators/java.md b/docs/generators/java.md index 4da0d1cbc90..36ac2ea4608 100644 --- a/docs/generators/java.md +++ b/docs/generators/java.md @@ -312,7 +312,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |Required|✓|OAS2,OAS3 |Then|✓|OAS3 |Type|✓|OAS2,OAS3 -|UnevaluatedItems|✗|OAS3 +|UnevaluatedItems|✓|OAS3 |UnevaluatedProperties|✗|OAS3 |UniqueItems|✓|OAS2,OAS3 |Xml|✗|OAS2,OAS3 diff --git a/samples/client/3_0_3_unit_test/java/.openapi-generator/FILES b/samples/client/3_0_3_unit_test/java/.openapi-generator/FILES index 027bfd37c24..f9c89d3a7f4 100644 --- a/samples/client/3_0_3_unit_test/java/.openapi-generator/FILES +++ b/samples/client/3_0_3_unit_test/java/.openapi-generator/FILES @@ -271,6 +271,7 @@ src/main/java/org/openapijsonschematools/client/schemas/validation/StringSchemaV src/main/java/org/openapijsonschematools/client/schemas/validation/StringValueMethod.java src/main/java/org/openapijsonschematools/client/schemas/validation/ThenValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/TypeValidator.java +src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UniqueItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UnsetAnyTypeJsonSchema.java src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java diff --git a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java index 1925008547c..f4c6b5a7efb 100644 --- a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java +++ b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java @@ -57,6 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; + public final @Nullable Class unevaluatedItems; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -208,6 +209,10 @@ protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { if (this.elseSchema != null) { keywordToValidator.put("else", new ElseValidator()); } + this.unevaluatedItems = jsonSchemaInfo.unevaluatedItems; + if (this.unevaluatedItems != null) { + keywordToValidator.put("unevaluatedItems", new UnevaluatedItemsValidator()); + } this.keywordToValidator = keywordToValidator; } @@ -223,8 +228,7 @@ private List getContainsPathToSchemas( } JsonSchema containsSchema = JsonSchemaFactory.getInstance(contains); @Nullable List containsPathToSchemas = new ArrayList<>(); - int i = 0; - for(Object itemValue: listArg) { + for(int i = 0; i < listArg.size(); i++) { PathToSchemasMap thesePathToSchemas = new PathToSchemasMap(); List itemPathToItem = new ArrayList<>(validationMetadata.pathToItem()); itemPathToItem.add(i); @@ -237,13 +241,12 @@ private List getContainsPathToSchemas( if (itemValidationMetadata.validationRanEarlier(containsSchema)) { // todo add_deeper_validated_schemas containsPathToSchemas.add(thesePathToSchemas); - i += 1; continue; } try { PathToSchemasMap otherPathToSchemas = JsonSchema.validate( - containsSchema, itemValue, itemValidationMetadata); + containsSchema, listArg.get(i), itemValidationMetadata); containsPathToSchemas.add(otherPathToSchemas); } catch (ValidationException ignored) {} } @@ -321,6 +324,7 @@ public static PathToSchemasMap validate( if (thisKeywordToValidator.containsKey("if")) { ifPathToSchemas = jsonSchema.getIfPathToSchemas(arg, validationMetadata); } + @Nullable PathToSchemasMap knownPathToSchemas = null; for (Map.Entry entry: thisKeywordToValidator.entrySet()) { String jsonKeyword = entry.getKey(); if (disabledKeywords.contains(jsonKeyword)) { @@ -329,6 +333,9 @@ public static PathToSchemasMap validate( continue; } } + if ("unevaluatedItems".equals(jsonKeyword)) { + knownPathToSchemas = pathToSchemas; + } KeywordValidator validator = entry.getValue(); ValidationData data = new ValidationData( jsonSchema, @@ -336,7 +343,8 @@ public static PathToSchemasMap validate( validationMetadata, containsPathToSchemas, patternPropertiesPathToSchemas, - ifPathToSchemas + ifPathToSchemas, + knownPathToSchemas ); @Nullable PathToSchemasMap otherPathToSchemas = validator.validate(data); if (otherPathToSchemas == null) { diff --git a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java index e423d151a5e..a9d63bf0c95 100644 --- a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java +++ b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java @@ -197,4 +197,9 @@ public JsonSchemaInfo elseSchema(Class elseSchema) { this.elseSchema = elseSchema; return this; } + public @Nullable Class unevaluatedItems = null; + public JsonSchemaInfo unevaluatedItems(Class unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + return this; + } } \ No newline at end of file diff --git a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java new file mode 100644 index 00000000000..cfb88550525 --- /dev/null +++ b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java @@ -0,0 +1,51 @@ +package org.openapijsonschematools.client.schemas.validation; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class UnevaluatedItemsValidator implements KeywordValidator { + @Override + public @Nullable PathToSchemasMap validate( + ValidationData data + ) { + var unevaluatedItems = data.schema().unevaluatedItems; + if (unevaluatedItems == null) { + return null; + } + var knownPathToSchemas = data.knownPathToSchemas(); + if (knownPathToSchemas == null) { + return null; + } + if (!(data.arg() instanceof List listArg)) { + return null; + } + if (listArg.isEmpty()) { + return null; + } + PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + int minIndex = data.schema().prefixItems != null ? data.schema().prefixItems.size() : 0; + JsonSchema unevaluatedItemsSchema = JsonSchemaFactory.getInstance(unevaluatedItems); + for(int i = minIndex; i < listArg.size(); i++) { + List itemPathToItem = new ArrayList<>(data.validationMetadata().pathToItem()); + itemPathToItem.add(i); + if (knownPathToSchemas.containsKey(itemPathToItem)) { + continue; + } + ValidationMetadata itemValidationMetadata = new ValidationMetadata( + itemPathToItem, + data.validationMetadata().configuration(), + data.validationMetadata().validatedPathToSchemas(), + data.validationMetadata().seenClasses() + ); + if (itemValidationMetadata.validationRanEarlier(unevaluatedItemsSchema)) { + // todo add_deeper_validated_schemas + continue; + } + PathToSchemasMap otherPathToSchemas = JsonSchema.validate(unevaluatedItemsSchema, listArg.get(i), itemValidationMetadata); + pathToSchemas.update(otherPathToSchemas); + } + return pathToSchemas; + } +} diff --git a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java index 55cb65fe9ef..d5c4f5de75a 100644 --- a/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java +++ b/samples/client/3_0_3_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java @@ -10,13 +10,14 @@ public record ValidationData( ValidationMetadata validationMetadata, @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, - @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap ifPathToSchemas, + @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( JsonSchema schema, @Nullable Object arg, ValidationMetadata validationMetadata ) { - this(schema, arg, validationMetadata, null, null, null); + this(schema, arg, validationMetadata, null, null, null, null); } } \ No newline at end of file diff --git a/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES b/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES index f8042362493..294a3c2f7f1 100644 --- a/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES +++ b/samples/client/3_1_0_unit_test/java/.openapi-generator/FILES @@ -125,7 +125,10 @@ docs/components/schemas/TimeFormat.md docs/components/schemas/TypeArrayObjectOrNull.md docs/components/schemas/TypeArrayOrObject.md docs/components/schemas/TypeAsArrayWithOneItem.md +docs/components/schemas/UnevaluateditemsAsSchema.md +docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md docs/components/schemas/UnevaluateditemsWithItems.md +docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md docs/components/schemas/UnevaluatedpropertiesWithAdjacentAdditionalproperties.md docs/components/schemas/UnevaluatedpropertiesWithNullValuedInstanceProperties.md docs/components/schemas/UniqueitemsFalseValidation.md @@ -265,7 +268,10 @@ src/main/java/org/openapijsonschematools/client/components/schemas/TimeFormat.ja src/main/java/org/openapijsonschematools/client/components/schemas/TypeArrayObjectOrNull.java src/main/java/org/openapijsonschematools/client/components/schemas/TypeArrayOrObject.java src/main/java/org/openapijsonschematools/client/components/schemas/TypeAsArrayWithOneItem.java +src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchema.java +src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.java src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithItems.java +src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElements.java src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluatedpropertiesWithAdjacentAdditionalproperties.java src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluatedpropertiesWithNullValuedInstanceProperties.java src/main/java/org/openapijsonschematools/client/components/schemas/UniqueitemsFalseValidation.java diff --git a/samples/client/3_1_0_unit_test/java/README.md b/samples/client/3_1_0_unit_test/java/README.md index e2ee48798be..712b6f256fa 100644 --- a/samples/client/3_1_0_unit_test/java/README.md +++ b/samples/client/3_1_0_unit_test/java/README.md @@ -283,7 +283,10 @@ allowed input and output types. | [TypeArrayObjectOrNull.TypeArrayObjectOrNull1](docs/components/schemas/TypeArrayObjectOrNull.md#typearrayobjectornull1) | | | [TypeArrayOrObject.TypeArrayOrObject1](docs/components/schemas/TypeArrayOrObject.md#typearrayorobject1) | | | [TypeAsArrayWithOneItem.TypeAsArrayWithOneItem1](docs/components/schemas/TypeAsArrayWithOneItem.md#typeasarraywithoneitem1) | | +| [UnevaluateditemsAsSchema.UnevaluateditemsAsSchema1](docs/components/schemas/UnevaluateditemsAsSchema.md#unevaluateditemsasschema1) | | +| [UnevaluateditemsDependsOnMultipleNestedContains.UnevaluateditemsDependsOnMultipleNestedContains1](docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md#unevaluateditemsdependsonmultiplenestedcontains1) | | | [UnevaluateditemsWithItems.UnevaluateditemsWithItems1](docs/components/schemas/UnevaluateditemsWithItems.md#unevaluateditemswithitems1) | | +| [UnevaluateditemsWithNullInstanceElements.UnevaluateditemsWithNullInstanceElements1](docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md#unevaluateditemswithnullinstanceelements1) | | | [UnevaluatedpropertiesWithAdjacentAdditionalproperties.UnevaluatedpropertiesWithAdjacentAdditionalproperties1](docs/components/schemas/UnevaluatedpropertiesWithAdjacentAdditionalproperties.md#unevaluatedpropertieswithadjacentadditionalproperties1) | | | [UnevaluatedpropertiesWithNullValuedInstanceProperties.UnevaluatedpropertiesWithNullValuedInstanceProperties1](docs/components/schemas/UnevaluatedpropertiesWithNullValuedInstanceProperties.md#unevaluatedpropertieswithnullvaluedinstanceproperties1) | | | [UniqueitemsFalseValidation.UniqueitemsFalseValidation1](docs/components/schemas/UniqueitemsFalseValidation.md#uniqueitemsfalsevalidation1) | | diff --git a/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsAsSchema.md b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsAsSchema.md new file mode 100644 index 00000000000..90ffd319276 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsAsSchema.md @@ -0,0 +1,48 @@ +# UnevaluateditemsAsSchema +org.openapijsonschematools.client.components.schemas.UnevaluateditemsAsSchema.java +public class UnevaluateditemsAsSchema + +A class that contains necessary nested +- schema classes (which validate payloads), extends JsonSchema + +## Nested Class Summary +| Modifier and Type | Class and Description | +| ----------------- | ---------------------- | +| static class | [UnevaluateditemsAsSchema.UnevaluateditemsAsSchema1](#unevaluateditemsasschema1)
schema class | +| static class | [UnevaluateditemsAsSchema.UnevaluatedItems](#unevaluateditems)
schema class | + +## UnevaluateditemsAsSchema1 +public static class UnevaluateditemsAsSchema1
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| Class | unevaluatedItems = [UnevaluatedItems.class](#unevaluateditems) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## UnevaluatedItems +public static class UnevaluatedItems
+extends StringJsonSchema + +A schema class that validates payloads + +| Methods Inherited from class org.openapijsonschematools.client.schemas.StringJsonSchema | +| ------------------------------------------------------------------ | +| validate | + +[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md) diff --git a/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md new file mode 100644 index 00000000000..5ef1a2912f9 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.md @@ -0,0 +1,163 @@ +# UnevaluateditemsDependsOnMultipleNestedContains +org.openapijsonschematools.client.components.schemas.UnevaluateditemsDependsOnMultipleNestedContains.java +public class UnevaluateditemsDependsOnMultipleNestedContains + +A class that contains necessary nested +- schema classes (which validate payloads), extends JsonSchema + +## Nested Class Summary +| Modifier and Type | Class and Description | +| ----------------- | ---------------------- | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.UnevaluateditemsDependsOnMultipleNestedContains1](#unevaluateditemsdependsonmultiplenestedcontains1)
schema class | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.UnevaluatedItems](#unevaluateditems)
schema class | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.Schema1](#schema1)
schema class | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.Contains1](#contains1)
schema class | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.Schema0](#schema0)
schema class | +| static class | [UnevaluateditemsDependsOnMultipleNestedContains.Contains](#contains)
schema class | + +## UnevaluateditemsDependsOnMultipleNestedContains1 +public static class UnevaluateditemsDependsOnMultipleNestedContains1
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| List> | allOf = List.of(
    [Schema0.class](#schema0),
    [Schema1.class](#schema1)
;)
| +| Class | unevaluatedItems = [UnevaluatedItems.class](#unevaluateditems) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## UnevaluatedItems +public static class UnevaluatedItems
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| BigDecimal | multipleOf = new BigDecimal("5") | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## Schema1 +public static class Schema1
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| Class | contains = [Contains1.class](#contains1) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## Contains1 +public static class Contains1
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| BigDecimal | multipleOf = new BigDecimal("3") | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## Schema0 +public static class Schema0
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| Class | contains = [Contains.class](#contains) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## Contains +public static class Contains
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| BigDecimal | multipleOf = new BigDecimal("2") | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md) diff --git a/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithItems.md b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithItems.md index a8fc1ce81ae..2a421c59879 100644 --- a/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithItems.md +++ b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithItems.md @@ -53,6 +53,7 @@ UnevaluateditemsWithItems.UnevaluateditemsWithItemsList validatedPayload = | ----------------- | ---------------------- | | Set> | type = Set.of(List.class) | | Class | items = [Items.class](#items) | +| Class | unevaluatedItems = [UnevaluatedItems.class](#unevaluateditems) | ### Method Summary | Modifier and Type | Method and Description | diff --git a/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md new file mode 100644 index 00000000000..617b717e204 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/docs/components/schemas/UnevaluateditemsWithNullInstanceElements.md @@ -0,0 +1,48 @@ +# UnevaluateditemsWithNullInstanceElements +org.openapijsonschematools.client.components.schemas.UnevaluateditemsWithNullInstanceElements.java +public class UnevaluateditemsWithNullInstanceElements + +A class that contains necessary nested +- schema classes (which validate payloads), extends JsonSchema + +## Nested Class Summary +| Modifier and Type | Class and Description | +| ----------------- | ---------------------- | +| static class | [UnevaluateditemsWithNullInstanceElements.UnevaluateditemsWithNullInstanceElements1](#unevaluateditemswithnullinstanceelements1)
schema class | +| static class | [UnevaluateditemsWithNullInstanceElements.UnevaluatedItems](#unevaluateditems)
schema class | + +## UnevaluateditemsWithNullInstanceElements1 +public static class UnevaluateditemsWithNullInstanceElements1
+extends JsonSchema + +A schema class that validates payloads + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| Class | unevaluatedItems = [UnevaluatedItems.class](#unevaluateditems) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| String | validate(String arg, SchemaConfiguration configuration) | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| int | validate(int arg, SchemaConfiguration configuration) | +| long | validate(long arg, SchemaConfiguration configuration) | +| float | validate(float arg, SchemaConfiguration configuration) | +| double | validate(double arg, SchemaConfiguration configuration) | +| boolean | validate(boolean arg, SchemaConfiguration configuration) | +| FrozenMap | validate(Map<?, ?> arg, SchemaConfiguration configuration) | +| FrozenList<@Nullable Object> | validate(List arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | +## UnevaluatedItems +public static class UnevaluatedItems
+extends NullJsonSchema + +A schema class that validates payloads + +| Methods Inherited from class org.openapijsonschematools.client.schemas.NumberJsonSchema | +| ------------------------------------------------------------------ | +| validate | + +[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md) diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchema.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchema.java new file mode 100644 index 00000000000..53453155f00 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchema.java @@ -0,0 +1,250 @@ +package org.openapijsonschematools.client.components.schemas; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.InvalidAdditionalPropertyException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.exceptions.UnsetPropertyException; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.schemas.StringJsonSchema; +import org.openapijsonschematools.client.schemas.UnsetAddPropsSetter; +import org.openapijsonschematools.client.schemas.validation.BooleanSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.FrozenList; +import org.openapijsonschematools.client.schemas.validation.FrozenMap; +import org.openapijsonschematools.client.schemas.validation.JsonSchema; +import org.openapijsonschematools.client.schemas.validation.JsonSchemaInfo; +import org.openapijsonschematools.client.schemas.validation.ListSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.MapSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NullSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NumberSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.PathToSchemasMap; +import org.openapijsonschematools.client.schemas.validation.StringSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.ValidationMetadata; + +public class UnevaluateditemsAsSchema { + // nest classes so all schemas and input/output classes can be public + + + public static class UnevaluatedItems extends StringJsonSchema { + private static @Nullable UnevaluatedItems instance = null; + public static UnevaluatedItems getInstance() { + if (instance == null) { + instance = new UnevaluatedItems(); + } + return instance; + } + } + + + public static class UnevaluateditemsAsSchema1 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + /* + NOTE: This class is auto generated by OpenAPI JSON Schema Generator. + Ref: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator + + Do not edit the class manually. + */ + private static @Nullable UnevaluateditemsAsSchema1 instance = null; + + protected UnevaluateditemsAsSchema1() { + super(new JsonSchemaInfo() + .unevaluatedItems(UnevaluatedItems.class) + ); + } + + public static UnevaluateditemsAsSchema1 getInstance() { + if (instance == null) { + instance = new UnevaluateditemsAsSchema1(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.java new file mode 100644 index 00000000000..928db0cbf69 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContains.java @@ -0,0 +1,1218 @@ +package org.openapijsonschematools.client.components.schemas; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.InvalidAdditionalPropertyException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.exceptions.UnsetPropertyException; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.schemas.UnsetAddPropsSetter; +import org.openapijsonschematools.client.schemas.validation.BooleanSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.FrozenList; +import org.openapijsonschematools.client.schemas.validation.FrozenMap; +import org.openapijsonschematools.client.schemas.validation.JsonSchema; +import org.openapijsonschematools.client.schemas.validation.JsonSchemaInfo; +import org.openapijsonschematools.client.schemas.validation.ListSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.MapSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NullSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NumberSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.PathToSchemasMap; +import org.openapijsonschematools.client.schemas.validation.StringSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.ValidationMetadata; + +public class UnevaluateditemsDependsOnMultipleNestedContains { + // nest classes so all schemas and input/output classes can be public + + + public static class Contains extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + private static @Nullable Contains instance = null; + + protected Contains() { + super(new JsonSchemaInfo() + .multipleOf(new BigDecimal("2")) + ); + } + + public static Contains getInstance() { + if (instance == null) { + instance = new Contains(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } + + public static class Schema0 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + private static @Nullable Schema0 instance = null; + + protected Schema0() { + super(new JsonSchemaInfo() + .contains(Contains.class) + ); + } + + public static Schema0 getInstance() { + if (instance == null) { + instance = new Schema0(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } + + public static class Contains1 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + private static @Nullable Contains1 instance = null; + + protected Contains1() { + super(new JsonSchemaInfo() + .multipleOf(new BigDecimal("3")) + ); + } + + public static Contains1 getInstance() { + if (instance == null) { + instance = new Contains1(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } + + public static class Schema1 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + private static @Nullable Schema1 instance = null; + + protected Schema1() { + super(new JsonSchemaInfo() + .contains(Contains1.class) + ); + } + + public static Schema1 getInstance() { + if (instance == null) { + instance = new Schema1(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } + + public static class UnevaluatedItems extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + private static @Nullable UnevaluatedItems instance = null; + + protected UnevaluatedItems() { + super(new JsonSchemaInfo() + .multipleOf(new BigDecimal("5")) + ); + } + + public static UnevaluatedItems getInstance() { + if (instance == null) { + instance = new UnevaluatedItems(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } + + public static class UnevaluateditemsDependsOnMultipleNestedContains1 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + /* + NOTE: This class is auto generated by OpenAPI JSON Schema Generator. + Ref: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator + + Do not edit the class manually. + */ + private static @Nullable UnevaluateditemsDependsOnMultipleNestedContains1 instance = null; + + protected UnevaluateditemsDependsOnMultipleNestedContains1() { + super(new JsonSchemaInfo() + .allOf(List.of( + Schema0.class, + Schema1.class + )) + .unevaluatedItems(UnevaluatedItems.class) + ); + } + + public static UnevaluateditemsDependsOnMultipleNestedContains1 getInstance() { + if (instance == null) { + instance = new UnevaluateditemsDependsOnMultipleNestedContains1(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithItems.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithItems.java index 9edc0e7d035..44fb0757dbb 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithItems.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithItems.java @@ -106,6 +106,7 @@ protected UnevaluateditemsWithItems1() { super(new JsonSchemaInfo() .type(Set.of(List.class)) .items(Items.class) + .unevaluatedItems(UnevaluatedItems.class) ); } diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElements.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElements.java new file mode 100644 index 00000000000..4f696e69c61 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElements.java @@ -0,0 +1,250 @@ +package org.openapijsonschematools.client.components.schemas; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.InvalidAdditionalPropertyException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.exceptions.UnsetPropertyException; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.schemas.NullJsonSchema; +import org.openapijsonschematools.client.schemas.UnsetAddPropsSetter; +import org.openapijsonschematools.client.schemas.validation.BooleanSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.FrozenList; +import org.openapijsonschematools.client.schemas.validation.FrozenMap; +import org.openapijsonschematools.client.schemas.validation.JsonSchema; +import org.openapijsonschematools.client.schemas.validation.JsonSchemaInfo; +import org.openapijsonschematools.client.schemas.validation.ListSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.MapSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NullSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.NumberSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.PathToSchemasMap; +import org.openapijsonschematools.client.schemas.validation.StringSchemaValidator; +import org.openapijsonschematools.client.schemas.validation.ValidationMetadata; + +public class UnevaluateditemsWithNullInstanceElements { + // nest classes so all schemas and input/output classes can be public + + + public static class UnevaluatedItems extends NullJsonSchema { + private static @Nullable UnevaluatedItems instance = null; + public static UnevaluatedItems getInstance() { + if (instance == null) { + instance = new UnevaluatedItems(); + } + return instance; + } + } + + + public static class UnevaluateditemsWithNullInstanceElements1 extends JsonSchema implements NullSchemaValidator, BooleanSchemaValidator, NumberSchemaValidator, StringSchemaValidator, ListSchemaValidator>, MapSchemaValidator> { + /* + NOTE: This class is auto generated by OpenAPI JSON Schema Generator. + Ref: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator + + Do not edit the class manually. + */ + private static @Nullable UnevaluateditemsWithNullInstanceElements1 instance = null; + + protected UnevaluateditemsWithNullInstanceElements1() { + super(new JsonSchemaInfo() + .unevaluatedItems(UnevaluatedItems.class) + ); + } + + public static UnevaluateditemsWithNullInstanceElements1 getInstance() { + if (instance == null) { + instance = new UnevaluateditemsWithNullInstanceElements1(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public boolean validate(boolean arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + boolean castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public Number validate(Number arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Number castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public int validate(int arg, SchemaConfiguration configuration) { + return (int) validate((Number) arg, configuration); + } + + public long validate(long arg, SchemaConfiguration configuration) { + return (long) validate((Number) arg, configuration); + } + + public float validate(float arg, SchemaConfiguration configuration) { + return (float) validate((Number) arg, configuration); + } + + public double validate(double arg, SchemaConfiguration configuration) { + return (double) validate((Number) arg, configuration); + } + + @Override + public String validate(String arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + String castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + public String validate(LocalDate arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(ZonedDateTime arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + public String validate(UUID arg, SchemaConfiguration configuration) throws ValidationException { + return validate(arg.toString(), configuration); + } + + @Override + public FrozenList<@Nullable Object> getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List<@Nullable Object> items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + items.add(itemInstance); + i += 1; + } + FrozenList<@Nullable Object> newInstanceItems = new FrozenList<>(items); + return newInstanceItems; + } + + public FrozenList<@Nullable Object> validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public FrozenMap<@Nullable Object> getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + for(Map.Entry entry: arg.entrySet()) { + @Nullable Object entryKey = entry.getKey(); + if (!(entryKey instanceof String)) { + throw new InvalidTypeException("Invalid non-string key value"); + } + String propertyName = (String) entryKey; + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Object value = entry.getValue(); + LinkedHashMap schemas = pathToSchemas.get(propertyPathToItem); + if (schemas == null) { + throw new InvalidTypeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, propertyInstance); + } + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); + return castProperties; + } + + public FrozenMap<@Nullable Object> validate(Map arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0]"); + Map castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, validatedPathToSchemas, new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return validate(boolArg, configuration); + } else if (arg instanceof Number) { + return validate((Number) arg, configuration); + } else if (arg instanceof String) { + return validate((String) arg, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } else if (arg instanceof Map) { + return validate((Map) arg, configuration); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) throws InvalidTypeException { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + boolean boolArg = (Boolean) arg; + return getNewInstance(boolArg, pathToItem, pathToSchemas); + } else if (arg instanceof Number) { + return getNewInstance((Number) arg, pathToItem, pathToSchemas); + } else if (arg instanceof String) { + return getNewInstance((String) arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } else if (arg instanceof Map) { + return getNewInstance((Map) arg, pathToItem, pathToSchemas); + } + throw new InvalidTypeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java index 89ac9daedff..f4c6b5a7efb 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java @@ -57,7 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; - public final @Nullable Class unevaluatedItems = null; + public final @Nullable Class unevaluatedItems; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -228,8 +228,7 @@ private List getContainsPathToSchemas( } JsonSchema containsSchema = JsonSchemaFactory.getInstance(contains); @Nullable List containsPathToSchemas = new ArrayList<>(); - int i = 0; - for(Object itemValue: listArg) { + for(int i = 0; i < listArg.size(); i++) { PathToSchemasMap thesePathToSchemas = new PathToSchemasMap(); List itemPathToItem = new ArrayList<>(validationMetadata.pathToItem()); itemPathToItem.add(i); @@ -242,13 +241,12 @@ private List getContainsPathToSchemas( if (itemValidationMetadata.validationRanEarlier(containsSchema)) { // todo add_deeper_validated_schemas containsPathToSchemas.add(thesePathToSchemas); - i += 1; continue; } try { PathToSchemasMap otherPathToSchemas = JsonSchema.validate( - containsSchema, itemValue, itemValidationMetadata); + containsSchema, listArg.get(i), itemValidationMetadata); containsPathToSchemas.add(otherPathToSchemas); } catch (ValidationException ignored) {} } diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java index 336ea7b7025..cfb88550525 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java @@ -39,7 +39,7 @@ public class UnevaluatedItemsValidator implements KeywordValidator { data.validationMetadata().validatedPathToSchemas(), data.validationMetadata().seenClasses() ); - if (itemValidationMetadata.validationRanEarlier(itemsSchema)) { + if (itemValidationMetadata.validationRanEarlier(unevaluatedItemsSchema)) { // todo add_deeper_validated_schemas continue; } diff --git a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java index 951ba3f9f0e..d5c4f5de75a 100644 --- a/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java +++ b/samples/client/3_1_0_unit_test/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java @@ -10,7 +10,7 @@ public record ValidationData( ValidationMetadata validationMetadata, @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, - @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap ifPathToSchemas, @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( diff --git a/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchemaTest.java b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchemaTest.java new file mode 100644 index 00000000000..4a0003042a0 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsAsSchemaTest.java @@ -0,0 +1,59 @@ +package org.openapijsonschematools.client.components.schemas; + +import org.junit.Assert; +import org.junit.Test; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.schemas.validation.MapUtils; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.AbstractMap; + +public class UnevaluateditemsAsSchemaTest { + static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.onlyFormat()); + + @Test + public void testWithValidUnevaluatedItemsPasses() { + // with valid unevaluated items + final var schema = UnevaluateditemsAsSchema.UnevaluateditemsAsSchema1.getInstance(); + schema.validate( + Arrays.asList( + "foo" + ), + configuration + ); + } + + @Test + public void testWithInvalidUnevaluatedItemsFails() { + // with invalid unevaluated items + final var schema = UnevaluateditemsAsSchema.UnevaluateditemsAsSchema1.getInstance(); + try { + schema.validate( + Arrays.asList( + 42 + ), + configuration + ); + throw new RuntimeException("A different exception must be thrown"); + } catch (ValidationException | InvalidTypeException ignored) { + ; + } + } + + @Test + public void testWithNoUnevaluatedItemsPasses() { + // with no unevaluated items + final var schema = UnevaluateditemsAsSchema.UnevaluateditemsAsSchema1.getInstance(); + schema.validate( + Arrays.asList( + ), + configuration + ); + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContainsTest.java b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContainsTest.java new file mode 100644 index 00000000000..9f4d7292bfc --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsDependsOnMultipleNestedContainsTest.java @@ -0,0 +1,56 @@ +package org.openapijsonschematools.client.components.schemas; + +import org.junit.Assert; +import org.junit.Test; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.schemas.validation.MapUtils; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.AbstractMap; + +public class UnevaluateditemsDependsOnMultipleNestedContainsTest { + static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.onlyFormat()); + + @Test + public void test7NotEvaluatedFailsUnevaluateditemsFails() { + // 7 not evaluated, fails unevaluatedItems + final var schema = UnevaluateditemsDependsOnMultipleNestedContains.UnevaluateditemsDependsOnMultipleNestedContains1.getInstance(); + try { + schema.validate( + Arrays.asList( + 2, + 3, + 4, + 7, + 8 + ), + configuration + ); + throw new RuntimeException("A different exception must be thrown"); + } catch (ValidationException | InvalidTypeException ignored) { + ; + } + } + + @Test + public void test5NotEvaluatedPassesUnevaluateditemsPasses() { + // 5 not evaluated, passes unevaluatedItems + final var schema = UnevaluateditemsDependsOnMultipleNestedContains.UnevaluateditemsDependsOnMultipleNestedContains1.getInstance(); + schema.validate( + Arrays.asList( + 2, + 3, + 4, + 5, + 6 + ), + configuration + ); + } +} diff --git a/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElementsTest.java b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElementsTest.java new file mode 100644 index 00000000000..2d0193e9f96 --- /dev/null +++ b/samples/client/3_1_0_unit_test/java/src/test/java/org/openapijsonschematools/client/components/schemas/UnevaluateditemsWithNullInstanceElementsTest.java @@ -0,0 +1,31 @@ +package org.openapijsonschematools.client.components.schemas; + +import org.junit.Assert; +import org.junit.Test; +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.exceptions.InvalidTypeException; +import org.openapijsonschematools.client.schemas.validation.MapUtils; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.AbstractMap; + +public class UnevaluateditemsWithNullInstanceElementsTest { + static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.onlyFormat()); + + @Test + public void testAllowsNullElementsPasses() { + // allows null elements + final var schema = UnevaluateditemsWithNullInstanceElements.UnevaluateditemsWithNullInstanceElements1.getInstance(); + schema.validate( + Arrays.asList( + (Void) null + ), + configuration + ); + } +} diff --git a/samples/client/petstore/java/.openapi-generator/FILES b/samples/client/petstore/java/.openapi-generator/FILES index eb646ed7b37..cb34f77ff80 100644 --- a/samples/client/petstore/java/.openapi-generator/FILES +++ b/samples/client/petstore/java/.openapi-generator/FILES @@ -749,6 +749,7 @@ src/main/java/org/openapijsonschematools/client/schemas/validation/StringSchemaV src/main/java/org/openapijsonschematools/client/schemas/validation/StringValueMethod.java src/main/java/org/openapijsonschematools/client/schemas/validation/ThenValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/TypeValidator.java +src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UniqueItemsValidator.java src/main/java/org/openapijsonschematools/client/schemas/validation/UnsetAnyTypeJsonSchema.java src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java index 1925008547c..f4c6b5a7efb 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchema.java @@ -57,6 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; + public final @Nullable Class unevaluatedItems; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -208,6 +209,10 @@ protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { if (this.elseSchema != null) { keywordToValidator.put("else", new ElseValidator()); } + this.unevaluatedItems = jsonSchemaInfo.unevaluatedItems; + if (this.unevaluatedItems != null) { + keywordToValidator.put("unevaluatedItems", new UnevaluatedItemsValidator()); + } this.keywordToValidator = keywordToValidator; } @@ -223,8 +228,7 @@ private List getContainsPathToSchemas( } JsonSchema containsSchema = JsonSchemaFactory.getInstance(contains); @Nullable List containsPathToSchemas = new ArrayList<>(); - int i = 0; - for(Object itemValue: listArg) { + for(int i = 0; i < listArg.size(); i++) { PathToSchemasMap thesePathToSchemas = new PathToSchemasMap(); List itemPathToItem = new ArrayList<>(validationMetadata.pathToItem()); itemPathToItem.add(i); @@ -237,13 +241,12 @@ private List getContainsPathToSchemas( if (itemValidationMetadata.validationRanEarlier(containsSchema)) { // todo add_deeper_validated_schemas containsPathToSchemas.add(thesePathToSchemas); - i += 1; continue; } try { PathToSchemasMap otherPathToSchemas = JsonSchema.validate( - containsSchema, itemValue, itemValidationMetadata); + containsSchema, listArg.get(i), itemValidationMetadata); containsPathToSchemas.add(otherPathToSchemas); } catch (ValidationException ignored) {} } @@ -321,6 +324,7 @@ public static PathToSchemasMap validate( if (thisKeywordToValidator.containsKey("if")) { ifPathToSchemas = jsonSchema.getIfPathToSchemas(arg, validationMetadata); } + @Nullable PathToSchemasMap knownPathToSchemas = null; for (Map.Entry entry: thisKeywordToValidator.entrySet()) { String jsonKeyword = entry.getKey(); if (disabledKeywords.contains(jsonKeyword)) { @@ -329,6 +333,9 @@ public static PathToSchemasMap validate( continue; } } + if ("unevaluatedItems".equals(jsonKeyword)) { + knownPathToSchemas = pathToSchemas; + } KeywordValidator validator = entry.getValue(); ValidationData data = new ValidationData( jsonSchema, @@ -336,7 +343,8 @@ public static PathToSchemasMap validate( validationMetadata, containsPathToSchemas, patternPropertiesPathToSchemas, - ifPathToSchemas + ifPathToSchemas, + knownPathToSchemas ); @Nullable PathToSchemasMap otherPathToSchemas = validator.validate(data); if (otherPathToSchemas == null) { diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java index e423d151a5e..a9d63bf0c95 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/JsonSchemaInfo.java @@ -197,4 +197,9 @@ public JsonSchemaInfo elseSchema(Class elseSchema) { this.elseSchema = elseSchema; return this; } + public @Nullable Class unevaluatedItems = null; + public JsonSchemaInfo unevaluatedItems(Class unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + return this; + } } \ No newline at end of file diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java new file mode 100644 index 00000000000..cfb88550525 --- /dev/null +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/UnevaluatedItemsValidator.java @@ -0,0 +1,51 @@ +package org.openapijsonschematools.client.schemas.validation; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class UnevaluatedItemsValidator implements KeywordValidator { + @Override + public @Nullable PathToSchemasMap validate( + ValidationData data + ) { + var unevaluatedItems = data.schema().unevaluatedItems; + if (unevaluatedItems == null) { + return null; + } + var knownPathToSchemas = data.knownPathToSchemas(); + if (knownPathToSchemas == null) { + return null; + } + if (!(data.arg() instanceof List listArg)) { + return null; + } + if (listArg.isEmpty()) { + return null; + } + PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + int minIndex = data.schema().prefixItems != null ? data.schema().prefixItems.size() : 0; + JsonSchema unevaluatedItemsSchema = JsonSchemaFactory.getInstance(unevaluatedItems); + for(int i = minIndex; i < listArg.size(); i++) { + List itemPathToItem = new ArrayList<>(data.validationMetadata().pathToItem()); + itemPathToItem.add(i); + if (knownPathToSchemas.containsKey(itemPathToItem)) { + continue; + } + ValidationMetadata itemValidationMetadata = new ValidationMetadata( + itemPathToItem, + data.validationMetadata().configuration(), + data.validationMetadata().validatedPathToSchemas(), + data.validationMetadata().seenClasses() + ); + if (itemValidationMetadata.validationRanEarlier(unevaluatedItemsSchema)) { + // todo add_deeper_validated_schemas + continue; + } + PathToSchemasMap otherPathToSchemas = JsonSchema.validate(unevaluatedItemsSchema, listArg.get(i), itemValidationMetadata); + pathToSchemas.update(otherPathToSchemas); + } + return pathToSchemas; + } +} diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java index 55cb65fe9ef..d5c4f5de75a 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationData.java @@ -10,13 +10,14 @@ public record ValidationData( ValidationMetadata validationMetadata, @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, - @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap ifPathToSchemas, + @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( JsonSchema schema, @Nullable Object arg, ValidationMetadata validationMetadata ) { - this(schema, arg, validationMetadata, null, null, null); + this(schema, arg, validationMetadata, null, null, null, null); } } \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_anytypeOrMultitype.hbs b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_anytypeOrMultitype.hbs index 101428586c3..32793fe2bd5 100644 --- a/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_anytypeOrMultitype.hbs +++ b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_anytypeOrMultitype.hbs @@ -132,6 +132,9 @@ public static class {{jsonPathPiece.pascalCase}} extends JsonSchema implements { {{#if else_}} {{> src/main/java/packagename/components/schemas/SchemaClass/_else }} {{/if}} + {{#if unevaluatedItems}} + {{> src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems }} + {{/if}} ); } @@ -147,9 +150,6 @@ public static class {{jsonPathPiece.pascalCase}} extends JsonSchema implements { {{#if unevaluatedProperties}} {{!> components/schemas/schema_cls/_unevaluated_properties }} {{/if}} -{{#if unevaluatedItems}} - {{!> components/schemas/schema_cls/_unevaluated_items }} -{{/if}} {{#or mapOutputJsonPathPiece arrayOutputJsonPathPiece}} {{/or}} {{> src/main/java/packagename/components/schemas/SchemaClass/_validate_implementor }} diff --git a/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_list.hbs b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_list.hbs index 16a9af200e7..42a84bb251e 100644 --- a/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_list.hbs +++ b/src/main/resources/java/src/main/java/packagename/components/schemas/SchemaClass/_Schema_list.hbs @@ -65,6 +65,9 @@ public static class {{jsonPathPiece.pascalCase}} extends JsonSchema implements L {{#if else_}} {{> src/main/java/packagename/components/schemas/SchemaClass/_else }} {{/if}} + {{#if unevaluatedItems}} + {{> src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems }} + {{/if}} ); } @@ -74,9 +77,6 @@ public static class {{jsonPathPiece.pascalCase}} extends JsonSchema implements L } return instance; } - {{#if unevaluatedItems}} - {{!> components/schemas/schema_cls/_unevaluated_items }} - {{/if}} {{> src/main/java/packagename/components/schemas/SchemaClass/_validate_implementor }} {{> src/main/java/packagename/components/schemas/SchemaClass/_getNewInstanceObject_implementor }} } \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/packagename/components/schemas/docschema_fields_field.hbs b/src/main/resources/java/src/main/java/packagename/components/schemas/docschema_fields_field.hbs index 20bb1453085..4704f594064 100644 --- a/src/main/resources/java/src/main/java/packagename/components/schemas/docschema_fields_field.hbs +++ b/src/main/resources/java/src/main/java/packagename/components/schemas/docschema_fields_field.hbs @@ -109,3 +109,6 @@ {{#if constInfo}} | @Nullable Object | {{> src/main/java/packagename/components/schemas/SchemaClass/_const }} | {{/if}} +{{#if unevaluatedItems}} +| Class | {{> src/main/java/packagename/components/schemas/SchemaClass/_unevaluatedItems }} | +{{/if}} diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs index 48121e68747..56d15da0c0a 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/JsonSchema.hbs @@ -57,7 +57,7 @@ public abstract class JsonSchema { public final @Nullable Class ifSchema; public final @Nullable Class then; public final @Nullable Class elseSchema; - public final @Nullable Class unevaluatedItems = null; + public final @Nullable Class unevaluatedItems; private final LinkedHashMap keywordToValidator; protected JsonSchema(JsonSchemaInfo jsonSchemaInfo) { @@ -228,8 +228,7 @@ public abstract class JsonSchema { } JsonSchema containsSchema = JsonSchemaFactory.getInstance(contains); @Nullable List containsPathToSchemas = new ArrayList<>(); - int i = 0; - for(Object itemValue: listArg) { + for(int i = 0; i < listArg.size(); i++) { PathToSchemasMap thesePathToSchemas = new PathToSchemasMap(); List itemPathToItem = new ArrayList<>(validationMetadata.pathToItem()); itemPathToItem.add(i); @@ -242,13 +241,12 @@ public abstract class JsonSchema { if (itemValidationMetadata.validationRanEarlier(containsSchema)) { // todo add_deeper_validated_schemas containsPathToSchemas.add(thesePathToSchemas); - i += 1; continue; } try { PathToSchemasMap otherPathToSchemas = JsonSchema.validate( - containsSchema, itemValue, itemValidationMetadata); + containsSchema, listArg.get(i), itemValidationMetadata); containsPathToSchemas.add(otherPathToSchemas); } catch (ValidationException ignored) {} } diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs index 9caa79a6a09..b6743e8f3f9 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/UnevaluatedItemsValidator.hbs @@ -39,7 +39,7 @@ public class UnevaluatedItemsValidator implements KeywordValidator { data.validationMetadata().validatedPathToSchemas(), data.validationMetadata().seenClasses() ); - if (itemValidationMetadata.validationRanEarlier(itemsSchema)) { + if (itemValidationMetadata.validationRanEarlier(unevaluatedItemsSchema)) { // todo add_deeper_validated_schemas continue; } diff --git a/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs b/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs index 951ba3f9f0e..d5c4f5de75a 100644 --- a/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs +++ b/src/main/resources/java/src/main/java/packagename/schemas/validation/ValidationData.hbs @@ -10,7 +10,7 @@ public record ValidationData( ValidationMetadata validationMetadata, @Nullable List containsPathToSchemas, @Nullable PathToSchemasMap patternPropertiesPathToSchemas, - @Nullable PathToSchemasMap ifPathToSchemas + @Nullable PathToSchemasMap ifPathToSchemas, @Nullable PathToSchemasMap knownPathToSchemas ) { public ValidationData( diff --git a/src/test/resources/3_1/unit_test_spec/3_1_0_unit_test_spec_nopaths.yaml b/src/test/resources/3_1/unit_test_spec/3_1_0_unit_test_spec_nopaths.yaml index 162fa782a7b..869b24cbe92 100644 --- a/src/test/resources/3_1/unit_test_spec/3_1_0_unit_test_spec_nopaths.yaml +++ b/src/test/resources/3_1/unit_test_spec/3_1_0_unit_test_spec_nopaths.yaml @@ -687,12 +687,29 @@ components: - array - object - 'null' + UnevaluateditemsAsSchema: + $schema: https://json-schema.org/draft/2020-12/schema + unevaluatedItems: + type: string UnevaluateditemsWithItems: $schema: https://json-schema.org/draft/2020-12/schema items: type: number unevaluatedItems: type: string + UnevaluateditemsDependsOnMultipleNestedContains: + $schema: https://json-schema.org/draft/2020-12/schema + allOf: + - contains: + multipleOf: 2 + - contains: + multipleOf: 3 + unevaluatedItems: + multipleOf: 5 + UnevaluateditemsWithNullInstanceElements: + $schema: https://json-schema.org/draft/2020-12/schema + unevaluatedItems: + type: 'null' UnevaluatedpropertiesWithAdjacentAdditionalproperties: $schema: https://json-schema.org/draft/2020-12/schema type: object @@ -3924,6 +3941,24 @@ components: data: foo valid: false comment: null + UnevaluateditemsAsSchema: + WithNoUnevaluatedItems: + description: with no unevaluated items + data: [] + valid: true + comment: null + WithValidUnevaluatedItems: + description: with valid unevaluated items + data: + - foo + valid: true + comment: null + WithInvalidUnevaluatedItems: + description: with invalid unevaluated items + data: + - 42 + valid: false + comment: null UnevaluateditemsWithItems: ValidUnderItems: description: valid under items @@ -3942,6 +3977,34 @@ components: - baz valid: false comment: null + UnevaluateditemsDependsOnMultipleNestedContains: + 5NotEvaluatedPassesUnevaluateditems: + description: 5 not evaluated, passes unevaluatedItems + data: + - 2 + - 3 + - 4 + - 5 + - 6 + valid: true + comment: null + 7NotEvaluatedFailsUnevaluateditems: + description: 7 not evaluated, fails unevaluatedItems + data: + - 2 + - 3 + - 4 + - 7 + - 8 + valid: false + comment: null + UnevaluateditemsWithNullInstanceElements: + AllowsNullElements: + description: allows null elements + data: + - null + valid: true + comment: null UnevaluatedpropertiesWithAdjacentAdditionalproperties: WithNoAdditionalProperties: description: with no additional properties diff --git a/src/test/resources/3_1/unit_test_spec/spec_writer.py b/src/test/resources/3_1/unit_test_spec/spec_writer.py index 39d384192a6..4b159428590 100644 --- a/src/test/resources/3_1/unit_test_spec/spec_writer.py +++ b/src/test/resources/3_1/unit_test_spec/spec_writer.py @@ -700,9 +700,6 @@ def write_openapi_spec(): openapi.paths = {} openapi.tags = [] removed_cases = { - 'UnevaluateditemsDependsOnMultipleNestedContains', - 'UnevaluateditemsAsSchema', - 'UnevaluateditemsWithNullInstanceElements', 'UnevaluatedpropertiesNotAffectedByPropertynames', 'UnevaluatedpropertiesSchema' }