From a5eca449dcbf94ac0d25e1f3611828f232938fd7 Mon Sep 17 00:00:00 2001 From: Prashanth Josyula Date: Sat, 16 Jan 2021 11:01:43 +0530 Subject: [PATCH] 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 --- .../schema/AdditionalPropertiesValidator.java | 44 +----- .../com/networknt/schema/AllOfValidator.java | 4 - .../com/networknt/schema/ItemsValidator.java | 137 ++++++++++-------- .../java/com/networknt/schema/JsonSchema.java | 28 +++- .../com/networknt/schema/NotValidator.java | 7 +- .../com/networknt/schema/OneOfValidator.java | 28 +++- .../networknt/schema/PatternValidator.java | 7 +- .../networknt/schema/PropertiesValidator.java | 84 ++++++----- .../com/networknt/schema/RefValidator.java | 9 +- .../schema/SchemaValidatorsConfig.java | 27 +++- .../com/networknt/schema/ValidatorState.java | 26 ++++ .../walk/DefaultItemWalkListenerRunner.java | 37 +++++ .../schema/walk/JsonSchemaWalker.java | 4 +- 13 files changed, 272 insertions(+), 170 deletions(-) create mode 100644 src/main/java/com/networknt/schema/walk/DefaultItemWalkListenerRunner.java diff --git a/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java b/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java index 278b3b5dc..5ec7181aa 100644 --- a/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java +++ b/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java @@ -94,49 +94,17 @@ public Set validate(JsonNode node, JsonNode rootNode, String errors.add(buildValidationMessage(at, pname)); } else { if (additionalPropertiesSchema != null) { - errors.addAll(additionalPropertiesSchema.validate(node.get(pname), rootNode, at + "." + pname)); + ValidatorState state = validatorState.get(); + if (state != null && state.isWalkEnabled()) { + errors.addAll(additionalPropertiesSchema.walk(node.get(pname), rootNode, at + "." + pname, state.isValidationEnabledWhileWalking())); + } else { + errors.addAll(additionalPropertiesSchema.validate(node.get(pname), rootNode, at + "." + pname)); + } } } } } return Collections.unmodifiableSet(errors); } - - @Override - public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - Set validationMessages = new LinkedHashSet(); - if (!node.isObject()) { - return validationMessages; - } - // Validate schema if required. - if (shouldValidateSchema) { - validationMessages.addAll(validate(node, rootNode, at)); - } - for (Iterator it = node.fieldNames(); it.hasNext();) { - String pname = it.next(); - // skip the context items - if (pname.startsWith("#")) { - continue; - } - boolean handledByPatternProperties = false; - for (Pattern pattern : patternProperties) { - Matcher m = pattern.matcher(pname); - if (m.find()) { - handledByPatternProperties = true; - break; - } - } - if (!allowedProperties.contains(pname) && !handledByPatternProperties) { - if (allowAdditionalProperties) { - if (additionalPropertiesSchema != null) { - validationMessages.addAll(additionalPropertiesSchema.walk(node.get(pname), rootNode, at + "." + pname, - shouldValidateSchema)); - } - } - } - } - - return validationMessages; - } } diff --git a/src/main/java/com/networknt/schema/AllOfValidator.java b/src/main/java/com/networknt/schema/AllOfValidator.java index 312f9ae16..af9b3145a 100644 --- a/src/main/java/com/networknt/schema/AllOfValidator.java +++ b/src/main/java/com/networknt/schema/AllOfValidator.java @@ -53,10 +53,6 @@ public Set walk(JsonNode node, JsonNode rootNode, String at, Set validationMessages = new LinkedHashSet(); for (JsonSchema schema : schemas) { - // Check if validation is needed. - if (shouldValidateSchema) { - validationMessages.addAll(schema.validate(node, rootNode, at)); - } // Walk through the schema validationMessages.addAll(schema.walk(node, rootNode, at, shouldValidateSchema)); } diff --git a/src/main/java/com/networknt/schema/ItemsValidator.java b/src/main/java/com/networknt/schema/ItemsValidator.java index c708762d8..ed5fb690d 100644 --- a/src/main/java/com/networknt/schema/ItemsValidator.java +++ b/src/main/java/com/networknt/schema/ItemsValidator.java @@ -17,6 +17,9 @@ package com.networknt.schema; import com.fasterxml.jackson.databind.JsonNode; +import com.networknt.schema.walk.DefaultItemWalkListenerRunner; +import com.networknt.schema.walk.WalkListenerRunner; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,17 +33,21 @@ public class ItemsValidator extends BaseJsonValidator implements JsonValidator { private List tupleSchema; private boolean additionalItems = true; private JsonSchema additionalSchema; + private WalkListenerRunner arrayItemWalkListenerRunner; + private ValidationContext validationContext; - public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) { + public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, + ValidationContext validationContext) { super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.ITEMS, validationContext); if (schemaNode.isObject() || schemaNode.isBoolean()) { - schema = new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), schemaNode, parentSchema) - .initialize(); + schema = new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), schemaNode, + parentSchema).initialize(); } else { tupleSchema = new ArrayList(); for (JsonNode s : schemaNode) { - tupleSchema.add(new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), s, parentSchema) - .initialize()); + tupleSchema.add( + new JsonSchema(validationContext, schemaPath, parentSchema.getCurrentUri(), s, parentSchema) + .initialize()); } JsonNode addItemNode = getParentSchema().getSchemaNode().get(PROPERTY_ADDITIONAL_ITEMS); @@ -49,10 +56,13 @@ public ItemsValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentS additionalItems = addItemNode.asBoolean(); } else if (addItemNode.isObject()) { additionalSchema = new JsonSchema(validationContext, parentSchema.getCurrentUri(), addItemNode) - .initialize(); + .initialize(); } } } + arrayItemWalkListenerRunner = new DefaultItemWalkListenerRunner(config.getArrayItemWalkListeners()); + + this.validationContext = validationContext; parseErrorCode(getValidatorType().getErrorCodeKey()); } @@ -100,57 +110,64 @@ private void doValidate(Set errors, int i, JsonNode node, Jso } } } - - @Override - public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - HashSet validationMessages = new LinkedHashSet(); - if (node != null && node.isArray()) { - int i = 0; - for (JsonNode n : node) { - doWalk(validationMessages, i, n, rootNode, at, shouldValidateSchema); - i++; - } - } else { - doWalk(validationMessages, 0, node, rootNode, at, shouldValidateSchema); - } - return validationMessages; - } - - private void doWalk(HashSet validationMessages, int i, JsonNode node, JsonNode rootNode, - String at, boolean shouldValidateSchema) { - if (schema != null) { - if (shouldValidateSchema) { - validationMessages.addAll(schema.validate(node, rootNode, at)); - } - // Walk the schema. - validationMessages.addAll(schema.walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema)); - } - - if (tupleSchema != null) { - if (i < tupleSchema.size()) { - if (shouldValidateSchema) { - validationMessages.addAll(tupleSchema.get(i).validate(node, rootNode, at)); - } - // walk tuple schema - validationMessages.addAll(tupleSchema.get(i).walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema)); - } else { - if (additionalSchema != null) { - if (shouldValidateSchema) { - validationMessages.addAll(additionalSchema.validate(node, rootNode, at)); - } - // walk additional item schema - validationMessages.addAll(additionalSchema.walk(node, rootNode, at + "[" + i + "]", shouldValidateSchema)); - } - } - } - } - - public List getTupleSchema() { - return this.tupleSchema; - } - - public JsonSchema getSchema() { - return schema; - } - -} + + @Override + public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { + HashSet validationMessages = new LinkedHashSet(); + if (node != null && node.isArray()) { + int i = 0; + for (JsonNode n : node) { + doWalk(validationMessages, i, n, rootNode, at, shouldValidateSchema); + i++; + } + } else { + doWalk(validationMessages, 0, node, rootNode, at, shouldValidateSchema); + } + return validationMessages; + } + + private void doWalk(HashSet validationMessages, int i, JsonNode node, JsonNode rootNode, + String at, boolean shouldValidateSchema) { + if (schema != null) { + // Walk the schema. + walkSchema(schema, node, rootNode, at + "[" + i + "]", shouldValidateSchema, validationMessages); + } + + if (tupleSchema != null) { + if (i < tupleSchema.size()) { + // walk tuple schema + walkSchema(tupleSchema.get(i), node, rootNode, at + "[" + i + "]", shouldValidateSchema, + validationMessages); + } else { + if (additionalSchema != null) { + // walk additional item schema + walkSchema(additionalSchema, node, rootNode, at + "[" + i + "]", shouldValidateSchema, + validationMessages); + } + } + } + } + + private void walkSchema(JsonSchema walkSchema, JsonNode node, JsonNode rootNode, String at, + boolean shouldValidateSchema, Set validationMessages) { + boolean executeWalk = arrayItemWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node, + rootNode, at, walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(), + validationContext.getJsonSchemaFactory()); + if (executeWalk) { + validationMessages.addAll(walkSchema.walk(node, rootNode, at, shouldValidateSchema)); + } + arrayItemWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.ITEMS.getValue(), node, rootNode, at, + walkSchema.getSchemaPath(), walkSchema.getSchemaNode(), walkSchema.getParentSchema(), + validationContext.getJsonSchemaFactory(), validationMessages); + + } + + public List getTupleSchema() { + return this.tupleSchema; + } + + public JsonSchema getSchema() { + return schema; + } + +} \ No newline at end of file diff --git a/src/main/java/com/networknt/schema/JsonSchema.java b/src/main/java/com/networknt/schema/JsonSchema.java index 0850e46d3..63299b647 100644 --- a/src/main/java/com/networknt/schema/JsonSchema.java +++ b/src/main/java/com/networknt/schema/JsonSchema.java @@ -246,8 +246,12 @@ public ValidationResult validateAndCollect(JsonNode node) { */ protected ValidationResult validateAndCollect(JsonNode jsonNode, JsonNode rootNode, String at) { try { - // Create the collector context object. - CollectorContext collectorContext = new CollectorContext(); + CollectorContext collectorContext; + if(this.config !=null && this.config.getCollectorContext() != null){ + collectorContext = this.config.getCollectorContext(); + } else { + collectorContext = new CollectorContext(); + } // Set the collector context in thread info, this is unique for every thread. ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext); Set errors = validate(jsonNode, rootNode, at); @@ -275,7 +279,10 @@ public ValidationResult walk(JsonNode node, boolean shouldValidateSchema) { // Create the collector context object. CollectorContext collectorContext = new CollectorContext(); // Set the collector context in thread info, this is unique for every thread. - ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext); + ThreadInfo.set(CollectorContext.COLLECTOR_CONTEXT_THREAD_LOCAL_KEY, collectorContext); + // Set the walkEnabled flag in internal validator state. + setValidatorState(true, shouldValidateSchema); + // Walk through the schema. Set errors = walk(node, node, AT_ROOT, shouldValidateSchema); // Load all the data from collectors into the context. collectorContext.loadCollectors(); @@ -284,7 +291,8 @@ public ValidationResult walk(JsonNode node, boolean shouldValidateSchema) { return validationResult; } - @Override + + @Override public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { Set validationMessages = new LinkedHashSet(); // Walk through all the JSONWalker's. @@ -309,6 +317,18 @@ public Set walk(JsonNode node, JsonNode rootNode, String at, /************************ END OF WALK METHODS **********************************/ + private void setValidatorState(boolean isWalkEnabled, boolean shouldValidateSchema) { + // Get the Validator state object storing validation data + ValidatorState state = validatorState.get(); + if (state == null) { + // if one has not been created, instantiate one + state = new ValidatorState(); + state.setWalkEnabled(isWalkEnabled); + state.setValidationEnabledWhileWalking(shouldValidateSchema); + validatorState.set(state); + } + } + @Override public String toString() { return "\"" + getSchemaPath() + "\" : " + getSchemaNode().toString(); diff --git a/src/main/java/com/networknt/schema/NotValidator.java b/src/main/java/com/networknt/schema/NotValidator.java index 8dbbda234..2f79bcda5 100644 --- a/src/main/java/com/networknt/schema/NotValidator.java +++ b/src/main/java/com/networknt/schema/NotValidator.java @@ -49,12 +49,7 @@ public Set validate(JsonNode node, JsonNode rootNode, String @Override public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - Set validationMessages = new LinkedHashSet(); - if (shouldValidateSchema) { - validationMessages.addAll(validate(node, rootNode, at)); - } - validationMessages.addAll(schema.walk(node, rootNode, at, shouldValidateSchema)); - return validationMessages; + return schema.walk(node, rootNode, at, shouldValidateSchema); } } diff --git a/src/main/java/com/networknt/schema/OneOfValidator.java b/src/main/java/com/networknt/schema/OneOfValidator.java index a2f5276d8..e0fb51a8e 100644 --- a/src/main/java/com/networknt/schema/OneOfValidator.java +++ b/src/main/java/com/networknt/schema/OneOfValidator.java @@ -129,10 +129,14 @@ public OneOfValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentS public Set validate(JsonNode node, JsonNode rootNode, String at) { debug(logger, node, rootNode, at); + ValidatorState state = validatorState.get(); + if (state == null) { + state = new ValidatorState(); + validatorState.set(state); + } // this is a complex validator, we set the flag to true - ValidatorState state = new ValidatorState(); state.setComplexValidator(true); - validatorState.set(state); + int numberOfValidSchema = 0; Set errors = new LinkedHashSet(); @@ -145,6 +149,7 @@ public Set validate(JsonNode node, JsonNode rootNode, String // } for (ShortcutValidator validator : schemas) { + Set schemaErrors = null; // Reset state in case the previous validator did not match state.setMatchedNode(true); if (!validator.allConstantsMatch(node)) { @@ -155,7 +160,11 @@ public Set validate(JsonNode node, JsonNode rootNode, String // get the current validator JsonSchema schema = validator.schema; - Set schemaErrors = schema.validate(node, rootNode, at); + if (!state.isWalkEnabled()) { + schemaErrors = schema.validate(node, rootNode, at); + } else { + schemaErrors = schema.walk(node, rootNode, at, state.isValidationEnabledWhileWalking()); + } // check if any validation errors have occurred if (schemaErrors.isEmpty()) { @@ -187,4 +196,17 @@ public List getChildSchemas() { return childJsonSchemas; } + @Override + public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { + HashSet validationMessages = new LinkedHashSet(); + if (shouldValidateSchema) { + validationMessages.addAll(validate(node, rootNode, at)); + } else { + for (ShortcutValidator validator : schemas) { + validator.schema.walk(node, rootNode, at , shouldValidateSchema); + } + } + return validationMessages; + } + } diff --git a/src/main/java/com/networknt/schema/PatternValidator.java b/src/main/java/com/networknt/schema/PatternValidator.java index 6fe4c22a9..1a1569789 100644 --- a/src/main/java/com/networknt/schema/PatternValidator.java +++ b/src/main/java/com/networknt/schema/PatternValidator.java @@ -55,12 +55,7 @@ public Set validate(JsonNode node, JsonNode rootNode, String @Override public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - Set validationMessages = new LinkedHashSet(); - if (shouldValidateSchema) { - validationMessages.addAll(validate(node, rootNode, at)); - } - validationMessages.addAll(delegate.walk(node, rootNode, at, shouldValidateSchema)); - return validationMessages; + return delegate.walk(node, rootNode, at, shouldValidateSchema); } private static class PatternValidatorJava extends BaseJsonValidator implements JsonValidator { diff --git a/src/main/java/com/networknt/schema/PropertiesValidator.java b/src/main/java/com/networknt/schema/PropertiesValidator.java index 7041702b3..f7e19747f 100644 --- a/src/main/java/com/networknt/schema/PropertiesValidator.java +++ b/src/main/java/com/networknt/schema/PropertiesValidator.java @@ -41,7 +41,7 @@ public PropertiesValidator(String schemaPath, JsonNode schemaNode, JsonSchema pa .initialize()); } propertyWalkListenerRunner = new DefaultPropertyWalkListenerRunner( - config.getPropertyWalkListeners()); + config.getPropertyWalkListeners()); } public Set validate(JsonNode node, JsonNode rootNode, String at) { @@ -64,15 +64,20 @@ public Set validate(JsonNode node, JsonNode rootNode, String if (propertyNode != null) { // check whether this is a complex validator. save the state boolean isComplex = state.isComplexValidator(); - // if this is a complex validator, the node has matched, and all it's child elements, if available, are to be validated + // if this is a complex validator, the node has matched, and all it's child elements, if available, are to be validated if (state.isComplexValidator()) { state.setMatchedNode(true); } - // reset the complex validator for child element validation, and reset it after the return from the recursive call + // reset the complex validator for child element validation, and reset it after the return from the recursive call state.setComplexValidator(false); - - //validate the child element(s) - errors.addAll(propertySchema.validate(propertyNode, rootNode, at + "." + entry.getKey())); + + if (!state.isWalkEnabled()) { + //validate the child element(s) + errors.addAll(propertySchema.validate(propertyNode, rootNode, at + "." + entry.getKey())); + } else { + // check if walker is enabled. If it is enabled it is upto the walker implementation to decide about the validation. + walkSchema(entry, node, rootNode, at, state.isValidationEnabledWhileWalking(), errors); + } // reset the complex flag to the original value before the recursive call state.setComplexValidator(isComplex); @@ -86,7 +91,7 @@ public Set validate(JsonNode node, JsonNode rootNode, String Set requiredErrors = getParentSchema().getRequiredValidator().validate(node, rootNode, at); if (!requiredErrors.isEmpty()) { - // the node was mandatory, decide which behavior to employ when validator has not matched + // the node was mandatory, decide which behavior to employ when validator has not matched if (state.isComplexValidator()) { // this was a complex validator (ex oneOf) and the node has not been matched state.setMatchedNode(false); @@ -101,37 +106,40 @@ public Set validate(JsonNode node, JsonNode rootNode, String return Collections.unmodifiableSet(errors); } - - @Override - public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - HashSet validationMessages = new LinkedHashSet(); - if (shouldValidateSchema) { - validationMessages.addAll(validate(node, rootNode, at)); - } else { - boolean executeWalk = true; - for (Map.Entry entry : schemas.entrySet()) { - JsonSchema propertySchema = entry.getValue(); - JsonNode propertyNode = (node == null ? null : node.get(entry.getKey())); - executeWalk = propertyWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(), - propertyNode, rootNode, at + "." + entry.getKey(), propertySchema.getSchemaPath(), - propertySchema.getSchemaNode(), propertySchema.getParentSchema(), - validationContext.getJsonSchemaFactory()); - if (executeWalk) { - validationMessages.addAll(propertySchema.walk(propertyNode, rootNode, at + "." + entry.getKey(), - shouldValidateSchema)); - } - propertyWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(), propertyNode, - rootNode, at + "." + entry.getKey(), propertySchema.getSchemaPath(), - propertySchema.getSchemaNode(), propertySchema.getParentSchema(), - validationContext.getJsonSchemaFactory(), validationMessages); - } - } - return validationMessages; - } - - public Map getSchemas() { - return schemas; - } + @Override + public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { + HashSet validationMessages = new LinkedHashSet(); + if (shouldValidateSchema) { + validationMessages.addAll(validate(node, rootNode, at)); + } else { + for (Map.Entry entry : schemas.entrySet()) { + walkSchema(entry, node, rootNode, at, shouldValidateSchema, validationMessages); + } + } + return validationMessages; + } + + private void walkSchema(Map.Entry entry, JsonNode node, JsonNode rootNode, String at, + boolean shouldValidateSchema, Set validationMessages) { + JsonSchema propertySchema = entry.getValue(); + JsonNode propertyNode = (node == null ? null : node.get(entry.getKey())); + boolean executeWalk = propertyWalkListenerRunner.runPreWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(), + propertyNode, rootNode, at + "." + entry.getKey(), propertySchema.getSchemaPath(), + propertySchema.getSchemaNode(), propertySchema.getParentSchema(), + validationContext.getJsonSchemaFactory()); + if (executeWalk) { + validationMessages.addAll( + propertySchema.walk(propertyNode, rootNode, at + "." + entry.getKey(), shouldValidateSchema)); + } + propertyWalkListenerRunner.runPostWalkListeners(ValidatorTypeCode.PROPERTIES.getValue(), propertyNode, rootNode, + at + "." + entry.getKey(), propertySchema.getSchemaPath(), propertySchema.getSchemaNode(), + propertySchema.getParentSchema(), validationContext.getJsonSchemaFactory(), validationMessages); + + } + + public Map getSchemas() { + return schemas; + } } diff --git a/src/main/java/com/networknt/schema/RefValidator.java b/src/main/java/com/networknt/schema/RefValidator.java index 4df7c7d90..1a6813412 100644 --- a/src/main/java/com/networknt/schema/RefValidator.java +++ b/src/main/java/com/networknt/schema/RefValidator.java @@ -144,15 +144,10 @@ public Set validate(JsonNode node, JsonNode rootNode, String @Override public Set walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) { - HashSet validationMessages = new LinkedHashSet(); - - if (shouldValidateSchema) { - validationMessages.addAll(validate(node, rootNode, at)); - } if (schema != null) { - validationMessages.addAll(schema.walk(node, rootNode, at, shouldValidateSchema)); + return schema.walk(node, rootNode, at, shouldValidateSchema); } - return validationMessages; + return Collections.emptySet(); } public JsonSchemaRef getSchemaRef() { diff --git a/src/main/java/com/networknt/schema/SchemaValidatorsConfig.java b/src/main/java/com/networknt/schema/SchemaValidatorsConfig.java index 8fbea105b..9f91d1ada 100644 --- a/src/main/java/com/networknt/schema/SchemaValidatorsConfig.java +++ b/src/main/java/com/networknt/schema/SchemaValidatorsConfig.java @@ -61,10 +61,14 @@ public class SchemaValidatorsConfig { // This is just a constant for listening to all Keywords. public static final String ALL_KEYWORD_WALK_LISTENER_KEY = "com.networknt.AllKeywordWalkListener"; - + private final Map> keywordWalkListenersMap = new HashMap>(); - private final List propertyWalkListeners = new ArrayList(); + private final List propertyWalkListeners = new ArrayList(); + + private final List itemWalkListeners = new ArrayList(); + + private CollectorContext collectorContext; public boolean isTypeLoose() { return typeLoose; @@ -157,6 +161,14 @@ public void addPropertyWalkListeners(List propertyWalkLi public void addPropertyWalkListener(JsonSchemaWalkListener propertyWalkListener) { this.propertyWalkListeners.add(propertyWalkListener); + } + + public void addItemWalkListener(JsonSchemaWalkListener itemWalkListener) { + this.itemWalkListeners.add(itemWalkListener); + } + + public void addItemWalkListeners(List itemWalkListeners) { + this.itemWalkListeners.addAll(itemWalkListeners); } public List getPropertyWalkListeners() { @@ -165,9 +177,20 @@ public List getPropertyWalkListeners() { public Map> getKeywordWalkListenersMap() { return this.keywordWalkListenersMap; + } + + public List getArrayItemWalkListeners() { + return this.itemWalkListeners; } public SchemaValidatorsConfig() { } + + public CollectorContext getCollectorContext() { + return collectorContext; + } + public void setCollectorContext(CollectorContext collectorContext) { + this.collectorContext = collectorContext; + } } diff --git a/src/main/java/com/networknt/schema/ValidatorState.java b/src/main/java/com/networknt/schema/ValidatorState.java index 8770cd6ad..e3a80d859 100644 --- a/src/main/java/com/networknt/schema/ValidatorState.java +++ b/src/main/java/com/networknt/schema/ValidatorState.java @@ -29,6 +29,16 @@ public class ValidatorState { */ private boolean isComplexValidator = false; + /** + * Flag to check if walking is enabled. + */ + private boolean isWalkEnabled = false; + + /** + * Flag to check if validation is enabled while walking. + */ + private boolean isValidationEnabledWhileWalking = false; + public void setMatchedNode(boolean matchedNode) { this.matchedNode = matchedNode; } @@ -45,4 +55,20 @@ public void setComplexValidator(boolean isComplexValidator) { this.isComplexValidator = isComplexValidator; } + public boolean isWalkEnabled() { + return isWalkEnabled; + } + + public void setWalkEnabled(boolean isWalkEnabled) { + this.isWalkEnabled = isWalkEnabled; + } + + public boolean isValidationEnabledWhileWalking() { + return isValidationEnabledWhileWalking; + } + + public void setValidationEnabledWhileWalking(boolean isValidationEnabledWhileWalking) { + this.isValidationEnabledWhileWalking = isValidationEnabledWhileWalking; + } + } diff --git a/src/main/java/com/networknt/schema/walk/DefaultItemWalkListenerRunner.java b/src/main/java/com/networknt/schema/walk/DefaultItemWalkListenerRunner.java new file mode 100644 index 000000000..bc5df0577 --- /dev/null +++ b/src/main/java/com/networknt/schema/walk/DefaultItemWalkListenerRunner.java @@ -0,0 +1,37 @@ +package com.networknt.schema.walk; + +import com.fasterxml.jackson.databind.JsonNode; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.JsonSchemaFactory; +import com.networknt.schema.ValidationMessage; + +import java.util.List; +import java.util.Set; + +public class DefaultItemWalkListenerRunner extends AbstractWalkListenerRunner { + + private List itemWalkListeners; + + public DefaultItemWalkListenerRunner(List itemWalkListeners) { + this.itemWalkListeners = itemWalkListeners; + } + + @Override + public boolean runPreWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at, + String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, + JsonSchemaFactory currentJsonSchemaFactory) { + WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema, + currentJsonSchemaFactory); + return runPreWalkListeners(itemWalkListeners, walkEvent); + } + + @Override + public void runPostWalkListeners(String keyWordPath, JsonNode node, JsonNode rootNode, String at, String schemaPath, + JsonNode schemaNode, JsonSchema parentSchema, JsonSchemaFactory currentJsonSchemaFactory, + Set validationMessages) { + WalkEvent walkEvent = constructWalkEvent(keyWordPath, node, rootNode, at, schemaPath, schemaNode, parentSchema, + currentJsonSchemaFactory); + runPostWalkListeners(itemWalkListeners, walkEvent, validationMessages); + } + +} \ No newline at end of file diff --git a/src/main/java/com/networknt/schema/walk/JsonSchemaWalker.java b/src/main/java/com/networknt/schema/walk/JsonSchemaWalker.java index 79be872ee..bb940b222 100644 --- a/src/main/java/com/networknt/schema/walk/JsonSchemaWalker.java +++ b/src/main/java/com/networknt/schema/walk/JsonSchemaWalker.java @@ -15,9 +15,9 @@ public interface JsonSchemaWalker { * the validation if {@code shouldValidateSchema} is set to true.
*
* {@link BaseJsonValidator#walk(JsonNode, JsonNode, String, boolean)} provides - * a default implementation of this method. However keywords that parse + * a default implementation of this method. However validators that parse * sub-schemas should override this method to call walk method on those - * subschemas. + * sub-schemas. * * @param node JsonNode * @param rootNode JsonNode