Skip to content

Commit 03bb6e0

Browse files
committed
Refactor discriminator
1 parent f5d86a2 commit 03bb6e0

File tree

11 files changed

+276
-550
lines changed

11 files changed

+276
-550
lines changed

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

Lines changed: 0 additions & 58 deletions
This file was deleted.

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

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,18 @@
1616

1717
package com.networknt.schema;
1818

19-
import com.networknt.schema.annotation.Annotations;
20-
import com.networknt.schema.keyword.DiscriminatorState;
21-
import com.networknt.schema.path.NodePath;
22-
import com.networknt.schema.result.SchemaResults;
23-
import com.networknt.schema.walk.WalkConfig;
24-
2519
import java.util.ArrayList;
2620
import java.util.HashMap;
2721
import java.util.List;
2822
import java.util.Map;
29-
import java.util.Stack;
3023
import java.util.function.Consumer;
3124

25+
import com.networknt.schema.annotation.Annotations;
26+
import com.networknt.schema.keyword.DiscriminatorState;
27+
import com.networknt.schema.path.NodePath;
28+
import com.networknt.schema.result.SchemaResults;
29+
import com.networknt.schema.walk.WalkConfig;
30+
3231
/**
3332
* Stores the execution context for the validation run.
3433
*/
@@ -37,7 +36,6 @@ public class ExecutionContext {
3736
private WalkConfig walkConfig = null;
3837
private CollectorContext collectorContext = null;
3938

40-
private Stack<DiscriminatorContext> discriminatorContexts = null;
4139
private Annotations annotations = null;
4240
private SchemaResults results = null;
4341
private List<Error> errors = new ArrayList<>();
@@ -190,28 +188,6 @@ public void setFailFast(boolean failFast) {
190188
this.failFast = failFast;
191189
}
192190

193-
public DiscriminatorContext getCurrentDiscriminatorContext() {
194-
if (this.discriminatorContexts == null) {
195-
return null;
196-
}
197-
198-
if (!this.discriminatorContexts.empty()) {
199-
return this.discriminatorContexts.peek();
200-
}
201-
return null; // this is the case when we get on a schema that has a discriminator, but it's not used in anyOf
202-
}
203-
204-
public void enterDiscriminatorContext(final DiscriminatorContext ctx, @SuppressWarnings("unused") NodePath instanceLocation) {
205-
if (this.discriminatorContexts == null) {
206-
this.discriminatorContexts = new Stack<>();
207-
}
208-
this.discriminatorContexts.push(ctx);
209-
}
210-
211-
public void leaveDiscriminatorContextImmediately(@SuppressWarnings("unused") NodePath instanceLocation) {
212-
this.discriminatorContexts.pop();
213-
}
214-
215191
public List<Error> getErrors() {
216192
return this.errors;
217193
}

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

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import java.util.function.Consumer;
3131

3232
import com.fasterxml.jackson.databind.JsonNode;
33-
import com.fasterxml.jackson.databind.node.ObjectNode;
34-
import com.networknt.schema.keyword.DiscriminatorValidator;
3533
import com.networknt.schema.keyword.KeywordValidator;
3634
import com.networknt.schema.keyword.TypeValidator;
3735
import com.networknt.schema.path.NodePath;
@@ -678,6 +676,10 @@ private List<KeywordValidator> read(JsonNode schemaNode) {
678676

679677
if (lhsName.equals(rhsName)) return 0;
680678

679+
// Discriminator needs to run first to set state in the execution context
680+
if (lhsName.equals("discriminator")) return -1;
681+
if (rhsName.equals("discriminator")) return 1;
682+
681683
if (lhsName.equals("properties")) return -1;
682684
if (rhsName.equals("properties")) return 1;
683685
if (lhsName.equals("patternProperties")) return -1;
@@ -694,47 +696,10 @@ private List<KeywordValidator> read(JsonNode schemaNode) {
694696

695697
@Override
696698
public void validate(ExecutionContext executionContext, JsonNode jsonNode, JsonNode rootNode, NodePath instanceLocation) {
697-
if (this.schemaContext.isDiscriminatorKeywordEnabled()) {
698-
ObjectNode discriminator = (ObjectNode) schemaNode.get("discriminator");
699-
if (null != discriminator && null != executionContext.getCurrentDiscriminatorContext()) {
700-
executionContext.getCurrentDiscriminatorContext().registerDiscriminator(schemaLocation,
701-
discriminator);
702-
}
703-
}
704699
int currentErrors = executionContext.getErrors().size();
705700
for (KeywordValidator v : getValidators()) {
706701
v.validate(executionContext, jsonNode, rootNode, instanceLocation);
707702
}
708-
709-
if (this.schemaContext.isDiscriminatorKeywordEnabled()) {
710-
ObjectNode discriminator = (ObjectNode) this.schemaNode.get("discriminator");
711-
if (null != discriminator) {
712-
final DiscriminatorContext discriminatorContext = executionContext
713-
.getCurrentDiscriminatorContext();
714-
if (null != discriminatorContext) {
715-
final ObjectNode discriminatorToUse;
716-
final ObjectNode discriminatorFromContext = discriminatorContext
717-
.getDiscriminatorForPath(this.schemaLocation);
718-
if (null == discriminatorFromContext) {
719-
// register the current discriminator. This can only happen when the current context discriminator
720-
// was not registered via allOf. In that case we have a $ref to the schema with discriminator that gets
721-
// used for validation before allOf validation has kicked in
722-
discriminatorContext.registerDiscriminator(this.schemaLocation, discriminator);
723-
discriminatorToUse = discriminator;
724-
} else {
725-
discriminatorToUse = discriminatorFromContext;
726-
}
727-
728-
final String discriminatorPropertyName = discriminatorToUse.get("propertyName").asText();
729-
final JsonNode discriminatorNode = jsonNode.get(discriminatorPropertyName);
730-
final String discriminatorPropertyValue = discriminatorNode == null ? null
731-
: discriminatorNode.asText();
732-
DiscriminatorValidator.checkDiscriminatorMatch(discriminatorContext, discriminatorToUse, discriminatorPropertyValue,
733-
this);
734-
}
735-
}
736-
}
737-
738703
if (executionContext.getErrors().size() > currentErrors) {
739704
// Failed with assertion set result and drop all annotations from this schema
740705
// and all subschemas

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

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,32 @@
1616

1717
package com.networknt.schema.keyword;
1818

19-
import java.util.*;
19+
import java.util.ArrayList;
20+
import java.util.List;
2021

2122
import com.fasterxml.jackson.databind.JsonNode;
22-
import com.fasterxml.jackson.databind.node.ObjectNode;
23-
import com.networknt.schema.DiscriminatorContext;
2423
import com.networknt.schema.ExecutionContext;
24+
import com.networknt.schema.JsonType;
2525
import com.networknt.schema.Schema;
26+
import com.networknt.schema.SchemaContext;
2627
import com.networknt.schema.SchemaException;
27-
import com.networknt.schema.JsonType;
2828
import com.networknt.schema.SchemaLocation;
2929
import com.networknt.schema.TypeFactory;
3030
import com.networknt.schema.path.NodePath;
31-
import com.networknt.schema.SchemaContext;
3231

3332
/**
3433
* {@link KeywordValidator} for allOf.
3534
*/
3635
public class AllOfValidator extends BaseKeywordValidator {
3736
private final List<Schema> schemas;
3837

39-
public AllOfValidator(SchemaLocation schemaLocation, NodePath evaluationPath, JsonNode schemaNode, Schema parentSchema, SchemaContext schemaContext) {
38+
public AllOfValidator(SchemaLocation schemaLocation, NodePath evaluationPath, JsonNode schemaNode,
39+
Schema parentSchema, SchemaContext schemaContext) {
4040
super(KeywordType.ALL_OF, schemaNode, schemaLocation, parentSchema, schemaContext, evaluationPath);
4141
if (!schemaNode.isArray()) {
4242
JsonType nodeType = TypeFactory.getValueNodeType(schemaNode, this.schemaContext.getSchemaRegistryConfig());
43-
throw new SchemaException(error().instanceNode(schemaNode)
44-
.instanceLocation(schemaLocation.getFragment())
45-
.messageKey("type")
46-
.arguments(nodeType.toString(), "array")
47-
.build());
43+
throw new SchemaException(error().instanceNode(schemaNode).instanceLocation(schemaLocation.getFragment())
44+
.messageKey("type").arguments(nodeType.toString(), "array").build());
4845
}
4946
int size = schemaNode.size();
5047
this.schemas = new ArrayList<>(size);
@@ -55,50 +52,25 @@ public AllOfValidator(SchemaLocation schemaLocation, NodePath evaluationPath, Js
5552
}
5653

5754
@Override
58-
public void validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, NodePath instanceLocation) {
55+
public void validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
56+
NodePath instanceLocation) {
5957
validate(executionContext, node, rootNode, instanceLocation, false);
6058
}
6159

62-
protected void validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, NodePath instanceLocation, boolean walk) {
60+
protected void validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
61+
NodePath instanceLocation, boolean walk) {
6362
for (Schema schema : this.schemas) {
6463
if (!walk) {
6564
schema.validate(executionContext, node, rootNode, instanceLocation);
6665
} else {
6766
schema.walk(executionContext, node, rootNode, instanceLocation, true);
6867
}
69-
if (this.schemaContext.isDiscriminatorKeywordEnabled()) {
70-
final Iterator<JsonNode> arrayElements = this.schemaNode.elements();
71-
while (arrayElements.hasNext()) {
72-
final ObjectNode allOfEntry = (ObjectNode) arrayElements.next();
73-
final JsonNode $ref = allOfEntry.get("$ref");
74-
if (null != $ref) {
75-
final DiscriminatorContext currentDiscriminatorContext = executionContext
76-
.getCurrentDiscriminatorContext();
77-
if (null != currentDiscriminatorContext) {
78-
final ObjectNode discriminator = currentDiscriminatorContext
79-
.getDiscriminatorForPath(allOfEntry.get("$ref").asText());
80-
if (null != discriminator) {
81-
DiscriminatorValidator.registerAndMergeDiscriminator(currentDiscriminatorContext, discriminator,
82-
this.parentSchema, instanceLocation);
83-
// now we have to check whether we have hit the right target
84-
final String discriminatorPropertyName = discriminator.get("propertyName").asText();
85-
final JsonNode discriminatorNode = node.get(discriminatorPropertyName);
86-
final String discriminatorPropertyValue = discriminatorNode == null ? null
87-
: discriminatorNode.textValue();
88-
89-
final Schema jsonSchema = this.parentSchema;
90-
DiscriminatorValidator.checkDiscriminatorMatch(currentDiscriminatorContext, discriminator,
91-
discriminatorPropertyValue, jsonSchema);
92-
}
93-
}
94-
}
95-
}
96-
}
9768
}
9869
}
9970

10071
@Override
101-
public void walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, NodePath instanceLocation, boolean shouldValidateSchema) {
72+
public void walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, NodePath instanceLocation,
73+
boolean shouldValidateSchema) {
10274
if (shouldValidateSchema && node != null) {
10375
validate(executionContext, node, rootNode, instanceLocation, true);
10476
return;
@@ -107,7 +79,7 @@ public void walk(ExecutionContext executionContext, JsonNode node, JsonNode root
10779
// Walk through the schema
10880
schema.walk(executionContext, node, rootNode, instanceLocation, false);
10981
}
110-
}
82+
}
11183

11284
@Override
11385
public void preloadSchema() {

0 commit comments

Comments
 (0)