Skip to content

Commit cc071ee

Browse files
committed
Add deferred future validation
1 parent 989a6a5 commit cc071ee

File tree

7 files changed

+128
-47
lines changed

7 files changed

+128
-47
lines changed
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.relogiclabs.json.schema.function;
22

3-
import com.relogiclabs.json.schema.exception.JsonSchemaException;
43
import com.relogiclabs.json.schema.tree.RuntimeContext;
54
import com.relogiclabs.json.schema.types.JFunction;
65
import lombok.Getter;
@@ -9,15 +8,13 @@
98
@Getter
109
public abstract class FunctionBase {
1110
protected final RuntimeContext runtime;
12-
13-
@Setter
14-
protected JFunction function;
11+
@Setter protected JFunction function;
1512

1613
public FunctionBase(RuntimeContext runtime) {
1714
this.runtime = runtime;
1815
}
1916

20-
protected boolean failWith(JsonSchemaException exception) {
17+
protected boolean failWith(RuntimeException exception) {
2118
return runtime.failWith(exception);
2219
}
2320
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.relogiclabs.json.schema.function;
2+
3+
@FunctionalInterface
4+
public interface FutureValidator {
5+
boolean validate();
6+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.relogiclabs.json.schema.tree;
2+
3+
import com.relogiclabs.json.schema.types.JRoot;
4+
5+
public interface DataTree {
6+
boolean match(DataTree dataTree);
7+
RuntimeContext getRuntime();
8+
JRoot getRoot();
9+
TreeType getType();
10+
}

src/main/java/com/relogiclabs/json/schema/tree/JsonTree.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,33 @@
1010
import org.antlr.v4.runtime.CharStreams;
1111
import org.antlr.v4.runtime.CommonTokenStream;
1212

13+
import static com.relogiclabs.json.schema.tree.TreeType.JSON_TREE;
14+
1315
@Getter
14-
public final class JsonTree {
16+
public final class JsonTree implements DataTree {
17+
private final RuntimeContext runtime;
1518
private final JRoot root;
1619

17-
public JsonTree(RuntimeContext context, String input) {
20+
public JsonTree(RuntimeContext runtime, String input) {
21+
this.runtime = runtime;
1822
var jsonLexer = new JsonLexer(CharStreams.fromString(input));
1923
jsonLexer.removeErrorListeners();
2024
jsonLexer.addErrorListener(LexerErrorListener.JSON);
2125
var jsonParser = new JsonParser(new CommonTokenStream(jsonLexer));
2226
jsonParser.removeErrorListeners();
2327
jsonParser.addErrorListener(ParserErrorListener.JSON);
24-
root = (JRoot) new JsonTreeVisitor(context).visit(jsonParser.json());
28+
root = (JRoot) new JsonTreeVisitor(runtime).visit(jsonParser.json());
29+
}
30+
31+
@Override
32+
public boolean match(DataTree dataTree) {
33+
var result = root.match(dataTree.getRoot());
34+
result &= runtime.invokeValidators();
35+
return result;
36+
}
37+
38+
@Override
39+
public TreeType getType() {
40+
return JSON_TREE;
2541
}
2642
}
Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
package com.relogiclabs.json.schema.tree;
22

33
import com.relogiclabs.json.schema.exception.DuplicateDefinitionException;
4-
import com.relogiclabs.json.schema.internal.tree.FunctionManager;
5-
import com.relogiclabs.json.schema.internal.tree.PragmaManager;
4+
import com.relogiclabs.json.schema.function.FutureValidator;
5+
import com.relogiclabs.json.schema.internal.tree.ExceptionRegistry;
6+
import com.relogiclabs.json.schema.internal.tree.FunctionRegistry;
7+
import com.relogiclabs.json.schema.internal.tree.PragmaRegistry;
68
import com.relogiclabs.json.schema.message.MessageFormatter;
79
import com.relogiclabs.json.schema.types.JAlias;
810
import com.relogiclabs.json.schema.types.JDefinition;
911
import com.relogiclabs.json.schema.types.JFunction;
1012
import com.relogiclabs.json.schema.types.JInclude;
1113
import com.relogiclabs.json.schema.types.JNode;
1214
import com.relogiclabs.json.schema.types.JPragma;
15+
import com.relogiclabs.json.schema.types.JReceiver;
1316
import com.relogiclabs.json.schema.types.JValidator;
1417
import lombok.Getter;
1518

19+
import java.util.ArrayList;
1620
import java.util.HashMap;
17-
import java.util.LinkedList;
21+
import java.util.List;
1822
import java.util.Map;
19-
import java.util.Queue;
23+
import java.util.UUID;
2024
import java.util.function.Supplier;
2125

2226
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
@@ -25,27 +29,28 @@
2529

2630

2731
public final class RuntimeContext {
28-
private final FunctionManager functionManager;
29-
private final PragmaManager pragmaManager;
30-
private int disableException = 0;
31-
32+
@Getter private final FunctionRegistry functions;
33+
@Getter private final PragmaRegistry pragmas;
3234
@Getter private final Map<JAlias, JValidator> definitions;
33-
@Getter private final boolean throwException;
34-
@Getter private final Queue<Exception> exceptions;
35+
@Getter private final ExceptionRegistry exceptions;
36+
@Getter private final Map<String, FutureValidator> validators;
37+
@Getter private final Map<JReceiver, List<JNode>> receivers;
38+
@Getter private final Map<String, Object> storage;
3539
@Getter private final MessageFormatter messageFormatter;
3640

37-
3841
public RuntimeContext(MessageFormatter messageFormatter, boolean throwException) {
3942
this.messageFormatter = messageFormatter;
40-
this.throwException = throwException;
4143
this.definitions = new HashMap<>();
42-
this.functionManager = new FunctionManager(this);
43-
this.pragmaManager = new PragmaManager();
44-
this.exceptions = new LinkedList<>();
44+
this.functions = new FunctionRegistry(this);
45+
this.pragmas = new PragmaRegistry();
46+
this.exceptions = new ExceptionRegistry(throwException);
47+
this.receivers = new HashMap<>();
48+
this.storage = new HashMap<>();
49+
this.validators = new HashMap<>();
4550
}
4651

4752
public JPragma addPragma(JPragma pragma) {
48-
return pragmaManager.addPragma(pragma);
53+
return pragmas.addPragma(pragma);
4954
}
5055

5156
public JInclude addClass(JInclude include) {
@@ -54,7 +59,7 @@ public JInclude addClass(JInclude include) {
5459
}
5560

5661
public void addClass(String className, Context context) {
57-
functionManager.addClass(className, context);
62+
functions.addClass(className, context);
5863
}
5964

6065
public JDefinition addDefinition(JDefinition definition) {
@@ -68,38 +73,49 @@ DEFI01, concat("Duplicate definition of ", quote(definition.getAlias()),
6873
return definition;
6974
}
7075

71-
public boolean getIgnoreUndefinedProperties() {
72-
return pragmaManager.getIgnoreUndefinedProperties();
76+
public boolean invokeFunction(JFunction function, JNode target) {
77+
return functions.invokeFunction(function, target);
7378
}
7479

75-
public double getFloatingPointTolerance() {
76-
return pragmaManager.getFloatingPointTolerance();
80+
public boolean areEqual(double value1, double value2) {
81+
return Math.abs(value1 - value2) < pragmas.getFloatingPointTolerance();
7782
}
7883

79-
public boolean getIgnoreObjectPropertyOrder() {
80-
return pragmaManager.getIgnoreObjectPropertyOrder();
84+
public <T> T tryExecute(Supplier<T> function) {
85+
return exceptions.tryExecute(function);
8186
}
8287

83-
public boolean invokeFunction(JFunction function, JNode target) {
84-
return functionManager.invokeFunction(function, target);
88+
public void register(List<JReceiver> list) {
89+
for(var r : list) receivers.put(r, new ArrayList<>());
8590
}
8691

87-
public boolean areEqual(double value1, double value2) {
88-
return Math.abs(value1 - value2) < getFloatingPointTolerance();
92+
public void receive(List<JReceiver> list, JNode node) {
93+
for(var r : list) receivers.get(r).add(node);
8994
}
9095

91-
public <T> T tryMatch(Supplier<T> function) {
92-
try {
93-
disableException += 1;
94-
return function.get();
95-
} finally {
96-
disableException -= 1;
97-
}
96+
public List<JNode> fetch(JReceiver receiver) {
97+
return receivers.get(receiver);
98+
}
99+
100+
public boolean addValidator(FutureValidator validator) {
101+
return validators.put(UUID.randomUUID().toString(), validator) == null;
102+
}
103+
104+
public boolean invokeValidators() {
105+
var result = true;
106+
for(var v : validators.values()) result &= v.validate();
107+
return result;
98108
}
99109

100110
public boolean failWith(RuntimeException exception) {
101-
if(throwException && disableException == 0) throw exception;
102-
if(disableException == 0) exceptions.add(exception);
111+
exceptions.tryThrow(exception);
112+
exceptions.tryAdd(exception);
103113
return false;
104114
}
115+
116+
public void clear() {
117+
exceptions.clear();
118+
storage.clear();
119+
for(var v : receivers.values()) v.clear();
120+
}
105121
}

src/main/java/com/relogiclabs/json/schema/tree/SchemaTree.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,33 @@
1010
import org.antlr.v4.runtime.CharStreams;
1111
import org.antlr.v4.runtime.CommonTokenStream;
1212

13+
import static com.relogiclabs.json.schema.tree.TreeType.SCHEMA_TREE;
14+
1315
@Getter
14-
public final class SchemaTree {
16+
public final class SchemaTree implements DataTree {
17+
private final RuntimeContext runtime;
1518
private final JRoot root;
1619

17-
public SchemaTree(RuntimeContext context, String input) {
20+
public SchemaTree(RuntimeContext runtime, String input) {
21+
this.runtime = runtime;
1822
var schemaLexer = new SchemaLexer(CharStreams.fromString(input));
1923
schemaLexer.removeErrorListeners();
2024
schemaLexer.addErrorListener(LexerErrorListener.SCHEMA);
2125
var schemaParser = new SchemaParser(new CommonTokenStream(schemaLexer));
2226
schemaParser.removeErrorListeners();
2327
schemaParser.addErrorListener(ParserErrorListener.SCHEMA);
24-
root = (JRoot) new SchemaTreeVisitor(context).visit(schemaParser.schema());
28+
root = (JRoot) new SchemaTreeVisitor(runtime).visit(schemaParser.schema());
29+
}
30+
31+
@Override
32+
public boolean match(DataTree dataTree) {
33+
var result = root.match(dataTree.getRoot());
34+
result &= runtime.invokeValidators();
35+
return result;
36+
}
37+
38+
@Override
39+
public TreeType getType() {
40+
return SCHEMA_TREE;
2541
}
2642
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.relogiclabs.json.schema.tree;
2+
3+
import lombok.Getter;
4+
5+
@Getter
6+
public enum TreeType {
7+
SCHEMA_TREE("Schema"),
8+
JSON_TREE("Json");
9+
10+
private final String name;
11+
12+
TreeType(String name) {
13+
this.name = name;
14+
}
15+
16+
@Override
17+
public String toString() {
18+
return name;
19+
}
20+
}

0 commit comments

Comments
 (0)