Skip to content

Commit 7904a26

Browse files
committed
Update error handlers and messages
1 parent 824dd37 commit 7904a26

19 files changed

+295
-226
lines changed

src/main/java/com/relogiclabs/json/schema/exception/FunctionMismatchException.java

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

src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeValidator.java

Lines changed: 108 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,126 @@
22

33
import com.relogiclabs.json.schema.exception.InvalidDateTimeException;
44
import com.relogiclabs.json.schema.internal.antlr.DateTimeLexer;
5-
import com.relogiclabs.json.schema.internal.util.DebugUtils;
5+
import com.relogiclabs.json.schema.internal.util.DebugUtilities;
66
import com.relogiclabs.json.schema.internal.util.LexerErrorListener;
7+
import com.relogiclabs.json.schema.internal.util.Reference;
78
import org.antlr.v4.runtime.CharStreams;
89
import org.antlr.v4.runtime.Token;
910

1011
import java.util.HashMap;
1112
import java.util.List;
1213
import java.util.Map;
1314

15+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.CLOCK_AM_PM;
16+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.DAY_NUMBER;
17+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.DAY_NUMBER2;
18+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.ERA;
19+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER;
20+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER1;
21+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER2;
22+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER3;
23+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER4;
24+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER5;
25+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER6;
26+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.HOUR_NUMBER;
27+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.HOUR_NUMBER2;
28+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MINUTE_NUMBER;
29+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MINUTE_NUMBER2;
30+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NAME;
31+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NUMBER;
32+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NUMBER2;
33+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_SHORT_NAME;
34+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SECOND_NUMBER;
35+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SECOND_NUMBER2;
36+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SYMBOL;
37+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.TEXT;
38+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_HOUR;
39+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_TIME1;
40+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_TIME2;
41+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WEEKDAY_NAME;
42+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WEEKDAY_SHORT_NAME;
43+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WHITESPACE;
44+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.YEAR_NUMBER2;
45+
import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.YEAR_NUMBER4;
46+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.ClockAmPm;
47+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.DayNumber;
48+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.DayNumber2;
49+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Era;
50+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber;
51+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber1;
52+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber2;
53+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber3;
54+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber4;
55+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber5;
56+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber6;
57+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.HourNumber;
58+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.HourNumber2;
59+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MinuteNumber;
60+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MinuteNumber2;
61+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthName;
62+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthNumber;
63+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthNumber2;
64+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthShortName;
65+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.SecondNumber;
66+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.SecondNumber2;
67+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Symbol;
68+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Text;
69+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetHour;
70+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetTime1;
71+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetTime2;
72+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.WeekdayName;
73+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.WeekdayShortName;
74+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Whitespace;
75+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.YearNumber2;
76+
import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.YearNumber4;
1477
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
1578
import static com.relogiclabs.json.schema.message.ErrorCode.DINV02;
1679

17-
public class DateTimeValidator {
80+
public final class DateTimeValidator {
1881
public static final String ISO_8601_DATE = "YYYY-MM-DD";
19-
public static final String ISO_8601_TIME = "YYYY-MM-DD'T'hh:mm:ss.fffZZ";
82+
public static final String ISO_8601_TIME = "YYYY-MM-DD'T'hh:mm:ss.FZZ";
2083

2184
private static final Map<String, SegmentProcessor> PROCESSORS;
2285
private final DateTimeLexer dateTimeLexer;
2386
private final List<Token> lexerTokens;
2487

2588
static {
2689
PROCESSORS = new HashMap<>(50);
27-
PROCESSORS.put("TEXT", SegmentProcessor.Text);
28-
PROCESSORS.put("SYMBOL", SegmentProcessor.Symbol);
29-
PROCESSORS.put("WHITESPACE", SegmentProcessor.Whitespace);
30-
PROCESSORS.put("ERA", SegmentProcessor.Era);
31-
PROCESSORS.put("YEAR_NUM4", SegmentProcessor.YearNum4);
32-
PROCESSORS.put("YEAR_NUM2", SegmentProcessor.YearNum2);
33-
PROCESSORS.put("MONTH_NAME", SegmentProcessor.MonthName);
34-
PROCESSORS.put("MONTH_SHORT_NAME", SegmentProcessor.MonthShortName);
35-
PROCESSORS.put("MONTH_NUM2", SegmentProcessor.MonthNum2);
36-
PROCESSORS.put("MONTH_NUM", SegmentProcessor.MonthNum);
37-
PROCESSORS.put("WEEKDAY_NAME", SegmentProcessor.WeekdayName);
38-
PROCESSORS.put("WEEKDAY_SHORT_NAME", SegmentProcessor.WeekdayShortName);
39-
PROCESSORS.put("DAY_NUM2", SegmentProcessor.DayNum2);
40-
PROCESSORS.put("DAY_NUM", SegmentProcessor.DayNum);
41-
PROCESSORS.put("AM_PM", SegmentProcessor.AmPm);
42-
PROCESSORS.put("HOUR_NUM2", SegmentProcessor.HourNum2);
43-
PROCESSORS.put("HOUR_NUM", SegmentProcessor.HourNum);
44-
PROCESSORS.put("MINUTE_NUM2", SegmentProcessor.MinuteNum2);
45-
PROCESSORS.put("MINUTE_NUM", SegmentProcessor.MinuteNum);
46-
PROCESSORS.put("SECOND_NUM2", SegmentProcessor.SecondNum2);
47-
PROCESSORS.put("SECOND_NUM", SegmentProcessor.SecondNum);
48-
PROCESSORS.put("FRACTION_NUM", SegmentProcessor.FractionNum);
49-
PROCESSORS.put("FRACTION_NUM01", SegmentProcessor.FractionNum01);
50-
PROCESSORS.put("FRACTION_NUM02", SegmentProcessor.FractionNum02);
51-
PROCESSORS.put("FRACTION_NUM03", SegmentProcessor.FractionNum03);
52-
PROCESSORS.put("FRACTION_NUM04", SegmentProcessor.FractionNum04);
53-
PROCESSORS.put("FRACTION_NUM05", SegmentProcessor.FractionNum05);
54-
PROCESSORS.put("FRACTION_NUM06", SegmentProcessor.FractionNum06);
55-
PROCESSORS.put("UTC_OFFSET_HOUR", SegmentProcessor.UtcOffsetHour);
56-
PROCESSORS.put("UTC_OFFSET_TIME1", SegmentProcessor.UtcOffsetTime1);
57-
PROCESSORS.put("UTC_OFFSET_TIME2", SegmentProcessor.UtcOffsetTime2);
90+
addProcessor(TEXT, Text);
91+
addProcessor(SYMBOL, Symbol);
92+
addProcessor(WHITESPACE, Whitespace);
93+
addProcessor(ERA, Era);
94+
addProcessor(YEAR_NUMBER4, YearNumber4);
95+
addProcessor(YEAR_NUMBER2, YearNumber2);
96+
addProcessor(MONTH_NAME, MonthName);
97+
addProcessor(MONTH_SHORT_NAME, MonthShortName);
98+
addProcessor(MONTH_NUMBER2, MonthNumber2);
99+
addProcessor(MONTH_NUMBER, MonthNumber);
100+
addProcessor(WEEKDAY_NAME, WeekdayName);
101+
addProcessor(WEEKDAY_SHORT_NAME, WeekdayShortName);
102+
addProcessor(DAY_NUMBER2, DayNumber2);
103+
addProcessor(DAY_NUMBER, DayNumber);
104+
addProcessor(CLOCK_AM_PM, ClockAmPm);
105+
addProcessor(HOUR_NUMBER2, HourNumber2);
106+
addProcessor(HOUR_NUMBER, HourNumber);
107+
addProcessor(MINUTE_NUMBER2, MinuteNumber2);
108+
addProcessor(MINUTE_NUMBER, MinuteNumber);
109+
addProcessor(SECOND_NUMBER2, SecondNumber2);
110+
addProcessor(SECOND_NUMBER, SecondNumber);
111+
addProcessor(FRACTION_NUMBER, FractionNumber);
112+
addProcessor(FRACTION_NUMBER1, FractionNumber1);
113+
addProcessor(FRACTION_NUMBER2, FractionNumber2);
114+
addProcessor(FRACTION_NUMBER3, FractionNumber3);
115+
addProcessor(FRACTION_NUMBER4, FractionNumber4);
116+
addProcessor(FRACTION_NUMBER5, FractionNumber5);
117+
addProcessor(FRACTION_NUMBER6, FractionNumber6);
118+
addProcessor(UTC_OFFSET_HOUR, UtcOffsetHour);
119+
addProcessor(UTC_OFFSET_TIME1, UtcOffsetTime1);
120+
addProcessor(UTC_OFFSET_TIME2, UtcOffsetTime2);
121+
}
122+
123+
private static void addProcessor(int index, SegmentProcessor processor) {
124+
PROCESSORS.put(DateTimeLexer.ruleNames[index - 1], processor);
58125
}
59126

60127
@SuppressWarnings("unchecked")
@@ -74,7 +141,7 @@ private void Validate(String input, DateTimeContext context) {
74141
concat("Invalid ", context.getType(), " input format"));
75142

76143
context.validate();
77-
DebugUtils.print(context);
144+
DebugUtilities.print(context);
78145
}
79146

80147
public void ValidateDate(String input) {
@@ -85,22 +152,24 @@ public void ValidateTime(String input) {
85152
Validate(input, new DateTimeContext(DateTimeType.TIME_TYPE));
86153
}
87154

88-
public boolean IsValidDate(String input) {
155+
public boolean IsValidDate(String input, Reference<String> error) {
89156
try {
90157
ValidateDate(input);
91158
return true;
92159
} catch(InvalidDateTimeException e) {
93-
DebugUtils.print(e);
160+
DebugUtilities.print(e);
161+
error.setValue(e.getMessage());
94162
return false;
95163
}
96164
}
97165

98-
public boolean IsValidTime(String input) {
166+
public boolean IsValidTime(String input, Reference<String> error) {
99167
try {
100168
ValidateTime(input);
101169
return true;
102170
} catch(InvalidDateTimeException e) {
103-
DebugUtils.print(e);
171+
DebugUtilities.print(e);
172+
error.setValue(e.getMessage());
104173
return false;
105174
}
106175
}

src/main/java/com/relogiclabs/json/schema/internal/tree/FunctionManager.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33
import com.relogiclabs.json.schema.exception.ClassInstantiationException;
44
import com.relogiclabs.json.schema.exception.CommonException;
55
import com.relogiclabs.json.schema.exception.DuplicateIncludeException;
6-
import com.relogiclabs.json.schema.exception.FunctionMismatchException;
76
import com.relogiclabs.json.schema.exception.FunctionNotFoundException;
87
import com.relogiclabs.json.schema.exception.InvalidFunctionException;
98
import com.relogiclabs.json.schema.exception.InvalidIncludeException;
9+
import com.relogiclabs.json.schema.exception.JsonSchemaException;
1010
import com.relogiclabs.json.schema.exception.NotFoundClassException;
1111
import com.relogiclabs.json.schema.function.FunctionBase;
12+
import com.relogiclabs.json.schema.message.ActualDetail;
13+
import com.relogiclabs.json.schema.message.ErrorDetail;
14+
import com.relogiclabs.json.schema.message.ExpectedDetail;
1215
import com.relogiclabs.json.schema.message.MessageFormatter;
1316
import com.relogiclabs.json.schema.tree.Context;
1417
import com.relogiclabs.json.schema.tree.RuntimeContext;
1518
import com.relogiclabs.json.schema.types.JFunction;
1619
import com.relogiclabs.json.schema.types.JNode;
17-
import com.relogiclabs.json.schema.types.JsonType;
1820

1921
import java.lang.reflect.Array;
2022
import java.lang.reflect.InvocationTargetException;
@@ -26,6 +28,7 @@
2628
import java.util.Map;
2729
import java.util.Set;
2830

31+
import static com.relogiclabs.json.schema.internal.message.MessageHelper.getTypeName;
2932
import static com.relogiclabs.json.schema.internal.tree.MethodPointer.getSignature;
3033
import static com.relogiclabs.json.schema.internal.util.CollectionHelper.merge;
3134
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
@@ -42,7 +45,7 @@
4245
import static com.relogiclabs.json.schema.message.ErrorCode.FUNC04;
4346
import static com.relogiclabs.json.schema.message.ErrorCode.FUNC05;
4447

45-
public class FunctionManager {
48+
public final class FunctionManager {
4649
private final Set<String> includes;
4750
private final Map<FunctionKey, List<MethodPointer>> functions;
4851
private final RuntimeContext runtime;
@@ -127,32 +130,30 @@ private static CommonException createException(String code, Exception ex, Class<
127130

128131
public boolean invokeFunction(JFunction function, JNode target) {
129132
var methods = getMethods(function);
130-
String mismatchMessage = null;
133+
Parameter mismatchParameter = null;
134+
131135
for(var method : methods) {
132136
var parameters = method.getParameters();
133137
var arguments = function.getArguments();
134138
var schemaArgs = processArgs(parameters, arguments);
135139
if(schemaArgs == null) continue;
136-
if(!isMatch(parameters.get(0), target)) {
137-
mismatchMessage = "Function %s is applicable on %s but applied on %s of %s"
138-
.formatted(function.getOutline(), getTypeName(parameters.get(0).getType()),
139-
getTypeName(target.getClass()), target);
140-
continue;
141-
}
142-
return method.invoke(function, addTarget(schemaArgs, target));
140+
if(isMatch(parameters.get(0), target))
141+
return method.invoke(function, addTarget(schemaArgs, target));
142+
mismatchParameter = parameters.get(0);
143143
}
144-
if(mismatchMessage != null) return failWith(new FunctionMismatchException(
145-
MessageFormatter.formatForSchema(FUNC03, mismatchMessage, function.getContext())));
144+
145+
if(mismatchParameter != null)
146+
return failWith(new JsonSchemaException(new ErrorDetail(FUNC03,
147+
"Function ", function.getOutline(), " is incompatible with the target data type"),
148+
new ExpectedDetail(function, "applying to a supported data type such as ",
149+
getTypeName(mismatchParameter.getType())),
150+
new ActualDetail(target, "applied to an unsupported data type ",
151+
getTypeName(target.getClass()), " of ", target)));
152+
146153
return failWith(new FunctionNotFoundException(MessageFormatter
147154
.formatForSchema(FUNC04, function.getOutline(), function.getContext())));
148155
}
149156

150-
private static String getTypeName(Class<?> type) {
151-
JsonType t = JsonType.from(type);
152-
if(t != null) return t.getName();
153-
else return type.getSimpleName();
154-
}
155-
156157
private List<MethodPointer> getMethods(JFunction function) {
157158
var methodPointers = functions.get(new FunctionKey(function));
158159
if(methodPointers == null)

src/main/java/com/relogiclabs/json/schema/internal/tree/TreeHelper.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
import static com.relogiclabs.json.schema.internal.util.StreamHelper.halt;
1111
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
1212
import static com.relogiclabs.json.schema.internal.util.StringHelper.quote;
13-
import static com.relogiclabs.json.schema.message.ErrorCode.PROP03;
1413
import static java.util.stream.Collectors.toMap;
1514

16-
public class TreeHelper {
15+
public final class TreeHelper {
1716

18-
public static List<JProperty> checkForDuplicate(List<JProperty> list) {
17+
public static List<JProperty> checkForDuplicate(List<JProperty> list, String errorCode) {
1918
list.stream().collect(toMap(JProperty::getKey, Function.identity(),
2019
(p1, p2) -> halt(new DuplicatePropertyKeyException(MessageFormatter.formatForJson(
21-
PROP03, concat("Multiple key with name ", quote(p2.getKey()), " found"),
20+
errorCode, concat("Multiple key with name ", quote(p2.getKey()), " found"),
2221
p2.getContext())))
2322
));
2423
return list;

src/main/java/com/relogiclabs/json/schema/internal/util/CollectionHelper.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
import com.relogiclabs.json.schema.types.JProperty;
66
import com.relogiclabs.json.schema.types.JString;
77

8+
import java.util.ArrayList;
89
import java.util.Arrays;
10+
import java.util.Collection;
11+
import java.util.Collections;
912
import java.util.List;
1013
import java.util.Map;
1114
import java.util.Set;
1215

1316
import static java.util.stream.Collectors.toSet;
1417

15-
public class CollectionHelper {
18+
public final class CollectionHelper {
1619
public static <K, V> void merge(Map<K, List<V>> target, Map<K, List<V>> source) {
1720
source.forEach((sk, sv) -> {
1821
var tv = target.get(sk);
@@ -33,4 +36,21 @@ public static Set<JNode> containsValues(IndexMap<String, JProperty> map, JNode..
3336
map.values().stream().forEach(p -> set.remove(p.getValue()));
3437
return set;
3538
}
39+
40+
@SafeVarargs
41+
public static <T> List<T> asList(T... elements) {
42+
List<T> list = new ArrayList<>(elements.length);
43+
for(var e : elements) if(e != null) list.add(e);
44+
return Collections.unmodifiableList(list);
45+
}
46+
47+
@SafeVarargs
48+
public static <T> void addToList(Collection<T> source, T... elements) {
49+
for(var e : elements) if(e != null) source.add(e);
50+
}
51+
52+
@SafeVarargs
53+
public static <T> void addToList(Collection<T> source, Collection<? extends T>... collections) {
54+
for(var c : collections) if(c != null) source.addAll(c);
55+
}
3656
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.relogiclabs.json.schema.internal.util;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public final class Reference<V> {
7+
private V value;
8+
9+
public Reference() {
10+
value = null;
11+
}
12+
13+
public Reference(V initialValue) {
14+
this.value = initialValue;
15+
}
16+
}

src/main/java/com/relogiclabs/json/schema/message/ErrorCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public interface ErrorCode {
120120
String PROP04 = "PROP04";
121121
String PROP05 = "PROP05";
122122
String PROP06 = "PROP06";
123+
String PROP07 = "PROP07";
123124
String RANG01 = "RANG01";
124125
String RANG02 = "RANG02";
125126
String RANG03 = "RANG03";

0 commit comments

Comments
 (0)