Skip to content

Commit

Permalink
Merge pull request #119 from lmontrieux/ARUHA-1271-less-ArrayLists
Browse files Browse the repository at this point in the history
Optimise validation performance
  • Loading branch information
erosb authored Nov 6, 2017
2 parents 724b94a + 15f0f5a commit b01b8aa
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 167 deletions.
66 changes: 33 additions & 33 deletions core/src/main/java/org/everit/json/schema/ArraySchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,44 +200,45 @@ public boolean requiresArray() {
return requiresArray;
}

private Optional<ValidationException> testItemCount(final JSONArray subject) {
private void testItemCount(final JSONArray subject, List<ValidationException> validationExceptions) {
int actualLength = subject.length();
if (minItems != null && actualLength < minItems) {
return Optional.of(failure("expected minimum item count: " + minItems
validationExceptions.add(
failure("expected minimum item count: " + minItems
+ ", found: " + actualLength, "minItems"));
return;
}
if (maxItems != null && maxItems < actualLength) {
return Optional.of(failure("expected maximum item count: " + maxItems
validationExceptions.add(
failure("expected maximum item count: " + maxItems
+ ", found: " + actualLength, "maxItems"));
}
return Optional.empty();
}

private List<ValidationException> testItems(final JSONArray subject) {
List<ValidationException> rval = new ArrayList<>();
private void testItems(final JSONArray subject, List<ValidationException> validationExceptions) {
if (allItemSchema != null) {
validateItemsAgainstSchema(IntStream.range(0, subject.length()),
subject,
allItemSchema,
rval::add);
validationExceptions::add);
} else if (itemSchemas != null) {
if (!additionalItems && subject.length() > itemSchemas.size()) {
rval.add(failure(format("expected: [%d] array items, found: [%d]",
validationExceptions.add(
failure(format("expected: [%d] array items, found: [%d]",
itemSchemas.size(), subject.length()), "items"));
}
int itemValidationUntil = Math.min(subject.length(), itemSchemas.size());
validateItemsAgainstSchema(IntStream.range(0, itemValidationUntil),
subject,
itemSchemas::get,
rval::add);
validationExceptions::add);
if (schemaOfAdditionalItems != null) {
validateItemsAgainstSchema(IntStream.range(itemValidationUntil, subject.length()),
subject,
schemaOfAdditionalItems,
rval::add);
validationExceptions::add);
}
}
return rval;
}

private void validateItemsAgainstSchema(final IntStream indices, final JSONArray items,
Expand All @@ -257,58 +258,57 @@ private void validateItemsAgainstSchema(final IntStream indices, final JSONArray
}
}

private Optional<ValidationException> testUniqueness(final JSONArray subject) {
private void testUniqueness(final JSONArray subject, List<ValidationException> validationExceptions) {
if (subject.length() == 0) {
return Optional.empty();
return;
}
Collection<Object> uniqueItems = new ArrayList<Object>(subject.length());
for (int i = 0; i < subject.length(); ++i) {
Object item = subject.get(i);
for (Object contained : uniqueItems) {
if (ObjectComparator.deepEquals(contained, item)) {
return Optional.of(
validationExceptions.add(
failure("array items are not unique", "uniqueItems"));
return;
}
}
uniqueItems.add(item);
}
return Optional.empty();
}

@Override
public void validate(final Object subject) {
List<ValidationException> failures = new ArrayList<>();
if (!(subject instanceof JSONArray)) {
if (requiresArray) {
throw failure(JSONArray.class, subject);
}
} else {
List<ValidationException> validationExceptions = new ArrayList<>();
JSONArray arrSubject = (JSONArray) subject;
testItemCount(arrSubject).ifPresent(failures::add);
testItemCount(arrSubject, validationExceptions);
if (uniqueItems) {
testUniqueness(arrSubject).ifPresent(failures::add);
testUniqueness(arrSubject, validationExceptions);
}
testItems(arrSubject, validationExceptions);
testContains(arrSubject, validationExceptions);
if (null != validationExceptions) {
ValidationException.throwFor(this, validationExceptions);
}
failures.addAll(testItems(arrSubject));
testContains(arrSubject).ifPresent(failures::add);
}
ValidationException.throwFor(this, failures);
}

private Optional<ValidationException> testContains(JSONArray arrSubject) {
private void testContains(JSONArray arrSubject, List<ValidationException> validationExceptions) {
if (containedItemSchema == null) {
return Optional.empty();
return;
}
boolean anyMatch = IntStream.range(0, arrSubject.length())
.mapToObj(arrSubject::get)
.map(item -> ifFails(containedItemSchema, item))
.filter(maybeFailure -> !maybeFailure.isPresent())
.findFirst()
.isPresent();
if (anyMatch) {
return Optional.empty();
} else {
return Optional.of(failure("expected at least one array item to match 'contains' schema", "contains"));
for (int i = 0; i < arrSubject.length(); i++) {
Optional<ValidationException> exception = ifFails(containedItemSchema, arrSubject.get(i));
if (!exception.isPresent()) {
return;
}
}
validationExceptions.add(
failure("expected at least one array item to match 'contains' schema", "contains"));
}

@Override
Expand Down
21 changes: 13 additions & 8 deletions core/src/main/java/org/everit/json/schema/CombinedSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.everit.json.schema.internal.JSONPrinter;

Expand Down Expand Up @@ -183,10 +182,13 @@ private ValidationException getFailure(final Schema schema, final Object subject

@Override
public void validate(final Object subject) {
List<ValidationException> failures = subschemas.stream()
.map(schema -> getFailure(schema, subject))
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<ValidationException> failures = new ArrayList<>();
for (Schema subschema: subschemas) {
ValidationException exception = getFailure(subschema, subject);
if (null != exception) {
failures.add(exception);
}
}
int matchingCount = subschemas.size() - failures.size();
try {
criterion.validate(subschemas.size(), matchingCount);
Expand All @@ -202,9 +204,12 @@ public void validate(final Object subject) {

@Override
public boolean definesProperty(final String field) {
List<Schema> matching = subschemas.stream()
.filter(schema -> schema.definesProperty(field))
.collect(Collectors.toList());
List<Schema> matching = new ArrayList<>();
for (Schema subschema: subschemas) {
if (subschema.definesProperty(field)) {
matching.add(subschema);
}
}
try {
criterion.validate(subschemas.size(), matching.size());
} catch (ValidationException e) {
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/java/org/everit/json/schema/EnumSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ public Set<Object> getPossibleValues() {
@Override
public void validate(final Object subject) {
Object effectiveSubject = toJavaValue(subject);
possibleValues
.stream()
.filter(val -> ObjectComparator.deepEquals(val, effectiveSubject))
.findAny()
.orElseThrow(
() -> failure(format("%s is not a valid enum value", subject), "enum"));
for (Object possibleValue: possibleValues) {
if (ObjectComparator.deepEquals(possibleValue, effectiveSubject)) {
return;
}
}
throw failure(format("%s is not a valid enum value", subject), "enum");
}

@Override
Expand Down
Loading

0 comments on commit b01b8aa

Please sign in to comment.