Skip to content

Commit d9d6f4a

Browse files
committed
Add and update validation functions
1 parent 36aaccb commit d9d6f4a

File tree

7 files changed

+163
-82
lines changed

7 files changed

+163
-82
lines changed

src/main/java/com/relogiclabs/json/schema/function/CoreFunctions2.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
import com.relogiclabs.json.schema.message.ErrorDetail;
66
import com.relogiclabs.json.schema.message.ExpectedDetail;
77
import com.relogiclabs.json.schema.tree.RuntimeContext;
8-
import com.relogiclabs.json.schema.types.JArray;
9-
import com.relogiclabs.json.schema.types.JBoolean;
10-
import com.relogiclabs.json.schema.types.JNumber;
11-
import com.relogiclabs.json.schema.types.JObject;
12-
import com.relogiclabs.json.schema.types.JString;
13-
import com.relogiclabs.json.schema.types.JUndefined;
8+
import com.relogiclabs.json.schema.type.JArray;
9+
import com.relogiclabs.json.schema.type.JBoolean;
10+
import com.relogiclabs.json.schema.type.JNumber;
11+
import com.relogiclabs.json.schema.type.JObject;
12+
import com.relogiclabs.json.schema.type.JString;
13+
import com.relogiclabs.json.schema.type.JUndefined;
1414

1515
import java.util.Arrays;
1616
import java.util.function.Supplier;
@@ -25,10 +25,12 @@
2525
import static com.relogiclabs.json.schema.message.ErrorCode.MINI02;
2626
import static com.relogiclabs.json.schema.message.ErrorCode.MINI03;
2727
import static com.relogiclabs.json.schema.message.ErrorCode.NEGI01;
28+
import static com.relogiclabs.json.schema.message.ErrorCode.NEGI02;
2829
import static com.relogiclabs.json.schema.message.ErrorCode.NEMT01;
2930
import static com.relogiclabs.json.schema.message.ErrorCode.NEMT02;
3031
import static com.relogiclabs.json.schema.message.ErrorCode.NEMT03;
3132
import static com.relogiclabs.json.schema.message.ErrorCode.POSI01;
33+
import static com.relogiclabs.json.schema.message.ErrorCode.POSI02;
3234
import static com.relogiclabs.json.schema.message.ErrorCode.RANG01;
3335
import static com.relogiclabs.json.schema.message.ErrorCode.RANG02;
3436
import static com.relogiclabs.json.schema.message.ErrorCode.RANG03;
@@ -128,6 +130,22 @@ public boolean negative(JNumber target) {
128130
return true;
129131
}
130132

133+
public boolean positive(JNumber target, JNumber reference) {
134+
if(target.compare(reference) < 0) return failWith(new JsonSchemaException(
135+
new ErrorDetail(POSI02, "Number is not positive from reference"),
136+
new ExpectedDetail(function, "a positive number from ", reference),
137+
new ActualDetail(target, "number ", target, " is less than reference")));
138+
return true;
139+
}
140+
141+
public boolean negative(JNumber target, JNumber reference) {
142+
if(target.compare(reference) > 0) return failWith(new JsonSchemaException(
143+
new ErrorDetail(NEGI02, "Number is not negative from reference"),
144+
new ExpectedDetail(function, "a negative number from ", reference),
145+
new ActualDetail(target, "number ", target, " is greater than reference")));
146+
return true;
147+
}
148+
131149
public boolean range(JNumber target, JNumber minimum, JNumber maximum) {
132150
if(target.compare(minimum) < 0) return failWith(new JsonSchemaException(
133151
new ErrorDetail(RANG01, "Number is outside of range"),

src/main/java/com/relogiclabs/json/schema/function/CoreFunctions4.java

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package com.relogiclabs.json.schema.function;
22

33
import com.relogiclabs.json.schema.exception.JsonSchemaException;
4+
import com.relogiclabs.json.schema.internal.function.DateTimeAgent;
45
import com.relogiclabs.json.schema.internal.time.DateTimeParser;
5-
import com.relogiclabs.json.schema.internal.time.DateTimeType;
66
import com.relogiclabs.json.schema.message.ActualDetail;
77
import com.relogiclabs.json.schema.message.ErrorDetail;
88
import com.relogiclabs.json.schema.message.ExpectedDetail;
9+
import com.relogiclabs.json.schema.time.DateTimeType;
910
import com.relogiclabs.json.schema.tree.RuntimeContext;
10-
import com.relogiclabs.json.schema.types.JDateTime;
11-
import com.relogiclabs.json.schema.types.JString;
12-
import com.relogiclabs.json.schema.types.JUndefined;
11+
import com.relogiclabs.json.schema.type.JDateTime;
12+
import com.relogiclabs.json.schema.type.JString;
13+
import com.relogiclabs.json.schema.type.JUndefined;
1314

14-
import static com.relogiclabs.json.schema.internal.time.DateTimeType.DATE_TYPE;
1515
import static com.relogiclabs.json.schema.message.ErrorCode.AFTR01;
1616
import static com.relogiclabs.json.schema.message.ErrorCode.AFTR02;
1717
import static com.relogiclabs.json.schema.message.ErrorCode.BFOR01;
@@ -28,6 +28,7 @@
2828
import static com.relogiclabs.json.schema.message.ErrorCode.ENDE02;
2929
import static com.relogiclabs.json.schema.message.ErrorCode.STRT01;
3030
import static com.relogiclabs.json.schema.message.ErrorCode.STRT02;
31+
import static com.relogiclabs.json.schema.time.DateTimeType.DATE_TYPE;
3132

3233
public class CoreFunctions4 extends CoreFunctions3 {
3334
public CoreFunctions4(RuntimeContext runtime) {
@@ -77,48 +78,47 @@ public boolean range(JDateTime target, JString start, JString end) {
7778
if(rStart == null) return false;
7879
var rEnd = getDateTime(target.getDateTimeParser(), end);
7980
if(rEnd == null) return false;
80-
boolean result = true;
81-
result &= isValidStart(target, rStart, DRNG01, DRNG02);
82-
result &= isValidEnd(target, rEnd, DRNG03, DRNG04);
83-
return result;
81+
if(target.getDateTime().compare(rStart.getDateTime()) < 0)
82+
return failOnStartDate(target, rStart, getErrorCode(target, DRNG01, DRNG02));
83+
if(target.getDateTime().compare(rEnd.getDateTime()) > 0)
84+
return failOnEndDate(target, rEnd, getErrorCode(target, DRNG03, DRNG04));
85+
return true;
86+
}
87+
88+
private static String getErrorCode(JDateTime target, String date, String time) {
89+
return target.getDateTime().getType() == DATE_TYPE ? date : time;
90+
}
91+
92+
private boolean failOnStartDate(JDateTime target, JDateTime start, String code) {
93+
var type = target.getDateTime().getType();
94+
return failWith(new JsonSchemaException(
95+
new ErrorDetail(code, type, " is earlier than start ", type),
96+
new ExpectedDetail(start, "a ", type, " from or after ", start),
97+
new ActualDetail(target, "found ", target, " which is before start ", type)
98+
));
99+
}
100+
101+
private boolean failOnEndDate(JDateTime target, JDateTime end, String code) {
102+
var type = target.getDateTime().getType();
103+
return failWith(new JsonSchemaException(
104+
new ErrorDetail(code, type, " is later than end ", type),
105+
new ExpectedDetail(end, "a ", type, " until or before ", end),
106+
new ActualDetail(target, "found ", target, " which is after end ", type)
107+
));
84108
}
85109

86110
public boolean range(JDateTime target, JUndefined start, JString end) {
87111
var rEnd = getDateTime(target.getDateTimeParser(), end);
88112
if(rEnd == null) return false;
89-
return isValidEnd(target, rEnd, DRNG05, DRNG06);
113+
if (target.getDateTime().compare(rEnd.getDateTime()) <= 0) return true;
114+
return failOnEndDate(target, rEnd, getErrorCode(target, DRNG05, DRNG06));
90115
}
91116

92117
public boolean range(JDateTime target, JString start, JUndefined end) {
93118
var rStart = getDateTime(target.getDateTimeParser(), start);
94119
if(rStart == null) return false;
95-
return isValidStart(target, rStart, DRNG07, DRNG08);
96-
}
97-
98-
private boolean isValidStart(JDateTime target, JDateTime start, String codeDate, String codeTime) {
99-
if(target.getDateTime().compare(start.getDateTime()) < 0) {
100-
var type = target.getDateTime().getType();
101-
var code = type == DATE_TYPE ? codeDate : codeTime;
102-
return failWith(new JsonSchemaException(
103-
new ErrorDetail(code, type, " is earlier than start ", type),
104-
new ExpectedDetail(start, "a ", type, " from or after ", start),
105-
new ActualDetail(target, "found ", target, " which is before start ", type)
106-
));
107-
}
108-
return true;
109-
}
110-
111-
private boolean isValidEnd(JDateTime target, JDateTime end, String codeDate, String codeTime) {
112-
if(target.getDateTime().compare(end.getDateTime()) > 0) {
113-
var type = target.getDateTime().getType();
114-
var code = type == DATE_TYPE ? codeDate : codeTime;
115-
return failWith(new JsonSchemaException(
116-
new ErrorDetail(code, type, " is later than end ", type),
117-
new ExpectedDetail(end, "a ", type, " until or before ", end),
118-
new ActualDetail(target, "found ", target, " which is after end ", type)
119-
));
120-
}
121-
return true;
120+
if (target.getDateTime().compare(rStart.getDateTime()) >= 0) return true;
121+
return failOnStartDate(target, rStart, getErrorCode(target, DRNG07, DRNG08));
122122
}
123123

124124
public boolean start(JDateTime target, JString reference) {
@@ -156,7 +156,7 @@ private JDateTime getDateTime(DateTimeParser parser, JString dateTime) {
156156
&& result.getDateTime().getType() == parser.getType()) return result;
157157
var jDateTime = new DateTimeAgent(parser).parse(function, dateTime);
158158
if(jDateTime == null) return null;
159-
dateTime.setDerived(jDateTime.create(dateTime));
159+
dateTime.setDerived(jDateTime.createNode(dateTime));
160160
return (JDateTime) dateTime.getDerived();
161161
}
162162
}

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

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

33
import com.relogiclabs.json.schema.exception.InvalidDateTimeException;
4+
import com.relogiclabs.json.schema.time.DateTimeType;
5+
import com.relogiclabs.json.schema.time.JsonDateTime;
6+
import com.relogiclabs.json.schema.time.JsonUtcOffset;
47
import lombok.Getter;
58
import lombok.RequiredArgsConstructor;
69

@@ -9,7 +12,6 @@
912
import java.util.HashMap;
1013
import java.util.Map;
1114

12-
import static com.relogiclabs.json.schema.internal.time.JsonDateTime.UNSET;
1315
import static com.relogiclabs.json.schema.internal.util.StringHelper.concat;
1416
import static com.relogiclabs.json.schema.message.ErrorCode.DCNF01;
1517
import static com.relogiclabs.json.schema.message.ErrorCode.DDAY03;
@@ -28,6 +30,7 @@
2830
import static com.relogiclabs.json.schema.message.ErrorCode.DUTC05;
2931
import static com.relogiclabs.json.schema.message.ErrorCode.DWKD03;
3032
import static com.relogiclabs.json.schema.message.ErrorCode.DYAR03;
33+
import static com.relogiclabs.json.schema.time.JsonDateTime.UNSET;
3134
import static java.time.DayOfWeek.FRIDAY;
3235
import static java.time.DayOfWeek.MONDAY;
3336
import static java.time.DayOfWeek.SATURDAY;
@@ -209,7 +212,7 @@ public JsonDateTime validate() {
209212
throw new InvalidDateTimeException(DHUR05, concat("Invalid ",
210213
type, " hour out of range"));
211214
return new JsonDateTime(type, year, month, day, hour, minute, second,
212-
fraction, utcHour, utcMinute);
215+
fraction, new JsonUtcOffset(utcHour, utcMinute));
213216
} catch(InvalidDateTimeException e) {
214217
throw e;
215218
} catch(Exception e) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.relogiclabs.json.schema.internal.antlr.DateTimeLexer;
55
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;
7+
import com.relogiclabs.json.schema.time.DateTimeType;
8+
import com.relogiclabs.json.schema.time.JsonDateTime;
9+
import com.relogiclabs.json.schema.util.Reference;
810
import lombok.Getter;
911
import org.antlr.v4.runtime.CharStreams;
1012
import org.antlr.v4.runtime.Token;

src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeType.java renamed to src/main/java/com/relogiclabs/json/schema/time/DateTimeType.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package com.relogiclabs.json.schema.internal.time;
1+
package com.relogiclabs.json.schema.time;
22

3-
import com.relogiclabs.json.schema.types.JsonType;
3+
import com.relogiclabs.json.schema.type.JsonType;
44
import lombok.AllArgsConstructor;
55
import lombok.Getter;
66

7-
import static com.relogiclabs.json.schema.types.JsonType.DATE;
8-
import static com.relogiclabs.json.schema.types.JsonType.TIME;
7+
import static com.relogiclabs.json.schema.type.JsonType.DATE;
8+
import static com.relogiclabs.json.schema.type.JsonType.TIME;
99

1010
@Getter
1111
@AllArgsConstructor
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
package com.relogiclabs.json.schema.internal.time;
1+
package com.relogiclabs.json.schema.time;
22

3-
import com.relogiclabs.json.schema.types.JDate;
4-
import com.relogiclabs.json.schema.types.JDateTime;
5-
import com.relogiclabs.json.schema.types.JString;
6-
import com.relogiclabs.json.schema.types.JTime;
3+
import com.relogiclabs.json.schema.type.JDate;
4+
import com.relogiclabs.json.schema.type.JDateTime;
5+
import com.relogiclabs.json.schema.type.JString;
6+
import com.relogiclabs.json.schema.type.JTime;
77
import lombok.Getter;
88

99
import java.time.DayOfWeek;
10-
import java.time.ZoneOffset;
1110
import java.time.ZonedDateTime;
1211
import java.util.Arrays;
1312

14-
import static com.relogiclabs.json.schema.internal.time.DateTimeType.DATE_TYPE;
15-
import static com.relogiclabs.json.schema.internal.time.DateTimeType.TIME_TYPE;
13+
import static com.relogiclabs.json.schema.time.DateTimeType.DATE_TYPE;
14+
import static com.relogiclabs.json.schema.time.DateTimeType.TIME_TYPE;
15+
import static lombok.AccessLevel.PACKAGE;
16+
import static org.apache.commons.lang3.StringUtils.removeEnd;
1617

1718
public class JsonDateTime {
1819
private static final int DEFAULT_YEAR = 2000;
@@ -22,8 +23,6 @@ public class JsonDateTime {
2223
private static final int DEFAULT_MINUTE = 0;
2324
private static final int DEFAULT_SECOND = 0;
2425
private static final int DEFAULT_FRACTION = 0;
25-
private static final int DEFAULT_UTC_HOUR = 0;
26-
private static final int DEFAULT_UTC_MINUTE = 0;
2726

2827
public static final int UNSET = -1000;
2928

@@ -35,18 +34,18 @@ public class JsonDateTime {
3534
@Getter private final int minute;
3635
@Getter private final int second;
3736
@Getter private final int fraction;
38-
@Getter private final int utcHour;
39-
@Getter private final int utcMinute;
37+
@Getter private final JsonUtcOffset utcOffset;
4038

41-
private final ZonedDateTime dateTime;
39+
@Getter(PACKAGE) private final ZonedDateTime dateTime;
4240

4341
public JsonDateTime(DateTimeType type, int year, int month, int day) {
44-
this(type, year, month, day, UNSET, UNSET, UNSET, UNSET, UNSET, UNSET);
42+
this(type, year, month, day, UNSET, UNSET, UNSET, UNSET, null);
4543
}
4644

4745
public JsonDateTime(DateTimeType type, int year, int month,
4846
int day, int hour, int minute, int second,
49-
int fraction, int utcHour, int utcMinute) {
47+
int fraction, JsonUtcOffset utcOffset) {
48+
if(utcOffset == null) utcOffset = new JsonUtcOffset();
5049
this.type = type;
5150
this.year = year;
5251
this.month = month;
@@ -55,8 +54,7 @@ public JsonDateTime(DateTimeType type, int year, int month,
5554
this.minute = minute;
5655
this.second = second;
5756
this.fraction = fraction;
58-
this.utcHour = utcHour;
59-
this.utcMinute = utcMinute;
57+
this.utcOffset = utcOffset;
6058
this.dateTime = ZonedDateTime.of(
6159
defaultIfUnset(year, DEFAULT_YEAR),
6260
defaultIfUnset(month, DEFAULT_MONTH),
@@ -65,16 +63,7 @@ public JsonDateTime(DateTimeType type, int year, int month,
6563
defaultIfUnset(minute, DEFAULT_MINUTE),
6664
defaultIfUnset(second, DEFAULT_SECOND),
6765
defaultIfUnset(fraction, DEFAULT_FRACTION),
68-
getZoneOffset(utcHour, utcMinute));
69-
}
70-
71-
private ZoneOffset getZoneOffset(int utcHour, int utcMinute) {
72-
int signum = 1;
73-
if(utcHour != UNSET) signum = (int) Math.signum(utcHour);
74-
if(utcMinute != UNSET) utcMinute *= signum;
75-
return ZoneOffset.ofHoursMinutes(
76-
defaultIfUnset(utcHour, DEFAULT_UTC_HOUR),
77-
defaultIfUnset(utcMinute, DEFAULT_UTC_MINUTE));
66+
utcOffset.getZoneOffset());
7867
}
7968

8069
public DayOfWeek getDayOfWeek() {
@@ -90,13 +79,31 @@ private static boolean isAllSet(int... values) {
9079
return Arrays.stream(values).allMatch(v -> v != UNSET);
9180
}
9281

93-
private static int defaultIfUnset(int value, int defaultValue) {
82+
static int defaultIfUnset(int value, int defaultValue) {
9483
return value == UNSET ? defaultValue : value;
9584
}
9685

97-
public JDateTime create(JString dateTime) {
98-
if(type == DATE_TYPE) return new JDate(dateTime, this);
99-
if(type == TIME_TYPE) return new JTime(dateTime, this);
86+
public JDateTime createNode(JString dateTime) {
87+
if(type == DATE_TYPE) return JDate.from(dateTime, this);
88+
if(type == TIME_TYPE) return JTime.from(dateTime, this);
10089
throw new IllegalStateException("Invalid date time type");
10190
}
91+
92+
@Override
93+
public String toString() {
94+
var builder = new StringBuilder("{");
95+
if(year != UNSET) append(builder, "Year: ", year);
96+
if(month != UNSET) append(builder, "Month: ", month);
97+
if(day != UNSET) append(builder, "Day: ", day);
98+
if(hour != UNSET) append(builder, "Hour: ", hour);
99+
if(minute != UNSET) append(builder, "Minute: ", minute);
100+
if(second != UNSET) append(builder, "Second: ", second);
101+
if(fraction != UNSET) append(builder, "Fraction: ", fraction);
102+
builder.append(utcOffset);
103+
return removeEnd(builder.toString(), ", ") + "}";
104+
}
105+
106+
private static void append(StringBuilder builder, String label, int value) {
107+
builder.append(label).append(value).append(", ");
108+
}
102109
}

0 commit comments

Comments
 (0)