Skip to content

Commit 9419ce7

Browse files
Correcting the ref listeners config in WalkEvent class when fetching the getRefSchema (#459)
* Fixing walk issues for properties * Correcting walk changes for few validators * adding item walk listener * walk listener changes * walk listener changes * merging changes from networknt * Fixing issues with ValidatorState * changing the method name to getCollectorContext * correcting the variable names and ValidatorState logic * correcting the documentation logic * Fixing compilation issues in TypeFactoryTest * Fixing the minor brace issue * Fixing the issue of propogating walk-listeners to child 's from parent schema * Adding tests for changing listeners * Correcting the ref listeners config in walk event * Correcting the ref listeners config in walk event Co-authored-by: Prashanth Josyula <[email protected]>
1 parent df9f67a commit 9419ce7

10 files changed

+309
-267
lines changed

src/main/java/com/networknt/schema/ItemsValidator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,16 @@ private void doWalk(HashSet<ValidationMessage> validationMessages, int i, JsonNo
153153
}
154154

155155
private void walkSchema(JsonSchema walkSchema, JsonNode node, JsonNode rootNode, String at,
156-
boolean shouldValidateSchema, Set<ValidationMessage> validationMessages) {
156+
boolean shouldValidateSchema, Set<ValidationMessage> validationMessages) {
157157
boolean executeWalk = arrayItemWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node,
158158
rootNode, at, walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(),
159-
validationContext.getJsonSchemaFactory());
159+
validationContext, validationContext.getJsonSchemaFactory());
160160
if (executeWalk) {
161161
validationMessages.addAll(walkSchema.walk(node, rootNode, at, shouldValidateSchema));
162162
}
163163
arrayItemWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node, rootNode, at,
164164
walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(),
165-
validationContext.getJsonSchemaFactory(), validationMessages);
165+
validationContext, validationContext.getJsonSchemaFactory(), validationMessages);
166166

167167
}
168168

src/main/java/com/networknt/schema/JsonSchema.java

+42-29
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public JsonSchema(ValidationContext validationContext, URI baseUri, JsonNode sch
8080
private JsonSchema(ValidationContext validationContext, String schemaPath, URI currentUri, JsonNode schemaNode,
8181
JsonSchema parent, boolean suppressSubSchemaRetrieval) {
8282
super(schemaPath, schemaNode, parent, null, suppressSubSchemaRetrieval,
83-
validationContext.getConfig() != null && validationContext.getConfig().isFailFast());
83+
validationContext.getConfig() != null && validationContext.getConfig().isFailFast());
8484
this.validationContext = validationContext;
8585
this.idKeyword = validationContext.getMetaSchema().getIdKeyword();
8686
this.currentUri = this.combineCurrentUriWithIds(currentUri, schemaNode);
@@ -109,9 +109,9 @@ private URI combineCurrentUriWithIds(URI currentUri, JsonNode schemaNode) {
109109
return this.validationContext.getURIFactory().create(currentUri, id);
110110
} catch (IllegalArgumentException e) {
111111
throw new JsonSchemaException(ValidationMessage.of(ValidatorTypeCode.ID.getValue(),
112-
ValidatorTypeCode.ID,
113-
id,
114-
currentUri == null ? "null" : currentUri.toString()));
112+
ValidatorTypeCode.ID,
113+
id,
114+
currentUri == null ? "null" : currentUri.toString()));
115115
}
116116
}
117117
}
@@ -242,7 +242,7 @@ private Map<String, JsonValidator> read(JsonNode schemaNode) {
242242
private String getCustomMessage(JsonNode schemaNode, String pname) {
243243
final JsonSchema parentSchema = getParentSchema();
244244
final JsonNode message = getMessageNode(schemaNode, parentSchema);
245-
if(message != null && message.get(pname) != null) {
245+
if (message != null && message.get(pname) != null) {
246246
return message.get(pname).asText();
247247
}
248248
return null;
@@ -251,7 +251,7 @@ private String getCustomMessage(JsonNode schemaNode, String pname) {
251251
private JsonNode getMessageNode(JsonNode schemaNode, JsonSchema parentSchema) {
252252
JsonNode nodeContainingMessage;
253253
if (parentSchema == null)
254-
nodeContainingMessage = schemaNode;
254+
nodeContainingMessage = schemaNode;
255255
else
256256
nodeContainingMessage = parentSchema.schemaNode;
257257
return nodeContainingMessage.get("message");
@@ -291,9 +291,9 @@ public Set<ValidationMessage> validate(JsonNode jsonNode, JsonNode rootNode, Str
291291
final JsonNode discriminatorNode = jsonNode.get(discriminatorPropertyName);
292292
final String discriminatorPropertyValue = discriminatorNode == null ? null : discriminatorNode.asText();
293293
checkDiscriminatorMatch(discriminatorContext,
294-
discriminatorToUse,
295-
discriminatorPropertyValue,
296-
this);
294+
discriminatorToUse,
295+
discriminatorPropertyValue,
296+
this);
297297
}
298298
}
299299
}
@@ -316,12 +316,17 @@ public ValidationResult validateAndCollect(JsonNode node) {
316316
*/
317317
protected ValidationResult validateAndCollect(JsonNode jsonNode, JsonNode rootNode, String at) {
318318
try {
319+
// Get the config.
320+
SchemaValidatorsConfig config = validationContext.getConfig();
319321
// Get the collector context from the thread local.
320322
CollectorContext collectorContext = getCollectorContext();
321323
// Valdiate.
322324
Set<ValidationMessage> errors = validate(jsonNode, rootNode, at);
323-
// Load all the data from collectors into the context.
324-
collectorContext.loadCollectors();
325+
// When walk is called in series of nested call we don't want to load the collectors every time. Leave to the API to decide when to call collectors.
326+
if (config.doLoadCollectors()) {
327+
// Load all the data from collectors into the context.
328+
collectorContext.loadCollectors();
329+
}
325330
// Collect errors and collector context into validation result.
326331
ValidationResult validationResult = new ValidationResult(errors, collectorContext);
327332
return validationResult;
@@ -336,19 +341,25 @@ protected ValidationResult validateAndCollect(JsonNode jsonNode, JsonNode rootNo
336341

337342
/**
338343
* Walk the JSON node
339-
* @param node JsonNode
344+
*
345+
* @param node JsonNode
340346
* @param shouldValidateSchema indicator on validation
341347
* @return result of ValidationResult
342348
*/
343349
public ValidationResult walk(JsonNode node, boolean shouldValidateSchema) {
350+
// Get the config.
351+
SchemaValidatorsConfig config = validationContext.getConfig();
344352
// Get the collector context from the thread local.
345353
CollectorContext collectorContext = getCollectorContext();
346354
// Set the walkEnabled flag in internal validator state.
347355
setValidatorState(true, shouldValidateSchema);
348356
// Walk through the schema.
349357
Set<ValidationMessage> errors = walk(node, node, AT_ROOT, shouldValidateSchema);
350-
// Load all the data from collectors into the context.
351-
collectorContext.loadCollectors();
358+
// When walk is called in series of nested call we don't want to load the collectors every time. Leave to the API to decide when to call collectors.
359+
if (config.doLoadCollectors()) {
360+
// Load all the data from collectors into the context.
361+
collectorContext.loadCollectors();
362+
}
352363
// Collect errors and collector context into validation result.
353364
ValidationResult validationResult = new ValidationResult(errors, collectorContext);
354365
return validationResult;
@@ -366,26 +377,28 @@ public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at,
366377
// Call all the pre-walk listeners. If atleast one of the pre walk listeners
367378
// returns SKIP, then skip the walk.
368379
if (keywordWalkListenerRunner.runPreWalkListeners(schemaPathWithKeyword,
369-
node,
370-
rootNode,
371-
at,
372-
schemaPath,
373-
schemaNode,
374-
parentSchema,
375-
validationContext.getJsonSchemaFactory())) {
380+
node,
381+
rootNode,
382+
at,
383+
schemaPath,
384+
schemaNode,
385+
parentSchema,
386+
validationContext,
387+
validationContext.getJsonSchemaFactory())) {
376388
validationMessages.addAll(jsonWalker.walk(node, rootNode, at, shouldValidateSchema));
377389
}
378390
} finally {
379391
// Call all the post-walk listeners.
380392
keywordWalkListenerRunner.runPostWalkListeners(schemaPathWithKeyword,
381-
node,
382-
rootNode,
383-
at,
384-
schemaPath,
385-
schemaNode,
386-
parentSchema,
387-
validationContext.getJsonSchemaFactory(),
388-
validationMessages);
393+
node,
394+
rootNode,
395+
at,
396+
schemaPath,
397+
schemaNode,
398+
parentSchema,
399+
validationContext,
400+
validationContext.getJsonSchemaFactory(),
401+
validationMessages);
389402
}
390403
}
391404
return validationMessages;

src/main/java/com/networknt/schema/PropertiesValidator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@ private void walkSchema(Map.Entry<String, JsonSchema> entry, JsonNode node, Json
119119
JsonNode propertyNode = (node == null ? null : node.get(entry.getKey()));
120120
boolean executeWalk = propertyWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(),
121121
propertyNode, rootNode, at + "." + entry.getKey(), propertySchema.getSchemaPath(),
122-
propertySchema.getSchemaNode(), propertySchema.getParentSchema(),
122+
propertySchema.getSchemaNode(), propertySchema.getParentSchema(), validationContext,
123123
validationContext.getJsonSchemaFactory());
124124
if (executeWalk) {
125125
validationMessages.addAll(
126126
propertySchema.walk(propertyNode, rootNode, at + "." + entry.getKey(), shouldValidateSchema));
127127
}
128128
propertyWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(), propertyNode, rootNode,
129129
at + "." + entry.getKey(), propertySchema.getSchemaPath(), propertySchema.getSchemaNode(),
130-
propertySchema.getParentSchema(), validationContext.getJsonSchemaFactory(), validationMessages);
130+
propertySchema.getParentSchema(), validationContext, validationContext.getJsonSchemaFactory(), validationMessages);
131131

132132
}
133133

src/main/java/com/networknt/schema/SchemaValidatorsConfig.java

+10
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public class SchemaValidatorsConfig {
8787

8888
private CollectorContext collectorContext;
8989

90+
private boolean loadCollectors = true;
91+
9092
public boolean isTypeLoose() {
9193
return typeLoose;
9294
}
@@ -257,4 +259,12 @@ public boolean isOpenAPI3StyleDiscriminators() {
257259
public void setOpenAPI3StyleDiscriminators(boolean openAPI3StyleDiscriminators) {
258260
this.openAPI3StyleDiscriminators = openAPI3StyleDiscriminators;
259261
}
262+
263+
public void setLoadCollectors(boolean loadCollectors) {
264+
this.loadCollectors = loadCollectors;
265+
}
266+
267+
public boolean doLoadCollectors() {
268+
return loadCollectors;
269+
}
260270
}

src/main/java/com/networknt/schema/walk/AbstractWalkListenerRunner.java

+34-33
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,48 @@
33
import com.fasterxml.jackson.databind.JsonNode;
44
import com.networknt.schema.JsonSchema;
55
import com.networknt.schema.JsonSchemaFactory;
6+
import com.networknt.schema.ValidationContext;
67
import com.networknt.schema.ValidationMessage;
78

89
import java.util.List;
910
import java.util.Set;
1011

1112
public abstract class AbstractWalkListenerRunner implements WalkListenerRunner {
1213

13-
protected String getKeywordName(String keyWordPath) {
14-
return keyWordPath.substring(keyWordPath.lastIndexOf('/') + 1);
15-
}
14+
protected String getKeywordName(String keyWordPath) {
15+
return keyWordPath.substring(keyWordPath.lastIndexOf('/') + 1);
16+
}
1617

17-
protected WalkEvent constructWalkEvent(String keyWordName, JsonNode node, JsonNode rootNode, String at,
18-
String schemaPath, JsonNode schemaNode, JsonSchema parentSchema,
19-
JsonSchemaFactory currentJsonSchemaFactory) {
20-
return WalkEvent.builder().at(at).keyWordName(keyWordName).node(node).parentSchema(parentSchema)
21-
.rootNode(rootNode).schemaNode(schemaNode).schemaPath(schemaPath)
22-
.currentJsonSchemaFactory(currentJsonSchemaFactory).build();
23-
}
18+
protected WalkEvent constructWalkEvent(String keyWordName, JsonNode node, JsonNode rootNode, String at,
19+
String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext,
20+
JsonSchemaFactory currentJsonSchemaFactory) {
21+
return WalkEvent.builder().at(at).keyWordName(keyWordName).node(node).parentSchema(parentSchema)
22+
.rootNode(rootNode).schemaNode(schemaNode).schemaPath(schemaPath)
23+
.currentJsonSchemaFactory(currentJsonSchemaFactory).validationContext(validationContext).build();
24+
}
2425

25-
protected boolean runPreWalkListeners(List<JsonSchemaWalkListener> walkListeners, WalkEvent walkEvent) {
26-
boolean continueToWalkMethod = true;
27-
if (walkListeners != null) {
28-
for (JsonSchemaWalkListener walkListener : walkListeners) {
29-
WalkFlow walkFlow = walkListener.onWalkStart(walkEvent);
30-
if (WalkFlow.SKIP.equals(walkFlow) || WalkFlow.ABORT.equals(walkFlow)) {
31-
continueToWalkMethod = false;
32-
if (WalkFlow.ABORT.equals(walkFlow)) {
33-
break;
34-
}
35-
}
36-
}
37-
}
38-
return continueToWalkMethod;
39-
}
26+
protected boolean runPreWalkListeners(List<JsonSchemaWalkListener> walkListeners, WalkEvent walkEvent) {
27+
boolean continueToWalkMethod = true;
28+
if (walkListeners != null) {
29+
for (JsonSchemaWalkListener walkListener : walkListeners) {
30+
WalkFlow walkFlow = walkListener.onWalkStart(walkEvent);
31+
if (WalkFlow.SKIP.equals(walkFlow) || WalkFlow.ABORT.equals(walkFlow)) {
32+
continueToWalkMethod = false;
33+
if (WalkFlow.ABORT.equals(walkFlow)) {
34+
break;
35+
}
36+
}
37+
}
38+
}
39+
return continueToWalkMethod;
40+
}
4041

41-
protected void runPostWalkListeners(List<JsonSchemaWalkListener> walkListeners, WalkEvent walkEvent,
42-
Set<ValidationMessage> validationMessages) {
43-
if (walkListeners != null) {
44-
for (JsonSchemaWalkListener walkListener : walkListeners) {
45-
walkListener.onWalkEnd(walkEvent, validationMessages);
46-
}
47-
}
48-
}
42+
protected void runPostWalkListeners(List<JsonSchemaWalkListener> walkListeners, WalkEvent walkEvent,
43+
Set<ValidationMessage> validationMessages) {
44+
if (walkListeners != null) {
45+
for (JsonSchemaWalkListener walkListener : walkListeners) {
46+
walkListener.onWalkEnd(walkEvent, validationMessages);
47+
}
48+
}
49+
}
4950
}

src/main/java/com/networknt/schema/walk/DefaultItemWalkListenerRunner.java

+24-23
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,36 @@
33
import com.fasterxml.jackson.databind.JsonNode;
44
import com.networknt.schema.JsonSchema;
55
import com.networknt.schema.JsonSchemaFactory;
6+
import com.networknt.schema.ValidationContext;
67
import com.networknt.schema.ValidationMessage;
78

89
import java.util.List;
910
import java.util.Set;
1011

1112
public class DefaultItemWalkListenerRunner extends AbstractWalkListenerRunner {
1213

13-
private List<JsonSchemaWalkListener> itemWalkListeners;
14-
15-
public DefaultItemWalkListenerRunner(List<JsonSchemaWalkListener> itemWalkListeners) {
16-
this.itemWalkListeners = itemWalkListeners;
17-
}
18-
19-
@Override
20-
public boolean runPreWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at,
21-
String schemaPath, JsonNode schemaNode, JsonSchema parentSchema,
22-
JsonSchemaFactory currentJsonSchemaFactory) {
23-
WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema,
24-
currentJsonSchemaFactory);
25-
return runPreWalkListeners(itemWalkListeners, walkEvent);
26-
}
27-
28-
@Override
29-
public void runPostWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at, String schemaPath,
30-
JsonNode schemaNode, JsonSchema parentSchema, JsonSchemaFactory currentJsonSchemaFactory,
31-
Set<ValidationMessage> validationMessages) {
32-
WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema,
33-
currentJsonSchemaFactory);
34-
runPostWalkListeners(itemWalkListeners, walkEvent, validationMessages);
35-
}
14+
private List<JsonSchemaWalkListener> itemWalkListeners;
15+
16+
public DefaultItemWalkListenerRunner(List<JsonSchemaWalkListener> itemWalkListeners) {
17+
this.itemWalkListeners = itemWalkListeners;
18+
}
19+
20+
@Override
21+
public boolean runPreWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at,
22+
String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext,
23+
JsonSchemaFactory currentJsonSchemaFactory) {
24+
WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema, validationContext,
25+
currentJsonSchemaFactory);
26+
return runPreWalkListeners(itemWalkListeners, walkEvent);
27+
}
28+
29+
@Override
30+
public void runPostWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at, String schemaPath,
31+
JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, JsonSchemaFactory currentJsonSchemaFactory,
32+
Set<ValidationMessage> validationMessages) {
33+
WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema,
34+
validationContext, currentJsonSchemaFactory);
35+
runPostWalkListeners(itemWalkListeners, walkEvent, validationMessages);
36+
}
3637

3738
}

0 commit comments

Comments
 (0)