Skip to content

Commit

Permalink
Java, refactoring to simplify schema validate (#370)
Browse files Browse the repository at this point in the history
* Updates many validators to accept a single input

* Updates remaining keywordValidators

* Fixes enum validator

* Adds vars to fix nullness checks

* Fixes TypeValidatorTest

* Fixes AdditionalPropertiesValidatorTest

* Fixes PropertiesValidatorTest

* Updates ItemsValidatorTest

* Updates FormatValidatorTest

* Extracts getContainsPathToSchemas

* Extracts getPatternPropertiesPathToSchemas

* Extracts getIfPathToSchemas

* Updates 5 validators

* Fixes AdditionalPropertiesValidatorTest

* Updates ItemsValidatorTest

* Updates RequiredValidatorTest

* Updates TypeValidatorTest

* Updates PropertiesValidatorTest

* Adds final modifers to schema data

* Adds functionalinterface annotation

* Samples regen
  • Loading branch information
spacether committed Jan 20, 2024
1 parent 2f3ff01 commit 73aa768
Show file tree
Hide file tree
Showing 176 changed files with 3,428 additions and 4,936 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ src/main/java/org/openapijsonschematools/client/schemas/validation/StringValueMe
src/main/java/org/openapijsonschematools/client/schemas/validation/TypeValidator.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
src/main/java/org/openapijsonschematools/client/schemas/validation/ValidationMetadata.java
src/main/java/org/openapijsonschematools/client/servers/Server0.java
src/main/java/org/openapijsonschematools/client/servers/ServerWithVariables.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,15 @@
import java.util.Set;

public class AdditionalPropertiesValidator implements KeywordValidator {
public final Class<? extends JsonSchema> additionalProperties;

public AdditionalPropertiesValidator(Class<? extends JsonSchema> additionalProperties) {
this.additionalProperties = additionalProperties;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
if (!(arg instanceof Map<?, ?> mapArg)) {
if (!(data.arg() instanceof Map<?, ?> mapArg)) {
return null;
}
var additionalProperties = data.schema().additionalProperties;
if (additionalProperties == null) {
return null;
}
Set<String> presentAdditionalProperties = new LinkedHashSet<>();
Expand All @@ -32,22 +25,23 @@ public AdditionalPropertiesValidator(Class<? extends JsonSchema> additionalPrope
presentAdditionalProperties.add((String) key);
}
}
if (schema.properties != null) {
presentAdditionalProperties.removeAll(schema.properties.keySet());
var properties = data.schema().properties;
if (properties != null) {
presentAdditionalProperties.removeAll(properties.keySet());
}
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
for(String addPropName: presentAdditionalProperties) {
@Nullable Object propValue = mapArg.get(addPropName);
List<Object> propPathToItem = new ArrayList<>(validationMetadata.pathToItem());
List<Object> propPathToItem = new ArrayList<>(data.validationMetadata().pathToItem());
propPathToItem.add(addPropName);
if (patternPropertiesPathToSchemas != null && patternPropertiesPathToSchemas.containsKey(propPathToItem)) {
if (data.patternPropertiesPathToSchemas() != null && data.patternPropertiesPathToSchemas().containsKey(propPathToItem)) {
continue;
}
ValidationMetadata propValidationMetadata = new ValidationMetadata(
propPathToItem,
validationMetadata.configuration(),
validationMetadata.validatedPathToSchemas(),
validationMetadata.seenClasses()
data.validationMetadata().configuration(),
data.validationMetadata().validatedPathToSchemas(),
data.validationMetadata().seenClasses()
);
JsonSchema addPropsSchema = JsonSchemaFactory.getInstance(additionalProperties);
if (propValidationMetadata.validationRanEarlier(addPropsSchema)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
package org.openapijsonschematools.client.schemas.validation;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.List;

public class AllOfValidator implements KeywordValidator {
public final List<Class<? extends JsonSchema>> allOf;

public AllOfValidator(List<Class<? extends JsonSchema>> allOf) {
this.allOf = allOf;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
var allOf = data.schema().allOf;
if (allOf == null) {
return null;
}
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
for(Class<? extends JsonSchema> allOfClass: allOf) {
JsonSchema allOfSchema = JsonSchemaFactory.getInstance(allOfClass);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(allOfSchema, arg, validationMetadata);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(allOfSchema, data.arg(), data.validationMetadata());
pathToSchemas.update(otherPathToSchemas);
}
return pathToSchemas;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,18 @@
import java.util.List;

public class AnyOfValidator implements KeywordValidator {
public final List<Class<? extends JsonSchema>> anyOf;

public AnyOfValidator(List<Class<? extends JsonSchema>> anyOf) {
this.anyOf = anyOf;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
var anyOf = data.schema().anyOf;
if (anyOf == null) {
return null;
}
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
List<Class<? extends JsonSchema>> validatedAnyOfClasses = new ArrayList<>();
for(Class<? extends JsonSchema> anyOfClass: anyOf) {
if (anyOfClass == schema.getClass()) {
if (anyOfClass == data.schema().getClass()) {
/*
optimistically assume that schema will pass validation
do not invoke _validate on it because that is recursive
Expand All @@ -35,15 +28,15 @@ public AnyOfValidator(List<Class<? extends JsonSchema>> anyOf) {
}
try {
JsonSchema anyOfSchema = JsonSchemaFactory.getInstance(anyOfClass);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(anyOfSchema, arg, validationMetadata);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(anyOfSchema, data.arg(), data.validationMetadata());
validatedAnyOfClasses.add(anyOfClass);
pathToSchemas.update(otherPathToSchemas);
} catch (ValidationException e) {
// silence exceptions because the code needs to accumulate anyof_classes
}
}
if (validatedAnyOfClasses.isEmpty()) {
throw new ValidationException("Invalid inputs given to generate an instance of "+schema.getClass()+". None "+
throw new ValidationException("Invalid inputs given to generate an instance of "+data.schema().getClass()+". None "+
"of the anyOf schemas matched the input data."
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,30 @@
import org.checkerframework.checker.nullness.qual.Nullable;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

public class ConstValidator extends BigDecimalValidator implements KeywordValidator {
public final @Nullable Object constValue;

public ConstValidator(@Nullable Object constValue) {
this.constValue = constValue;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
if (arg instanceof Number) {
BigDecimal castArg = getBigDecimal((Number) arg);
if (!data.schema().constValueSet) {
return null;
}
var constValue = data.schema().constValue;
if (data.arg() instanceof Number numberArg) {
BigDecimal castArg = getBigDecimal(numberArg);
if (Objects.equals(castArg, constValue)) {
return null;
}
if (constValue instanceof BigDecimal && ((BigDecimal) constValue).compareTo(castArg) == 0) {
return null;
}
} else {
if (Objects.equals(arg, constValue)) {
if (Objects.equals(data.arg(), constValue)) {
return null;
}
}
throw new ValidationException("Invalid value "+arg+" was not equal to const "+constValue);
throw new ValidationException("Invalid value "+data.arg()+" was not equal to const "+constValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,21 @@
import org.checkerframework.checker.nullness.qual.Nullable;
import org.openapijsonschematools.client.exceptions.ValidationException;

import java.util.ArrayList;
import java.util.List;

public class ContainsValidator implements KeywordValidator {
public final Class<? extends JsonSchema> contains;

public ContainsValidator(Class<? extends JsonSchema> contains) {
this.contains = contains;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
if (!(arg instanceof List)) {
if (!(data.arg() instanceof List)) {
return null;
}
var containsPathToSchemas = data.containsPathToSchemas();
if (containsPathToSchemas == null || containsPathToSchemas.isEmpty()) {
throw new ValidationException(
"Validation failed for contains keyword in class="+schema.getClass()
+ " at pathToItem="+validationMetadata.pathToItem()+". No "
"Validation failed for contains keyword in class="+data.schema().getClass()
+ " at pathToItem="+data.validationMetadata().pathToItem()+". No "
+ "items validated to the contains schema."
);
}
Expand All @@ -38,42 +27,4 @@ public ContainsValidator(Class<? extends JsonSchema> contains) {
}
return pathToSchemas;
}

public List<PathToSchemasMap> getContainsPathToSchemas(
@Nullable Object arg,
ValidationMetadata validationMetadata
) {
if (!(arg instanceof List)) {
return new ArrayList<>();
}
@Nullable List<PathToSchemasMap> containsPathToSchemas = new ArrayList<>();
int i = 0;
for(Object itemValue: (List<?>) arg) {
PathToSchemasMap thesePathToSchemas = new PathToSchemasMap();
List<Object> itemPathToItem = new ArrayList<>(validationMetadata.pathToItem());
itemPathToItem.add(i);
ValidationMetadata itemValidationMetadata = new ValidationMetadata(
itemPathToItem,
validationMetadata.configuration(),
validationMetadata.validatedPathToSchemas(),
validationMetadata.seenClasses()
);
JsonSchema containsSchema = JsonSchemaFactory.getInstance(contains);
if (itemValidationMetadata.validationRanEarlier(containsSchema)) {
// todo add_deeper_validated_schemas
containsPathToSchemas.add(thesePathToSchemas);
i += 1;
continue;
}

try {
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(
containsSchema, itemValue, itemValidationMetadata);
containsPathToSchemas.add(otherPathToSchemas);
} catch (ValidationException ignored) {
;
}
}
return containsPathToSchemas;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,27 @@
import org.openapijsonschematools.client.exceptions.ValidationException;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class DependentRequiredValidator implements KeywordValidator {
public final Map<String, Set<String>> dependentRequired;

public DependentRequiredValidator(Map<String, Set<String>> dependentRequired) {
this.dependentRequired = dependentRequired;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
if (!(arg instanceof Map)) {
if (!(data.arg() instanceof Map<?, ?> mapArg)) {
return null;
}
var dependentRequired = data.schema().dependentRequired;
if (dependentRequired == null) {
return null;
}
for (Map.Entry<String, Set<String>> entry: dependentRequired.entrySet()) {
if (!((Map<?, ?>) arg).containsKey(entry.getKey())) {
if (!mapArg.containsKey(entry.getKey())) {
continue;
}
Set<String> missingKeys = new HashSet<>(entry.getValue());
for (Object objKey: ((Map<?, ?>) arg).keySet()) {
for (Object objKey: mapArg.keySet()) {
if (objKey instanceof String key) {
missingKeys.remove(key);
}
Expand All @@ -42,7 +34,7 @@ public DependentRequiredValidator(Map<String, Set<String>> dependentRequired) {
}
throw new ValidationException(
"Validation failed for dependentRequired because these_keys="+missingKeys+" are "+
"missing at pathToItem="+validationMetadata.pathToItem()+" in class "+schema.getClass()
"missing at pathToItem="+data.validationMetadata().pathToItem()+" in class "+data.schema().getClass()
);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,20 @@

import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class DependentSchemasValidator implements KeywordValidator {
public final Map<String, Class<? extends JsonSchema>> dependentSchemas;

public DependentSchemasValidator(Map<String, Class<? extends JsonSchema>> dependentSchemas) {
this.dependentSchemas = dependentSchemas;
}

@Override
public @Nullable PathToSchemasMap validate(
JsonSchema schema,
@Nullable Object arg,
ValidationMetadata validationMetadata,
@Nullable List<PathToSchemasMap> containsPathToSchemas,
@Nullable PathToSchemasMap patternPropertiesPathToSchemas,
@Nullable PathToSchemasMap ifPathToSchemas
ValidationData data
) {
if (!(arg instanceof Map<?, ?> mapArg)) {
if (!(data.arg() instanceof Map<?, ?> mapArg)) {
return null;
}
var dependentSchemas = data.schema().dependentSchemas;
if (dependentSchemas == null) {
return null;
}
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
Expand All @@ -41,10 +32,9 @@ public DependentSchemasValidator(Map<String, Class<? extends JsonSchema>> depend
}
Class<? extends JsonSchema> dependentSchemaClass = entry.getValue();
JsonSchema dependentSchema = JsonSchemaFactory.getInstance(dependentSchemaClass);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(dependentSchema, arg, validationMetadata);
PathToSchemasMap otherPathToSchemas = JsonSchema.validate(dependentSchema, mapArg, data.validationMetadata());
pathToSchemas.update(otherPathToSchemas);
}
return pathToSchemas;
}
}

Loading

0 comments on commit 73aa768

Please sign in to comment.