Skip to content

Commit 39f6cdd

Browse files
committed
Refactor VisitorListener to be more event oriented
1 parent ac586b7 commit 39f6cdd

File tree

9 files changed

+361
-137
lines changed

9 files changed

+361
-137
lines changed

core/src/main/java/org/everit/json/schema/ConditionalSchemaValidatingVisitor.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ConditionalSchemaValidatingVisitor extends Visitor {
1515

1616
private ValidationException ifSchemaException;
1717

18-
public ConditionalSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
18+
ConditionalSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
1919
this.subject = subject;
2020
this.owner = requireNonNull(owner, "owner cannot be null");
2121
}
@@ -35,20 +35,28 @@ void visitIfSchema(Schema ifSchema) {
3535
if (conditionalSchema.getIfSchema().isPresent()) {
3636
ifSchemaException = owner.getFailureOfSchema(ifSchema, subject);
3737
}
38+
owner.reportSchemaMatchEvent(ifSchema, ifSchemaException);
3839
}
3940

4041
@Override
4142
void visitThenSchema(Schema thenSchema) {
4243
if (ifSchemaException == null) {
4344
ValidationException thenSchemaException = owner.getFailureOfSchema(thenSchema, subject);
4445
if (thenSchemaException != null) {
45-
owner.failure(new ValidationException(conditionalSchema,
46+
ValidationException failure = new ValidationException(conditionalSchema,
4647
new StringBuilder(new StringBuilder("#")),
4748
"input is invalid against the \"then\" schema",
4849
Arrays.asList(thenSchemaException),
4950
"then",
50-
conditionalSchema.getSchemaLocation()));
51+
conditionalSchema.getSchemaLocation());
52+
53+
owner.failure(failure);
54+
owner.reportSchemaMatchEvent(thenSchema, failure);
55+
} else {
56+
owner.reportSchemaMatchEvent(thenSchema, null);
5157
}
58+
} else {
59+
owner.reportSchemaMatchEvent(thenSchema, ifSchemaException);
5260
}
5361
}
5462

@@ -57,12 +65,16 @@ void visitElseSchema(Schema elseSchema) {
5765
if (ifSchemaException != null) {
5866
ValidationException elseSchemaException = owner.getFailureOfSchema(elseSchema, subject);
5967
if (elseSchemaException != null) {
60-
owner.failure(new ValidationException(conditionalSchema,
68+
ValidationException failure = new ValidationException(conditionalSchema,
6169
new StringBuilder(new StringBuilder("#")),
6270
"input is invalid against both the \"if\" and \"else\" schema",
6371
Arrays.asList(ifSchemaException, elseSchemaException),
6472
"else",
65-
conditionalSchema.getSchemaLocation()));
73+
conditionalSchema.getSchemaLocation());
74+
owner.failure(failure);
75+
owner.reportSchemaMatchEvent(elseSchema, failure);
76+
} else {
77+
owner.reportSchemaMatchEvent(elseSchema, null);
6678
}
6779
}
6880
}
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
package org.everit.json.schema;
22

3+
4+
import org.everit.json.schema.listener.SubschemaReferencedEvent;
5+
import org.everit.json.schema.listener.SubschemaMatchEvent;
6+
import org.everit.json.schema.listener.SubschemaMismatchEvent;
7+
38
/**
49
* Interface to capture which schemas are matching against a specific event in the {@link ValidatingVisitor}.
510
*/
611
public interface SchemaVisitorListener {
712

8-
void addValidSchema(Schema schema);
13+
void subschemaMatch(SubschemaMatchEvent matchEvent);
14+
15+
void subschemaMismatch(SubschemaMismatchEvent mismatchEvent);
916

10-
void addInvalidSchema(Schema schema);
17+
void subschemaReferenced(SubschemaReferencedEvent referencedEvent);
1118

1219
}
1320

core/src/main/java/org/everit/json/schema/ValidatingVisitor.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import java.util.Collection;
1111
import java.util.List;
1212

13+
import org.everit.json.schema.listener.SubschemaMatchEvent;
14+
import org.everit.json.schema.listener.SubschemaMismatchEvent;
15+
import org.everit.json.schema.listener.SubschemaReferencedEvent;
1316
import org.json.JSONArray;
1417
import org.json.JSONObject;
1518

@@ -128,6 +131,7 @@ void visitReferenceSchema(ReferenceSchema referenceSchema) {
128131
if (failure != null) {
129132
failureReporter.failure(failure);
130133
}
134+
reportSchemaReferencedEvent(referenceSchema, failure);
131135
}
132136

133137
@Override
@@ -150,6 +154,7 @@ void visitCombinedSchema(CombinedSchema combinedSchema) {
150154
if (null != exception) {
151155
failures.add(exception);
152156
}
157+
reportSchemaMatchEvent(subschema, exception);
153158
}
154159
int matchingCount = subschemas.size() - failures.size();
155160
try {
@@ -169,22 +174,27 @@ void visitConditionalSchema(ConditionalSchema conditionalSchema) {
169174
conditionalSchema.accept(new ConditionalSchemaValidatingVisitor(subject, this));
170175
}
171176

172-
void reportSchemaValidation(Schema schema, ValidationException rval) {
173-
if(schemaVisitorListener != null) {
177+
void reportSchemaMatchEvent(Schema schema, ValidationException rval) {
178+
if (schemaVisitorListener != null) {
174179
if (rval == null) {
175-
schemaVisitorListener.addValidSchema(schema);
180+
schemaVisitorListener.subschemaMatch(new SubschemaMatchEvent(schema));
176181
} else {
177-
schemaVisitorListener.addInvalidSchema(schema);
182+
schemaVisitorListener.subschemaMismatch(new SubschemaMismatchEvent(schema, rval));
178183
}
179184
}
180185
}
181186

187+
void reportSchemaReferencedEvent(Schema schema, ValidationException rval) {
188+
if (schemaVisitorListener != null) {
189+
schemaVisitorListener.subschemaReferenced(new SubschemaReferencedEvent(schema, rval));
190+
}
191+
}
192+
182193
ValidationException getFailureOfSchema(Schema schema, Object input) {
183194
Object origSubject = this.subject;
184195
this.subject = input;
185196
ValidationException rval = failureReporter.inContextOfSchema(schema, () -> visit(schema));
186197
this.subject = origSubject;
187-
reportSchemaValidation(schema, rval);
188198
return rval;
189199
}
190200

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.everit.json.schema.listener;
2+
3+
import org.everit.json.schema.Schema;
4+
import org.everit.json.schema.ValidationException;
5+
6+
public abstract class AbstractSchemaEvent {
7+
8+
protected final Schema schema;
9+
protected final ValidationException rval;
10+
11+
AbstractSchemaEvent(Schema schema, ValidationException rval) {
12+
this.schema = schema;
13+
this.rval = rval;
14+
}
15+
16+
public Schema getSchema() {
17+
return schema;
18+
}
19+
20+
public ValidationException getValidationException() {
21+
return rval;
22+
}
23+
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.everit.json.schema.listener;
2+
3+
import org.everit.json.schema.Schema;
4+
5+
public class SubschemaMatchEvent extends AbstractSchemaEvent {
6+
7+
public SubschemaMatchEvent(Schema schema) {
8+
super(schema, null);
9+
}
10+
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.everit.json.schema.listener;
2+
3+
import org.everit.json.schema.Schema;
4+
import org.everit.json.schema.ValidationException;
5+
6+
public class SubschemaMismatchEvent extends AbstractSchemaEvent {
7+
8+
public SubschemaMismatchEvent(Schema schema, ValidationException rval) {
9+
super(schema, rval);
10+
}
11+
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.everit.json.schema.listener;
2+
3+
import org.everit.json.schema.Schema;
4+
import org.everit.json.schema.ValidationException;
5+
6+
public class SubschemaReferencedEvent extends AbstractSchemaEvent {
7+
8+
public SubschemaReferencedEvent(Schema schema, ValidationException rval) {
9+
super(schema, rval);
10+
}
11+
12+
}

core/src/test/java/org/everit/json/schema/SchemaVisitorListenerTest.java

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.everit.json.schema;
22

3+
import org.everit.json.schema.listener.AbstractSchemaEvent;
4+
import org.everit.json.schema.listener.SubschemaMatchEvent;
5+
import org.everit.json.schema.listener.SubschemaMismatchEvent;
6+
import org.everit.json.schema.listener.SubschemaReferencedEvent;
37
import org.json.JSONObject;
48
import org.junit.Before;
59
import org.junit.Test;
@@ -14,36 +18,53 @@ public class SchemaVisitorListenerTest {
1418

1519
public class DummySchemaVisitorListener implements SchemaVisitorListener {
1620

17-
private List<Schema> validSchemas = new ArrayList<>();
18-
private List<Schema> invalidSchemas = new ArrayList<>();
21+
private List<SubschemaMatchEvent> validSchemas = new ArrayList<>();
22+
private List<SubschemaMismatchEvent> invalidSchemas = new ArrayList<>();
23+
private List<SubschemaReferencedEvent> referencedSchemas = new ArrayList<>();
1924

2025
@Override
21-
public void addValidSchema(Schema schema) {
22-
validSchemas.add(schema);
26+
public void subschemaMatch(SubschemaMatchEvent matchEvent) {
27+
validSchemas.add(matchEvent);
2328
}
2429

2530
@Override
26-
public void addInvalidSchema(Schema schema) {
27-
invalidSchemas.add(schema);
31+
public void subschemaMismatch(SubschemaMismatchEvent mismatchEvent) {
32+
invalidSchemas.add(mismatchEvent);
33+
}
34+
35+
@Override
36+
public void subschemaReferenced(SubschemaReferencedEvent referencedEvent) {
37+
referencedSchemas.add(referencedEvent);
2838
}
2939

3040
void clear() {
3141
validSchemas.clear();
3242
invalidSchemas.clear();
43+
referencedSchemas.clear();
44+
}
45+
46+
String eventToString(AbstractSchemaEvent event) {
47+
List<String> failureMessages = null;
48+
if (event.getValidationException() != null) {
49+
failureMessages = event.getValidationException().getAllMessages();
50+
}
51+
52+
Schema schema = event.getSchema();
53+
return String.format("{\"location\": \"%s\"", schema.getSchemaLocation()) +
54+
String.format(",\"schema\": %s", schema) +
55+
String.format(",\"failures\": \"%s\"}", failureMessages);
3356
}
3457

58+
3559
@Override
3660
public String toString() {
37-
List<String> valid = validSchemas
38-
.stream().map(s -> String.format("{\"location\": \"%s\", \"schema\": %s}", s.getSchemaLocation(), s))
39-
.collect(Collectors.toList());
40-
41-
List<String> invalid = invalidSchemas
42-
.stream().map(s -> String.format("{\"location\": \"%s\", \"schema\": %s}", s.getSchemaLocation(), s))
43-
.collect(Collectors.toList());
61+
List<String> valid = validSchemas.stream().map(this::eventToString).collect(Collectors.toList());
62+
List<String> invalid = invalidSchemas.stream().map(this::eventToString).collect(Collectors.toList());
63+
List<String> referenced = referencedSchemas.stream().map(this::eventToString).collect(Collectors.toList());
4464

45-
return String.format("{\"valid\": %s, \"invalid\": %s}", valid, invalid);
65+
return String.format("{\"valid\": %s, \"invalid\": %s, \"referenced\": %s}", valid, invalid, referenced);
4666
}
67+
4768
}
4869

4970

@@ -65,22 +86,38 @@ private void testCase(String schemaPath, String eventPath, String expectedPath)
6586
Schema schema = TestSupport.loadAsV7(schemaContent);
6687

6788
JSONObject event = resource.getJSONObject(eventPath);
68-
validator.performValidation(schema, event);
89+
try {
90+
validator.performValidation(schema, event);
91+
} catch (Exception ignored) {
92+
}
6993

70-
JSONObject expectedValidations = resource.getJSONObject(expectedPath);
7194
JSONObject validation = new JSONObject(schemaVisitorListener.toString());
72-
95+
JSONObject expectedValidations = resource.getJSONObject(expectedPath);
7396
assertEquals(validation.toString(), expectedValidations.toString());
97+
98+
schemaVisitorListener.clear();
7499
}
75100

76101
@Test
77102
public void refSchema() {
78-
testCase("schema1", "example1", "expected1");
103+
testCase("refSchema1", "refExample1", "refExpected1");
79104
}
80105

81106
@Test
82107
public void combinedSchemaOneOf() {
83-
testCase("schema2", "example2", "expected2");
108+
testCase("combinedSchema2", "combinedExample2", "combinedExpected2");
109+
}
110+
111+
@Test
112+
public void directRefSchema() {
113+
testCase("refSchema3", "refExample3", "refExpected3");
114+
}
115+
116+
@Test
117+
public void ifThenElseSchema() {
118+
testCase("ifThenElseSchema", "ifThenElseExample4.1", "ifThenElseExpected4.1");
119+
testCase("ifThenElseSchema", "ifThenElseExample4.2", "ifThenElseExpected4.2");
120+
testCase("ifThenElseSchema", "ifThenElseExample4.3", "ifThenElseExpected4.3");
84121
}
85122

86123
}

0 commit comments

Comments
 (0)