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

Add Schema validation path traceability #256

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.everit.json</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>0.0.0-develop</version>
<version>1.10.1-afranzi-SNAPSHOT</version>
<packaging>bundle</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/everit/json/schema/ArraySchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ void describePropertiesTo(final JSONPrinter writer) {
}
}

@Override void accept(Visitor visitor) {
visitor.visitArraySchema(this);
@Override void accept(Visitor visitor, List<String> path) {
visitor.visitArraySchema(this, path);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static java.lang.String.format;
import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand All @@ -29,12 +28,12 @@ public ArraySchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
this.owner = requireNonNull(owner, "owner cannot be null");
}

@Override void visitArraySchema(ArraySchema arraySchema) {
@Override void visitArraySchema(ArraySchema arraySchema, List<String> path) {
if (owner.passesTypeCheck(JSONArray.class, arraySchema.requiresArray(), arraySchema.isNullable())) {
this.arraySubject = (JSONArray) subject;
this.subjectLength = arraySubject.length();
this.arraySchema = arraySchema;
super.visitArraySchema(arraySchema);
super.visitArraySchema(arraySchema, path);
}
}

Expand Down Expand Up @@ -67,19 +66,19 @@ public ArraySchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
}
}

@Override void visitAllItemSchema(Schema allItemSchema) {
@Override void visitAllItemSchema(Schema allItemSchema, List<String> path) {
if (allItemSchema != null) {
validateItemsAgainstSchema(IntStream.range(0, subjectLength), allItemSchema);
validateItemsAgainstSchema(IntStream.range(0, subjectLength), allItemSchema, path);
}
}

@Override void visitItemSchema(int index, Schema itemSchema) {
@Override void visitItemSchema(int index, Schema itemSchema, List<String> path) {
if (index >= subjectLength) {
return;
}
Object subject = arraySubject.get(index);
String idx = String.valueOf(index);
ifFails(itemSchema, subject)
ifFails(itemSchema, subject, path)
.map(exc -> exc.prepend(idx))
.ifPresent(owner::failure);
}
Expand All @@ -92,37 +91,37 @@ public ArraySchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
}
}

@Override void visitSchemaOfAdditionalItems(Schema schemaOfAdditionalItems) {
@Override void visitSchemaOfAdditionalItems(Schema schemaOfAdditionalItems, List<String> path) {
if (schemaOfAdditionalItems == null) {
return;
}
int validationFrom = Math.min(subjectLength, arraySchema.getItemSchemas().size());
validateItemsAgainstSchema(IntStream.range(validationFrom, subjectLength), schemaOfAdditionalItems);
validateItemsAgainstSchema(IntStream.range(validationFrom, subjectLength), schemaOfAdditionalItems, path);
}

private void validateItemsAgainstSchema(IntStream indices, Schema schema) {
validateItemsAgainstSchema(indices, i -> schema);
private void validateItemsAgainstSchema(IntStream indices, Schema schema, List<String> path) {
validateItemsAgainstSchema(indices, i -> schema, path);
}

private void validateItemsAgainstSchema(IntStream indices, IntFunction<Schema> schemaForIndex) {
private void validateItemsAgainstSchema(IntStream indices, IntFunction<Schema> schemaForIndex, List<String> path) {
for (int i : indices.toArray()) {
String copyOfI = String.valueOf(i); // i is not effectively final so we copy it
ifFails(schemaForIndex.apply(i), arraySubject.get(i))
ifFails(schemaForIndex.apply(i), arraySubject.get(i), appendPath(path, i))
.map(exc -> exc.prepend(copyOfI))
.ifPresent(owner::failure);
}
}

private Optional<ValidationException> ifFails(Schema schema, Object input) {
return Optional.ofNullable(owner.getFailureOfSchema(schema, input));
private Optional<ValidationException> ifFails(Schema schema, Object input, List<String> path) {
return Optional.ofNullable(owner.getFailureOfSchema(schema, input, path));
}

@Override void visitContainedItemSchema(Schema containedItemSchema) {
@Override void visitContainedItemSchema(Schema containedItemSchema, List<String> path) {
if (containedItemSchema == null) {
return;
}
for (int i = 0; i < arraySubject.length(); i++) {
Optional<ValidationException> exception = ifFails(containedItemSchema, arraySubject.get(i));
Optional<ValidationException> exception = ifFails(containedItemSchema, arraySubject.get(i), appendPath(path, i));
if (!exception.isPresent()) {
return;
}
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/org/everit/json/schema/BooleanSchema.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.everit.json.schema;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;


/**
* Boolean schema validator.
*/
Expand Down Expand Up @@ -48,7 +50,7 @@ public boolean equals(final Object o) {
}
}

@Override void accept(Visitor visitor) {
@Override void accept(Visitor visitor, List<String> path) {
visitor.visitBooleanSchema(this);
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/everit/json/schema/CombinedSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ public Collection<Schema> getSubschemas() {
return subschemas;
}

@Override void accept(Visitor visitor) {
visitor.visitCombinedSchema(this);
@Override void accept(Visitor visitor, List<String> path) {
visitor.visitCombinedSchema(this, path);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.everit.json.schema;

import java.util.Optional;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;

/**
Expand Down Expand Up @@ -66,8 +66,8 @@ public Optional<Schema> getElseSchema() {
}

@Override
void accept(Visitor visitor) {
visitor.visitConditionalSchema(this);
void accept(Visitor visitor, List<String> path) {
visitor.visitConditionalSchema(this, path);
}

@Override void describePropertiesTo(JSONPrinter writer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.everit.json.schema.event.ConditionalSchemaMismatchEvent;
import org.everit.json.schema.event.ConditionalSchemaValidationEvent;

import java.util.List;

class ConditionalSchemaValidatingVisitor extends Visitor {

private final Object subject;
Expand All @@ -26,19 +28,19 @@ class ConditionalSchemaValidatingVisitor extends Visitor {
}

@Override
void visitConditionalSchema(ConditionalSchema conditionalSchema) {
void visitConditionalSchema(ConditionalSchema conditionalSchema, List<String> path) {
this.conditionalSchema = conditionalSchema;
if (!conditionalSchema.getIfSchema().isPresent() ||
(!conditionalSchema.getThenSchema().isPresent() && !conditionalSchema.getElseSchema().isPresent())) {
return;
}
super.visitConditionalSchema(conditionalSchema);
super.visitConditionalSchema(conditionalSchema, path);
}

@Override
void visitIfSchema(Schema ifSchema) {
void visitIfSchema(Schema ifSchema, List<String> path) {
if (conditionalSchema.getIfSchema().isPresent()) {
ifSchemaException = owner.getFailureOfSchema(ifSchema, subject);
ifSchemaException = owner.getFailureOfSchema(ifSchema, subject, path);
if (ifSchemaException == null) {
owner.validationListener.ifSchemaMatch(createMatchEvent(IF));
} else {
Expand All @@ -48,9 +50,9 @@ void visitIfSchema(Schema ifSchema) {
}

@Override
void visitThenSchema(Schema thenSchema) {
void visitThenSchema(Schema thenSchema, List<String> path) {
if (ifSchemaException == null) {
ValidationException thenSchemaException = owner.getFailureOfSchema(thenSchema, subject);
ValidationException thenSchemaException = owner.getFailureOfSchema(thenSchema, subject, path);
if (thenSchemaException != null) {
ValidationException failure = new ValidationException(conditionalSchema,
new StringBuilder(new StringBuilder("#")),
Expand All @@ -68,9 +70,9 @@ void visitThenSchema(Schema thenSchema) {
}

@Override
void visitElseSchema(Schema elseSchema) {
void visitElseSchema(Schema elseSchema, List<String> path) {
if (ifSchemaException != null) {
ValidationException elseSchemaException = owner.getFailureOfSchema(elseSchema, subject);
ValidationException elseSchemaException = owner.getFailureOfSchema(elseSchema, subject, path);
if (elseSchemaException != null) {
ValidationException failure = new ValidationException(conditionalSchema,
new StringBuilder(new StringBuilder("#")),
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/everit/json/schema/ConstSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.everit.json.schema.EnumSchema.toJavaValue;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;

public class ConstSchema extends Schema {
Expand Down Expand Up @@ -40,6 +41,10 @@ protected ConstSchema(ConstSchemaBuilder builder) {
visitor.visitConstSchema(this);
}

@Override void accept(Visitor visitor, List<String> path) {
visitor.visitConstSchema(this);
}

public Object getPermittedValue() {
return permittedValue;
}
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/org/everit/json/schema/EmptySchema.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.everit.json.schema;

import java.util.List;

/**
* A schema not specifying any restrictions, ie. accepting any values.
*/
Expand Down Expand Up @@ -31,6 +33,10 @@ public EmptySchema(Builder builder) {
visitor.visitEmptySchema();
}

@Override void accept(Visitor visitor, List<String> path) {
visitor.visitEmptySchema();
}

@Override
public boolean equals(Object o) {
if (this == o)
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/org/everit/json/schema/EnumSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ public int hashCode() {
visitor.visitEnumSchema(this);
}

@Override public void accept(Visitor visitor, List<String> path) {
visitor.visitEnumSchema(this);
}

@Override
protected boolean canEqual(Object other) {
return other instanceof EnumSchema;
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/org/everit/json/schema/FalseSchema.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.everit.json.schema;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;


/**
* @author erosb
*/
Expand Down Expand Up @@ -31,7 +33,7 @@ public FalseSchema(Builder builder) {
}

@Override
void accept(Visitor visitor) {
void accept(Visitor visitor, List<String> path) {
visitor.visitFalseSchema(this);
}

Expand Down
9 changes: 7 additions & 2 deletions core/src/main/java/org/everit/json/schema/NotSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.Objects;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;

/**
Expand Down Expand Up @@ -46,7 +47,11 @@ public Schema getMustNotMatch() {
}

@Override void accept(Visitor visitor) {
visitor.visitNotSchema(this);
visitor.visitNotSchema(this, new ArrayList<>());
}

@Override void accept(Visitor visitor, List<String> path) {
visitor.visitNotSchema(this, path);
}

@Override
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/everit/json/schema/NullSchema.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.everit.json.schema;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;

/**
Expand Down Expand Up @@ -54,6 +55,10 @@ protected boolean canEqual(Object other) {
visitor.visitNullSchema(this);
}

@Override void accept(Visitor visitor, List<String> path) {
visitor.visitNullSchema(this);
}

@Override
void describePropertiesTo(JSONPrinter writer) {
writer.key("type");
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/everit/json/schema/NumberSchema.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.everit.json.schema;

import java.util.Objects;

import java.util.List;
import org.everit.json.schema.internal.JSONPrinter;
import org.json.JSONException;

Expand Down Expand Up @@ -165,7 +165,7 @@ public Number getExclusiveMaximumLimit() {
return exclusiveMaximumLimit;
}

@Override void accept(Visitor visitor) {
@Override void accept(Visitor visitor, List<String> path) {
visitor.visitNumberSchema(this);
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/everit/json/schema/ObjectSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ public Schema getPropertyNameSchema() {
return propertyNameSchema;
}

@Override void accept(Visitor visitor) {
visitor.visitObjectSchema(this);
@Override void accept(Visitor visitor, List<String> path) {
visitor.visitObjectSchema(this, path);
}

public boolean permitsAdditionalProperties() {
Expand Down