Skip to content

Commit dc35ab1

Browse files
committed
Update schema nodes for script engine
1 parent 5e7ed38 commit dc35ab1

38 files changed

+1461
-95
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.relogiclabs.jschema.node;
2+
3+
public interface Derivable {
4+
JNode getDerived();
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.relogiclabs.jschema.node;
2+
3+
import com.relogiclabs.jschema.exception.DefinitionNotFoundException;
4+
import com.relogiclabs.jschema.internal.builder.JAliasBuilder;
5+
import lombok.EqualsAndHashCode;
6+
import lombok.Getter;
7+
8+
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
9+
import static com.relogiclabs.jschema.message.ErrorCode.DEFI02;
10+
import static com.relogiclabs.jschema.message.MessageFormatter.formatForSchema;
11+
import static java.util.Objects.requireNonNull;
12+
13+
@Getter
14+
@EqualsAndHashCode
15+
public final class JAlias extends JLeaf {
16+
private final String name;
17+
18+
private JAlias(JAliasBuilder builder) {
19+
super(builder);
20+
name = requireNonNull(builder.name());
21+
}
22+
23+
public static JAlias from(JAliasBuilder builder) {
24+
return new JAlias(builder).initialize();
25+
}
26+
27+
@Override
28+
public boolean match(JNode node) {
29+
var definitions = getRuntime().getDefinitions();
30+
if(!definitions.containsKey(this)) throw new DefinitionNotFoundException(formatForSchema(
31+
DEFI02, concat("Definition of '", name, "' not found"), getContext()));
32+
return definitions.get(this).match(node);
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return name;
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.relogiclabs.jschema.node;
2+
3+
import com.relogiclabs.jschema.exception.JsonSchemaException;
4+
import com.relogiclabs.jschema.exception.MisplacedOptionalException;
5+
import com.relogiclabs.jschema.internal.builder.JArrayBuilder;
6+
import com.relogiclabs.jschema.internal.message.ActualHelper;
7+
import com.relogiclabs.jschema.internal.message.ExpectedHelper;
8+
import com.relogiclabs.jschema.message.ErrorDetail;
9+
import com.relogiclabs.jschema.type.EArray;
10+
import com.relogiclabs.jschema.type.EValue;
11+
import lombok.EqualsAndHashCode;
12+
import lombok.Getter;
13+
14+
import java.util.Collection;
15+
import java.util.Iterator;
16+
import java.util.List;
17+
18+
import static com.relogiclabs.jschema.internal.message.MessageHelper.ArrayElementNotFound;
19+
import static com.relogiclabs.jschema.internal.util.StringHelper.joinWith;
20+
import static com.relogiclabs.jschema.message.ErrorCode.ARRY01;
21+
import static com.relogiclabs.jschema.message.ErrorCode.ARRY02;
22+
import static com.relogiclabs.jschema.message.MessageFormatter.formatForSchema;
23+
import static java.util.Objects.requireNonNull;
24+
25+
@Getter
26+
@EqualsAndHashCode
27+
public final class JArray extends JComposite implements EArray, Iterable<JNode> {
28+
private final List<JNode> elements;
29+
30+
private JArray(JArrayBuilder builder) {
31+
super(builder);
32+
elements = requireNonNull(builder.elements());
33+
children = elements;
34+
}
35+
36+
public static JArray from(JArrayBuilder builder) {
37+
return new JArray(builder).initialize();
38+
}
39+
40+
@Override
41+
public Collection<? extends JNode> components() {
42+
return elements;
43+
}
44+
45+
@Override
46+
public boolean match(JNode node) {
47+
var other = castType(node, JArray.class);
48+
if(other == null) return false;
49+
boolean result = true, restOptional = false;
50+
for(var i = 0; i < elements.size(); i++) {
51+
var optional = isOptional(elements.get(i));
52+
if((restOptional |= optional) != optional)
53+
return fail(new MisplacedOptionalException(formatForSchema(ARRY02,
54+
"Mandatory array element cannot appear after optional element",
55+
elements.get(i))));
56+
if(i >= other.elements.size() && !optional)
57+
return fail(new JsonSchemaException(
58+
new ErrorDetail(ARRY01, ArrayElementNotFound),
59+
ExpectedHelper.asArrayElementNotFound(elements.get(i), i),
60+
ActualHelper.asArrayElementNotFound(other, i)));
61+
if(i >= other.elements.size()) continue;
62+
result &= elements.get(i).match(other.elements.get(i));
63+
}
64+
return result;
65+
}
66+
67+
private static boolean isOptional(JNode node) {
68+
if(node instanceof JValidator validator)
69+
return validator.isOptional();
70+
return false;
71+
}
72+
73+
@Override
74+
public EValue get(int index) {
75+
return elements.get(index);
76+
}
77+
78+
@Override
79+
public List<? extends EValue> elements() {
80+
return elements;
81+
}
82+
83+
@Override
84+
public Iterator<JNode> iterator() {
85+
return elements.iterator();
86+
}
87+
88+
@Override
89+
public String toString() {
90+
return joinWith(elements, ", ", "[", "]");
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.relogiclabs.jschema.node;
2+
3+
import com.relogiclabs.jschema.exception.JsonSchemaException;
4+
import com.relogiclabs.jschema.internal.builder.JBooleanBuilder;
5+
import com.relogiclabs.jschema.internal.message.ActualHelper;
6+
import com.relogiclabs.jschema.internal.message.ExpectedHelper;
7+
import com.relogiclabs.jschema.message.ErrorDetail;
8+
import com.relogiclabs.jschema.type.EBoolean;
9+
import lombok.EqualsAndHashCode;
10+
11+
import static com.relogiclabs.jschema.internal.message.MessageHelper.ValueMismatch;
12+
import static com.relogiclabs.jschema.message.ErrorCode.BOOL01;
13+
import static java.util.Objects.requireNonNull;
14+
15+
@EqualsAndHashCode
16+
public final class JBoolean extends JPrimitive implements EBoolean, PragmaValue<Boolean> {
17+
private final boolean value;
18+
19+
private JBoolean(JBooleanBuilder builder) {
20+
super(builder);
21+
value = requireNonNull(builder.value());
22+
}
23+
24+
public static JBoolean from(JBooleanBuilder builder) {
25+
return new JBoolean(builder).initialize();
26+
}
27+
28+
@Override
29+
public boolean match(JNode node) {
30+
var other = castType(node, JBoolean.class);
31+
if(other == null) return false;
32+
if(value == other.value) return true;
33+
return fail(new JsonSchemaException(
34+
new ErrorDetail(BOOL01, ValueMismatch),
35+
ExpectedHelper.asValueMismatch(this),
36+
ActualHelper.asValueMismatch(other)));
37+
}
38+
39+
@Override
40+
public boolean getValue() {
41+
return value;
42+
}
43+
44+
@Override
45+
public Boolean toNativeValue() {
46+
return value;
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return String.valueOf(value);
52+
}
53+
}

src/main/java/com/relogiclabs/json/schema/type/JBranch.java renamed to src/main/java/com/relogiclabs/jschema/node/JBranch.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.internal.builder.JNodeBuilder;
3+
import com.relogiclabs.jschema.internal.builder.JNodeBuilder;
44

55
public abstract class JBranch extends JNode {
66
JBranch(JNodeBuilder<?> builder) {

src/main/java/com/relogiclabs/json/schema/type/JComposite.java renamed to src/main/java/com/relogiclabs/jschema/node/JComposite.java

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.internal.builder.JNodeBuilder;
3+
import com.relogiclabs.jschema.internal.builder.JNodeBuilder;
44

55
import java.util.Collection;
66

@@ -11,11 +11,6 @@ public abstract class JComposite extends JBranch implements JsonTypable {
1111

1212
public abstract Collection<? extends JNode> components();
1313

14-
@Override
15-
public JsonType getType() {
16-
return JsonType.COMPOSITE;
17-
}
18-
1914
@Override
2015
public JNode getNode() {
2116
return this;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.relogiclabs.jschema.node;
2+
3+
import com.relogiclabs.jschema.exception.DefinitionNotFoundException;
4+
import com.relogiclabs.jschema.exception.JsonSchemaException;
5+
import com.relogiclabs.jschema.internal.builder.JDataTypeBuilder;
6+
import com.relogiclabs.jschema.internal.message.ActualHelper;
7+
import com.relogiclabs.jschema.internal.message.ExpectedHelper;
8+
import com.relogiclabs.jschema.message.ErrorDetail;
9+
import com.relogiclabs.jschema.util.Reference;
10+
import lombok.EqualsAndHashCode;
11+
import lombok.Getter;
12+
13+
import static com.relogiclabs.jschema.internal.message.MessageHelper.DataTypeArgumentFailed;
14+
import static com.relogiclabs.jschema.internal.message.MessageHelper.DataTypeMismatch;
15+
import static com.relogiclabs.jschema.internal.util.CollectionHelper.asList;
16+
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
17+
import static com.relogiclabs.jschema.message.ErrorCode.DEFI03;
18+
import static com.relogiclabs.jschema.message.ErrorCode.DEFI04;
19+
import static com.relogiclabs.jschema.message.ErrorCode.DTYP04;
20+
import static com.relogiclabs.jschema.message.ErrorCode.DTYP05;
21+
import static com.relogiclabs.jschema.message.ErrorCode.DTYP06;
22+
import static com.relogiclabs.jschema.message.ErrorCode.DTYP07;
23+
import static com.relogiclabs.jschema.message.MessageFormatter.formatForSchema;
24+
import static java.util.Objects.requireNonNull;
25+
import static org.apache.commons.lang3.StringUtils.isEmpty;
26+
import static org.apache.commons.lang3.StringUtils.uncapitalize;
27+
28+
@Getter
29+
@EqualsAndHashCode
30+
public final class JDataType extends JBranch implements NestedMode {
31+
static final String NESTED_MARKER = "*";
32+
static final String DATA_TYPE_NAME = "DATA_TYPE_NAME";
33+
private final JsonType jsonType;
34+
private final JAlias alias;
35+
private final boolean nested;
36+
37+
private JDataType(JDataTypeBuilder builder) {
38+
super(builder);
39+
jsonType = requireNonNull(builder.jsonType());
40+
nested = requireNonNull(builder.nested());
41+
alias = builder.alias();
42+
children = asList(alias);
43+
}
44+
45+
public static JDataType from(JDataTypeBuilder builder) {
46+
return new JDataType(builder).initialize();
47+
}
48+
49+
@Override
50+
public boolean match(JNode node) {
51+
Reference<String> error = new Reference<>();
52+
if(!jsonType.match(node, error)) return failTypeWith(new JsonSchemaException(
53+
new ErrorDetail(nested ? DTYP06 : DTYP04,
54+
formatMessage(DataTypeMismatch, error.getValue())),
55+
ExpectedHelper.asDataTypeMismatch(this),
56+
ActualHelper.asDataTypeMismatch(node)));
57+
if(alias == null) return true;
58+
var validator = getRuntime().getDefinitions().get(alias);
59+
if(validator == null) return fail(new DefinitionNotFoundException(formatForSchema(
60+
nested ? DEFI04 : DEFI03, concat("No definition found for '", alias, "'"), this)));
61+
if(!validator.match(node)) return fail(new JsonSchemaException(
62+
new ErrorDetail(nested ? DTYP07 : DTYP05, DataTypeArgumentFailed),
63+
ExpectedHelper.asDataTypeArgumentFailed(this),
64+
ActualHelper.asDataTypeArgumentFailed(node)));
65+
return true;
66+
}
67+
68+
private boolean failTypeWith(JsonSchemaException exception) {
69+
exception.setAttribute(DATA_TYPE_NAME, toString(true));
70+
return fail(exception);
71+
}
72+
73+
private static String formatMessage(String main, String optional) {
74+
return isEmpty(optional) ? main : concat(main, " (", uncapitalize(optional), ")");
75+
}
76+
77+
boolean isApplicable(JNode node) {
78+
return !nested || node instanceof JComposite;
79+
}
80+
81+
boolean isMatchNull() {
82+
return !nested && jsonType.isNullType();
83+
}
84+
85+
@Override
86+
public String toString() {
87+
return toString(false);
88+
}
89+
90+
public String toString(boolean baseForm) {
91+
var builder = new StringBuilder(jsonType.toString());
92+
if(nested && !baseForm) builder.append(NESTED_MARKER);
93+
if(alias != null && !baseForm) builder.append("(").append(alias).append(")");
94+
return builder.toString();
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.time.JsonDateTime;
3+
import com.relogiclabs.jschema.time.JsonDateTime;
4+
import com.relogiclabs.jschema.type.EType;
45

56
public final class JDate extends JDateTime {
67
private JDate(JString node, JsonDateTime dateTime) {
@@ -11,7 +12,7 @@ public static JDate from(JString node, JsonDateTime dateTime) {
1112
return new JDate(node, dateTime);
1213
}
1314

14-
public JsonType getType() {
15-
return JsonType.DATE;
15+
public EType getType() {
16+
return EType.DATE;
1617
}
1718
}

src/main/java/com/relogiclabs/json/schema/type/JDateTime.java renamed to src/main/java/com/relogiclabs/jschema/node/JDateTime.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.internal.time.DateTimeParser;
4-
import com.relogiclabs.json.schema.time.JsonDateTime;
3+
import com.relogiclabs.jschema.internal.time.DateTimeParser;
4+
import com.relogiclabs.jschema.time.JsonDateTime;
5+
import com.relogiclabs.jschema.type.EType;
56
import lombok.EqualsAndHashCode;
67
import lombok.Getter;
78

@@ -16,8 +17,8 @@ public abstract class JDateTime extends JString {
1617
}
1718

1819
public DateTimeParser getDateTimeParser() {
19-
if(getType() == JsonType.DATE) return getRuntime().getPragmas().getDateTypeParser();
20-
if(getType() == JsonType.TIME) return getRuntime().getPragmas().getTimeTypeParser();
20+
if(getType() == EType.DATE) return getRuntime().getPragmas().getDateTypeParser();
21+
if(getType() == EType.TIME) return getRuntime().getPragmas().getTimeTypeParser();
2122
throw new IllegalStateException("Invalid date time type");
2223
}
2324
}

src/main/java/com/relogiclabs/json/schema/type/JDefinition.java renamed to src/main/java/com/relogiclabs/jschema/node/JDefinition.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.internal.builder.JDefinitionBuilder;
3+
import com.relogiclabs.jschema.internal.builder.JDefinitionBuilder;
44
import lombok.EqualsAndHashCode;
55
import lombok.Getter;
66

7-
import static com.relogiclabs.json.schema.internal.util.CollectionHelper.asList;
8-
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
7+
import static com.relogiclabs.jschema.internal.util.CollectionHelper.asList;
8+
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
99
import static java.util.Objects.requireNonNull;
1010

1111
@Getter

src/main/java/com/relogiclabs/json/schema/type/JDirective.java renamed to src/main/java/com/relogiclabs/jschema/node/JDirective.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.relogiclabs.json.schema.type;
1+
package com.relogiclabs.jschema.node;
22

3-
import com.relogiclabs.json.schema.internal.builder.JNodeBuilder;
3+
import com.relogiclabs.jschema.internal.builder.JNodeBuilder;
44

55
public abstract class JDirective extends JNode {
66
JDirective(JNodeBuilder<?> builder) {

0 commit comments

Comments
 (0)