Skip to content

Commit 6f070a8

Browse files
committed
EvaluationParentSchema refactor
1 parent 1a525c7 commit 6f070a8

File tree

8 files changed

+33
-136
lines changed

8 files changed

+33
-136
lines changed

src/main/java/com/networknt/schema/keyword/AbstractKeywordValidator.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ public String toString() {
9797
* @return true if annotations should be reported
9898
*/
9999
protected boolean collectAnnotations(ExecutionContext executionContext) {
100-
boolean hasUnevaluatedProperties = executionContext.isUnevaluatedPropertiesPresent() && hasAdjacentKeywordInEvaluationPath(executionContext, "unevaluatedProperties");
101-
if (hasUnevaluatedProperties) {
102-
return true;
103-
}
104100
return collectAnnotations(executionContext, getKeyword());
105101
}
106102

@@ -130,6 +126,7 @@ protected void putAnnotation(ExecutionContext executionContext, Consumer<Annotat
130126
}
131127

132128

129+
133130
/**
134131
* Determines if the keyword exists adjacent in the evaluation path.
135132
* <p>
@@ -190,4 +187,21 @@ protected boolean hasAdjacentKeywordInEvaluationPath(ExecutionContext executionC
190187
}
191188
return false;
192189
}
190+
191+
protected boolean hasUnevaluatedItemsInEvaluationPath(ExecutionContext executionContext) {
192+
if (executionContext.isUnevaluatedItemsPresent()
193+
&& hasAdjacentKeywordInEvaluationPath(executionContext, "unevaluatedItems")) {
194+
return true;
195+
}
196+
return false;
197+
}
198+
199+
protected boolean hasUnevaluatedPropertiesInEvaluationPath(ExecutionContext executionContext) {
200+
if (executionContext.isUnevaluatedPropertiesPresent()
201+
&& hasAdjacentKeywordInEvaluationPath(executionContext, "unevaluatedProperties")) {
202+
return true;
203+
}
204+
return false;
205+
}
206+
193207
}

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ protected void validate(ExecutionContext executionContext, JsonNode node, JsonNo
9595

9696
Set<String> matchedInstancePropertyNames = null;
9797

98-
boolean collectAnnotations = collectAnnotations() || collectAnnotations(executionContext);
98+
boolean collectAnnotations = hasUnevaluatedPropertiesInEvaluationPath(executionContext)
99+
|| collectAnnotations(executionContext);
99100
// if allowAdditionalProperties is true, add all the properties as evaluated.
100101
if (allowAdditionalProperties && collectAnnotations) {
101102
for (Iterator<String> it = node.fieldNames(); it.hasNext();) {
@@ -180,22 +181,10 @@ private boolean handledByPatternProperties(String pname) {
180181
return false;
181182
}
182183

183-
private boolean collectAnnotations() {
184-
return hasUnevaluatedPropertiesValidator();
185-
}
186-
187-
private boolean hasUnevaluatedPropertiesValidator() {
188-
if (this.hasUnevaluatedPropertiesValidator == null) {
189-
this.hasUnevaluatedPropertiesValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedProperties");
190-
}
191-
return hasUnevaluatedPropertiesValidator;
192-
}
193-
194184
@Override
195185
public void preloadSchema() {
196186
if(additionalPropertiesSchema != null) {
197187
additionalPropertiesSchema.initializeValidators();
198188
}
199-
collectAnnotations(); // cache the flag
200189
}
201190
}

src/main/java/com/networknt/schema/keyword/AnyOfValidator.java

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
public class AnyOfValidator extends BaseKeywordValidator {
3737
private final List<Schema> schemas;
3838

39-
private Boolean canShortCircuit = null;
40-
4139
public AnyOfValidator(SchemaLocation schemaLocation, NodePath evaluationPath, JsonNode schemaNode,
4240
Schema parentSchema, SchemaContext schemaContext) {
4341
super(KeywordType.ANY_OF, schemaNode, schemaLocation, parentSchema, schemaContext, evaluationPath);
@@ -111,7 +109,7 @@ protected void validate(ExecutionContext executionContext, JsonNode node, JsonNo
111109
}
112110

113111
if (subSchemaErrors.isEmpty() && (!this.schemaContext.isDiscriminatorKeywordEnabled())
114-
&& canShortCircuit() && canShortCircuit(executionContext)) {
112+
&& canShortCircuit(executionContext)) {
115113
// Successful so return only the existing errors, ie. no new errors
116114
executionContext.setErrors(existingErrors);
117115
return;
@@ -230,31 +228,17 @@ public void walk(ExecutionContext executionContext, JsonNode node, JsonNode root
230228
* @return true if can short circuit
231229
*/
232230
protected boolean canShortCircuit(ExecutionContext executionContext) {
233-
return !executionContext.getExecutionConfig().isAnnotationCollectionEnabled();
234-
}
235-
236-
/**
237-
* If annotations are require for evaluation cannot short circuit.
238-
*
239-
* @return true if can short circuit
240-
*/
241-
protected boolean canShortCircuit() {
242-
if (this.canShortCircuit == null) {
243-
boolean canShortCircuit = true;
244-
for (KeywordValidator validator : getEvaluationParentSchema().getValidators()) {
245-
if ("unevaluatedProperties".equals(validator.getKeyword())
246-
|| "unevaluatedItems".equals(validator.getKeyword())) {
247-
canShortCircuit = false;
248-
}
249-
}
250-
this.canShortCircuit = canShortCircuit;
231+
if (hasUnevaluatedItemsInEvaluationPath(executionContext)) {
232+
return true;
233+
}
234+
if (hasUnevaluatedPropertiesInEvaluationPath(executionContext)) {
235+
return true;
251236
}
252-
return this.canShortCircuit;
237+
return !executionContext.getExecutionConfig().isAnnotationCollectionEnabled();
253238
}
254239

255240
@Override
256241
public void preloadSchema() {
257242
preloadSchemas(this.schemas);
258-
canShortCircuit(); // cache flag
259243
}
260244
}

src/main/java/com/networknt/schema/keyword/BaseKeywordValidator.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -123,37 +123,6 @@ protected void preloadSchemas(final Collection<Schema> schemas) {
123123
}
124124
}
125125

126-
/**
127-
* Determines if the keyword exists adjacent in the evaluation path.
128-
* <p>
129-
* This does not check if the keyword exists in the current meta schema as this
130-
* can be a cross-draft case where the properties keyword is in a Draft 7 schema
131-
* and the unevaluatedProperties keyword is in an outer Draft 2020-12 schema.
132-
* <p>
133-
* The fact that the validator exists in the evaluation path implies that the
134-
* keyword was valid in whatever meta schema for that schema it was created for.
135-
*
136-
* @param keyword the keyword to check
137-
* @return true if found
138-
*/
139-
protected boolean hasAdjacentKeywordInEvaluationPath(String keyword) {
140-
Schema schema = getEvaluationParentSchema();
141-
while (schema != null) {
142-
for (KeywordValidator validator : schema.getValidators()) {
143-
if (keyword.equals(validator.getKeyword())) {
144-
return true;
145-
}
146-
}
147-
Object element = schema.getEvaluationPath().getElement(-1);
148-
if ("properties".equals(element) || "items".equals(element)) {
149-
// If there is a change in instance location then return false
150-
return false;
151-
}
152-
schema = schema.getEvaluationParentSchema();
153-
}
154-
return false;
155-
}
156-
157126
protected MessageSourceError.Builder error() {
158127
return MessageSourceError
159128
.builder(this.schemaContext.getSchemaRegistryConfig().getMessageSource(), this.errorMessage)

src/main/java/com/networknt/schema/keyword/ContainsValidator.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public class ContainsValidator extends BaseKeywordValidator {
4545
private final Integer min;
4646
private final Integer max;
4747

48-
private Boolean hasUnevaluatedItemsValidator = null;
49-
5048
public ContainsValidator(SchemaLocation schemaLocation, NodePath evaluationPath, JsonNode schemaNode, Schema parentSchema, SchemaContext schemaContext) {
5149
super(KeywordType.CONTAINS, schemaNode, schemaLocation, parentSchema, schemaContext, evaluationPath);
5250

@@ -126,7 +124,7 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
126124
}
127125
}
128126

129-
boolean collectAnnotations = collectAnnotations();
127+
boolean collectAnnotations = hasUnevaluatedItemsInEvaluationPath(executionContext);
130128
if (this.schema != null) {
131129
// This keyword produces an annotation value which is an array of the indexes to
132130
// which this keyword validates successfully when applying its subschema, in
@@ -181,7 +179,6 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
181179
@Override
182180
public void preloadSchema() {
183181
Optional.ofNullable(this.schema).ifPresent(Schema::initializeValidators);
184-
collectAnnotations(); // cache the flag
185182
}
186183

187184
private void boundsViolated(ExecutionContext executionContext, KeywordType validatorTypeCode, Locale locale,
@@ -197,21 +194,4 @@ private void boundsViolated(ExecutionContext executionContext, KeywordType valid
197194
.keyword(validatorTypeCode.getValue()).build());
198195
}
199196

200-
/**
201-
* Determine if annotations must be collected for evaluation.
202-
* <p>
203-
* This will be collected regardless of whether it is needed for reporting.
204-
*
205-
* @return true if annotations must be collected for evaluation.
206-
*/
207-
private boolean collectAnnotations() {
208-
return hasUnevaluatedItemsValidator();
209-
}
210-
211-
private boolean hasUnevaluatedItemsValidator() {
212-
if (this.hasUnevaluatedItemsValidator == null) {
213-
this.hasUnevaluatedItemsValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedItems");
214-
}
215-
return hasUnevaluatedItemsValidator;
216-
}
217197
}

src/main/java/com/networknt/schema/keyword/ItemsLegacyValidator.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
9898
// ignores non-arrays
9999
return;
100100
}
101-
boolean collectAnnotations = collectAnnotations();
101+
boolean collectAnnotations = hasUnevaluatedItemsInEvaluationPath(executionContext);
102102

103103
// Add items annotation
104104
if (collectAnnotations || collectAnnotations(executionContext)) {
@@ -211,7 +211,7 @@ private boolean doValidate(ExecutionContext executionContext, int i, JsonNode no
211211

212212
@Override
213213
public void walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, NodePath instanceLocation, boolean shouldValidateSchema) {
214-
boolean collectAnnotations = collectAnnotations();
214+
boolean collectAnnotations = hasUnevaluatedItemsInEvaluationPath(executionContext);
215215

216216
// Add items annotation
217217
if (collectAnnotations || collectAnnotations(executionContext)) {
@@ -394,17 +394,6 @@ public Schema getSchema() {
394394
return this.schema;
395395
}
396396

397-
private boolean collectAnnotations() {
398-
return hasUnevaluatedItemsValidator();
399-
}
400-
401-
private boolean hasUnevaluatedItemsValidator() {
402-
if (this.hasUnevaluatedItemsValidator == null) {
403-
this.hasUnevaluatedItemsValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedItems");
404-
}
405-
return hasUnevaluatedItemsValidator;
406-
}
407-
408397
@Override
409398
public void preloadSchema() {
410399
if (null != this.schema) {
@@ -414,6 +403,5 @@ public void preloadSchema() {
414403
if (null != this.additionalSchema) {
415404
this.additionalSchema.initializeValidators();
416405
}
417-
collectAnnotations(); // cache the flag
418406
}
419407
}

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

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
8585
evaluated = true;
8686
}
8787
if (evaluated) {
88-
if (collectAnnotations() || collectAnnotations(executionContext)) {
88+
if (hasUnevaluatedItemsInEvaluationPath(executionContext) || collectAnnotations(executionContext)) {
8989
// Applies to all
9090
executionContext.getAnnotations()
9191
.put(Annotation.builder().instanceLocation(instanceLocation)
@@ -120,7 +120,7 @@ public void walk(ExecutionContext executionContext, JsonNode node, JsonNode root
120120
}
121121
}
122122
if (evaluated) {
123-
if (collectAnnotations() || collectAnnotations(executionContext)) {
123+
if (hasUnevaluatedItemsInEvaluationPath(executionContext) || collectAnnotations(executionContext)) {
124124
// Applies to all
125125
executionContext.getAnnotations()
126126
.put(Annotation.builder().instanceLocation(instanceLocation)
@@ -189,18 +189,5 @@ public Schema getSchema() {
189189
@Override
190190
public void preloadSchema() {
191191
this.schema.initializeValidators();
192-
collectAnnotations(); // cache the flag
193192
}
194-
195-
private boolean collectAnnotations() {
196-
return hasUnevaluatedItemsValidator();
197-
}
198-
199-
private boolean hasUnevaluatedItemsValidator() {
200-
if (this.hasUnevaluatedItemsValidator == null) {
201-
this.hasUnevaluatedItemsValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedItems");
202-
}
203-
return hasUnevaluatedItemsValidator;
204-
}
205-
206193
}

src/main/java/com/networknt/schema/keyword/PatternPropertiesValidator.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ public class PatternPropertiesValidator extends BaseKeywordValidator {
3434
public static final String PROPERTY = "patternProperties";
3535
private final Map<RegularExpression, Schema> schemas = new IdentityHashMap<>();
3636

37-
private Boolean hasUnevaluatedPropertiesValidator = null;
38-
3937
public PatternPropertiesValidator(SchemaLocation schemaLocation, NodePath evaluationPath, JsonNode schemaNode, Schema parentSchema,
4038
SchemaContext schemaContext) {
4139
super(KeywordType.PATTERN_PROPERTIES, schemaNode, schemaLocation, parentSchema, schemaContext, evaluationPath);
@@ -59,7 +57,7 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
5957
}
6058
Set<String> matchedInstancePropertyNames = null;
6159
Iterator<String> names = node.fieldNames();
62-
boolean collectAnnotations = collectAnnotations() || collectAnnotations(executionContext);
60+
boolean collectAnnotations = hasUnevaluatedPropertiesInEvaluationPath(executionContext) || collectAnnotations(executionContext);
6361
while (names.hasNext()) {
6462
String name = names.next();
6563
JsonNode n = node.get(name);
@@ -96,20 +94,8 @@ public void validate(ExecutionContext executionContext, JsonNode node, JsonNode
9694
}
9795
}
9896

99-
private boolean collectAnnotations() {
100-
return hasUnevaluatedPropertiesValidator();
101-
}
102-
103-
private boolean hasUnevaluatedPropertiesValidator() {
104-
if (this.hasUnevaluatedPropertiesValidator == null) {
105-
this.hasUnevaluatedPropertiesValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedProperties");
106-
}
107-
return hasUnevaluatedPropertiesValidator;
108-
}
109-
11097
@Override
11198
public void preloadSchema() {
11299
preloadSchemas(schemas.values());
113-
collectAnnotations(); // cache the flag
114100
}
115101
}

0 commit comments

Comments
 (0)