Skip to content

Commit a5eca44

Browse files
Fixing Walk Listeners Issues. (#368)
* Fixing walk issues for properties * Correcting walk changes for few validators * adding item walk listener * walk listener changes * walk listener changes Co-authored-by: Prashanth Josyula <[email protected]>
1 parent 1783eb5 commit a5eca44

13 files changed

+272
-170
lines changed

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

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -94,49 +94,17 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
9494
errors.add(buildValidationMessage(at, pname));
9595
} else {
9696
if (additionalPropertiesSchema != null) {
97-
errors.addAll(additionalPropertiesSchema.validate(node.get(pname), rootNode, at + "." + pname));
97+
ValidatorState state = validatorState.get();
98+
if (state != null && state.isWalkEnabled()) {
99+
errors.addAll(additionalPropertiesSchema.walk(node.get(pname), rootNode, at + "." + pname, state.isValidationEnabledWhileWalking()));
100+
} else {
101+
errors.addAll(additionalPropertiesSchema.validate(node.get(pname), rootNode, at + "." + pname));
102+
}
98103
}
99104
}
100105
}
101106
}
102107
return Collections.unmodifiableSet(errors);
103108
}
104-
105-
@Override
106-
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
107-
Set<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
108-
if (!node.isObject()) {
109-
return validationMessages;
110-
}
111-
// Validate schema if required.
112-
if (shouldValidateSchema) {
113-
validationMessages.addAll(validate(node, rootNode, at));
114-
}
115-
for (Iterator<String> it = node.fieldNames(); it.hasNext();) {
116-
String pname = it.next();
117-
// skip the context items
118-
if (pname.startsWith("#")) {
119-
continue;
120-
}
121-
boolean handledByPatternProperties = false;
122-
for (Pattern pattern : patternProperties) {
123-
Matcher m = pattern.matcher(pname);
124-
if (m.find()) {
125-
handledByPatternProperties = true;
126-
break;
127-
}
128-
}
129-
if (!allowedProperties.contains(pname) && !handledByPatternProperties) {
130-
if (allowAdditionalProperties) {
131-
if (additionalPropertiesSchema != null) {
132-
validationMessages.addAll(additionalPropertiesSchema.walk(node.get(pname), rootNode, at + "." + pname,
133-
shouldValidateSchema));
134-
}
135-
}
136-
}
137-
}
138-
139-
return validationMessages;
140-
}
141109

142110
}

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at,
5353
Set<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
5454

5555
for (JsonSchema schema : schemas) {
56-
// Check if validation is needed.
57-
if (shouldValidateSchema) {
58-
validationMessages.addAll(schema.validate(node, rootNode, at));
59-
}
6056
// Walk through the schema
6157
validationMessages.addAll(schema.walk(node, rootNode, at, shouldValidateSchema));
6258
}

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

Lines changed: 77 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
package com.networknt.schema;
1818

1919
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.networknt.schema.walk.DefaultItemWalkListenerRunner;
21+
import com.networknt.schema.walk.WalkListenerRunner;
22+
2023
import org.slf4j.Logger;
2124
import org.slf4j.LoggerFactory;
2225

@@ -30,17 +33,21 @@ public class ItemsValidator extends BaseJsonValidator implements JsonValidator {
3033
private List<JsonSchema> tupleSchema;
3134
private boolean additionalItems = true;
3235
private JsonSchema additionalSchema;
36+
private WalkListenerRunner arrayItemWalkListenerRunner;
37+
private ValidationContext validationContext;
3338

34-
public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
39+
public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema,
40+
ValidationContext validationContext) {
3541
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.ITEMS, validationContext);
3642
if (schemaNode.isObject() || schemaNode.isBoolean()) {
37-
schema = new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), schemaNode, parentSchema)
38-
.initialize();
43+
schema = new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), schemaNode,
44+
parentSchema).initialize();
3945
} else {
4046
tupleSchema = new ArrayList<JsonSchema>();
4147
for (JsonNode s : schemaNode) {
42-
tupleSchema.add(new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), s, parentSchema)
43-
.initialize());
48+
tupleSchema.add(
49+
new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), s, parentSchema)
50+
.initialize());
4451
}
4552

4653
JsonNode addItemNode = getParentSchema().getSchemaNode().get(PROPERTY_ADDITIONAL_ITEMS);
@@ -49,10 +56,13 @@ public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentS
4956
additionalItems = addItemNode.asBoolean();
5057
} else if (addItemNode.isObject()) {
5158
additionalSchema = new JsonSchema(validationContext, parentSchema.getCurrentUri(), addItemNode)
52-
.initialize();
59+
.initialize();
5360
}
5461
}
5562
}
63+
arrayItemWalkListenerRunner = new DefaultItemWalkListenerRunner(config.getArrayItemWalkListeners());
64+
65+
this.validationContext = validationContext;
5666

5767
parseErrorCode(getValidatorType().getErrorCodeKey());
5868
}
@@ -100,57 +110,64 @@ private void doValidate(Set<ValidationMessage> errors, int i, JsonNode node, Jso
100110
}
101111
}
102112
}
103-
104-
@Override
105-
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
106-
HashSet<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
107-
if (node != null && node.isArray()) {
108-
int i = 0;
109-
for (JsonNode n : node) {
110-
doWalk(validationMessages, i, n, rootNode, at, shouldValidateSchema);
111-
i++;
112-
}
113-
} else {
114-
doWalk(validationMessages, 0, node, rootNode, at, shouldValidateSchema);
115-
}
116-
return validationMessages;
117-
}
118-
119-
private void doWalk(HashSet<ValidationMessage> validationMessages, int i, JsonNode node, JsonNode rootNode,
120-
String at, boolean shouldValidateSchema) {
121-
if (schema != null) {
122-
if (shouldValidateSchema) {
123-
validationMessages.addAll(schema.validate(node, rootNode, at));
124-
}
125-
// Walk the schema.
126-
validationMessages.addAll(schema.walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema));
127-
}
128-
129-
if (tupleSchema != null) {
130-
if (i < tupleSchema.size()) {
131-
if (shouldValidateSchema) {
132-
validationMessages.addAll(tupleSchema.get(i).validate(node, rootNode, at));
133-
}
134-
// walk tuple schema
135-
validationMessages.addAll(tupleSchema.get(i).walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema));
136-
} else {
137-
if (additionalSchema != null) {
138-
if (shouldValidateSchema) {
139-
validationMessages.addAll(additionalSchema.validate(node, rootNode, at));
140-
}
141-
// walk additional item schema
142-
validationMessages.addAll(additionalSchema.walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema));
143-
}
144-
}
145-
}
146-
}
147-
148-
public List<JsonSchema> getTupleSchema() {
149-
return this.tupleSchema;
150-
}
151-
152-
public JsonSchema getSchema() {
153-
return schema;
154-
}
155-
156-
}
113+
114+
@Override
115+
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
116+
HashSet<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
117+
if (node != null && node.isArray()) {
118+
int i = 0;
119+
for (JsonNode n : node) {
120+
doWalk(validationMessages, i, n, rootNode, at, shouldValidateSchema);
121+
i++;
122+
}
123+
} else {
124+
doWalk(validationMessages, 0, node, rootNode, at, shouldValidateSchema);
125+
}
126+
return validationMessages;
127+
}
128+
129+
private void doWalk(HashSet<ValidationMessage> validationMessages, int i, JsonNode node, JsonNode rootNode,
130+
String at, boolean shouldValidateSchema) {
131+
if (schema != null) {
132+
// Walk the schema.
133+
walkSchema(schema, node, rootNode, at + "[" + i + "]", shouldValidateSchema, validationMessages);
134+
}
135+
136+
if (tupleSchema != null) {
137+
if (i < tupleSchema.size()) {
138+
// walk tuple schema
139+
walkSchema(tupleSchema.get(i), node, rootNode, at + "[" + i + "]", shouldValidateSchema,
140+
validationMessages);
141+
} else {
142+
if (additionalSchema != null) {
143+
// walk additional item schema
144+
walkSchema(additionalSchema, node, rootNode, at + "[" + i + "]", shouldValidateSchema,
145+
validationMessages);
146+
}
147+
}
148+
}
149+
}
150+
151+
private void walkSchema(JsonSchema walkSchema, JsonNode node, JsonNode rootNode, String at,
152+
boolean shouldValidateSchema, Set<ValidationMessage> validationMessages) {
153+
boolean executeWalk = arrayItemWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node,
154+
rootNode, at, walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(),
155+
validationContext.getJsonSchemaFactory());
156+
if (executeWalk) {
157+
validationMessages.addAll(walkSchema.walk(node, rootNode, at, shouldValidateSchema));
158+
}
159+
arrayItemWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node, rootNode, at,
160+
walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(),
161+
validationContext.getJsonSchemaFactory(), validationMessages);
162+
163+
}
164+
165+
public List<JsonSchema> getTupleSchema() {
166+
return this.tupleSchema;
167+
}
168+
169+
public JsonSchema getSchema() {
170+
return schema;
171+
}
172+
173+
}

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,12 @@ public ValidationResult validateAndCollect(JsonNode node) {
246246
*/
247247
protected ValidationResult validateAndCollect(JsonNode jsonNode, JsonNode rootNode, String at) {
248248
try {
249-
// Create the collector context object.
250-
CollectorContext collectorContext = new CollectorContext();
249+
CollectorContext collectorContext;
250+
if(this.config !=null && this.config.getCollectorContext() != null){
251+
collectorContext = this.config.getCollectorContext();
252+
} else {
253+
collectorContext = new CollectorContext();
254+
}
251255
// Set the collector context in thread info, this is unique for every thread.
252256
ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext);
253257
Set<ValidationMessage> errors = validate(jsonNode, rootNode, at);
@@ -275,7 +279,10 @@ public ValidationResult walk(JsonNode node, boolean shouldValidateSchema) {
275279
// Create the collector context object.
276280
CollectorContext collectorContext = new CollectorContext();
277281
// Set the collector context in thread info, this is unique for every thread.
278-
ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext);
282+
ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext);
283+
// Set the walkEnabled flag in internal validator state.
284+
setValidatorState(true, shouldValidateSchema);
285+
// Walk through the schema.
279286
Set<ValidationMessage> errors = walk(node, node, AT_ROOT, shouldValidateSchema);
280287
// Load all the data from collectors into the context.
281288
collectorContext.loadCollectors();
@@ -284,7 +291,8 @@ public ValidationResult walk(JsonNode node, boolean shouldValidateSchema) {
284291
return validationResult;
285292
}
286293

287-
@Override
294+
295+
@Override
288296
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
289297
Set<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
290298
// Walk through all the JSONWalker's.
@@ -309,6 +317,18 @@ public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at,
309317

310318
/************************ END OF WALK METHODS **********************************/
311319

320+
private void setValidatorState(boolean isWalkEnabled, boolean shouldValidateSchema) {
321+
// Get the Validator state object storing validation data
322+
ValidatorState state = validatorState.get();
323+
if (state == null) {
324+
// if one has not been created, instantiate one
325+
state = new ValidatorState();
326+
state.setWalkEnabled(isWalkEnabled);
327+
state.setValidationEnabledWhileWalking(shouldValidateSchema);
328+
validatorState.set(state);
329+
}
330+
}
331+
312332
@Override
313333
public String toString() {
314334
return "\"" + getSchemaPath() + "\" : " + getSchemaNode().toString();

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,7 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
4949

5050
@Override
5151
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
52-
Set<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
53-
if (shouldValidateSchema) {
54-
validationMessages.addAll(validate(node, rootNode, at));
55-
}
56-
validationMessages.addAll(schema.walk(node, rootNode, at, shouldValidateSchema));
57-
return validationMessages;
52+
return schema.walk(node, rootNode, at, shouldValidateSchema);
5853
}
5954

6055
}

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,14 @@ public OneOfValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentS
129129
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
130130
debug(logger, node, rootNode, at);
131131

132+
ValidatorState state = validatorState.get();
133+
if (state == null) {
134+
state = new ValidatorState();
135+
validatorState.set(state);
136+
}
132137
// this is a complex validator, we set the flag to true
133-
ValidatorState state = new ValidatorState();
134138
state.setComplexValidator(true);
135-
validatorState.set(state);
139+
136140

137141
int numberOfValidSchema = 0;
138142
Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
@@ -145,6 +149,7 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
145149
// }
146150

147151
for (ShortcutValidator validator : schemas) {
152+
Set<ValidationMessage> schemaErrors = null;
148153
// Reset state in case the previous validator did not match
149154
state.setMatchedNode(true);
150155
if (!validator.allConstantsMatch(node)) {
@@ -155,7 +160,11 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
155160

156161
// get the current validator
157162
JsonSchema schema = validator.schema;
158-
Set<ValidationMessage> schemaErrors = schema.validate(node, rootNode, at);
163+
if (!state.isWalkEnabled()) {
164+
schemaErrors = schema.validate(node, rootNode, at);
165+
} else {
166+
schemaErrors = schema.walk(node, rootNode, at, state.isValidationEnabledWhileWalking());
167+
}
159168

160169
// check if any validation errors have occurred
161170
if (schemaErrors.isEmpty()) {
@@ -187,4 +196,17 @@ public List<JsonSchema> getChildSchemas() {
187196
return childJsonSchemas;
188197
}
189198

199+
@Override
200+
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
201+
HashSet<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
202+
if (shouldValidateSchema) {
203+
validationMessages.addAll(validate(node, rootNode, at));
204+
} else {
205+
for (ShortcutValidator validator : schemas) {
206+
validator.schema.walk(node, rootNode, at , shouldValidateSchema);
207+
}
208+
}
209+
return validationMessages;
210+
}
211+
190212
}

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,7 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
5555

5656
@Override
5757
public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
58-
Set<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
59-
if (shouldValidateSchema) {
60-
validationMessages.addAll(validate(node, rootNode, at));
61-
}
62-
validationMessages.addAll(delegate.walk(node, rootNode, at, shouldValidateSchema));
63-
return validationMessages;
58+
return delegate.walk(node, rootNode, at, shouldValidateSchema);
6459
}
6560

6661
private static class PatternValidatorJava extends BaseJsonValidator implements JsonValidator {

0 commit comments

Comments
 (0)