Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with hierarchy output report #947

Merged
merged 26 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
errors = new LinkedHashSet<>();
}
errors.add(message().instanceNode(node).property(pname)
.instanceLocation(instanceLocation.append(pname))
.instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(pname).build());
.failFast(executionContext.isFailFast()).arguments(pname).build());
} else {
if (additionalPropertiesSchema != null) {
ValidatorState state = executionContext.getValidatorState();
Expand Down
29 changes: 23 additions & 6 deletions src/main/java/com/networknt/schema/AnyOfValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
int numberOfValidSubSchemas = 0;
try {
// Save flag as nested schema evaluation shouldn't trigger fail fast
boolean failFast = executionContext.getExecutionConfig().isFailFast();
boolean failFast = executionContext.isFailFast();
try {
executionContext.getExecutionConfig().setFailFast(false);
executionContext.setFailFast(false);
for (JsonSchema schema : this.schemas) {
Set<ValidationMessage> errors = Collections.emptySet();
state.setMatchedNode(initialHasMatchedNode);
Expand Down Expand Up @@ -104,7 +104,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
}

if (errors.isEmpty() && (!this.validationContext.getConfig().isOpenAPI3StyleDiscriminators())
&& canShortCircuit()) {
&& canShortCircuit() && canShortCircuit(executionContext)) {
// Clear all errors.
allErrors.clear();
// return empty errors.
Expand All @@ -115,7 +115,7 @@ && canShortCircuit()) {
allErrors.addAll(errors);
allErrors.add(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast())
.failFast(executionContext.isFailFast())
.arguments(DISCRIMINATOR_REMARK).build());
} else {
// Clear all errors.
Expand All @@ -128,7 +128,7 @@ && canShortCircuit()) {
}
} finally {
// Restore flag
executionContext.getExecutionConfig().setFailFast(failFast);
executionContext.setFailFast(failFast);
}

// determine only those errors which are NOT of type "required" property missing
Expand Down Expand Up @@ -174,7 +174,24 @@ public Set<ValidationMessage> walk(ExecutionContext executionContext, JsonNode n
}
return new LinkedHashSet<>();
}


/**
* If annotation collection is enabled cannot short circuit.
*
* @see <a href=
* "https://github.com/json-schema-org/json-schema-spec/blob/f8967bcbc6cee27753046f63024b55336a9b1b54/jsonschema-core.md?plain=1#L1717-L1720">anyOf</a>
* @param executionContext the execution context
* @return true if can short circuit
*/
protected boolean canShortCircuit(ExecutionContext executionContext) {
return !executionContext.getExecutionConfig().isAnnotationCollectionEnabled();
}

/**
* If annotations are require for evaluation cannot short circuit.
*
* @return true if can short circuit
*/
protected boolean canShortCircuit() {
if (this.canShortCircuit == null) {
boolean canShortCircuit = true;
Expand Down
13 changes: 1 addition & 12 deletions src/main/java/com/networknt/schema/BaseJsonValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@

public abstract class BaseJsonValidator extends ValidationMessageHandler implements JsonValidator {
protected final boolean suppressSubSchemaRetrieval;
protected final ApplyDefaultsStrategy applyDefaultsStrategy;
private final PathType pathType;

protected final JsonNode schemaNode;

Expand All @@ -59,13 +57,6 @@ public BaseJsonValidator(SchemaLocation schemaLocation, JsonNodePath evaluationP
this.validationContext = validationContext;
this.schemaNode = schemaNode;
this.suppressSubSchemaRetrieval = suppressSubSchemaRetrieval;
this.applyDefaultsStrategy = (validationContext != null && validationContext.getConfig() != null
&& validationContext.getConfig().getApplyDefaultsStrategy() != null)
? validationContext.getConfig().getApplyDefaultsStrategy()
: ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY;
this.pathType = (validationContext != null && validationContext.getConfig() != null
&& validationContext.getConfig().getPathType() != null) ? validationContext.getConfig().getPathType()
: PathType.DEFAULT;
}

/**
Expand All @@ -76,8 +67,6 @@ public BaseJsonValidator(SchemaLocation schemaLocation, JsonNodePath evaluationP
protected BaseJsonValidator(BaseJsonValidator copy) {
super(copy);
this.suppressSubSchemaRetrieval = copy.suppressSubSchemaRetrieval;
this.applyDefaultsStrategy = copy.applyDefaultsStrategy;
this.pathType = copy.pathType;
this.schemaNode = copy.schemaNode;
this.validationContext = copy.validationContext;
}
Expand Down Expand Up @@ -307,7 +296,7 @@ protected void preloadJsonSchemas(final Collection<JsonSchema> schemas) {
* @return The path.
*/
protected JsonNodePath atRoot() {
return new JsonNodePath(this.pathType);
return new JsonNodePath(this.validationContext.getConfig().getPathType());
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/networknt/schema/ConstValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (schemaNode.decimalValue().compareTo(node.decimalValue()) != 0) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(schemaNode.asText())
.failFast(executionContext.isFailFast()).arguments(schemaNode.asText())
.build());
}
} else if (!schemaNode.equals(node)) {
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/networknt/schema/ContainsValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
List<Integer> indexes = new ArrayList<>(); // for the annotation
if (null != this.schema && node.isArray()) {
// Save flag as nested schema evaluation shouldn't trigger fail fast
boolean failFast = executionContext.getExecutionConfig().isFailFast();
boolean failFast = executionContext.isFailFast();
try {
executionContext.getExecutionConfig().setFailFast(false);
executionContext.setFailFast(false);
for (JsonNode n : node) {
JsonNodePath path = instanceLocation.append(i);
if (this.schema.validate(executionContext, n, rootNode, path).isEmpty()) {
Expand All @@ -93,7 +93,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
}
} finally {
// Restore flag
executionContext.getExecutionConfig().setFailFast(failFast);
executionContext.setFailFast(failFast);
}
int m = 1; // default to 1 if "min" not specified
if (this.min != null) {
Expand All @@ -102,13 +102,13 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (actual < m) {
results = boundsViolated(isMinV201909 ? ValidatorTypeCode.MIN_CONTAINS : ValidatorTypeCode.CONTAINS,
executionContext.getExecutionConfig().getLocale(),
executionContext.getExecutionConfig().isFailFast(), node, instanceLocation, m);
executionContext.isFailFast(), node, instanceLocation, m);
}

if (this.max != null && actual > this.max) {
results = boundsViolated(isMinV201909 ? ValidatorTypeCode.MAX_CONTAINS : ValidatorTypeCode.CONTAINS,
executionContext.getExecutionConfig().getLocale(),
executionContext.getExecutionConfig().isFailFast(), node, instanceLocation, this.max);
executionContext.isFailFast(), node, instanceLocation, this.max);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (!matches(node.asText())) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(this.contentEncoding)
.failFast(executionContext.isFailFast()).arguments(this.contentEncoding)
.build());
}
return Collections.emptySet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (!matches(node.asText())) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(this.contentMediaType)
.failFast(executionContext.isFailFast()).arguments(this.contentMediaType)
.build());
}
return Collections.emptySet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (node.get(field) == null) {
errors.add(message().instanceNode(node).property(pname).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast())
.failFast(executionContext.isFailFast())
.arguments(propertyDeps.toString()).build());
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/networknt/schema/DependentRequired.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (node.get(field) == null) {
errors.add(message().instanceNode(node).property(pname).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(field, pname)
.failFast(executionContext.isFailFast()).arguments(field, pname)
.build());
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/networknt/schema/EnumValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (!nodes.contains(node) && !( this.validationContext.getConfig().isTypeLoose() && isTypeLooseContainsInEnum(node))) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).arguments(error).build());
.failFast(executionContext.isFailFast()).arguments(error).build());
}

return Collections.emptySet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (typedMaximum.crossesThreshold(node)) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast())
.failFast(executionContext.isFailFast())
.arguments(typedMaximum.thresholdValue()).build());
}
return Collections.emptySet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
if (typedMinimum.crossesThreshold(node)) {
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast())
.failFast(executionContext.isFailFast())
.arguments(typedMinimum.thresholdValue()).build());
}
return Collections.emptySet();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/networknt/schema/ExecutionConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class ExecutionConfig {
* Determine if the validation execution can fail fast.
*/
private boolean failFast = false;

/**
* Gets the locale to use for formatting messages.
*
Expand Down
34 changes: 33 additions & 1 deletion src/main/java/com/networknt/schema/ExecutionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ public class ExecutionContext {
private Stack<DiscriminatorContext> discriminatorContexts = new Stack<>();
private JsonNodeAnnotations annotations = new JsonNodeAnnotations();
private JsonNodeResults results = new JsonNodeResults();

/**
* This is used during the execution to determine if the validator should fail fast.
* <p>
* This valid is determined by the previous validator.
*/
private Boolean failFast = null;

/**
* Creates an execution context.
Expand Down Expand Up @@ -111,7 +118,32 @@ public JsonNodeAnnotations getAnnotations() {
public JsonNodeResults getResults() {
return results;
}


/**
* Determines if the validator should immediately throw a fail fast exception if
* an error has occurred.
* <p>
* This defaults to the execution config fail fast at the start of the execution.
*
* @return true if fail fast
*/
public boolean isFailFast() {
if (this.failFast == null) {
this.failFast = getExecutionConfig().isFailFast();
}
return failFast;
}

/**
* Sets if the validator should immediately throw a fail fast exception if an
* error has occurred.
*
* @param failFast true to fail fast
*/
public void setFailFast(boolean failFast) {
this.failFast = failFast;
}

/**
* Gets the validator state.
*
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/networknt/schema/FalseValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@
public class FalseValidator extends BaseJsonValidator implements JsonValidator {
private static final Logger logger = LoggerFactory.getLogger(FalseValidator.class);

private final String reason;

public FalseValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, final JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
super(schemaLocation, evaluationPath, schemaNode, parentSchema, ValidatorTypeCode.FALSE, validationContext);
this.reason = this.evaluationPath.getParent().getName(-1);
}

public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
debug(logger, node, rootNode, instanceLocation);
// For the false validator, it is always not valid
return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast()).build());
.failFast(executionContext.isFailFast()).arguments(reason).build());
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/networknt/schema/FormatValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
// leading and trailing spaces
errors.add(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.getExecutionConfig().isFailFast())
.failFast(executionContext.isFailFast())
.arguments(format.getName(), format.getErrorMessageDescription()).build());
}
} else if(node.textValue().contains("%")) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/networknt/schema/IfValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNo
boolean ifConditionPassed = false;

// Save flag as nested schema evaluation shouldn't trigger fail fast
boolean failFast = executionContext.getExecutionConfig().isFailFast();
boolean failFast = executionContext.isFailFast();
try {
executionContext.getExecutionConfig().setFailFast(false);
executionContext.setFailFast(false);
ifConditionPassed = this.ifSchema.validate(executionContext, node, rootNode, instanceLocation).isEmpty();
} finally {
// Restore flag
executionContext.getExecutionConfig().setFailFast(failFast);
executionContext.setFailFast(failFast);
}

if (ifConditionPassed && this.thenSchema != null) {
Expand Down
Loading
Loading