From 824dd378a8931edeb5b18871cf4ecd3094e82b14 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Fri, 3 Nov 2023 22:41:56 +0600 Subject: [PATCH 1/4] Refactor and optimize code --- .../relogiclabs/json/schema/JsonAssert.java | 8 +- .../relogiclabs/json/schema/JsonSchema.java | 4 +- .../json/schema/collection/IndexHashMap.java | 17 ++- .../json/schema/collection/IndexMap.java | 6 +- .../internal/antlr/DateTimeLexer.interp | 80 +++++----- .../schema/internal/antlr/DateTimeLexer.java | 39 ++--- .../internal/antlr/DateTimeLexer.tokens | 40 ++--- .../schema/internal/grammar/DateTimeLexer.g4 | 43 +++--- .../schema/internal/message/ActualHelper.java | 2 +- .../internal/message/ExpectedHelper.java | 2 +- .../internal/message/MessageHelper.java | 9 +- .../schema/internal/time/DateTimeContext.java | 2 +- .../internal/time/SegmentProcessor.java | 138 +++++++++--------- .../schema/internal/tree/JsonTreeVisitor.java | 31 ++-- .../schema/internal/tree/MethodPointer.java | 3 +- .../internal/tree/PragmaDescriptor.java | 2 +- .../schema/internal/tree/PragmaManager.java | 2 +- .../internal/tree/SchemaTreeVisitor.java | 53 +++---- .../{DebugUtils.java => DebugUtilities.java} | 4 +- .../internal/util/LexerErrorListener.java | 6 +- .../internal/util/MiscellaneousHelper.java | 2 +- .../internal/util/ParserErrorListener.java | 10 +- .../schema/internal/util/StreamHelper.java | 2 +- .../schema/internal/util/StringHelper.java | 9 +- .../json/schema/message/ActualDetail.java | 2 +- .../json/schema/message/ContextDetail.java | 4 +- .../json/schema/message/ErrorDetail.java | 2 +- .../json/schema/message/ExpectedDetail.java | 2 +- .../json/schema/message/MessageFormatter.java | 8 +- .../relogiclabs/json/schema/tree/Context.java | 4 +- .../json/schema/tree/JsonTree.java | 2 +- .../json/schema/tree/SchemaTree.java | 2 +- .../relogiclabs/json/schema/types/JArray.java | 20 +-- .../json/schema/types/JBoolean.java | 16 +- .../json/schema/types/JBranch.java | 8 +- .../json/schema/types/JDirective.java | 17 +-- .../json/schema/types/JDouble.java | 14 +- .../relogiclabs/json/schema/types/JFloat.java | 14 +- .../json/schema/types/JFunction.java | 31 ++-- .../json/schema/types/JInteger.java | 14 +- .../relogiclabs/json/schema/types/JLeaf.java | 17 +-- .../relogiclabs/json/schema/types/JNode.java | 24 +-- .../relogiclabs/json/schema/types/JNull.java | 13 +- .../json/schema/types/JNumber.java | 17 +-- .../json/schema/types/JPragma.java | 26 ++-- .../json/schema/types/JProperty.java | 27 ++-- .../relogiclabs/json/schema/types/JRoot.java | 68 +++------ .../json/schema/types/JString.java | 16 +- .../json/schema/types/JUndefined.java | 10 +- .../json/schema/types/JValidator.java | 56 ++----- 50 files changed, 403 insertions(+), 545 deletions(-) rename src/main/java/com/relogiclabs/json/schema/internal/util/{DebugUtils.java => DebugUtilities.java} (94%) diff --git a/src/main/java/com/relogiclabs/json/schema/JsonAssert.java b/src/main/java/com/relogiclabs/json/schema/JsonAssert.java index 14efd80..f72a846 100644 --- a/src/main/java/com/relogiclabs/json/schema/JsonAssert.java +++ b/src/main/java/com/relogiclabs/json/schema/JsonAssert.java @@ -1,6 +1,6 @@ package com.relogiclabs.json.schema; -import com.relogiclabs.json.schema.internal.util.DebugUtils; +import com.relogiclabs.json.schema.internal.util.DebugUtilities; import com.relogiclabs.json.schema.message.MessageFormatter; import com.relogiclabs.json.schema.tree.JsonTree; import com.relogiclabs.json.schema.tree.RuntimeContext; @@ -34,7 +34,7 @@ public JsonAssert(String schema) { public void isValid(String jsonActual) { runtime.getExceptions().clear(); var jsonTree = new JsonTree(runtime, jsonActual); - DebugUtils.print(schemaTree, jsonTree); + DebugUtilities.print(schemaTree, jsonTree); schemaTree.getRoot().match(jsonTree.getRoot()); if(!schemaTree.getRoot().match(jsonTree.getRoot())) throw new IllegalStateException("Exception not thrown"); @@ -50,7 +50,7 @@ public static void isValid(String schemaExpected, String jsonActual) { var runtime = new RuntimeContext(MessageFormatter.SCHEMA_ASSERTION, true); var schemaTree = new SchemaTree(runtime, schemaExpected); var jsonTree = new JsonTree(runtime, jsonActual); - DebugUtils.print(schemaTree, jsonTree); + DebugUtilities.print(schemaTree, jsonTree); if(!schemaTree.getRoot().match(jsonTree.getRoot())) throw new IllegalStateException("Exception not thrown"); } @@ -66,7 +66,7 @@ public static void areEqual(String jsonExpected, String jsonActual) { var runtime = new RuntimeContext(MessageFormatter.JSON_ASSERTION, true); var expectedTree = new JsonTree(runtime, jsonExpected); var actualTree = new JsonTree(runtime, jsonActual); - DebugUtils.print(expectedTree, actualTree); + DebugUtilities.print(expectedTree, actualTree); if(!expectedTree.getRoot().match(actualTree.getRoot())) throw new IllegalStateException("Exception not thrown"); } diff --git a/src/main/java/com/relogiclabs/json/schema/JsonSchema.java b/src/main/java/com/relogiclabs/json/schema/JsonSchema.java index ff873d9..f745c9b 100644 --- a/src/main/java/com/relogiclabs/json/schema/JsonSchema.java +++ b/src/main/java/com/relogiclabs/json/schema/JsonSchema.java @@ -1,6 +1,6 @@ package com.relogiclabs.json.schema; -import com.relogiclabs.json.schema.internal.util.DebugUtils; +import com.relogiclabs.json.schema.internal.util.DebugUtilities; import com.relogiclabs.json.schema.message.MessageFormatter; import com.relogiclabs.json.schema.tree.JsonTree; import com.relogiclabs.json.schema.tree.RuntimeContext; @@ -38,7 +38,7 @@ public JsonSchema(String schema) { public boolean isValid(String json) { exceptions.clear(); var jsonTree = new JsonTree(runtime, json); - DebugUtils.print(schemaTree, jsonTree); + DebugUtilities.print(schemaTree, jsonTree); return schemaTree.getRoot().match(jsonTree.getRoot()); } diff --git a/src/main/java/com/relogiclabs/json/schema/collection/IndexHashMap.java b/src/main/java/com/relogiclabs/json/schema/collection/IndexHashMap.java index fb471ef..cfedbdf 100644 --- a/src/main/java/com/relogiclabs/json/schema/collection/IndexHashMap.java +++ b/src/main/java/com/relogiclabs/json/schema/collection/IndexHashMap.java @@ -9,9 +9,9 @@ import java.util.Map; import java.util.Set; -public class IndexHashMap> implements IndexMap { +public final class IndexHashMap> implements IndexMap { - private boolean readOnly; + private boolean unmodifiable; private Map map; private List list; @@ -42,16 +42,17 @@ public Collection values() { } @Override - public boolean isReadOnly() { - return readOnly; + public boolean isUnmodifiable() { + return unmodifiable; } @Override - public void makeReadOnly() { - if(readOnly) return; + public IndexHashMap asUnmodifiable() { + if(unmodifiable) return this; list = Collections.unmodifiableList(list); map = Collections.unmodifiableMap(map); - readOnly = true; + unmodifiable = true; + return this; } @Override @@ -134,4 +135,4 @@ public void clear() { list.clear(); map.clear(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/collection/IndexMap.java b/src/main/java/com/relogiclabs/json/schema/collection/IndexMap.java index b6bba4b..0fb032e 100644 --- a/src/main/java/com/relogiclabs/json/schema/collection/IndexMap.java +++ b/src/main/java/com/relogiclabs/json/schema/collection/IndexMap.java @@ -8,6 +8,6 @@ public interface IndexMap> extends Collection { TV get(TK key); Set keySet(); Collection values(); - boolean isReadOnly(); - void makeReadOnly(); -} + boolean isUnmodifiable(); + IndexMap asUnmodifiable(); +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.interp b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.interp index c55349b..5e85dd7 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.interp +++ b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.interp @@ -35,30 +35,30 @@ null token symbolic names: null ERA -YEAR_NUM4 -YEAR_NUM2 +YEAR_NUMBER4 +YEAR_NUMBER2 MONTH_NAME MONTH_SHORT_NAME -MONTH_NUM2 -MONTH_NUM +MONTH_NUMBER2 +MONTH_NUMBER WEEKDAY_NAME WEEKDAY_SHORT_NAME -DAY_NUM2 -DAY_NUM -AM_PM -HOUR_NUM2 -HOUR_NUM -MINUTE_NUM2 -MINUTE_NUM -SECOND_NUM2 -SECOND_NUM -FRACTION_NUM06 -FRACTION_NUM05 -FRACTION_NUM04 -FRACTION_NUM03 -FRACTION_NUM02 -FRACTION_NUM01 -FRACTION_NUM +DAY_NUMBER2 +DAY_NUMBER +CLOCK_AM_PM +HOUR_NUMBER2 +HOUR_NUMBER +MINUTE_NUMBER2 +MINUTE_NUMBER +SECOND_NUMBER2 +SECOND_NUMBER +FRACTION_NUMBER6 +FRACTION_NUMBER5 +FRACTION_NUMBER4 +FRACTION_NUMBER3 +FRACTION_NUMBER2 +FRACTION_NUMBER1 +FRACTION_NUMBER UTC_OFFSET_TIME2 UTC_OFFSET_TIME1 UTC_OFFSET_HOUR @@ -68,30 +68,30 @@ TEXT rule names: ERA -YEAR_NUM4 -YEAR_NUM2 +YEAR_NUMBER4 +YEAR_NUMBER2 MONTH_NAME MONTH_SHORT_NAME -MONTH_NUM2 -MONTH_NUM +MONTH_NUMBER2 +MONTH_NUMBER WEEKDAY_NAME WEEKDAY_SHORT_NAME -DAY_NUM2 -DAY_NUM -AM_PM -HOUR_NUM2 -HOUR_NUM -MINUTE_NUM2 -MINUTE_NUM -SECOND_NUM2 -SECOND_NUM -FRACTION_NUM06 -FRACTION_NUM05 -FRACTION_NUM04 -FRACTION_NUM03 -FRACTION_NUM02 -FRACTION_NUM01 -FRACTION_NUM +DAY_NUMBER2 +DAY_NUMBER +CLOCK_AM_PM +HOUR_NUMBER2 +HOUR_NUMBER +MINUTE_NUMBER2 +MINUTE_NUMBER +SECOND_NUMBER2 +SECOND_NUMBER +FRACTION_NUMBER6 +FRACTION_NUMBER5 +FRACTION_NUMBER4 +FRACTION_NUMBER3 +FRACTION_NUMBER2 +FRACTION_NUMBER1 +FRACTION_NUMBER UTC_OFFSET_TIME2 UTC_OFFSET_TIME1 UTC_OFFSET_HOUR diff --git a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.java b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.java index 22e123b..3797c37 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.java @@ -19,13 +19,13 @@ public class DateTimeLexer extends Lexer { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - ERA=1, YEAR_NUM4=2, YEAR_NUM2=3, MONTH_NAME=4, MONTH_SHORT_NAME=5, MONTH_NUM2=6, - MONTH_NUM=7, WEEKDAY_NAME=8, WEEKDAY_SHORT_NAME=9, DAY_NUM2=10, DAY_NUM=11, - AM_PM=12, HOUR_NUM2=13, HOUR_NUM=14, MINUTE_NUM2=15, MINUTE_NUM=16, SECOND_NUM2=17, - SECOND_NUM=18, FRACTION_NUM06=19, FRACTION_NUM05=20, FRACTION_NUM04=21, - FRACTION_NUM03=22, FRACTION_NUM02=23, FRACTION_NUM01=24, FRACTION_NUM=25, - UTC_OFFSET_TIME2=26, UTC_OFFSET_TIME1=27, UTC_OFFSET_HOUR=28, SYMBOL=29, - WHITESPACE=30, TEXT=31; + ERA=1, YEAR_NUMBER4=2, YEAR_NUMBER2=3, MONTH_NAME=4, MONTH_SHORT_NAME=5, + MONTH_NUMBER2=6, MONTH_NUMBER=7, WEEKDAY_NAME=8, WEEKDAY_SHORT_NAME=9, + DAY_NUMBER2=10, DAY_NUMBER=11, CLOCK_AM_PM=12, HOUR_NUMBER2=13, HOUR_NUMBER=14, + MINUTE_NUMBER2=15, MINUTE_NUMBER=16, SECOND_NUMBER2=17, SECOND_NUMBER=18, + FRACTION_NUMBER6=19, FRACTION_NUMBER5=20, FRACTION_NUMBER4=21, FRACTION_NUMBER3=22, + FRACTION_NUMBER2=23, FRACTION_NUMBER1=24, FRACTION_NUMBER=25, UTC_OFFSET_TIME2=26, + UTC_OFFSET_TIME1=27, UTC_OFFSET_HOUR=28, SYMBOL=29, WHITESPACE=30, TEXT=31; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -36,11 +36,12 @@ public class DateTimeLexer extends Lexer { private static String[] makeRuleNames() { return new String[] { - "ERA", "YEAR_NUM4", "YEAR_NUM2", "MONTH_NAME", "MONTH_SHORT_NAME", "MONTH_NUM2", - "MONTH_NUM", "WEEKDAY_NAME", "WEEKDAY_SHORT_NAME", "DAY_NUM2", "DAY_NUM", - "AM_PM", "HOUR_NUM2", "HOUR_NUM", "MINUTE_NUM2", "MINUTE_NUM", "SECOND_NUM2", - "SECOND_NUM", "FRACTION_NUM06", "FRACTION_NUM05", "FRACTION_NUM04", "FRACTION_NUM03", - "FRACTION_NUM02", "FRACTION_NUM01", "FRACTION_NUM", "UTC_OFFSET_TIME2", + "ERA", "YEAR_NUMBER4", "YEAR_NUMBER2", "MONTH_NAME", "MONTH_SHORT_NAME", + "MONTH_NUMBER2", "MONTH_NUMBER", "WEEKDAY_NAME", "WEEKDAY_SHORT_NAME", + "DAY_NUMBER2", "DAY_NUMBER", "CLOCK_AM_PM", "HOUR_NUMBER2", "HOUR_NUMBER", + "MINUTE_NUMBER2", "MINUTE_NUMBER", "SECOND_NUMBER2", "SECOND_NUMBER", + "FRACTION_NUMBER6", "FRACTION_NUMBER5", "FRACTION_NUMBER4", "FRACTION_NUMBER3", + "FRACTION_NUMBER2", "FRACTION_NUMBER1", "FRACTION_NUMBER", "UTC_OFFSET_TIME2", "UTC_OFFSET_TIME1", "UTC_OFFSET_HOUR", "SYMBOL", "WHITESPACE", "TEXT" }; } @@ -57,13 +58,13 @@ private static String[] makeLiteralNames() { private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { - null, "ERA", "YEAR_NUM4", "YEAR_NUM2", "MONTH_NAME", "MONTH_SHORT_NAME", - "MONTH_NUM2", "MONTH_NUM", "WEEKDAY_NAME", "WEEKDAY_SHORT_NAME", "DAY_NUM2", - "DAY_NUM", "AM_PM", "HOUR_NUM2", "HOUR_NUM", "MINUTE_NUM2", "MINUTE_NUM", - "SECOND_NUM2", "SECOND_NUM", "FRACTION_NUM06", "FRACTION_NUM05", "FRACTION_NUM04", - "FRACTION_NUM03", "FRACTION_NUM02", "FRACTION_NUM01", "FRACTION_NUM", - "UTC_OFFSET_TIME2", "UTC_OFFSET_TIME1", "UTC_OFFSET_HOUR", "SYMBOL", - "WHITESPACE", "TEXT" + null, "ERA", "YEAR_NUMBER4", "YEAR_NUMBER2", "MONTH_NAME", "MONTH_SHORT_NAME", + "MONTH_NUMBER2", "MONTH_NUMBER", "WEEKDAY_NAME", "WEEKDAY_SHORT_NAME", + "DAY_NUMBER2", "DAY_NUMBER", "CLOCK_AM_PM", "HOUR_NUMBER2", "HOUR_NUMBER", + "MINUTE_NUMBER2", "MINUTE_NUMBER", "SECOND_NUMBER2", "SECOND_NUMBER", + "FRACTION_NUMBER6", "FRACTION_NUMBER5", "FRACTION_NUMBER4", "FRACTION_NUMBER3", + "FRACTION_NUMBER2", "FRACTION_NUMBER1", "FRACTION_NUMBER", "UTC_OFFSET_TIME2", + "UTC_OFFSET_TIME1", "UTC_OFFSET_HOUR", "SYMBOL", "WHITESPACE", "TEXT" }; } private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.tokens b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.tokens index 3510d6e..2a83917 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.tokens +++ b/src/main/java/com/relogiclabs/json/schema/internal/antlr/DateTimeLexer.tokens @@ -1,28 +1,28 @@ ERA=1 -YEAR_NUM4=2 -YEAR_NUM2=3 +YEAR_NUMBER4=2 +YEAR_NUMBER2=3 MONTH_NAME=4 MONTH_SHORT_NAME=5 -MONTH_NUM2=6 -MONTH_NUM=7 +MONTH_NUMBER2=6 +MONTH_NUMBER=7 WEEKDAY_NAME=8 WEEKDAY_SHORT_NAME=9 -DAY_NUM2=10 -DAY_NUM=11 -AM_PM=12 -HOUR_NUM2=13 -HOUR_NUM=14 -MINUTE_NUM2=15 -MINUTE_NUM=16 -SECOND_NUM2=17 -SECOND_NUM=18 -FRACTION_NUM06=19 -FRACTION_NUM05=20 -FRACTION_NUM04=21 -FRACTION_NUM03=22 -FRACTION_NUM02=23 -FRACTION_NUM01=24 -FRACTION_NUM=25 +DAY_NUMBER2=10 +DAY_NUMBER=11 +CLOCK_AM_PM=12 +HOUR_NUMBER2=13 +HOUR_NUMBER=14 +MINUTE_NUMBER2=15 +MINUTE_NUMBER=16 +SECOND_NUMBER2=17 +SECOND_NUMBER=18 +FRACTION_NUMBER6=19 +FRACTION_NUMBER5=20 +FRACTION_NUMBER4=21 +FRACTION_NUMBER3=22 +FRACTION_NUMBER2=23 +FRACTION_NUMBER1=24 +FRACTION_NUMBER=25 UTC_OFFSET_TIME2=26 UTC_OFFSET_TIME1=27 UTC_OFFSET_HOUR=28 diff --git a/src/main/java/com/relogiclabs/json/schema/internal/grammar/DateTimeLexer.g4 b/src/main/java/com/relogiclabs/json/schema/internal/grammar/DateTimeLexer.g4 index 7ffcf79..9db7c71 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/grammar/DateTimeLexer.g4 +++ b/src/main/java/com/relogiclabs/json/schema/internal/grammar/DateTimeLexer.g4 @@ -2,39 +2,39 @@ lexer grammar DateTimeLexer; ERA : 'G'; -YEAR_NUM4 : 'YYYY'; -YEAR_NUM2 : 'YY'; +YEAR_NUMBER4 : 'YYYY'; +YEAR_NUMBER2 : 'YY'; MONTH_NAME : 'MMMM'; MONTH_SHORT_NAME : 'MMM'; -MONTH_NUM2 : 'MM'; -MONTH_NUM : 'M'; +MONTH_NUMBER2 : 'MM'; +MONTH_NUMBER : 'M'; WEEKDAY_NAME : 'DDDD'; WEEKDAY_SHORT_NAME : 'DDD'; -DAY_NUM2 : 'DD'; -DAY_NUM : 'D'; +DAY_NUMBER2 : 'DD'; +DAY_NUMBER : 'D'; -AM_PM : 't'; +CLOCK_AM_PM : 't'; -HOUR_NUM2 : 'hh'; -HOUR_NUM : 'h'; +HOUR_NUMBER2 : 'hh'; +HOUR_NUMBER : 'h'; -MINUTE_NUM2 : 'mm'; -MINUTE_NUM : 'm'; +MINUTE_NUMBER2 : 'mm'; +MINUTE_NUMBER : 'm'; -SECOND_NUM2 : 'ss'; -SECOND_NUM : 's'; +SECOND_NUMBER2 : 'ss'; +SECOND_NUMBER : 's'; -FRACTION_NUM06 : 'ffffff'; -FRACTION_NUM05 : 'fffff'; -FRACTION_NUM04 : 'ffff'; -FRACTION_NUM03 : 'fff'; -FRACTION_NUM02 : 'ff'; -FRACTION_NUM01 : 'f'; +FRACTION_NUMBER6 : 'ffffff'; +FRACTION_NUMBER5 : 'fffff'; +FRACTION_NUMBER4 : 'ffff'; +FRACTION_NUMBER3 : 'fff'; +FRACTION_NUMBER2 : 'ff'; +FRACTION_NUMBER1 : 'f'; -FRACTION_NUM : 'F'; +FRACTION_NUMBER : 'F'; UTC_OFFSET_TIME2 : 'ZZZ'; UTC_OFFSET_TIME1 : 'ZZ'; @@ -43,5 +43,4 @@ UTC_OFFSET_HOUR : 'Z'; SYMBOL : [!-/:-@[-`{-~]+; WHITESPACE : [\n\r\t ]+; -TEXT : '\'' ( ~'\'' | '\'\'')* '\''; - +TEXT : '\'' ( ~'\'' | '\'\'')* '\''; \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/internal/message/ActualHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/message/ActualHelper.java index 379188a..1266434 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/message/ActualHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/message/ActualHelper.java @@ -8,7 +8,7 @@ import static com.relogiclabs.json.schema.internal.message.MessageHelper.getTypeName; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; -public class ActualHelper { +public final class ActualHelper { private ActualHelper() { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/message/ExpectedHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/message/ExpectedHelper.java index ddaa960..8d27315 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/message/ExpectedHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/message/ExpectedHelper.java @@ -10,7 +10,7 @@ import static com.relogiclabs.json.schema.internal.message.MessageHelper.getTypeName; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; -public class ExpectedHelper { +public final class ExpectedHelper { private ExpectedHelper() { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/message/MessageHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/message/MessageHelper.java index ea7de30..a339e35 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/message/MessageHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/message/MessageHelper.java @@ -2,8 +2,9 @@ import com.relogiclabs.json.schema.types.JNode; import com.relogiclabs.json.schema.types.JsonTypable; +import com.relogiclabs.json.schema.types.JsonType; -public class MessageHelper { +public final class MessageHelper { public static final String ValidationFailed = "Validation failed"; public static final String ValueMismatch = "Value mismatch"; @@ -27,4 +28,10 @@ public static String getTypeName(JNode node) { ? jsonNode.getType().getName() : node.getClass().getName(); } + + public static String getTypeName(Class type) { + JsonType t = JsonType.from(type); + if(t != null) return t.getName(); + else return type.getSimpleName(); + } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeContext.java b/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeContext.java index 54e8f1a..9054785 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeContext.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeContext.java @@ -225,7 +225,7 @@ private void convertTo24Hour() { } private static boolean isLeapYear(int year) { - return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } private static int toFourDigitYear(int year) { diff --git a/src/main/java/com/relogiclabs/json/schema/internal/time/SegmentProcessor.java b/src/main/java/com/relogiclabs/json/schema/internal/time/SegmentProcessor.java index 5e74b20..0e93fb1 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/time/SegmentProcessor.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/time/SegmentProcessor.java @@ -46,8 +46,8 @@ abstract class SegmentProcessor { private static final Pattern EraRegex = compile("^(BC|AD)", CASE_INSENSITIVE); - private static final Pattern YearNum4Regex = compile("^(\\d{4})"); - private static final Pattern YearNum2Regex = compile("^(\\d{2})"); + private static final Pattern YearNumber4Regex = compile("^(\\d{4})"); + private static final Pattern YearNumber2Regex = compile("^(\\d{2})"); private static final Pattern MonthNameRegex = compile( "^(January|February|March|April|May|June|July" + "|August|September|October|November|December)", @@ -55,29 +55,29 @@ abstract class SegmentProcessor { private static final Pattern MonthShortNameRegex = compile( "^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)", CASE_INSENSITIVE); - private static final Pattern MonthNum2Regex = compile("^(\\d{2})"); - private static final Pattern MonthNumRegex = compile("^(\\d{1,2})"); + private static final Pattern MonthNumber2Regex = compile("^(\\d{2})"); + private static final Pattern MonthNumberRegex = compile("^(\\d{1,2})"); private static final Pattern WeekdayNameRegex = compile( "^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)", CASE_INSENSITIVE); private static final Pattern WeekdayShortNameRegex = compile( "^(Sun|Mon|Tue|Wed|Thu|Fri|Sat)", CASE_INSENSITIVE); - private static final Pattern DayNum2Regex = compile("^(\\d{2})"); - private static final Pattern DayNumRegex = compile("^(\\d{1,2})"); - private static final Pattern AmPmRegex = compile("^(AM|PM)", CASE_INSENSITIVE); - private static final Pattern HourNum2Regex = compile("^(\\d{2})"); - private static final Pattern HourNumRegex = compile("^(\\d{1,2})"); - private static final Pattern MinuteNum2Regex = compile("^(\\d{2})"); - private static final Pattern MinuteNumRegex = compile("^(\\d{1,2})"); - private static final Pattern SecondNum2Regex = compile("^(\\d{2})"); - private static final Pattern SecondNumRegex = compile("^(\\d{1,2})"); - private static final Pattern FractionNumRegex = compile("^(\\d{1,6})"); - private static final Pattern FractionNum1Regex = compile("^(\\d)"); - private static final Pattern FractionNum2Regex = compile("^(\\d{2})"); - private static final Pattern FractionNum3Regex = compile("^(\\d{3})"); - private static final Pattern FractionNum4Regex = compile("^(\\d{4})"); - private static final Pattern FractionNum5Regex = compile("^(\\d{5})"); - private static final Pattern FractionNum6Regex = compile("^(\\d{6})"); + private static final Pattern DayNumber2Regex = compile("^(\\d{2})"); + private static final Pattern DayNumberRegex = compile("^(\\d{1,2})"); + private static final Pattern ClockAmPmRegex = compile("^(AM|PM)", CASE_INSENSITIVE); + private static final Pattern HourNumber2Regex = compile("^(\\d{2})"); + private static final Pattern HourNumberRegex = compile("^(\\d{1,2})"); + private static final Pattern MinuteNumber2Regex = compile("^(\\d{2})"); + private static final Pattern MinuteNumberRegex = compile("^(\\d{1,2})"); + private static final Pattern SecondNumber2Regex = compile("^(\\d{2})"); + private static final Pattern SecondNumberRegex = compile("^(\\d{1,2})"); + private static final Pattern FractionNumberRegex = compile("^(\\d{1,6})"); + private static final Pattern FractionNumber1Regex = compile("^(\\d)"); + private static final Pattern FractionNumber2Regex = compile("^(\\d{2})"); + private static final Pattern FractionNumber3Regex = compile("^(\\d{3})"); + private static final Pattern FractionNumber4Regex = compile("^(\\d{4})"); + private static final Pattern FractionNumber5Regex = compile("^(\\d{5})"); + private static final Pattern FractionNumber6Regex = compile("^(\\d{6})"); private static final Pattern UtcOffsetHourRegex = compile("^([+-]\\d{2}|Z)"); private static final Pattern UtcOffsetTime1Regex = compile("^([+-]\\d{2}):(\\d{2})|Z"); private static final Pattern UtcOffsetTime2Regex = compile("^([+-]\\d{2})(\\d{2})|Z"); @@ -88,36 +88,36 @@ abstract class SegmentProcessor { public static final SegmentProcessor Whitespace = new WhitespaceProcessor(); public static final SegmentProcessor Era = new EraProcessor(EraRegex, DERA01); - public static final SegmentProcessor YearNum4 = new YearNumProcessor(YearNum4Regex, DYAR01); - public static final SegmentProcessor YearNum2 = new YearNumProcessor(YearNum2Regex, DYAR02); + public static final SegmentProcessor YearNumber4 = new YearNumberProcessor(YearNumber4Regex, DYAR01); + public static final SegmentProcessor YearNumber2 = new YearNumberProcessor(YearNumber2Regex, DYAR02); public static final SegmentProcessor MonthName = new MonthNameProcessor(MonthNameRegex, DMON01); public static final SegmentProcessor MonthShortName = new MonthNameProcessor(MonthShortNameRegex, DMON02); - public static final SegmentProcessor MonthNum2 = new MonthNumProcessor(MonthNum2Regex, DMON03); - public static final SegmentProcessor MonthNum = new MonthNumProcessor(MonthNumRegex, DMON04); + public static final SegmentProcessor MonthNumber2 = new MonthNumberProcessor(MonthNumber2Regex, DMON03); + public static final SegmentProcessor MonthNumber = new MonthNumberProcessor(MonthNumberRegex, DMON04); public static final SegmentProcessor WeekdayName = new WeekdayProcessor(WeekdayNameRegex, DWKD01); public static final SegmentProcessor WeekdayShortName = new WeekdayProcessor(WeekdayShortNameRegex, DWKD02); - public static final SegmentProcessor DayNum2 = new DayNumProcessor(DayNum2Regex, DDAY01); - public static final SegmentProcessor DayNum = new DayNumProcessor(DayNumRegex, DDAY02); + public static final SegmentProcessor DayNumber2 = new DayNumberProcessor(DayNumber2Regex, DDAY01); + public static final SegmentProcessor DayNumber = new DayNumberProcessor(DayNumberRegex, DDAY02); - public static final SegmentProcessor AmPm = new AmPmProcessor(AmPmRegex, DTAP01); - public static final SegmentProcessor HourNum2 = new HourNumProcessor(HourNum2Regex, DHUR01); - public static final SegmentProcessor HourNum = new HourNumProcessor(HourNumRegex, DHUR02); + public static final SegmentProcessor ClockAmPm = new ClockAmPmProcessor(ClockAmPmRegex, DTAP01); + public static final SegmentProcessor HourNumber2 = new HourNumberProcessor(HourNumber2Regex, DHUR01); + public static final SegmentProcessor HourNumber = new HourNumberProcessor(HourNumberRegex, DHUR02); - public static final SegmentProcessor MinuteNum2 = new MinuteNumProcessor(MinuteNum2Regex, DMIN01); - public static final SegmentProcessor MinuteNum = new MinuteNumProcessor(MinuteNumRegex, DMIN02); + public static final SegmentProcessor MinuteNumber2 = new MinuteNumberProcessor(MinuteNumber2Regex, DMIN01); + public static final SegmentProcessor MinuteNumber = new MinuteNumberProcessor(MinuteNumberRegex, DMIN02); - public static final SegmentProcessor SecondNum2 = new SecondNumProcessor(SecondNum2Regex, DSEC01); - public static final SegmentProcessor SecondNum = new SecondNumProcessor(SecondNumRegex, DSEC02); + public static final SegmentProcessor SecondNumber2 = new SecondNumberProcessor(SecondNumber2Regex, DSEC01); + public static final SegmentProcessor SecondNumber = new SecondNumberProcessor(SecondNumberRegex, DSEC02); - public static final SegmentProcessor FractionNum = new FractionNumProcessor(FractionNumRegex, DFRC01); - public static final SegmentProcessor FractionNum01 = new FractionNumProcessor(FractionNum1Regex, DFRC02); - public static final SegmentProcessor FractionNum02 = new FractionNumProcessor(FractionNum2Regex, DFRC03); - public static final SegmentProcessor FractionNum03 = new FractionNumProcessor(FractionNum3Regex, DFRC04); - public static final SegmentProcessor FractionNum04 = new FractionNumProcessor(FractionNum4Regex, DFRC05); - public static final SegmentProcessor FractionNum05 = new FractionNumProcessor(FractionNum5Regex, DFRC06); - public static final SegmentProcessor FractionNum06 = new FractionNumProcessor(FractionNum6Regex, DFRC07); + public static final SegmentProcessor FractionNumber = new FractionNumberProcessor(FractionNumberRegex, DFRC01); + public static final SegmentProcessor FractionNumber1 = new FractionNumberProcessor(FractionNumber1Regex, DFRC02); + public static final SegmentProcessor FractionNumber2 = new FractionNumberProcessor(FractionNumber2Regex, DFRC03); + public static final SegmentProcessor FractionNumber3 = new FractionNumberProcessor(FractionNumber3Regex, DFRC04); + public static final SegmentProcessor FractionNumber4 = new FractionNumberProcessor(FractionNumber4Regex, DFRC05); + public static final SegmentProcessor FractionNumber5 = new FractionNumberProcessor(FractionNumber5Regex, DFRC06); + public static final SegmentProcessor FractionNumber6 = new FractionNumberProcessor(FractionNumber6Regex, DFRC07); public static final SegmentProcessor UtcOffsetHour = new UtcOffsetHourProcessor(UtcOffsetHourRegex, DUTC01); public static final SegmentProcessor UtcOffsetTime1 = new UtcOffsetTimeProcessor(UtcOffsetTime1Regex, DUTC02); @@ -126,7 +126,7 @@ abstract class SegmentProcessor { public abstract String process(String input, Token token, DateTimeContext context); - private static class TextProcessor extends SegmentProcessor { + private static final class TextProcessor extends SegmentProcessor { @Override public String process(String input, Token token, DateTimeContext context) { var text = replaceChars(substring(token.getText(), 1, -1), "''", "'"); @@ -136,7 +136,7 @@ public String process(String input, Token token, DateTimeContext context) { } } - private static class SymbolProcessor extends SegmentProcessor { + private static final class SymbolProcessor extends SegmentProcessor { @Override public String process(String input, Token token, DateTimeContext context) { if(!input.startsWith(token.getText())) throw new InvalidDateTimeException(DSYM01, @@ -145,7 +145,7 @@ public String process(String input, Token token, DateTimeContext context) { } } - private static class WhitespaceProcessor extends SegmentProcessor { + private static final class WhitespaceProcessor extends SegmentProcessor { @Override public String process(String input, Token token, DateTimeContext context) { if(!input.startsWith(token.getText())) throw new InvalidDateTimeException(DWTS01, @@ -173,8 +173,8 @@ public String process(String input, Token token, DateTimeContext context) { protected abstract void process(Matcher matcher, DateTimeContext context); } - private static class EraProcessor extends SegmentRegexProcessor { - protected EraProcessor(Pattern regex, String code) { + private static final class EraProcessor extends SegmentRegexProcessor { + private EraProcessor(Pattern regex, String code) { super(regex, code); } @@ -186,8 +186,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class YearNumProcessor extends SegmentRegexProcessor { - protected YearNumProcessor(Pattern regex, String code) { + private static final class YearNumberProcessor extends SegmentRegexProcessor { + private YearNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -200,8 +200,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class MonthNameProcessor extends SegmentRegexProcessor { - protected MonthNameProcessor(Pattern regex, String code) { + private static final class MonthNameProcessor extends SegmentRegexProcessor { + private MonthNameProcessor(Pattern regex, String code) { super(regex, code); } @@ -213,8 +213,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class MonthNumProcessor extends SegmentRegexProcessor { - protected MonthNumProcessor(Pattern regex, String code) { + private static final class MonthNumberProcessor extends SegmentRegexProcessor { + private MonthNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -226,8 +226,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class WeekdayProcessor extends SegmentRegexProcessor { - protected WeekdayProcessor(Pattern regex, String code) { + private static final class WeekdayProcessor extends SegmentRegexProcessor { + private WeekdayProcessor(Pattern regex, String code) { super(regex, code); } @@ -239,8 +239,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class DayNumProcessor extends SegmentRegexProcessor { - protected DayNumProcessor(Pattern regex, String code) { + private static final class DayNumberProcessor extends SegmentRegexProcessor { + private DayNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -252,8 +252,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class AmPmProcessor extends SegmentRegexProcessor { - protected AmPmProcessor(Pattern regex, String code) { + private static final class ClockAmPmProcessor extends SegmentRegexProcessor { + private ClockAmPmProcessor(Pattern regex, String code) { super(regex, code); } @@ -265,8 +265,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class HourNumProcessor extends SegmentRegexProcessor { - protected HourNumProcessor(Pattern regex, String code) { + private static final class HourNumberProcessor extends SegmentRegexProcessor { + private HourNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -278,8 +278,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class MinuteNumProcessor extends SegmentRegexProcessor { - protected MinuteNumProcessor(Pattern regex, String code) { + private static final class MinuteNumberProcessor extends SegmentRegexProcessor { + private MinuteNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -291,8 +291,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class SecondNumProcessor extends SegmentRegexProcessor { - protected SecondNumProcessor(Pattern regex, String code) { + private static final class SecondNumberProcessor extends SegmentRegexProcessor { + private SecondNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -304,8 +304,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class FractionNumProcessor extends SegmentRegexProcessor { - protected FractionNumProcessor(Pattern regex, String code) { + private static final class FractionNumberProcessor extends SegmentRegexProcessor { + private FractionNumberProcessor(Pattern regex, String code) { super(regex, code); } @@ -317,8 +317,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class UtcOffsetHourProcessor extends SegmentRegexProcessor { - protected UtcOffsetHourProcessor(Pattern regex, String code) { + private static final class UtcOffsetHourProcessor extends SegmentRegexProcessor { + private UtcOffsetHourProcessor(Pattern regex, String code) { super(regex, code); } @@ -331,8 +331,8 @@ protected void process(Matcher matcher, DateTimeContext context) { } } - private static class UtcOffsetTimeProcessor extends SegmentRegexProcessor { - protected UtcOffsetTimeProcessor(Pattern regex, String code) { + private static final class UtcOffsetTimeProcessor extends SegmentRegexProcessor { + private UtcOffsetTimeProcessor(Pattern regex, String code) { super(regex, code); } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/JsonTreeVisitor.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/JsonTreeVisitor.java index 8fd55b2..f57b690 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/JsonTreeVisitor.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/JsonTreeVisitor.java @@ -2,7 +2,6 @@ import com.relogiclabs.json.schema.internal.antlr.JsonParser; import com.relogiclabs.json.schema.internal.antlr.JsonParserBaseVisitor; -import com.relogiclabs.json.schema.internal.util.StringHelper; import com.relogiclabs.json.schema.tree.Context; import com.relogiclabs.json.schema.tree.RuntimeContext; import com.relogiclabs.json.schema.types.JArray; @@ -22,8 +21,10 @@ import static com.relogiclabs.json.schema.internal.tree.TreeHelper.checkForDuplicate; import static com.relogiclabs.json.schema.internal.util.StringHelper.toEncoded; +import static com.relogiclabs.json.schema.internal.util.StringHelper.unquote; +import static com.relogiclabs.json.schema.message.ErrorCode.PROP03; -public class JsonTreeVisitor extends JsonParserBaseVisitor { +public final class JsonTreeVisitor extends JsonParserBaseVisitor { private final Map relations; private final RuntimeContext runtime; @@ -34,7 +35,7 @@ public JsonTreeVisitor(RuntimeContext runtime) { @Override public JNode visitJson(JsonParser.JsonContext ctx) { - return JRoot.builder() + return new JRoot.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(visit(ctx.value())) @@ -51,27 +52,27 @@ public JNode visitValue(JsonParser.ValueContext ctx) { @Override public JNode visitObject(JsonParser.ObjectContext ctx) { - return JObject.builder() + return new JObject.Builder() .relations(relations) .context(new Context(ctx, runtime)) .properties(checkForDuplicate(ctx.property().stream() - .map(p -> (JProperty) visit(p)).toList())) + .map(p -> (JProperty) visit(p)).toList(), PROP03)) .build(); } @Override public JNode visitProperty(JsonParser.PropertyContext ctx) { - return JProperty.builder() + return new JProperty.Builder() .relations(relations) .context(new Context(ctx, runtime)) - .key(StringHelper.unquote(ctx.STRING().getText())) + .key(unquote(ctx.STRING().getText())) .value(visit(ctx.value())) .build(); } @Override public JNode visitArray(JsonParser.ArrayContext ctx) { - return JArray.builder() + return new JArray.Builder() .relations(relations) .context(new Context(ctx, runtime)) .elements(ctx.value().stream().map(this::visit).toList()) @@ -80,7 +81,7 @@ public JNode visitArray(JsonParser.ArrayContext ctx) { @Override public JNode visitPrimitiveTrue(JsonParser.PrimitiveTrueContext ctx) { - return JBoolean.builder() + return new JBoolean.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(true).build(); @@ -88,7 +89,7 @@ public JNode visitPrimitiveTrue(JsonParser.PrimitiveTrueContext ctx) { @Override public JNode visitPrimitiveFalse(JsonParser.PrimitiveFalseContext ctx) { - return JBoolean.builder() + return new JBoolean.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(false).build(); @@ -96,7 +97,7 @@ public JNode visitPrimitiveFalse(JsonParser.PrimitiveFalseContext ctx) { @Override public JNode visitPrimitiveString(JsonParser.PrimitiveStringContext ctx) { - return JString.builder() + return new JString.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(toEncoded(ctx.STRING().getText())) @@ -105,7 +106,7 @@ public JNode visitPrimitiveString(JsonParser.PrimitiveStringContext ctx) { @Override public JNode visitPrimitiveInteger(JsonParser.PrimitiveIntegerContext ctx) { - return JInteger.builder() + return new JInteger.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Long.valueOf(ctx.INTEGER().getText())) @@ -114,7 +115,7 @@ public JNode visitPrimitiveInteger(JsonParser.PrimitiveIntegerContext ctx) { @Override public JNode visitPrimitiveFloat(JsonParser.PrimitiveFloatContext ctx) { - return JFloat.builder() + return new JFloat.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Double.valueOf(ctx.FLOAT().getText())) @@ -123,7 +124,7 @@ public JNode visitPrimitiveFloat(JsonParser.PrimitiveFloatContext ctx) { @Override public JNode visitPrimitiveDouble(JsonParser.PrimitiveDoubleContext ctx) { - return JDouble.builder() + return new JDouble.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Double.valueOf(ctx.DOUBLE().getText())) @@ -132,7 +133,7 @@ public JNode visitPrimitiveDouble(JsonParser.PrimitiveDoubleContext ctx) { @Override public JNode visitPrimitiveNull(JsonParser.PrimitiveNullContext ctx) { - return JNull.builder() + return new JNull.Builder() .relations(relations) .context(new Context(ctx, runtime)) .build(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/MethodPointer.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/MethodPointer.java index 0684daf..687a5d1 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/MethodPointer.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/MethodPointer.java @@ -17,7 +17,7 @@ import static java.util.stream.Collectors.joining; @Getter -public class MethodPointer { +public final class MethodPointer { private final FunctionBase instance; private final Method method; @@ -55,7 +55,6 @@ public static String getSignature(Method method) { private static String stringOf(Parameter parameter) { var builder = new StringBuilder(parameter.getType().getSimpleName()); - if(parameter.isVarArgs()) builder.append("..."); builder.append(" ").append(parameter.getName()); return builder.toString(); } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaDescriptor.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaDescriptor.java index f2c97ff..d8337d0 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaDescriptor.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaDescriptor.java @@ -8,7 +8,7 @@ import java.util.Map; @Getter -public class PragmaDescriptor { +public final class PragmaDescriptor { private static final Map> PRAGMAS = new HashMap<>(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaManager.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaManager.java index 1074171..5e837eb 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaManager.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/PragmaManager.java @@ -11,7 +11,7 @@ import static com.relogiclabs.json.schema.message.ErrorCode.PRAG03; @Getter -public class PragmaManager { +public final class PragmaManager { public static final String IGNORE_UNDEFINED_PROPERTIES = "IgnoreUndefinedProperties"; public static final String FLOATING_POINT_TOLERANCE = "FloatingPointTolerance"; diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/SchemaTreeVisitor.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/SchemaTreeVisitor.java index 5cccd52..256b2fa 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/SchemaTreeVisitor.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/SchemaTreeVisitor.java @@ -3,7 +3,6 @@ import com.relogiclabs.json.schema.function.CoreFunctions3; import com.relogiclabs.json.schema.internal.antlr.SchemaParser; import com.relogiclabs.json.schema.internal.antlr.SchemaParserBaseVisitor; -import com.relogiclabs.json.schema.internal.util.StringHelper; import com.relogiclabs.json.schema.tree.Context; import com.relogiclabs.json.schema.tree.RuntimeContext; import com.relogiclabs.json.schema.types.JAlias; @@ -37,9 +36,11 @@ import static com.relogiclabs.json.schema.internal.tree.TreeHelper.checkForDuplicate; import static com.relogiclabs.json.schema.internal.util.StringHelper.toEncoded; +import static com.relogiclabs.json.schema.internal.util.StringHelper.unquote; +import static com.relogiclabs.json.schema.message.ErrorCode.PROP04; import static java.util.stream.Collectors.joining; -public class SchemaTreeVisitor extends SchemaParserBaseVisitor { +public final class SchemaTreeVisitor extends SchemaParserBaseVisitor { private final Map relations; private final RuntimeContext runtime; @@ -50,7 +51,7 @@ public SchemaTreeVisitor(RuntimeContext runtime) { @Override public JNode visitAggregateSchema(SchemaParser.AggregateSchemaContext ctx) { - return JRoot.builder() + return new JRoot.Builder() .relations(relations) .context(new Context(ctx, runtime)) .title((JTitle) visit(ctx.title())) @@ -64,7 +65,7 @@ public JNode visitAggregateSchema(SchemaParser.AggregateSchemaContext ctx) { @Override public JNode visitCoreSchema(SchemaParser.CoreSchemaContext ctx) { - return JRoot.builder() + return new JRoot.Builder() .relations(relations) .context(new Context(ctx, runtime)) .includes(processIncludes(Collections.emptyList())) @@ -84,7 +85,7 @@ private List processIncludes(List context @Override public JNode visitTitle(SchemaParser.TitleContext ctx) { - return JTitle.builder() + return new JTitle.Builder() .relations(relations) .context(new Context(ctx, runtime)) .title(ctx.STRING().getText()) @@ -93,7 +94,7 @@ public JNode visitTitle(SchemaParser.TitleContext ctx) { @Override public JNode visitVersion(SchemaParser.VersionContext ctx) { - return JVersion.builder() + return new JVersion.Builder() .relations(relations) .context(new Context(ctx, runtime)) .version(ctx.VERSION_NUMBER1().getText()) @@ -102,7 +103,7 @@ public JNode visitVersion(SchemaParser.VersionContext ctx) { @Override public JNode visitInclude(SchemaParser.IncludeContext ctx) { - var include = JInclude.builder() + var include = new JInclude.Builder() .relations(relations) .context(new Context(ctx, runtime)) .className(ctx.IDENTIFIER().stream().map(ParseTree::getText) @@ -113,7 +114,7 @@ public JNode visitInclude(SchemaParser.IncludeContext ctx) { @Override public JNode visitPragma(SchemaParser.PragmaContext ctx) { - var pragma = JPragma.builder() + var pragma = new JPragma.Builder() .relations(relations) .context(new Context(ctx, runtime)) .name(ctx.IDENTIFIER().getText()) @@ -123,7 +124,7 @@ public JNode visitPragma(SchemaParser.PragmaContext ctx) { @Override public JNode visitDefine(SchemaParser.DefineContext ctx) { - var definition = JDefinition.builder() + var definition = new JDefinition.Builder() .relations(relations) .context(new Context(ctx, runtime)) .alias((JAlias) visit(ctx.aliasName())) @@ -134,7 +135,7 @@ public JNode visitDefine(SchemaParser.DefineContext ctx) { @Override public JNode visitAliasName(SchemaParser.AliasNameContext ctx) { - return JAlias.builder() + return new JAlias.Builder() .relations(relations) .context(new Context(ctx, runtime)) .name(ctx.ALIAS().getText()) @@ -143,7 +144,7 @@ public JNode visitAliasName(SchemaParser.AliasNameContext ctx) { @Override public JNode visitValidatorMain(SchemaParser.ValidatorMainContext ctx) { - return JValidator.builder() + return new JValidator.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(visit(ctx.value())) @@ -170,27 +171,27 @@ public JNode visitValue(SchemaParser.ValueContext ctx) { @Override public JNode visitObject(SchemaParser.ObjectContext ctx) { - return JObject.builder() + return new JObject.Builder() .relations(relations) .context(new Context(ctx, runtime)) .properties(checkForDuplicate(ctx.property().stream() - .map(c -> (JProperty) visit(c)).toList())) + .map(c -> (JProperty) visit(c)).toList(), PROP04)) .build(); } @Override public JNode visitProperty(SchemaParser.PropertyContext ctx) { - return JProperty.builder() + return new JProperty.Builder() .relations(relations) .context(new Context(ctx, runtime)) - .key(StringHelper.unquote(ctx.STRING().getText())) + .key(unquote(ctx.STRING().getText())) .value(visit(ctx.validator())) .build(); } @Override public JNode visitArray(SchemaParser.ArrayContext ctx) { - return JArray.builder() + return new JArray.Builder() .relations(relations) .context(new Context(ctx, runtime)) .elements(ctx.validator().stream().map(this::visit).toList()) @@ -199,7 +200,7 @@ public JNode visitArray(SchemaParser.ArrayContext ctx) { @Override public JNode visitDatatype(SchemaParser.DatatypeContext ctx) { - return JDataType.builder() + return new JDataType.Builder() .relations(relations) .context(new Context(ctx, runtime)) .jsonType(JsonType.from(ctx.DATATYPE())) @@ -210,7 +211,7 @@ public JNode visitDatatype(SchemaParser.DatatypeContext ctx) { @Override public JNode visitFunction(SchemaParser.FunctionContext ctx) { - return JFunction.builder() + return new JFunction.Builder() .relations(relations) .context(new Context(ctx, runtime)) .name(ctx.FUNCTION().getText()) @@ -221,7 +222,7 @@ public JNode visitFunction(SchemaParser.FunctionContext ctx) { @Override public JNode visitPrimitiveTrue(SchemaParser.PrimitiveTrueContext ctx) { - return JBoolean.builder() + return new JBoolean.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(true).build(); @@ -229,7 +230,7 @@ public JNode visitPrimitiveTrue(SchemaParser.PrimitiveTrueContext ctx) { @Override public JNode visitPrimitiveFalse(SchemaParser.PrimitiveFalseContext ctx) { - return JBoolean.builder() + return new JBoolean.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(false).build(); @@ -237,7 +238,7 @@ public JNode visitPrimitiveFalse(SchemaParser.PrimitiveFalseContext ctx) { @Override public JNode visitPrimitiveString(SchemaParser.PrimitiveStringContext ctx) { - return JString.builder() + return new JString.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(toEncoded(ctx.STRING().getText())) @@ -246,7 +247,7 @@ public JNode visitPrimitiveString(SchemaParser.PrimitiveStringContext ctx) { @Override public JNode visitPrimitiveInteger(SchemaParser.PrimitiveIntegerContext ctx) { - return JInteger.builder() + return new JInteger.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Long.valueOf(ctx.INTEGER().getText())) @@ -255,7 +256,7 @@ public JNode visitPrimitiveInteger(SchemaParser.PrimitiveIntegerContext ctx) { @Override public JNode visitPrimitiveFloat(SchemaParser.PrimitiveFloatContext ctx) { - return JFloat.builder() + return new JFloat.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Double.valueOf(ctx.FLOAT().getText())) @@ -264,7 +265,7 @@ public JNode visitPrimitiveFloat(SchemaParser.PrimitiveFloatContext ctx) { @Override public JNode visitPrimitiveDouble(SchemaParser.PrimitiveDoubleContext ctx) { - return JDouble.builder() + return new JDouble.Builder() .relations(relations) .context(new Context(ctx, runtime)) .value(Double.valueOf(ctx.DOUBLE().getText())) @@ -273,7 +274,7 @@ public JNode visitPrimitiveDouble(SchemaParser.PrimitiveDoubleContext ctx) { @Override public JNode visitPrimitiveNull(SchemaParser.PrimitiveNullContext ctx) { - return JNull.builder() + return new JNull.Builder() .relations(relations) .context(new Context(ctx, runtime)) .build(); @@ -281,7 +282,7 @@ public JNode visitPrimitiveNull(SchemaParser.PrimitiveNullContext ctx) { @Override public JNode visitPrimitiveUndefined(SchemaParser.PrimitiveUndefinedContext ctx) { - return JUndefined.builder() + return new JUndefined.Builder() .relations(relations) .context(new Context(ctx, runtime)) .build(); diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtils.java b/src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtilities.java similarity index 94% rename from src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtils.java rename to src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtilities.java index 133cb1b..d45286b 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtils.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/DebugUtilities.java @@ -9,7 +9,9 @@ import java.util.Collections; import java.util.List; -public class DebugUtils { +// External logging library may consider +// Kept it lightweight for now +public final class DebugUtilities { public static boolean debugPrint = false; diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/LexerErrorListener.java b/src/main/java/com/relogiclabs/json/schema/internal/util/LexerErrorListener.java index 3f561c9..47b5bc1 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/LexerErrorListener.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/LexerErrorListener.java @@ -22,7 +22,7 @@ public abstract class LexerErrorListener extends BaseErrorListener { protected abstract CommonException createException(String message, Throwable cause); protected abstract String getMessageFormat(); - private static class SchemaErrorListener extends LexerErrorListener { + private static final class SchemaErrorListener extends LexerErrorListener { @Override protected CommonException createException(String message, Throwable cause) { @@ -35,7 +35,7 @@ protected String getMessageFormat() { } } - private static class JsonErrorListener extends LexerErrorListener { + private static final class JsonErrorListener extends LexerErrorListener { @Override protected CommonException createException(String message, Throwable cause) { @@ -48,7 +48,7 @@ protected String getMessageFormat() { } } - private static class DateTimeErrorListener extends LexerErrorListener { + private static final class DateTimeErrorListener extends LexerErrorListener { @Override protected CommonException createException(String message, Throwable cause) { diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/MiscellaneousHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/util/MiscellaneousHelper.java index 80ce5de..3fbc82e 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/MiscellaneousHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/MiscellaneousHelper.java @@ -1,6 +1,6 @@ package com.relogiclabs.json.schema.internal.util; -public class MiscellaneousHelper { +public final class MiscellaneousHelper { public static T nonNull(T value, T defaultValue) { return value != null ? value : defaultValue; } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/ParserErrorListener.java b/src/main/java/com/relogiclabs/json/schema/internal/util/ParserErrorListener.java index 2c02472..6c9c9b7 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/ParserErrorListener.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/ParserErrorListener.java @@ -11,16 +11,13 @@ import static com.relogiclabs.json.schema.message.ErrorCode.SPRS01; public abstract class ParserErrorListener extends BaseErrorListener { - public static final ParserErrorListener SCHEMA = new SchemaErrorListener(); public static final ParserErrorListener JSON = new JsonErrorListener(); - protected abstract CommonException createException(String message, Throwable cause); protected abstract String getMessageFormat(); - private static class SchemaErrorListener extends ParserErrorListener { - + private static final class SchemaErrorListener extends ParserErrorListener { @Override protected CommonException createException(String message, Throwable cause) { return new SchemaParserException(SPRS01, message, cause); @@ -32,8 +29,7 @@ protected String getMessageFormat() { } } - private static class JsonErrorListener extends ParserErrorListener { - + private static final class JsonErrorListener extends ParserErrorListener { @Override protected CommonException createException(String message, Throwable cause) { return new JsonParserException(JPRS01, message, cause); @@ -48,7 +44,7 @@ protected String getMessageFormat() { @Override public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { - DebugUtils.print(recognizer); + DebugUtilities.print(recognizer); var message = getMessageFormat().formatted(line, charPositionInLine, msg, offendingSymbol); throw createException(message, e); } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/StreamHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/util/StreamHelper.java index 89f596a..e2e9fb5 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/StreamHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/StreamHelper.java @@ -3,7 +3,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; -public class StreamHelper { +public final class StreamHelper { public static T halt(RuntimeException exception) { throw exception; } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/StringHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/util/StringHelper.java index f2ab4d0..c59e874 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/StringHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/StringHelper.java @@ -6,8 +6,10 @@ import java.util.Collection; import static java.util.stream.Collectors.joining; +import static org.apache.commons.lang3.StringUtils.left; +import static org.apache.commons.lang3.StringUtils.right; -public class StringHelper { +public final class StringHelper { private StringHelper() { throw new UnsupportedOperationException(); } @@ -16,8 +18,7 @@ public static String createOutline(String target, int length) { int front = 2 * length / 3; int back = 1 * length / 3; if(front + back >= target.length()) return target; - return StringUtils.left(target, front) + "..." + - StringUtils.right(target, back); + return left(target, front) + "..." + right(target, back); } public static String toEncoded(String target) @@ -78,7 +79,7 @@ public static String concat(Object s1, Object s2) { public static String concat(Object s1, Object s2, Object s3) { var builder = new StringBuilder(); - return builder.append(s1).append(s2.toString()).append(s3).toString(); + return builder.append(s1).append(s2).append(s3).toString(); } public static String concat(Object s1, Object s2, Object s3, Object s4) { diff --git a/src/main/java/com/relogiclabs/json/schema/message/ActualDetail.java b/src/main/java/com/relogiclabs/json/schema/message/ActualDetail.java index 43745b2..b4430da 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/ActualDetail.java +++ b/src/main/java/com/relogiclabs/json/schema/message/ActualDetail.java @@ -5,7 +5,7 @@ import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; -public class ActualDetail extends ContextDetail { +public final class ActualDetail extends ContextDetail { public ActualDetail(Context context, String message) { super(context, message); } diff --git a/src/main/java/com/relogiclabs/json/schema/message/ContextDetail.java b/src/main/java/com/relogiclabs/json/schema/message/ContextDetail.java index c0eb083..6effaac 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/ContextDetail.java +++ b/src/main/java/com/relogiclabs/json/schema/message/ContextDetail.java @@ -8,7 +8,7 @@ @Getter @AllArgsConstructor -public class ContextDetail { +public abstract class ContextDetail { private Context context; private String message; @@ -20,4 +20,4 @@ public ContextDetail(JNode node, String message) { public Location getLocation() { return context.getLocation(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/message/ErrorDetail.java b/src/main/java/com/relogiclabs/json/schema/message/ErrorDetail.java index 8272531..89d8f98 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/ErrorDetail.java +++ b/src/main/java/com/relogiclabs/json/schema/message/ErrorDetail.java @@ -7,7 +7,7 @@ @Getter @AllArgsConstructor -public class ErrorDetail { +public final class ErrorDetail { private String code; private String message; diff --git a/src/main/java/com/relogiclabs/json/schema/message/ExpectedDetail.java b/src/main/java/com/relogiclabs/json/schema/message/ExpectedDetail.java index 4acc538..fcb157b 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/ExpectedDetail.java +++ b/src/main/java/com/relogiclabs/json/schema/message/ExpectedDetail.java @@ -5,7 +5,7 @@ import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; -public class ExpectedDetail extends ContextDetail { +public final class ExpectedDetail extends ContextDetail { public ExpectedDetail(Context context, String message) { super(context, message); } diff --git a/src/main/java/com/relogiclabs/json/schema/message/MessageFormatter.java b/src/main/java/com/relogiclabs/json/schema/message/MessageFormatter.java index 5c6692a..d0ecefc 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/MessageFormatter.java +++ b/src/main/java/com/relogiclabs/json/schema/message/MessageFormatter.java @@ -46,8 +46,8 @@ protected MessageFormatter(String summary, String expected, String actual) { public abstract String format(ErrorDetail error, ExpectedDetail expected, ActualDetail actual); - private static class ValidationFormatter extends MessageFormatter { - protected ValidationFormatter(String summary, String expected, String actual) { + private static final class ValidationFormatter extends MessageFormatter { + private ValidationFormatter(String summary, String expected, String actual) { super(summary, expected, actual); } @@ -60,7 +60,7 @@ public String format(ErrorDetail error, ExpectedDetail expected, ActualDetail ac } } - private static class AssertionFormatter extends MessageFormatter { + private static final class AssertionFormatter extends MessageFormatter { public AssertionFormatter(String summary, String expected, String actual) { super(summary, expected, actual); } @@ -101,4 +101,4 @@ private static ErrorDetail createDetail(String code, String format, String messa Location location) { return new ErrorDetail(code, format.formatted(location, code, message)); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/tree/Context.java b/src/main/java/com/relogiclabs/json/schema/tree/Context.java index 6daa7b4..ea1e6b9 100644 --- a/src/main/java/com/relogiclabs/json/schema/tree/Context.java +++ b/src/main/java/com/relogiclabs/json/schema/tree/Context.java @@ -4,7 +4,7 @@ import org.antlr.v4.runtime.ParserRuleContext; @Getter -public class Context { +public final class Context { private final ParserRuleContext parser; private final RuntimeContext runtime; private final Location location; @@ -19,4 +19,4 @@ private Location getLocation(ParserRuleContext parser) { var token = parser.getStart(); return new Location(token.getLine(), token.getCharPositionInLine()); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/tree/JsonTree.java b/src/main/java/com/relogiclabs/json/schema/tree/JsonTree.java index 26c6882..f9a382d 100644 --- a/src/main/java/com/relogiclabs/json/schema/tree/JsonTree.java +++ b/src/main/java/com/relogiclabs/json/schema/tree/JsonTree.java @@ -11,7 +11,7 @@ import org.antlr.v4.runtime.CommonTokenStream; @Getter -public class JsonTree { +public final class JsonTree { private final JRoot root; public JsonTree(RuntimeContext context, String input) { diff --git a/src/main/java/com/relogiclabs/json/schema/tree/SchemaTree.java b/src/main/java/com/relogiclabs/json/schema/tree/SchemaTree.java index 6f795a4..3c4467d 100644 --- a/src/main/java/com/relogiclabs/json/schema/tree/SchemaTree.java +++ b/src/main/java/com/relogiclabs/json/schema/tree/SchemaTree.java @@ -11,7 +11,7 @@ import org.antlr.v4.runtime.CommonTokenStream; @Getter -public class SchemaTree { +public final class SchemaTree { private final JRoot root; public SchemaTree(RuntimeContext context, String input) { diff --git a/src/main/java/com/relogiclabs/json/schema/types/JArray.java b/src/main/java/com/relogiclabs/json/schema/types/JArray.java index 833604e..8f09c77 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JArray.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JArray.java @@ -19,16 +19,13 @@ @Getter @EqualsAndHashCode -public class JArray extends JComposite { +public final class JArray extends JComposite { private final List elements; private JArray(Builder builder) { - super(builder.relations, builder.context); - this.elements = requireNonNull(builder.elements); - } - - public static Builder builder() { - return new Builder(); + super(builder); + elements = requireNonNull(builder.elements); + children = elements; } @Override @@ -36,11 +33,6 @@ public JsonType getType() { return JsonType.ARRAY; } - @Override - public Collection getChildren() { - return elements; - } - @Override public Collection components() { return elements; @@ -71,11 +63,11 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected List elements; + private List elements; @Override public JArray build() { - return new JArray(this).initialize(); + return build(new JArray(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JBoolean.java b/src/main/java/com/relogiclabs/json/schema/types/JBoolean.java index 8773a72..854e281 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JBoolean.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JBoolean.java @@ -15,16 +15,12 @@ @Getter @EqualsAndHashCode -public class JBoolean extends JPrimitive implements PragmaValue { +public final class JBoolean extends JPrimitive implements PragmaValue { private final boolean value; private JBoolean(Builder builder) { - super(builder.relations, builder.context); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + value = requireNonNull(builder.value); } @Override @@ -55,12 +51,10 @@ public String toString() { @Setter @Accessors(fluent = true) - public static class Builder extends JNode.Builder { - protected Boolean value; - + public static class Builder extends JPrimitive.Builder { @Override public JBoolean build() { - return new JBoolean(this).initialize(); + return build(new JBoolean(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JBranch.java b/src/main/java/com/relogiclabs/json/schema/types/JBranch.java index 6c22ec4..56d7f33 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JBranch.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JBranch.java @@ -1,11 +1,7 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; - -import java.util.Map; - public abstract class JBranch extends JNode { - protected JBranch(Map relations, Context context) { - super(relations, context); + protected JBranch(Builder builder) { + super(builder); } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JDirective.java b/src/main/java/com/relogiclabs/json/schema/types/JDirective.java index c5e9101..8b7991c 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JDirective.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JDirective.java @@ -1,23 +1,12 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - public abstract class JDirective extends JNode { - protected JDirective(Map relations, Context context) { - super(relations, context); - } - - @Override - public Collection getChildren() { - return Collections.emptyList(); + protected JDirective(Builder builder) { + super(builder); } @Override public boolean match(JNode node) { throw new IllegalStateException(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JDouble.java b/src/main/java/com/relogiclabs/json/schema/types/JDouble.java index 7d379ad..b4d5a3d 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JDouble.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JDouble.java @@ -15,17 +15,13 @@ @Getter @EqualsAndHashCode -public class JDouble extends JNumber implements PragmaValue { +public final class JDouble extends JNumber implements PragmaValue { private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("0.0##############E0"); private final double value; private JDouble(Builder builder) { - super(builder.relations, builder.context); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + value = requireNonNull(builder.value); } @Override @@ -59,10 +55,10 @@ public String toString() { return DOUBLE_FORMAT.format(value); } - public static class Builder extends JNumber.Builder { + public static class Builder extends JPrimitive.Builder { @Override public JDouble build() { - return new JDouble(this).initialize(); + return build(new JDouble(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JFloat.java b/src/main/java/com/relogiclabs/json/schema/types/JFloat.java index 2910f10..4be83a1 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JFloat.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JFloat.java @@ -15,17 +15,13 @@ @Getter @EqualsAndHashCode -public class JFloat extends JNumber implements PragmaValue { +public final class JFloat extends JNumber implements PragmaValue { private static final DecimalFormat FLOAT_FORMAT = new DecimalFormat("0.0##############"); private final double value; private JFloat(Builder builder) { - super(builder.relations, builder.context); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + value = requireNonNull(builder.value); } @Override @@ -59,10 +55,10 @@ public String toString() { return FLOAT_FORMAT.format(value); } - public static class Builder extends JNumber.Builder { + public static class Builder extends JPrimitive.Builder { @Override public JFloat build() { - return new JFloat(this).initialize(); + return build(new JFloat(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JFunction.java b/src/main/java/com/relogiclabs/json/schema/types/JFunction.java index 8f63123..dfcc3c1 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JFunction.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JFunction.java @@ -10,7 +10,6 @@ import lombok.Setter; import lombok.experimental.Accessors; -import java.util.Collection; import java.util.List; import static com.relogiclabs.json.schema.internal.message.MessageHelper.InvalidNestedFunction; @@ -22,25 +21,17 @@ @Getter @EqualsAndHashCode -public class JFunction extends JBranch implements NestedMode { +public final class JFunction extends JBranch implements NestedMode { private final String name; - private final List arguments; private final boolean nested; + private final List arguments; private JFunction(Builder builder) { - super(builder.relations, builder.context); - this.name = requireNonNull(builder.name); - this.arguments = requireNonNull(builder.arguments); - this.nested = builder.nested; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public Collection getChildren() { - return arguments; + super(builder); + name = requireNonNull(builder.name); + nested = requireNonNull(builder.nested); + arguments = requireNonNull(builder.arguments); + children = arguments; } @Override @@ -84,13 +75,13 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String name; - protected List arguments; - protected boolean nested; + private String name; + private Boolean nested; + private List arguments; @Override public JFunction build() { - return new JFunction(this).initialize(); + return build(new JFunction(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JInteger.java b/src/main/java/com/relogiclabs/json/schema/types/JInteger.java index b8d0a7a..37e8140 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JInteger.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JInteger.java @@ -13,16 +13,12 @@ @Getter @EqualsAndHashCode -public class JInteger extends JNumber implements PragmaValue { +public final class JInteger extends JNumber implements PragmaValue { private final long value; private JInteger(Builder builder) { - super(builder.relations, builder.context); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + value = requireNonNull(builder.value); } @Override @@ -56,10 +52,10 @@ public String toString() { return String.valueOf(value); } - public static class Builder extends JNumber.Builder { + public static class Builder extends JPrimitive.Builder { @Override public JInteger build() { - return new JInteger(this).initialize(); + return build(new JInteger(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JLeaf.java b/src/main/java/com/relogiclabs/json/schema/types/JLeaf.java index 4c7950c..489d6e6 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JLeaf.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JLeaf.java @@ -1,18 +1,7 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - public abstract class JLeaf extends JNode { - protected JLeaf(Map relations, Context context) { - super(relations, context); - } - - @Override - public Collection getChildren() { - return Collections.emptyList(); + protected JLeaf(Builder builder) { + super(builder); } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JNode.java b/src/main/java/com/relogiclabs/json/schema/types/JNode.java index 84693a0..96ebba6 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JNode.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JNode.java @@ -17,29 +17,26 @@ import static com.relogiclabs.json.schema.internal.message.MessageHelper.DataTypeMismatch; import static com.relogiclabs.json.schema.internal.util.StringHelper.createOutline; import static com.relogiclabs.json.schema.message.ErrorCode.DTYP02; +import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; public abstract class JNode { private final Map relations; + @Getter private final Context context; + @Getter protected Collection children = emptyList(); - @Getter - private final Context context; - - protected JNode(Map relations, Context context) { - this.relations = requireNonNull(relations); - this.context = requireNonNull(context); + protected JNode(Builder builder) { + relations = requireNonNull(builder.relations); + context = requireNonNull(builder.context); } public JNode getParent() { return relations.get(this); } - public abstract Collection getChildren(); - @SuppressWarnings("unchecked") - protected T initialize() { + protected void initialize() { for(var c : getChildren()) relations.put(c, this); - return (T) this; } public ParserRuleContext getParser() { @@ -63,7 +60,7 @@ protected T castType(JNode node, Class type) { return null; } - protected boolean isOfType(JNode node, Class type) { + protected boolean checkType(JNode node, Class type) { return castType(node, type) != null; } @@ -95,5 +92,10 @@ public T context(Context context) { } public abstract JNode build(); + + public static T build(T node) { + node.initialize(); + return node; + } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JNull.java b/src/main/java/com/relogiclabs/json/schema/types/JNull.java index 4bbf0d1..c77040e 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JNull.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JNull.java @@ -3,16 +3,11 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode -public class JNull extends JPrimitive { - +public final class JNull extends JPrimitive { public static final String NULL_MARKER = "null"; private JNull(Builder builder) { - super(builder.relations, builder.context); - } - - public static Builder builder() { - return new Builder(); + super(builder); } @Override @@ -22,7 +17,7 @@ public JsonType getType() { @Override public boolean match(JNode node) { - return isOfType(node, JNull.class); + return checkType(node, JNull.class); } @Override @@ -33,7 +28,7 @@ public String toString() { public static class Builder extends JNode.Builder { @Override public JNull build() { - return new JNull(this).initialize(); + return build(new JNull(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JNumber.java b/src/main/java/com/relogiclabs/json/schema/types/JNumber.java index 31b39be..46c5817 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JNumber.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JNumber.java @@ -1,14 +1,8 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.util.Map; - public abstract class JNumber extends JPrimitive { - protected JNumber(Map relations, Context context) { - super(relations, context); + protected JNumber(Builder builder) { + super(builder); } public abstract double toDouble(); @@ -31,11 +25,4 @@ public boolean areEqual(double value1, double value2) { public JsonType getType() { return JsonType.NUMBER; } - - @Setter - @Accessors(fluent = true) - public abstract static class Builder - extends JNode.Builder> { - protected T value; - } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JPragma.java b/src/main/java/com/relogiclabs/json/schema/types/JPragma.java index 8ead40c..ce63ec5 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JPragma.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JPragma.java @@ -3,13 +3,13 @@ import com.relogiclabs.json.schema.exception.InvalidPragmaValueException; import com.relogiclabs.json.schema.exception.PragmaNotFoundException; import com.relogiclabs.json.schema.internal.tree.PragmaDescriptor; -import com.relogiclabs.json.schema.internal.util.StringHelper; import com.relogiclabs.json.schema.message.MessageFormatter; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.asList; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; import static com.relogiclabs.json.schema.message.ErrorCode.PRAG01; @@ -18,20 +18,16 @@ @Getter @EqualsAndHashCode -public class JPragma extends JDirective { +public final class JPragma extends JDirective { public static final String PRAGMA_MARKER = "%pragma"; - private final String name; private final PragmaValue value; private JPragma(Builder builder) { - super(builder.relations, builder.context); - this.name = requireNonNull(builder.name); - this.value = (PragmaValue) requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + name = requireNonNull(builder.name); + value = (PragmaValue) requireNonNull(builder.value); + children = asList(builder.value); } @SuppressWarnings("unchecked") @@ -47,8 +43,8 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String name; - protected JNode value; + private String name; + private JNode value; private void checkPragma() { var descriptor = PragmaDescriptor.from(name); @@ -58,15 +54,15 @@ PRAG01, concat("Invalid pragma ", quote(name), " with value ", value.getOutline(), " found"), context)); if(!descriptor.matchType(value.getClass())) throw new InvalidPragmaValueException(MessageFormatter.formatForSchema( - PRAG02, StringHelper.concat("Invalid value ", value.getOutline(), + PRAG02, concat("Invalid value ", value.getOutline(), " for pragma ", quote(name), " found"), - context)); + value.getContext())); } @Override public JPragma build() { checkPragma(); - return new JPragma(this).initialize(); + return build(new JPragma(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JProperty.java b/src/main/java/com/relogiclabs/json/schema/types/JProperty.java index bac94d5..487a62a 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JProperty.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JProperty.java @@ -9,35 +9,26 @@ import lombok.Setter; import lombok.experimental.Accessors; -import java.util.Collection; -import java.util.List; import java.util.Objects; import static com.relogiclabs.json.schema.internal.message.MessageHelper.PropertyKeyMismatch; import static com.relogiclabs.json.schema.internal.message.MessageHelper.PropertyValueMismatch; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.asList; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; import static com.relogiclabs.json.schema.message.ErrorCode.PROP01; import static com.relogiclabs.json.schema.message.ErrorCode.PROP02; import static java.util.Objects.requireNonNull; @Getter -public class JProperty extends JBranch implements Keyable { +public final class JProperty extends JBranch implements Keyable { private final String key; private final JNode value; private JProperty(Builder builder) { - super(builder.relations, builder.context); - this.key = requireNonNull(builder.key); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public Collection getChildren() { - return List.of(value); + super(builder); + key = requireNonNull(builder.key); + value = requireNonNull(builder.value); + children = asList(value); } @Override @@ -76,12 +67,12 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String key; - protected JNode value; + private String key; + private JNode value; @Override public JProperty build() { - return new JProperty(this).initialize(); + return build(new JProperty(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JRoot.java b/src/main/java/com/relogiclabs/json/schema/types/JRoot.java index 98d1944..d3fdd1b 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JRoot.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JRoot.java @@ -6,16 +6,16 @@ import lombok.experimental.Accessors; import java.util.ArrayList; -import java.util.Collection; import java.util.List; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.addToList; import static com.relogiclabs.json.schema.internal.util.StringHelper.join; import static java.util.Collections.unmodifiableCollection; import static java.util.Objects.requireNonNull; @Getter @EqualsAndHashCode -public class JRoot extends JNode { +public final class JRoot extends JNode { private static final String NEW_LINE = System.lineSeparator(); private final JTitle title; @@ -24,46 +24,20 @@ public class JRoot extends JNode { private final List pragmas; private final List definitions; private final JNode value; - private Collection children; private JRoot(Builder builder) { - super(builder.relations, builder.context); - this.title = builder.title; - this.version = builder.version; - this.includes = builder.includes; - this.pragmas = builder.pragmas; - this.definitions = builder.definitions; - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public Collection getChildren() { - return children; - } - - @Override - protected T initialize() { - children = new ArrayList<>(); - addToList(children, title); - addToList(children, version); - addToList(children, includes); - addToList(children, pragmas); - addToList(children, definitions); - addToList(children, value); + super(builder); + title = builder.title; + version = builder.version; + includes = builder.includes; + pragmas = builder.pragmas; + definitions = builder.definitions; + value = requireNonNull(builder.value); + var nodes = new ArrayList(); + addToList(nodes, title, version); + addToList(nodes, includes, pragmas, definitions); + addToList(nodes, value); children = unmodifiableCollection(children); - return super.initialize(); - } - - private void addToList(Collection list, JNode node) { - if(node != null) list.add(node); - } - - private void addToList(Collection list, List nodes) { - if(nodes != null) list.addAll(nodes); } @Override @@ -95,19 +69,19 @@ private void appendTo(StringBuilder builder, List list) { builder.append(join(list, NEW_LINE, "", NEW_LINE)); } - @Setter() + @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected JTitle title; - protected JVersion version; - protected List includes; - protected List pragmas; - protected List definitions; - protected JNode value; + private JTitle title; + private JVersion version; + private List includes; + private List pragmas; + private List definitions; + private JNode value; @Override public JRoot build() { - return new JRoot(this).initialize(); + return build(new JRoot(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JString.java b/src/main/java/com/relogiclabs/json/schema/types/JString.java index df4d708..de13c6c 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JString.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JString.java @@ -16,16 +16,12 @@ @Getter @EqualsAndHashCode -public class JString extends JPrimitive { +public final class JString extends JPrimitive { private final String value; private JString(Builder builder) { - super(builder.relations, builder.context); - this.value = requireNonNull(builder.value); - } - - public static Builder builder() { - return new Builder(); + super(builder); + value = requireNonNull(builder.value); } @Override @@ -51,12 +47,10 @@ public String toString() { @Setter @Accessors(fluent = true) - public static class Builder extends JNode.Builder { - protected String value; - + public static class Builder extends JPrimitive.Builder { @Override public JString build() { - return new JString(this).initialize(); + return build(new JString(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JUndefined.java b/src/main/java/com/relogiclabs/json/schema/types/JUndefined.java index d9cba70..05a6f13 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JUndefined.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JUndefined.java @@ -3,15 +3,11 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode -public class JUndefined extends JLeaf { +public final class JUndefined extends JLeaf { public static final String UNDEFINED_MARKER = "!"; private JUndefined(Builder builder) { - super(builder.relations, builder.context); - } - - public static Builder builder() { - return new Builder(); + super(builder); } @Override @@ -27,7 +23,7 @@ public String toString() { public static class Builder extends JNode.Builder { @Override public JUndefined build() { - return new JUndefined(this).initialize(); + return build(new JUndefined(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JValidator.java b/src/main/java/com/relogiclabs/json/schema/types/JValidator.java index 376dedb..55516af 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JValidator.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JValidator.java @@ -10,10 +10,10 @@ import lombok.experimental.Accessors; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import static com.relogiclabs.json.schema.internal.message.MessageHelper.ValidationFailed; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.addToList; import static com.relogiclabs.json.schema.internal.util.StreamHelper.allTrue; import static com.relogiclabs.json.schema.internal.util.StreamHelper.anyTrue; import static com.relogiclabs.json.schema.internal.util.StringHelper.join; @@ -22,48 +22,24 @@ @Getter @EqualsAndHashCode -public class JValidator extends JBranch { +public final class JValidator extends JBranch { public static final String OPTIONAL_MARKER = "?"; - private Collection children; private final JNode value; private final List functions; private final List dataTypes; private final boolean optional; private JValidator(Builder builder) { - super(builder.relations, builder.context); - this.value = builder.value; - this.functions = builder.functions; - this.dataTypes = builder.dataTypes; - this.optional = builder.optional; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public Collection getChildren() { - return children; - } - - @Override - protected T initialize() { - children = new ArrayList<>(); - addToList(children, value); - addToList(children, functions); - addToList(children, dataTypes); - children = unmodifiableCollection(children); - return super.initialize(); - } - - private void addToList(Collection list, JNode node) { - if(node != null) list.add(node); - } - - private void addToList(Collection list, List nodes) { - if(nodes != null) list.addAll(nodes); + super(builder); + value = builder.value; + functions = builder.functions; + dataTypes = builder.dataTypes; + optional = builder.optional; + var nodes = new ArrayList(); + addToList(nodes, value); + addToList(nodes, functions, dataTypes); + children = unmodifiableCollection(nodes); } @Override @@ -115,14 +91,14 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected JNode value; - protected List functions; - protected List dataTypes; - protected boolean optional; + private JNode value; + private List functions; + private List dataTypes; + private boolean optional; @Override public JValidator build() { - return new JValidator(this).initialize(); + return build(new JValidator(this)); } } } \ No newline at end of file From 7904a26c3f04354f2aca519a782683063ad7ca80 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Fri, 3 Nov 2023 22:54:17 +0600 Subject: [PATCH 2/4] Update error handlers and messages --- .../exception/FunctionMismatchException.java | 9 -- .../internal/time/DateTimeValidator.java | 147 +++++++++++++----- .../schema/internal/tree/FunctionManager.java | 39 ++--- .../json/schema/internal/tree/TreeHelper.java | 7 +- .../internal/util/CollectionHelper.java | 22 ++- .../json/schema/internal/util/Reference.java | 16 ++ .../json/schema/message/ErrorCode.java | 1 + .../json/schema/tree/RuntimeContext.java | 7 +- .../relogiclabs/json/schema/types/JAlias.java | 22 ++- .../json/schema/types/JComposite.java | 9 +- .../json/schema/types/JDataType.java | 60 ++++--- .../json/schema/types/JDefinition.java | 26 ++-- .../json/schema/types/JInclude.java | 16 +- .../json/schema/types/JObject.java | 49 +++--- .../json/schema/types/JPrimitive.java | 19 ++- .../relogiclabs/json/schema/types/JTitle.java | 16 +- .../json/schema/types/JVersion.java | 16 +- .../json/schema/types/JsonTypable.java | 6 +- .../json/schema/types/JsonType.java | 34 ++-- 19 files changed, 295 insertions(+), 226 deletions(-) delete mode 100644 src/main/java/com/relogiclabs/json/schema/exception/FunctionMismatchException.java create mode 100644 src/main/java/com/relogiclabs/json/schema/internal/util/Reference.java diff --git a/src/main/java/com/relogiclabs/json/schema/exception/FunctionMismatchException.java b/src/main/java/com/relogiclabs/json/schema/exception/FunctionMismatchException.java deleted file mode 100644 index dc0ef41..0000000 --- a/src/main/java/com/relogiclabs/json/schema/exception/FunctionMismatchException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.relogiclabs.json.schema.exception; - -import com.relogiclabs.json.schema.message.ErrorDetail; - -public class FunctionMismatchException extends CommonException { - public FunctionMismatchException(ErrorDetail detail) { - super(detail); - } -} diff --git a/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeValidator.java b/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeValidator.java index 069b980..80bedae 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeValidator.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/time/DateTimeValidator.java @@ -2,8 +2,9 @@ import com.relogiclabs.json.schema.exception.InvalidDateTimeException; import com.relogiclabs.json.schema.internal.antlr.DateTimeLexer; -import com.relogiclabs.json.schema.internal.util.DebugUtils; +import com.relogiclabs.json.schema.internal.util.DebugUtilities; import com.relogiclabs.json.schema.internal.util.LexerErrorListener; +import com.relogiclabs.json.schema.internal.util.Reference; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.Token; @@ -11,12 +12,74 @@ import java.util.List; import java.util.Map; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.CLOCK_AM_PM; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.DAY_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.DAY_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.ERA; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER1; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER3; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER4; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER5; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.FRACTION_NUMBER6; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.HOUR_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.HOUR_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MINUTE_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MINUTE_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NAME; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.MONTH_SHORT_NAME; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SECOND_NUMBER; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SECOND_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.SYMBOL; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.TEXT; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_HOUR; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_TIME1; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.UTC_OFFSET_TIME2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WEEKDAY_NAME; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WEEKDAY_SHORT_NAME; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.WHITESPACE; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.YEAR_NUMBER2; +import static com.relogiclabs.json.schema.internal.antlr.DateTimeLexer.YEAR_NUMBER4; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.ClockAmPm; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.DayNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.DayNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Era; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber1; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber3; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber4; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber5; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.FractionNumber6; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.HourNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.HourNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MinuteNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MinuteNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthName; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.MonthShortName; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.SecondNumber; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.SecondNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Symbol; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Text; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetHour; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetTime1; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.UtcOffsetTime2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.WeekdayName; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.WeekdayShortName; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.Whitespace; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.YearNumber2; +import static com.relogiclabs.json.schema.internal.time.SegmentProcessor.YearNumber4; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; import static com.relogiclabs.json.schema.message.ErrorCode.DINV02; -public class DateTimeValidator { +public final class DateTimeValidator { public static final String ISO_8601_DATE = "YYYY-MM-DD"; - public static final String ISO_8601_TIME = "YYYY-MM-DD'T'hh:mm:ss.fffZZ"; + public static final String ISO_8601_TIME = "YYYY-MM-DD'T'hh:mm:ss.FZZ"; private static final Map PROCESSORS; private final DateTimeLexer dateTimeLexer; @@ -24,37 +87,41 @@ public class DateTimeValidator { static { PROCESSORS = new HashMap<>(50); - PROCESSORS.put("TEXT", SegmentProcessor.Text); - PROCESSORS.put("SYMBOL", SegmentProcessor.Symbol); - PROCESSORS.put("WHITESPACE", SegmentProcessor.Whitespace); - PROCESSORS.put("ERA", SegmentProcessor.Era); - PROCESSORS.put("YEAR_NUM4", SegmentProcessor.YearNum4); - PROCESSORS.put("YEAR_NUM2", SegmentProcessor.YearNum2); - PROCESSORS.put("MONTH_NAME", SegmentProcessor.MonthName); - PROCESSORS.put("MONTH_SHORT_NAME", SegmentProcessor.MonthShortName); - PROCESSORS.put("MONTH_NUM2", SegmentProcessor.MonthNum2); - PROCESSORS.put("MONTH_NUM", SegmentProcessor.MonthNum); - PROCESSORS.put("WEEKDAY_NAME", SegmentProcessor.WeekdayName); - PROCESSORS.put("WEEKDAY_SHORT_NAME", SegmentProcessor.WeekdayShortName); - PROCESSORS.put("DAY_NUM2", SegmentProcessor.DayNum2); - PROCESSORS.put("DAY_NUM", SegmentProcessor.DayNum); - PROCESSORS.put("AM_PM", SegmentProcessor.AmPm); - PROCESSORS.put("HOUR_NUM2", SegmentProcessor.HourNum2); - PROCESSORS.put("HOUR_NUM", SegmentProcessor.HourNum); - PROCESSORS.put("MINUTE_NUM2", SegmentProcessor.MinuteNum2); - PROCESSORS.put("MINUTE_NUM", SegmentProcessor.MinuteNum); - PROCESSORS.put("SECOND_NUM2", SegmentProcessor.SecondNum2); - PROCESSORS.put("SECOND_NUM", SegmentProcessor.SecondNum); - PROCESSORS.put("FRACTION_NUM", SegmentProcessor.FractionNum); - PROCESSORS.put("FRACTION_NUM01", SegmentProcessor.FractionNum01); - PROCESSORS.put("FRACTION_NUM02", SegmentProcessor.FractionNum02); - PROCESSORS.put("FRACTION_NUM03", SegmentProcessor.FractionNum03); - PROCESSORS.put("FRACTION_NUM04", SegmentProcessor.FractionNum04); - PROCESSORS.put("FRACTION_NUM05", SegmentProcessor.FractionNum05); - PROCESSORS.put("FRACTION_NUM06", SegmentProcessor.FractionNum06); - PROCESSORS.put("UTC_OFFSET_HOUR", SegmentProcessor.UtcOffsetHour); - PROCESSORS.put("UTC_OFFSET_TIME1", SegmentProcessor.UtcOffsetTime1); - PROCESSORS.put("UTC_OFFSET_TIME2", SegmentProcessor.UtcOffsetTime2); + addProcessor(TEXT, Text); + addProcessor(SYMBOL, Symbol); + addProcessor(WHITESPACE, Whitespace); + addProcessor(ERA, Era); + addProcessor(YEAR_NUMBER4, YearNumber4); + addProcessor(YEAR_NUMBER2, YearNumber2); + addProcessor(MONTH_NAME, MonthName); + addProcessor(MONTH_SHORT_NAME, MonthShortName); + addProcessor(MONTH_NUMBER2, MonthNumber2); + addProcessor(MONTH_NUMBER, MonthNumber); + addProcessor(WEEKDAY_NAME, WeekdayName); + addProcessor(WEEKDAY_SHORT_NAME, WeekdayShortName); + addProcessor(DAY_NUMBER2, DayNumber2); + addProcessor(DAY_NUMBER, DayNumber); + addProcessor(CLOCK_AM_PM, ClockAmPm); + addProcessor(HOUR_NUMBER2, HourNumber2); + addProcessor(HOUR_NUMBER, HourNumber); + addProcessor(MINUTE_NUMBER2, MinuteNumber2); + addProcessor(MINUTE_NUMBER, MinuteNumber); + addProcessor(SECOND_NUMBER2, SecondNumber2); + addProcessor(SECOND_NUMBER, SecondNumber); + addProcessor(FRACTION_NUMBER, FractionNumber); + addProcessor(FRACTION_NUMBER1, FractionNumber1); + addProcessor(FRACTION_NUMBER2, FractionNumber2); + addProcessor(FRACTION_NUMBER3, FractionNumber3); + addProcessor(FRACTION_NUMBER4, FractionNumber4); + addProcessor(FRACTION_NUMBER5, FractionNumber5); + addProcessor(FRACTION_NUMBER6, FractionNumber6); + addProcessor(UTC_OFFSET_HOUR, UtcOffsetHour); + addProcessor(UTC_OFFSET_TIME1, UtcOffsetTime1); + addProcessor(UTC_OFFSET_TIME2, UtcOffsetTime2); + } + + private static void addProcessor(int index, SegmentProcessor processor) { + PROCESSORS.put(DateTimeLexer.ruleNames[index - 1], processor); } @SuppressWarnings("unchecked") @@ -74,7 +141,7 @@ private void Validate(String input, DateTimeContext context) { concat("Invalid ", context.getType(), " input format")); context.validate(); - DebugUtils.print(context); + DebugUtilities.print(context); } public void ValidateDate(String input) { @@ -85,22 +152,24 @@ public void ValidateTime(String input) { Validate(input, new DateTimeContext(DateTimeType.TIME_TYPE)); } - public boolean IsValidDate(String input) { + public boolean IsValidDate(String input, Reference error) { try { ValidateDate(input); return true; } catch(InvalidDateTimeException e) { - DebugUtils.print(e); + DebugUtilities.print(e); + error.setValue(e.getMessage()); return false; } } - public boolean IsValidTime(String input) { + public boolean IsValidTime(String input, Reference error) { try { ValidateTime(input); return true; } catch(InvalidDateTimeException e) { - DebugUtils.print(e); + DebugUtilities.print(e); + error.setValue(e.getMessage()); return false; } } diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/FunctionManager.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/FunctionManager.java index 2f8f6cd..7534d7d 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/FunctionManager.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/FunctionManager.java @@ -3,18 +3,20 @@ import com.relogiclabs.json.schema.exception.ClassInstantiationException; import com.relogiclabs.json.schema.exception.CommonException; import com.relogiclabs.json.schema.exception.DuplicateIncludeException; -import com.relogiclabs.json.schema.exception.FunctionMismatchException; import com.relogiclabs.json.schema.exception.FunctionNotFoundException; import com.relogiclabs.json.schema.exception.InvalidFunctionException; import com.relogiclabs.json.schema.exception.InvalidIncludeException; +import com.relogiclabs.json.schema.exception.JsonSchemaException; import com.relogiclabs.json.schema.exception.NotFoundClassException; import com.relogiclabs.json.schema.function.FunctionBase; +import com.relogiclabs.json.schema.message.ActualDetail; +import com.relogiclabs.json.schema.message.ErrorDetail; +import com.relogiclabs.json.schema.message.ExpectedDetail; import com.relogiclabs.json.schema.message.MessageFormatter; import com.relogiclabs.json.schema.tree.Context; import com.relogiclabs.json.schema.tree.RuntimeContext; import com.relogiclabs.json.schema.types.JFunction; import com.relogiclabs.json.schema.types.JNode; -import com.relogiclabs.json.schema.types.JsonType; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; @@ -26,6 +28,7 @@ import java.util.Map; import java.util.Set; +import static com.relogiclabs.json.schema.internal.message.MessageHelper.getTypeName; import static com.relogiclabs.json.schema.internal.tree.MethodPointer.getSignature; import static com.relogiclabs.json.schema.internal.util.CollectionHelper.merge; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; @@ -42,7 +45,7 @@ import static com.relogiclabs.json.schema.message.ErrorCode.FUNC04; import static com.relogiclabs.json.schema.message.ErrorCode.FUNC05; -public class FunctionManager { +public final class FunctionManager { private final Set includes; private final Map> functions; private final RuntimeContext runtime; @@ -127,32 +130,30 @@ private static CommonException createException(String code, Exception ex, Class< public boolean invokeFunction(JFunction function, JNode target) { var methods = getMethods(function); - String mismatchMessage = null; + Parameter mismatchParameter = null; + for(var method : methods) { var parameters = method.getParameters(); var arguments = function.getArguments(); var schemaArgs = processArgs(parameters, arguments); if(schemaArgs == null) continue; - if(!isMatch(parameters.get(0), target)) { - mismatchMessage = "Function %s is applicable on %s but applied on %s of %s" - .formatted(function.getOutline(), getTypeName(parameters.get(0).getType()), - getTypeName(target.getClass()), target); - continue; - } - return method.invoke(function, addTarget(schemaArgs, target)); + if(isMatch(parameters.get(0), target)) + return method.invoke(function, addTarget(schemaArgs, target)); + mismatchParameter = parameters.get(0); } - if(mismatchMessage != null) return failWith(new FunctionMismatchException( - MessageFormatter.formatForSchema(FUNC03, mismatchMessage, function.getContext()))); + + if(mismatchParameter != null) + return failWith(new JsonSchemaException(new ErrorDetail(FUNC03, + "Function ", function.getOutline(), " is incompatible with the target data type"), + new ExpectedDetail(function, "applying to a supported data type such as ", + getTypeName(mismatchParameter.getType())), + new ActualDetail(target, "applied to an unsupported data type ", + getTypeName(target.getClass()), " of ", target))); + return failWith(new FunctionNotFoundException(MessageFormatter .formatForSchema(FUNC04, function.getOutline(), function.getContext()))); } - private static String getTypeName(Class type) { - JsonType t = JsonType.from(type); - if(t != null) return t.getName(); - else return type.getSimpleName(); - } - private List getMethods(JFunction function) { var methodPointers = functions.get(new FunctionKey(function)); if(methodPointers == null) diff --git a/src/main/java/com/relogiclabs/json/schema/internal/tree/TreeHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/tree/TreeHelper.java index b004b05..45cf68c 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/tree/TreeHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/tree/TreeHelper.java @@ -10,15 +10,14 @@ import static com.relogiclabs.json.schema.internal.util.StreamHelper.halt; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; -import static com.relogiclabs.json.schema.message.ErrorCode.PROP03; import static java.util.stream.Collectors.toMap; -public class TreeHelper { +public final class TreeHelper { - public static List checkForDuplicate(List list) { + public static List checkForDuplicate(List list, String errorCode) { list.stream().collect(toMap(JProperty::getKey, Function.identity(), (p1, p2) -> halt(new DuplicatePropertyKeyException(MessageFormatter.formatForJson( - PROP03, concat("Multiple key with name ", quote(p2.getKey()), " found"), + errorCode, concat("Multiple key with name ", quote(p2.getKey()), " found"), p2.getContext()))) )); return list; diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/CollectionHelper.java b/src/main/java/com/relogiclabs/json/schema/internal/util/CollectionHelper.java index feb4384..c9fa419 100644 --- a/src/main/java/com/relogiclabs/json/schema/internal/util/CollectionHelper.java +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/CollectionHelper.java @@ -5,14 +5,17 @@ import com.relogiclabs.json.schema.types.JProperty; import com.relogiclabs.json.schema.types.JString; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.stream.Collectors.toSet; -public class CollectionHelper { +public final class CollectionHelper { public static void merge(Map> target, Map> source) { source.forEach((sk, sv) -> { var tv = target.get(sk); @@ -33,4 +36,21 @@ public static Set containsValues(IndexMap map, JNode.. map.values().stream().forEach(p -> set.remove(p.getValue())); return set; } + + @SafeVarargs + public static List asList(T... elements) { + List list = new ArrayList<>(elements.length); + for(var e : elements) if(e != null) list.add(e); + return Collections.unmodifiableList(list); + } + + @SafeVarargs + public static void addToList(Collection source, T... elements) { + for(var e : elements) if(e != null) source.add(e); + } + + @SafeVarargs + public static void addToList(Collection source, Collection... collections) { + for(var c : collections) if(c != null) source.addAll(c); + } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/internal/util/Reference.java b/src/main/java/com/relogiclabs/json/schema/internal/util/Reference.java new file mode 100644 index 0000000..ce3fb87 --- /dev/null +++ b/src/main/java/com/relogiclabs/json/schema/internal/util/Reference.java @@ -0,0 +1,16 @@ +package com.relogiclabs.json.schema.internal.util; + +import lombok.Data; + +@Data +public final class Reference { + private V value; + + public Reference() { + value = null; + } + + public Reference(V initialValue) { + this.value = initialValue; + } +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/message/ErrorCode.java b/src/main/java/com/relogiclabs/json/schema/message/ErrorCode.java index 8f42ac0..6a7fd23 100644 --- a/src/main/java/com/relogiclabs/json/schema/message/ErrorCode.java +++ b/src/main/java/com/relogiclabs/json/schema/message/ErrorCode.java @@ -120,6 +120,7 @@ public interface ErrorCode { String PROP04 = "PROP04"; String PROP05 = "PROP05"; String PROP06 = "PROP06"; + String PROP07 = "PROP07"; String RANG01 = "RANG01"; String RANG02 = "RANG02"; String RANG03 = "RANG03"; diff --git a/src/main/java/com/relogiclabs/json/schema/tree/RuntimeContext.java b/src/main/java/com/relogiclabs/json/schema/tree/RuntimeContext.java index 6684ce1..5ab3c4a 100644 --- a/src/main/java/com/relogiclabs/json/schema/tree/RuntimeContext.java +++ b/src/main/java/com/relogiclabs/json/schema/tree/RuntimeContext.java @@ -20,10 +20,11 @@ import java.util.function.Supplier; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; +import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; import static com.relogiclabs.json.schema.message.ErrorCode.DEFI01; -public class RuntimeContext { +public final class RuntimeContext { private final FunctionManager functionManager; private final PragmaManager pragmaManager; private int disableException = 0; @@ -32,7 +33,7 @@ public class RuntimeContext { @Getter private final boolean throwException; @Getter private final Queue exceptions; @Getter private final MessageFormatter messageFormatter; - + public RuntimeContext(MessageFormatter messageFormatter, boolean throwException) { this.messageFormatter = messageFormatter; @@ -60,7 +61,7 @@ public JDefinition addDefinition(JDefinition definition) { var previous = definitions.get(definition.getAlias()); if(previous != null) throw new DuplicateDefinitionException(MessageFormatter.formatForSchema( - DEFI01, concat("Duplicate definition of ", definition.getAlias(), + DEFI01, concat("Duplicate definition of ", quote(definition.getAlias()), " is found and already defined as ", previous.getOutline()), definition.getContext())); definitions.put(definition.getAlias(), definition.getValidator()); diff --git a/src/main/java/com/relogiclabs/json/schema/types/JAlias.java b/src/main/java/com/relogiclabs/json/schema/types/JAlias.java index a0101e8..e9cb641 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JAlias.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JAlias.java @@ -6,31 +6,27 @@ import lombok.Setter; import lombok.experimental.Accessors; +import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; import static com.relogiclabs.json.schema.message.ErrorCode.DEFI02; import static com.relogiclabs.json.schema.message.MessageFormatter.formatForSchema; import static java.util.Objects.requireNonNull; @Getter @EqualsAndHashCode -public class JAlias extends JLeaf { +public final class JAlias extends JLeaf { private final String name; private JAlias(Builder builder) { - super(builder.relations, builder.context); - this.name = requireNonNull(builder.name); - } - - public static Builder builder() { - return new Builder(); + super(builder); + name = requireNonNull(builder.name); } @Override public boolean match(JNode node) { var definitions = getRuntime().getDefinitions(); if(!definitions.containsKey(this)) - throw new DefinitionNotFoundException( - formatForSchema(DEFI02, "Definition of " + name - + " not found", getContext())); + throw new DefinitionNotFoundException(formatForSchema(DEFI02, "Definition of " + + quote(name) + " not found", getContext())); return definitions.get(this).match(node); } @@ -42,11 +38,11 @@ public String toString() { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String name; + private String name; @Override public JAlias build() { - return new JAlias(this).initialize(); + return build(new JAlias(this)); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JComposite.java b/src/main/java/com/relogiclabs/json/schema/types/JComposite.java index 12b2f30..56ca1f6 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JComposite.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JComposite.java @@ -1,20 +1,17 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; - import java.util.Collection; -import java.util.Map; public abstract class JComposite extends JBranch implements JsonTypable { - protected JComposite(Map relations, Context context) { - super(relations, context); + protected JComposite(Builder builder) { + super(builder); } public abstract Collection components(); @Override public JsonType getType() { - return JsonType.ANY; + return JsonType.COMPOSITE; } @Override diff --git a/src/main/java/com/relogiclabs/json/schema/types/JDataType.java b/src/main/java/com/relogiclabs/json/schema/types/JDataType.java index 38e7882..a5c7c97 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JDataType.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JDataType.java @@ -5,6 +5,7 @@ import com.relogiclabs.json.schema.internal.message.ActualHelper; import com.relogiclabs.json.schema.internal.message.ExpectedHelper; import com.relogiclabs.json.schema.internal.message.MatchReport; +import com.relogiclabs.json.schema.internal.util.Reference; import com.relogiclabs.json.schema.message.ErrorDetail; import com.relogiclabs.json.schema.message.MessageFormatter; import lombok.EqualsAndHashCode; @@ -12,9 +13,6 @@ import lombok.Setter; import lombok.experimental.Accessors; -import java.util.Collection; -import java.util.List; - import static com.relogiclabs.json.schema.internal.message.MatchReport.AliasError; import static com.relogiclabs.json.schema.internal.message.MatchReport.ArgumentError; import static com.relogiclabs.json.schema.internal.message.MatchReport.Success; @@ -22,40 +20,28 @@ import static com.relogiclabs.json.schema.internal.message.MessageHelper.DataTypeArgumentFailed; import static com.relogiclabs.json.schema.internal.message.MessageHelper.DataTypeMismatch; import static com.relogiclabs.json.schema.internal.message.MessageHelper.InvalidNestedDataType; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.asList; import static com.relogiclabs.json.schema.internal.util.StreamHelper.allTrue; +import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; import static com.relogiclabs.json.schema.internal.util.StringHelper.quote; import static com.relogiclabs.json.schema.message.ErrorCode.DTYP03; -import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.apache.commons.lang3.StringUtils.uncapitalize; @Getter @EqualsAndHashCode -public class JDataType extends JBranch implements NestedMode { - private Collection children; +public final class JDataType extends JBranch implements NestedMode { private final JsonType jsonType; private final JAlias alias; private final boolean nested; private JDataType(Builder builder) { - super(builder.relations, builder.context); - this.jsonType = requireNonNull(builder.jsonType); - this.alias = builder.alias; - this.nested = builder.nested; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public Collection getChildren() { - return children; - } - - @Override - protected T initialize() { - children = alias != null ? List.of(alias) : emptyList(); - return super.initialize(); + super(builder); + jsonType = requireNonNull(builder.jsonType); + nested = requireNonNull(builder.nested); + alias = builder.alias; + children = asList(alias); } @Override @@ -66,11 +52,11 @@ public boolean match(JNode node) { } private boolean isMatchCurrent(JNode node) { - return matchCurrent(node) == Success; + return matchCurrent(node, new Reference<>()) == Success; } - private MatchReport matchCurrent(JNode node) { - var result = jsonType.match(node) ? Success : TypeError; + private MatchReport matchCurrent(JNode node, Reference error) { + var result = jsonType.match(node, error) ? Success : TypeError; if(alias == null || result != Success) return result; var validator = getRuntime().getDefinitions().get(alias); if(validator == null) return AliasError; @@ -91,9 +77,11 @@ public boolean matchForReport(JNode node) { } private boolean matchForReport(JNode node, boolean nested) { - var result = matchCurrent(node); + Reference error = new Reference<>(); + var result = matchCurrent(node, error); if(result == TypeError) return failWith(new JsonSchemaException( - new ErrorDetail(TypeError.getCode(nested), DataTypeMismatch), + new ErrorDetail(TypeError.getCode(nested), + formatMessage(DataTypeMismatch, error.getValue())), ExpectedHelper.asDataTypeMismatch(this), ActualHelper.asDataTypeMismatch(node))); if(result == AliasError) return failWith(new DefinitionNotFoundException( @@ -106,6 +94,10 @@ private boolean matchForReport(JNode node, boolean nested) { return true; } + private static String formatMessage(String main, String optional) { + return isEmpty(optional) ? main : concat(main, " (", uncapitalize(optional), ")"); + } + public boolean isApplicable(JNode node) { return !nested || node instanceof JComposite; } @@ -129,13 +121,13 @@ public String toString(boolean baseForm) { @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected JsonType jsonType; - protected JAlias alias; - protected boolean nested; + private JsonType jsonType; + private Boolean nested; + private JAlias alias; @Override public JDataType build() { - return new JDataType(this).initialize(); + return build(new JDataType(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JDefinition.java b/src/main/java/com/relogiclabs/json/schema/types/JDefinition.java index 3bc5ef6..c548093 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JDefinition.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JDefinition.java @@ -5,40 +5,38 @@ import lombok.Setter; import lombok.experimental.Accessors; +import static com.relogiclabs.json.schema.internal.util.CollectionHelper.asList; import static com.relogiclabs.json.schema.internal.util.StringHelper.concat; import static java.util.Objects.requireNonNull; @Getter @EqualsAndHashCode -public class JDefinition extends JDirective { +public final class JDefinition extends JDirective { public static final String DEFINE_MARKER = "%define"; - public final JAlias alias; - public final JValidator validator; + private final JAlias alias; + private final JValidator validator; private JDefinition(Builder builder) { - super(builder.relations, builder.context); - this.alias = requireNonNull(builder.alias); - this.validator = requireNonNull(builder.validator); - } - - public static Builder builder() { - return new Builder(); + super(builder); + alias = requireNonNull(builder.alias); + validator = requireNonNull(builder.validator); + children = asList(alias, validator); } @Override public String toString() { - return concat(DEFINE_MARKER, " ", alias, " ", validator); + return concat(DEFINE_MARKER, " ", alias, ": ", validator); } @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected JAlias alias; - protected JValidator validator; + private JAlias alias; + private JValidator validator; @Override public JDefinition build() { - return new JDefinition(this).initialize(); + return build(new JDefinition(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JInclude.java b/src/main/java/com/relogiclabs/json/schema/types/JInclude.java index ce3c6af..5e1675a 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JInclude.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JInclude.java @@ -10,32 +10,28 @@ @Getter @EqualsAndHashCode -public class JInclude extends JDirective { +public final class JInclude extends JDirective { public static final String INCLUDE_MARKER = "%include"; private final String className; private JInclude(Builder builder) { - super(builder.relations, builder.context); - this.className = requireNonNull(builder.className); - } - - public static Builder builder() { - return new Builder(); + super(builder); + className = requireNonNull(builder.className); } @Override public String toString() { - return concat(INCLUDE_MARKER, " ", className); + return concat(INCLUDE_MARKER, ": ", className); } @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String className; + private String className; @Override public JInclude build() { - return new JInclude(this).initialize(); + return build(new JInclude(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JObject.java b/src/main/java/com/relogiclabs/json/schema/types/JObject.java index 61bc5eb..67adc44 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JObject.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JObject.java @@ -18,26 +18,23 @@ import static com.relogiclabs.json.schema.internal.message.MessageHelper.UndefinedPropertyFound; import static com.relogiclabs.json.schema.internal.util.MiscellaneousHelper.nonNull; import static com.relogiclabs.json.schema.internal.util.StringHelper.join; -import static com.relogiclabs.json.schema.message.ErrorCode.PROP04; import static com.relogiclabs.json.schema.message.ErrorCode.PROP05; import static com.relogiclabs.json.schema.message.ErrorCode.PROP06; +import static com.relogiclabs.json.schema.message.ErrorCode.PROP07; import static java.util.Objects.requireNonNull; @Getter @EqualsAndHashCode -public class JObject extends JComposite { +public final class JObject extends JComposite { private final IndexMap properties; private final List components; private JObject(Builder builder) { - super(builder.relations, builder.context); - this.properties = requireNonNull(builder.properties); - this.components = builder.properties.values() - .stream().map(JProperty::getValue).toList(); - } - - public static Builder builder() { - return new Builder(); + super(builder); + properties = requireNonNull(builder.properties); + components = builder.properties.values().stream() + .map(JProperty::getValue).toList(); + children = properties.values(); } @Override @@ -45,11 +42,6 @@ public JsonType getType() { return JsonType.OBJECT; } - @Override - public Collection getChildren() { - return properties.values(); - } - @Override public boolean match(JNode node) { var other = castType(node, JObject.class); @@ -66,18 +58,17 @@ public boolean match(JNode node) { } if(!((JValidator) thisProp.getValue()).getOptional()) return failWith(new JsonSchemaException( - new ErrorDetail(PROP04, PropertyNotFound), + new ErrorDetail(PROP05, PropertyNotFound), ExpectedHelper.asPropertyNotFound(thisProp), ActualHelper.asPropertyNotFound(node, thisProp))); } - if(unresolved.size() > 0 && !getRuntime().getIgnoreUndefinedProperties()) { - for(String key : unresolved) { - var property = other.properties.get(key); - result &= failWith(new JsonSchemaException( - new ErrorDetail(PROP05, UndefinedPropertyFound), - ExpectedHelper.asUndefinedProperty(this, property), - ActualHelper.asUndefinedProperty(property))); - } + if(unresolved.isEmpty() || getRuntime().getIgnoreUndefinedProperties()) return result; + for(String key : unresolved) { + var property = other.properties.get(key); + result &= failWith(new JsonSchemaException( + new ErrorDetail(PROP06, UndefinedPropertyFound), + ExpectedHelper.asUndefinedProperty(this, property), + ActualHelper.asUndefinedProperty(property))); } return result; } @@ -92,7 +83,7 @@ private JProperty getOtherProp(JObject other, int index) { if(otherProp == null) existing = other.properties.get(thisProp.getKey()); if(otherProp == null && existing != null) failWith(new JsonSchemaException( - new ErrorDetail(PROP06, PropertyOrderMismatch), + new ErrorDetail(PROP07, PropertyOrderMismatch), ExpectedHelper.asPropertyOrderMismatch(thisProp), ActualHelper.asPropertyOrderMismatch(nonNull(atProp, other)))); } else otherProp = other.properties.get(thisProp.getKey()); @@ -119,18 +110,16 @@ public Collection components() { } public static class Builder extends JNode.Builder { - protected IndexMap properties; + private IndexMap properties; public Builder properties(List properties) { - var indexMap = new IndexHashMap<>(properties); - indexMap.makeReadOnly(); - this.properties = indexMap; + this.properties = new IndexHashMap<>(properties).asUnmodifiable(); return this; } @Override public JObject build() { - return new JObject(this).initialize(); + return build(new JObject(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JPrimitive.java b/src/main/java/com/relogiclabs/json/schema/types/JPrimitive.java index 00880b5..63513a3 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JPrimitive.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JPrimitive.java @@ -1,21 +1,26 @@ package com.relogiclabs.json.schema.types; -import com.relogiclabs.json.schema.tree.Context; - -import java.util.Map; +import lombok.Setter; +import lombok.experimental.Accessors; public abstract class JPrimitive extends JLeaf implements JsonTypable { - protected JPrimitive(Map relations, Context context) { - super(relations, context); + protected JPrimitive(JNode.Builder builder) { + super(builder); } @Override public JsonType getType() { - return JsonType.ANY; + return JsonType.PRIMITIVE; } @Override public JNode getNode() { return this; } -} + + @Setter + @Accessors(fluent = true) + public abstract static class Builder extends JNode.Builder> { + protected T value; + } +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JTitle.java b/src/main/java/com/relogiclabs/json/schema/types/JTitle.java index 22edcbc..16669da 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JTitle.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JTitle.java @@ -10,32 +10,28 @@ @Getter @EqualsAndHashCode -public class JTitle extends JDirective { +public final class JTitle extends JDirective { public static final String TITLE_MARKER = "%title"; private final String title; private JTitle(Builder builder) { - super(builder.relations, builder.context); - this.title = requireNonNull(builder.title); - } - - public static Builder builder() { - return new Builder(); + super(builder); + title = requireNonNull(builder.title); } @Override public String toString() { - return concat(TITLE_MARKER, " ", title); + return concat(TITLE_MARKER, ": ", title); } @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String title; + private String title; @Override public JTitle build() { - return new JTitle(this).initialize(); + return build(new JTitle(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JVersion.java b/src/main/java/com/relogiclabs/json/schema/types/JVersion.java index c6f3ffe..553904e 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JVersion.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JVersion.java @@ -7,32 +7,28 @@ @Getter @EqualsAndHashCode -public class JVersion extends JDirective { +public final class JVersion extends JDirective { public static final String VERSION_MARKER = "%version"; private final String version; private JVersion(Builder builder) { - super(builder.relations, builder.context); - this.version = builder.version; - } - - public static Builder builder() { - return new Builder(); + super(builder); + version = builder.version; } @Override public String toString() { - return VERSION_MARKER + " " + version; + return VERSION_MARKER + ": " + version; } @Setter @Accessors(fluent = true) public static class Builder extends JNode.Builder { - protected String version; + private String version; @Override public JVersion build() { - return new JVersion(this).initialize(); + return build(new JVersion(this)); } } } \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JsonTypable.java b/src/main/java/com/relogiclabs/json/schema/types/JsonTypable.java index 7cdd0ab..3302d2a 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JsonTypable.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JsonTypable.java @@ -1,6 +1,8 @@ package com.relogiclabs.json.schema.types; public interface JsonTypable { - JsonType getType(); + default JsonType getType() { + return JsonType.ANY; + } JNode getNode(); -} +} \ No newline at end of file diff --git a/src/main/java/com/relogiclabs/json/schema/types/JsonType.java b/src/main/java/com/relogiclabs/json/schema/types/JsonType.java index 0843861..47ac2eb 100644 --- a/src/main/java/com/relogiclabs/json/schema/types/JsonType.java +++ b/src/main/java/com/relogiclabs/json/schema/types/JsonType.java @@ -2,6 +2,7 @@ import com.relogiclabs.json.schema.exception.InvalidDataTypeException; import com.relogiclabs.json.schema.internal.time.DateTimeValidator; +import com.relogiclabs.json.schema.internal.util.Reference; import com.relogiclabs.json.schema.message.MessageFormatter; import com.relogiclabs.json.schema.tree.Location; import lombok.AllArgsConstructor; @@ -27,6 +28,8 @@ public enum JsonType { NUMBER("#number", JNumber.class), DATE("#date", JString.class), TIME("#time", JString.class), + PRIMITIVE("#primitive", JPrimitive.class), + COMPOSITE("#composite", JComposite.class), ANY("#any", JsonTypable.class); private static final DateTimeValidator ISO_8601_DATE @@ -34,41 +37,42 @@ public enum JsonType { private static final DateTimeValidator ISO_8601_TIME = new DateTimeValidator(DateTimeValidator.ISO_8601_TIME); - private static final Map typeMap; + private static final Map stringTypeMap; + private static final Map, JsonType> classTypeMap; private final String name; private final Class type; static { - typeMap = new HashMap<>(); - for(JsonType t : JsonType.values()) - typeMap.put(t.name, t); + stringTypeMap = new HashMap<>(); + classTypeMap = new HashMap<>(); + for(JsonType t : JsonType.values()) { + stringTypeMap.put(t.name, t); + classTypeMap.putIfAbsent(t.type, t); + } } public static JsonType from(TerminalNode node) { return from(node.getText(), Location.from(node.getSymbol())); } + public static JsonType from(Class type) { + return classTypeMap.get(type); + } + public static JsonType from(String name, Location location) { - var result = typeMap.get(name); + var result = stringTypeMap.get(name); if(result == null) throw new InvalidDataTypeException( MessageFormatter.formatForSchema(DTYP01, "Invalid data type " + name, location)); return result; } - public static JsonType from(Class type) { - for(var t : values()) { - if(t.getType().isAssignableFrom(type)) return t; - } - return null; - } - - public boolean match(JNode node) { + public boolean match(JNode node, Reference error) { if(!type.isInstance(node)) return false; - if(this == DATE) return ISO_8601_DATE.IsValidDate(((JString) node).getValue()); - if(this == TIME) return ISO_8601_TIME.IsValidTime(((JString) node).getValue()); + if(this == DATE) return ISO_8601_DATE.IsValidDate(((JString) node).getValue(), error); + if(this == TIME) return ISO_8601_TIME.IsValidTime(((JString) node).getValue(), error); return true; } From d6d007923ad6ebdd5b15c2cd783a086652c325b0 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Fri, 3 Nov 2023 22:57:04 +0600 Subject: [PATCH 3/4] Add and update test cases --- .../json/schema/negative/DataTypeTests.java | 6 +++- .../json/schema/negative/DateTimeTests.java | 28 +++++++++++++++++-- .../json/schema/negative/FunctionTests.java | 7 +++-- .../json/schema/negative/ObjectTests.java | 3 +- .../json/schema/negative/PragmaTests.java | 6 ++-- .../json/schema/positive/DateTimeTests.java | 8 +++--- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/relogiclabs/json/schema/negative/DataTypeTests.java b/src/test/java/com/relogiclabs/json/schema/negative/DataTypeTests.java index ab2eef0..361aae5 100644 --- a/src/test/java/com/relogiclabs/json/schema/negative/DataTypeTests.java +++ b/src/test/java/com/relogiclabs/json/schema/negative/DataTypeTests.java @@ -6,7 +6,11 @@ import com.relogiclabs.json.schema.exception.JsonSchemaException; import org.junit.jupiter.api.Test; -import static com.relogiclabs.json.schema.message.ErrorCode.*; +import static com.relogiclabs.json.schema.message.ErrorCode.DEFI03; +import static com.relogiclabs.json.schema.message.ErrorCode.DEFI04; +import static com.relogiclabs.json.schema.message.ErrorCode.DTYP03; +import static com.relogiclabs.json.schema.message.ErrorCode.DTYP04; +import static com.relogiclabs.json.schema.message.ErrorCode.DTYP06; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/src/test/java/com/relogiclabs/json/schema/negative/DateTimeTests.java b/src/test/java/com/relogiclabs/json/schema/negative/DateTimeTests.java index 287ae9b..baf746e 100644 --- a/src/test/java/com/relogiclabs/json/schema/negative/DateTimeTests.java +++ b/src/test/java/com/relogiclabs/json/schema/negative/DateTimeTests.java @@ -42,7 +42,19 @@ public class DateTimeTests { @Test public void When_JsonNotDate_ExceptionThrown() { var schema = "#date"; - var json = "\"This is not a valid date\""; + var json = "\"This is not a date\""; + + JsonSchema.isValid(schema, json); + var exception = assertThrows(JsonSchemaException.class, + () -> JsonAssert.isValid(schema, json)); + assertEquals(DTYP04, exception.getCode()); + exception.printStackTrace(); + } + + @Test + public void When_JsonNotValidDate_ExceptionThrown() { + var schema = "#date"; + var json = "\"1939-02-29\""; JsonSchema.isValid(schema, json); var exception = assertThrows(JsonSchemaException.class, @@ -54,7 +66,19 @@ public void When_JsonNotDate_ExceptionThrown() { @Test public void When_JsonNotTime_ExceptionThrown() { var schema = "#time"; - var json = "\"This is not a valid time\""; + var json = "\"This is not a time\""; + + JsonSchema.isValid(schema, json); + var exception = assertThrows(JsonSchemaException.class, + () -> JsonAssert.isValid(schema, json)); + assertEquals(DTYP04, exception.getCode()); + exception.printStackTrace(); + } + + @Test + public void When_JsonNotValidTime_ExceptionThrown() { + var schema = "#time"; + var json = "\"1939-09-02T2:12:12.000Z\""; JsonSchema.isValid(schema, json); var exception = assertThrows(JsonSchemaException.class, diff --git a/src/test/java/com/relogiclabs/json/schema/negative/FunctionTests.java b/src/test/java/com/relogiclabs/json/schema/negative/FunctionTests.java index 46082e6..a4cc05c 100644 --- a/src/test/java/com/relogiclabs/json/schema/negative/FunctionTests.java +++ b/src/test/java/com/relogiclabs/json/schema/negative/FunctionTests.java @@ -1,12 +1,13 @@ package com.relogiclabs.json.schema.negative; import com.relogiclabs.json.schema.JsonAssert; +import com.relogiclabs.json.schema.JsonSchema; import com.relogiclabs.json.schema.exception.ClassInstantiationException; import com.relogiclabs.json.schema.exception.DuplicateIncludeException; -import com.relogiclabs.json.schema.exception.FunctionMismatchException; import com.relogiclabs.json.schema.exception.FunctionNotFoundException; import com.relogiclabs.json.schema.exception.InvalidFunctionException; import com.relogiclabs.json.schema.exception.InvalidIncludeException; +import com.relogiclabs.json.schema.exception.JsonSchemaException; import com.relogiclabs.json.schema.exception.NotFoundClassException; import org.junit.jupiter.api.Test; @@ -34,8 +35,8 @@ public void When_FunctionAppliedOnWrongType_ExceptionThrown() { "test" """; - //JsonSchema.IsValid(schema, json); - var exception = assertThrows(FunctionMismatchException.class, + JsonSchema.isValid(schema, json); + var exception = assertThrows(JsonSchemaException.class, () -> JsonAssert.isValid(schema, json)); assertEquals(FUNC03, exception.getCode()); exception.printStackTrace(); diff --git a/src/test/java/com/relogiclabs/json/schema/negative/ObjectTests.java b/src/test/java/com/relogiclabs/json/schema/negative/ObjectTests.java index e368be6..934b0de 100644 --- a/src/test/java/com/relogiclabs/json/schema/negative/ObjectTests.java +++ b/src/test/java/com/relogiclabs/json/schema/negative/ObjectTests.java @@ -16,6 +16,7 @@ import static com.relogiclabs.json.schema.message.ErrorCode.OLEN04; import static com.relogiclabs.json.schema.message.ErrorCode.OLEN05; import static com.relogiclabs.json.schema.message.ErrorCode.PROP03; +import static com.relogiclabs.json.schema.message.ErrorCode.PROP04; import static com.relogiclabs.json.schema.message.ErrorCode.VALU01; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -264,7 +265,7 @@ public void When_DuplicateSchemaPropertyInObject_ExceptionThrown() { //JsonSchema.IsValid(schema, json); var exception = assertThrows(DuplicatePropertyKeyException.class, () -> JsonAssert.isValid(schema, json)); - assertEquals(PROP03, exception.getCode()); + assertEquals(PROP04, exception.getCode()); exception.printStackTrace(); } diff --git a/src/test/java/com/relogiclabs/json/schema/negative/PragmaTests.java b/src/test/java/com/relogiclabs/json/schema/negative/PragmaTests.java index 9368026..5596b32 100644 --- a/src/test/java/com/relogiclabs/json/schema/negative/PragmaTests.java +++ b/src/test/java/com/relogiclabs/json/schema/negative/PragmaTests.java @@ -13,8 +13,8 @@ import static com.relogiclabs.json.schema.message.ErrorCode.PRAG01; import static com.relogiclabs.json.schema.message.ErrorCode.PRAG02; import static com.relogiclabs.json.schema.message.ErrorCode.PRAG03; -import static com.relogiclabs.json.schema.message.ErrorCode.PROP05; import static com.relogiclabs.json.schema.message.ErrorCode.PROP06; +import static com.relogiclabs.json.schema.message.ErrorCode.PROP07; import static com.relogiclabs.json.schema.message.ErrorCode.SPRS01; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -40,7 +40,7 @@ public void When_UndefinedPropertyOfObject_ExceptionThrown() { JsonSchema.isValid(schema, json); var exception = assertThrows(JsonSchemaException.class, () -> JsonAssert.isValid(schema, json)); - assertEquals(PROP05, exception.getCode()); + assertEquals(PROP06, exception.getCode()); exception.printStackTrace(); } @@ -139,7 +139,7 @@ public void When_IgnorePropertyOrderOfObject_ExceptionThrown() { JsonSchema.isValid(schema, json); var exception = assertThrows(JsonSchemaException.class, () -> JsonAssert.isValid(schema, json)); - assertEquals(PROP06, exception.getCode()); + assertEquals(PROP07, exception.getCode()); exception.printStackTrace(); } diff --git a/src/test/java/com/relogiclabs/json/schema/positive/DateTimeTests.java b/src/test/java/com/relogiclabs/json/schema/positive/DateTimeTests.java index ce48bde..65c3eae 100644 --- a/src/test/java/com/relogiclabs/json/schema/positive/DateTimeTests.java +++ b/src/test/java/com/relogiclabs/json/schema/positive/DateTimeTests.java @@ -52,9 +52,9 @@ public void When_DataTypeTimeInObject_ValidTrue() { var json = """ { - "key1": "1950-12-31T11:40:10.000+06:30", - "key2": "0001-01-01T00:00:00.000+00:00", - "key3": "1600-02-29T23:59:59.999Z" + "key1": "1950-12-31T11:40:10.333+06:30", + "key2": "0001-01-01T00:00:00.0+00:00", + "key3": "1600-02-29T23:59:59.99999Z" } """; JsonAssert.isValid(schema, json); @@ -81,7 +81,7 @@ public void When_DataTypeTimeInArray_ValidTrue() { """; var json = """ - ["0001-01-01T00:00:00.000Z", "9999-12-31T23:59:59.999+12:59"] + ["0001-01-01T00:00:00.0Z", "9999-12-31T23:59:59.999999+12:59"] """; JsonAssert.isValid(schema, json); } From bf3206192768d073d7cbf3139a3eef90832f9900 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Fri, 3 Nov 2023 23:10:02 +0600 Subject: [PATCH 4/4] Update project documentations --- README.md | 6 +- doc/content/articles/datetime.md | 79 +++---- doc/content/articles/quickstart.md | 42 ++-- doc/content/articles/sourcebuild.md | 42 ++-- doc/layouts/partials/head.html | 2 + doc/layouts/partials/header.html | 10 +- doc/layouts/partials/sidebar.html | 1 + doc/public/api/allclasses-index.html | 182 ++++++++-------- doc/public/api/allpackages-index.html | 6 +- .../relogiclabs/json/schema/JsonAssert.html | 6 +- .../relogiclabs/json/schema/JsonSchema.html | 6 +- .../json/schema/class-use/JsonAssert.html | 6 +- .../json/schema/class-use/JsonSchema.html | 6 +- .../json/schema/collection/IndexHashMap.html | 58 ++--- .../json/schema/collection/IndexMap.html | 36 ++-- .../json/schema/collection/Keyable.html | 6 +- .../collection/class-use/IndexHashMap.html | 33 ++- .../schema/collection/class-use/IndexMap.html | 17 +- .../schema/collection/class-use/Keyable.html | 10 +- .../schema/collection/package-summary.html | 6 +- .../json/schema/collection/package-tree.html | 6 +- .../json/schema/collection/package-use.html | 12 +- .../ClassInstantiationException.html | 6 +- .../schema/exception/CommonException.html | 8 +- .../exception/DateTimeLexerException.html | 6 +- .../DefinitionNotFoundException.html | 6 +- .../DuplicateDefinitionException.html | 6 +- .../exception/DuplicateIncludeException.html | 6 +- .../exception/DuplicatePragmaException.html | 6 +- .../DuplicatePropertyKeyException.html | 6 +- .../exception/FunctionMismatchException.html | 158 -------------- .../exception/FunctionNotFoundException.html | 6 +- .../exception/InvalidDataTypeException.html | 6 +- .../exception/InvalidDateTimeException.html | 6 +- .../exception/InvalidFunctionException.html | 6 +- .../exception/InvalidIncludeException.html | 6 +- .../InvalidPragmaValueException.html | 6 +- .../schema/exception/JsonLexerException.html | 6 +- .../schema/exception/JsonParserException.html | 6 +- .../schema/exception/JsonSchemaException.html | 6 +- .../exception/NotFoundClassException.html | 6 +- .../exception/PragmaNotFoundException.html | 6 +- .../exception/SchemaLexerException.html | 6 +- .../exception/SchemaParserException.html | 6 +- .../exception/TargetInvocationException.html | 6 +- .../ClassInstantiationException.html | 6 +- .../exception/class-use/CommonException.html | 37 ++-- .../class-use/DateTimeLexerException.html | 6 +- .../DefinitionNotFoundException.html | 6 +- .../DuplicateDefinitionException.html | 6 +- .../class-use/DuplicateIncludeException.html | 6 +- .../class-use/DuplicatePragmaException.html | 6 +- .../DuplicatePropertyKeyException.html | 6 +- .../class-use/FunctionMismatchException.html | 62 ------ .../class-use/FunctionNotFoundException.html | 6 +- .../class-use/InvalidDataTypeException.html | 6 +- .../class-use/InvalidDateTimeException.html | 6 +- .../class-use/InvalidFunctionException.html | 6 +- .../class-use/InvalidIncludeException.html | 6 +- .../InvalidPragmaValueException.html | 6 +- .../class-use/JsonLexerException.html | 6 +- .../class-use/JsonParserException.html | 6 +- .../class-use/JsonSchemaException.html | 6 +- .../class-use/NotFoundClassException.html | 6 +- .../class-use/PragmaNotFoundException.html | 6 +- .../class-use/SchemaLexerException.html | 6 +- .../class-use/SchemaParserException.html | 6 +- .../class-use/TargetInvocationException.html | 6 +- .../schema/exception/package-summary.html | 36 ++-- .../json/schema/exception/package-tree.html | 7 +- .../json/schema/exception/package-use.html | 6 +- .../json/schema/function/CoreFunctions1.html | 6 +- .../json/schema/function/CoreFunctions2.html | 6 +- .../json/schema/function/CoreFunctions3.html | 6 +- .../json/schema/function/FunctionBase.html | 6 +- .../function/class-use/CoreFunctions1.html | 6 +- .../function/class-use/CoreFunctions2.html | 6 +- .../function/class-use/CoreFunctions3.html | 6 +- .../function/class-use/FunctionBase.html | 6 +- .../json/schema/function/package-summary.html | 6 +- .../json/schema/function/package-tree.html | 6 +- .../json/schema/function/package-use.html | 6 +- .../json/schema/message/ActualDetail.html | 8 +- .../json/schema/message/ContextDetail.html | 8 +- .../json/schema/message/ErrorCode.html | 61 ++++-- .../json/schema/message/ErrorDetail.html | 8 +- .../json/schema/message/ExpectedDetail.html | 8 +- .../json/schema/message/MessageFormatter.html | 6 +- .../message/class-use/ActualDetail.html | 6 +- .../message/class-use/ContextDetail.html | 10 +- .../schema/message/class-use/ErrorCode.html | 6 +- .../schema/message/class-use/ErrorDetail.html | 35 ++- .../message/class-use/ExpectedDetail.html | 6 +- .../message/class-use/MessageFormatter.html | 6 +- .../json/schema/message/package-summary.html | 6 +- .../json/schema/message/package-tree.html | 6 +- .../json/schema/message/package-use.html | 6 +- .../json/schema/package-summary.html | 6 +- .../relogiclabs/json/schema/package-tree.html | 6 +- .../relogiclabs/json/schema/package-use.html | 6 +- .../relogiclabs/json/schema/tree/Context.html | 8 +- .../json/schema/tree/JsonTree.html | 8 +- .../json/schema/tree/Location.html | 6 +- .../json/schema/tree/RuntimeContext.html | 8 +- .../json/schema/tree/SchemaTree.html | 8 +- .../json/schema/tree/class-use/Context.html | 6 +- .../json/schema/tree/class-use/JsonTree.html | 6 +- .../json/schema/tree/class-use/Location.html | 6 +- .../schema/tree/class-use/RuntimeContext.html | 6 +- .../schema/tree/class-use/SchemaTree.html | 6 +- .../json/schema/tree/package-summary.html | 6 +- .../json/schema/tree/package-tree.html | 6 +- .../json/schema/tree/package-use.html | 6 +- .../json/schema/types/JAlias.Builder.html | 6 +- .../relogiclabs/json/schema/types/JAlias.html | 46 ++-- .../json/schema/types/JArray.Builder.html | 6 +- .../relogiclabs/json/schema/types/JArray.html | 42 +--- .../json/schema/types/JBoolean.Builder.html | 26 +-- .../json/schema/types/JBoolean.html | 54 ++--- .../json/schema/types/JBranch.html | 6 +- .../json/schema/types/JComposite.html | 6 +- .../json/schema/types/JDataType.Builder.html | 20 +- .../json/schema/types/JDataType.html | 42 +--- .../schema/types/JDefinition.Builder.html | 6 +- .../json/schema/types/JDefinition.html | 67 ++---- .../json/schema/types/JDirective.html | 25 +-- .../json/schema/types/JDouble.Builder.html | 14 +- .../json/schema/types/JDouble.html | 58 ++--- .../json/schema/types/JFloat.Builder.html | 14 +- .../relogiclabs/json/schema/types/JFloat.html | 58 ++--- .../json/schema/types/JFunction.Builder.html | 20 +- .../json/schema/types/JFunction.html | 42 +--- .../json/schema/types/JInclude.Builder.html | 6 +- .../json/schema/types/JInclude.html | 41 ++-- .../json/schema/types/JInteger.Builder.html | 14 +- .../json/schema/types/JInteger.html | 58 ++--- .../relogiclabs/json/schema/types/JLeaf.html | 51 +---- .../relogiclabs/json/schema/types/JNode.html | 24 +-- .../json/schema/types/JNull.Builder.html | 6 +- .../relogiclabs/json/schema/types/JNull.html | 46 ++-- .../json/schema/types/JNumber.html | 23 +- .../json/schema/types/JObject.Builder.html | 6 +- .../json/schema/types/JObject.html | 42 +--- .../json/schema/types/JPragma.Builder.html | 6 +- .../json/schema/types/JPragma.html | 45 ++-- ...r.Builder.html => JPrimitive.Builder.html} | 28 +-- .../json/schema/types/JPrimitive.html | 28 ++- .../json/schema/types/JProperty.Builder.html | 6 +- .../json/schema/types/JProperty.html | 38 +--- .../json/schema/types/JRoot.Builder.html | 6 +- .../relogiclabs/json/schema/types/JRoot.html | 38 +--- .../json/schema/types/JString.Builder.html | 26 +-- .../json/schema/types/JString.html | 50 ++--- .../json/schema/types/JTitle.Builder.html | 6 +- .../relogiclabs/json/schema/types/JTitle.html | 41 ++-- .../json/schema/types/JUndefined.Builder.html | 6 +- .../json/schema/types/JUndefined.html | 42 ++-- .../json/schema/types/JValidator.Builder.html | 6 +- .../json/schema/types/JValidator.html | 38 +--- .../json/schema/types/JVersion.Builder.html | 6 +- .../json/schema/types/JVersion.html | 41 ++-- .../json/schema/types/JsonTypable.html | 16 +- .../json/schema/types/JsonType.html | 54 +++-- .../json/schema/types/NestedMode.html | 6 +- .../json/schema/types/PragmaValue.html | 6 +- .../types/class-use/JAlias.Builder.html | 13 +- .../json/schema/types/class-use/JAlias.html | 15 +- .../types/class-use/JArray.Builder.html | 13 +- .../json/schema/types/class-use/JArray.html | 6 +- .../types/class-use/JBoolean.Builder.html | 36 +--- .../json/schema/types/class-use/JBoolean.html | 6 +- .../json/schema/types/class-use/JBranch.html | 18 +- .../schema/types/class-use/JComposite.html | 10 +- .../types/class-use/JDataType.Builder.html | 15 +- .../schema/types/class-use/JDataType.html | 6 +- .../types/class-use/JDefinition.Builder.html | 13 +- .../schema/types/class-use/JDefinition.html | 6 +- .../schema/types/class-use/JDirective.html | 16 +- .../types/class-use/JDouble.Builder.html | 33 +-- .../json/schema/types/class-use/JDouble.html | 6 +- .../types/class-use/JFloat.Builder.html | 33 +-- .../json/schema/types/class-use/JFloat.html | 6 +- .../types/class-use/JFunction.Builder.html | 15 +- .../schema/types/class-use/JFunction.html | 6 +- .../types/class-use/JInclude.Builder.html | 13 +- .../json/schema/types/class-use/JInclude.html | 6 +- .../types/class-use/JInteger.Builder.html | 33 +-- .../json/schema/types/class-use/JInteger.html | 6 +- .../json/schema/types/class-use/JLeaf.html | 22 +- .../json/schema/types/class-use/JNode.html | 84 +++----- .../schema/types/class-use/JNull.Builder.html | 33 +-- .../json/schema/types/class-use/JNull.html | 6 +- .../json/schema/types/class-use/JNumber.html | 12 +- .../types/class-use/JObject.Builder.html | 13 +- .../json/schema/types/class-use/JObject.html | 6 +- .../types/class-use/JPragma.Builder.html | 15 +- .../json/schema/types/class-use/JPragma.html | 6 +- ...r.Builder.html => JPrimitive.Builder.html} | 36 ++-- .../schema/types/class-use/JPrimitive.html | 18 +- .../types/class-use/JProperty.Builder.html | 15 +- .../schema/types/class-use/JProperty.html | 6 +- .../schema/types/class-use/JRoot.Builder.html | 23 +- .../json/schema/types/class-use/JRoot.html | 6 +- .../types/class-use/JString.Builder.html | 36 +--- .../json/schema/types/class-use/JString.html | 6 +- .../types/class-use/JTitle.Builder.html | 13 +- .../json/schema/types/class-use/JTitle.html | 6 +- .../types/class-use/JUndefined.Builder.html | 33 +-- .../schema/types/class-use/JUndefined.html | 6 +- .../types/class-use/JValidator.Builder.html | 19 +- .../schema/types/class-use/JValidator.html | 15 +- .../types/class-use/JVersion.Builder.html | 13 +- .../json/schema/types/class-use/JVersion.html | 6 +- .../schema/types/class-use/JsonTypable.html | 22 +- .../json/schema/types/class-use/JsonType.html | 8 +- .../schema/types/class-use/NestedMode.html | 10 +- .../schema/types/class-use/PragmaValue.html | 14 +- .../json/schema/types/package-summary.html | 18 +- .../json/schema/types/package-tree.html | 16 +- .../json/schema/types/package-use.html | 76 +++---- doc/public/api/constant-values.html | 123 +++++------ doc/public/api/help-doc.html | 6 +- doc/public/api/index-all.html | 112 +++------- doc/public/api/index.html | 8 +- doc/public/api/member-search-index.js | 2 +- doc/public/api/overview-summary.html | 6 +- doc/public/api/overview-tree.html | 17 +- doc/public/api/serialized-form.html | 12 +- doc/public/api/type-search-index.js | 2 +- doc/public/articles/datatypes/index.html | 14 +- doc/public/articles/datetime/index.html | 204 ++++++++++++------ doc/public/articles/directives/index.html | 14 +- doc/public/articles/functions/index.html | 14 +- doc/public/articles/index.html | 18 +- doc/public/articles/index.xml | 8 +- doc/public/articles/intro/index.html | 14 +- doc/public/articles/quickstart/index.html | 50 +++-- doc/public/articles/sourcebuild/index.html | 52 +++-- doc/public/articles/specification/index.html | 14 +- doc/public/articles/validation/index.html | 14 +- doc/public/categories/index.html | 14 +- doc/public/css/style.css | 69 +++++- doc/public/index.html | 14 +- doc/public/index.xml | 8 +- doc/public/js/script.js | 15 ++ doc/public/sitemap.xml | 4 +- doc/public/tags/index.html | 14 +- doc/static/css/style.css | 69 +++++- doc/static/js/script.js | 15 ++ pom.xml | 2 +- 250 files changed, 2145 insertions(+), 2645 deletions(-) delete mode 100644 doc/public/api/com/relogiclabs/json/schema/exception/FunctionMismatchException.html delete mode 100644 doc/public/api/com/relogiclabs/json/schema/exception/class-use/FunctionMismatchException.html rename doc/public/api/com/relogiclabs/json/schema/types/{JNumber.Builder.html => JPrimitive.Builder.html} (80%) rename doc/public/api/com/relogiclabs/json/schema/types/class-use/{JNumber.Builder.html => JPrimitive.Builder.html} (59%) create mode 100644 doc/public/js/script.js create mode 100644 doc/static/js/script.js diff --git a/README.md b/README.md index ae47b38..449f38e 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Let's explore an example of our schema for a typical JSON API response containin } } ``` -In the above example, two types of constraint or rule descriptors are used: constraint functions (also known as validation functions, such as `@range(1, 10000)`) and constraint data types (also known as validation data types, such as `#integer`). All constraint functions begin with the `@` symbol, while all constraint data types start with `#`. C-style comments are also permitted in the schema. Please note that `address` can be `null` (eg. an optional input for users) and if it is `null` then no constraints of `address` are applicable. The following JSON is one of the examples which can successfully validate against the above schema. To start your journey with the JSON validation library, please consult the documentation available [here](https://relogiclabs.github.io/JsonSchema-Java/articles/intro). +In the above example, two types of constraints are used: constraint functions (also referred to as validation functions, such as `@range(1, 10000)`) and constraint data types (also referred to as validation data types, such as `#integer`). All constraint functions begin with the `@` symbol, while all constraint data types start with `#`. C-style comments are also supported within the schema. In this example, `address` can be `null` (like an optional input for users) and if it is `null` then no constraints of `address` are applicable. The following JSON is one of the examples that will be successfully validated against the above schema. To start your journey with the JSON validation library, please consult the documentation available [here](https://relogiclabs.github.io/JsonSchema-Java/articles/intro). ```json { "user": { @@ -130,7 +130,7 @@ The next example represents an expanded version of the previous one, which bring } } ``` -The subsequent JSON sample is an illustrative example that successfully validates against the expanded schema mentioned earlier. Within this example, recurring JSON structure appear that can be validated through defining components. By reusing defined components, you can achieve a clear and concise schema when validating large JSON with repetitive structures instead of duplicating large and complex validation constraints across the schema. This improves the overall readability and maintainability of the schema. +The subsequent JSON sample is an illustrative example that successfully validates against the expanded schema mentioned earlier. Within this example, recurring JSON structures appear that can be validated by defining components or nested functions and data types. Besides, reusing simple component definitions, you can achieve a clear and concise schema when validating large JSON with repetitive structures instead of duplicating or referring to various structures across the schema. This improves the overall readability and maintainability of the schema. ```json { "user": { @@ -219,4 +219,4 @@ The subsequent JSON sample is an illustrative example that successfully validate } } ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](https://relogiclabs.github.io/JsonSchema-Java/api/index.html). \ No newline at end of file +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](https://relogiclabs.github.io/JsonSchema-Java/api/index.html). diff --git a/doc/content/articles/datetime.md b/doc/content/articles/datetime.md index 0f7dd02..5ab455e 100644 --- a/doc/content/articles/datetime.md +++ b/doc/content/articles/datetime.md @@ -11,46 +11,49 @@ Date and time formats are defined using date and time pattern strings. Within th Below, you will find a list of pattern letters and strings that are defined for date and time patterns. Please note that any characters within the 'A' to 'Z' and 'a' to 'z' range are reserved and should not be directly included in the pattern string. -| Pattern | Description | Example | -|---------|---------------------------------------|---------| -| G | Era period designator | AD | -| YYYY | Four digit year number | 1970 | -| YY | Two digit year number | 70 | -| MM | Month number in year (2 digit form) | 01 | -| MMMM | Full name of month | January | -| MMM | Short name of month | Jan | -| M | Month number in year (1-2 digit form) | 1, 01 | -| DDDD | Full name of day in week | Monday | -| DDD | Short name of day in week | Mon | -| DD | Day in month (2 digit form) | 01 | -| D | Day in month (1-2 digit form) | 1, 01 | -| t | AM/PM designator | AM, PM | -| hh | Hour in day (2 digit form) | 01, 12 | -| h | Hour in day (1-2 digit form) | 1, 01 | -| mm | Minute in hour (2 digit form) | 01, 20 | -| m | Minute in hour (1-2 digit form) | 1, 01 | -| ss | Second in minute (2 digit form) | 1, 01 | -| s | Second in minute (1-2 digit form) | 1, 01 | -| f | Tenths of a second | 1 | -| ff | Hundredths of a second | 11 | -| fff | Milliseconds of a second | 111 | -| ffff | Ten thousandths of a second | 1111 | -| fffff | Hundred thousandths of a second | 11111 | -| ffffff | Millionths of a second | 111111 | -| F | Fraction of a second upto 6 digits | 1, 111 | +| SN | Pattern | Description | Example | +|----|----------|---------------------------------------|-------------------------| +| 1 | `G` | Era period designator | `AD` | +| 2 | `YYYY` | Four digit year number | `1970` | +| 3 | `YY` | Two digit year number | `70` | +| 4 | `MM` | Month number in year (2 digit form) | `01` | +| 5 | `MMMM` | Full name of month | `January` | +| 6 | `MMM` | Short name of month | `Jan` | +| 7 | `M` | Month number in year (1-2 digit form) | `1`; `01` | +| 8 | `DDDD` | Full name of day in week | `Monday` | +| 9 | `DDD` | Short name of day in week | `Mon` | +| 10 | `DD` | Day in month (2 digit form) | `01` | +| 11 | `D` | Day in month (1-2 digit form) | `1`; `01` | +| 12 | `t` | AM/PM designator | `AM`; `PM` | +| 13 | `hh` | Hour in day (2 digit form) | `01`; `12` | +| 14 | `h` | Hour in day (1-2 digit form) | `1`; `01` | +| 15 | `mm` | Minute in hour (2 digit form) | `01`; `20` | +| 16 | `m` | Minute in hour (1-2 digit form) | `1`; `01` | +| 17 | `ss` | Second in minute (2 digit form) | `01`; `30` | +| 18 | `s` | Second in minute (1-2 digit form) | `1`; `01` | +| 19 | `f` | Tenths of a second | `1` | +| 20 | `ff` | Hundredths of a second | `11` | +| 21 | `fff` | Milliseconds of a second | `111` | +| 22 | `ffff` | Ten thousandths of a second | `1111` | +| 23 | `fffff` | Hundred thousandths of a second | `11111` | +| 24 | `ffffff` | Millionths of a second | `111111` | +| 25 | `F` | Fraction of a second upto 6 digits | `1`; `111`; `111111` | +| 26 | `Z` | Time zone hours only offset | `+06`; `-05`; `Z` | +| 27 | `ZZ` | Time zone hours and minutes offset | `+09:30`; `−03:30`; `Z` | +| 28 | `ZZZ` | Time zone hours and minutes offset | `+0930`; `−0330`; `Z` | The pattern components listed above can be combined to create comprehensive and customized date and time patterns to accommodate all system and user requirements. The following table illustrates some examples of how different date-time pattern components can be combined. -| Combined Pattern | Example | -|-----------------------------|-------------------------------| -| YYYY-MM-DD | 2023-09-01 | -| YYYY-MM-DD'T'hh:mm:ss.fffZZ | 2023-09-01T14:35:10.123+06:00 | -| MMMM DD, YYYY G | January 01, 1980 AD | -| DDDD, D MMMM YYYY | Tuesday, 11 July 2023 | -| YYYY.MM.DD hh.mm.ss t | 1980.11.21 10.30.50 pm | -| DDD, D MMM YY hh:mm:ss ZZ | Sun, 4 Jul 99 12:08:56 -06:00 | -| hh:mm:ss t ZZ | 03:11:30 AM +06:00 | +| SN | Usage | Combined Pattern | Example | +|----|---------|-----------------------------|---------------------------------| +| 1 | `#date` | `YYYY-MM-DD` | `2023-09-01` | +| 2 | `#time` | `YYYY-MM-DD'T'hh:mm:ss.FZZ` | `2023-09-01T14:35:10.111+06:00` | +| 3 | `@date` | `MMMM DD, YYYY G` | `January 01, 1980 AD` | +| 4 | `@date` | `DDDD, D MMMM YYYY` | `Tuesday, 11 July 2023` | +| 5 | `@time` | `YYYY.MM.DD hh.mm.ss t` | `1980.11.21 10.30.50 pm` | +| 6 | `@time` | `DDD, D MMM YY hh:mm:ss ZZ` | `Sun, 4 Jul 99 12:08:56 -06:00` | +| 7 | `@time` | `hh:mm:ss t ZZ` | `03:11:30 AM +06:00` | -The first pattern in the table above adheres to the ISO 8601 date format and is used to validate the `#date` data type within the schema. The second pattern in the table follows the ISO 8601 format for date and time, validating the `#time` data type in the schema. Instead of explicitly specifying these patterns in the `@date` or `@time` functions, a more concise approach is to directly utilize the `#date` or `#time` type within the schema. +The first pattern in the table above adheres to the ISO 8601 date format and is used to validate the `#date` data type within the schema. The second pattern in the table follows the ISO 8601 format for date and time, validating the `#time` data type in the schema. Instead of explicitly specifying these patterns in the `@date` or `@time` functions, a more concise approach is to directly utilize the `#date` or `#time` type within the schema. Detailed explanations regarding the date and time format of the ISO 8601 standard are available in this [document](https://www.iso.org/iso-8601-date-and-time-format.html). -When the AM/PM designator is included in the date and time pattern, the presence of any hour format specifier indicates that the time is in the 12-hour clock format. Conversely, when the AM/PM designator is omitted, the presence of any hour format specifier indicates that the time is in the 24-hour clock format. \ No newline at end of file +When the AM/PM designator is included in the date and time pattern, the presence of any hour format specifier indicates that the time is in the 12-hour clock format. Conversely, when the AM/PM designator is omitted, the presence of any hour format specifier indicates that the time is in the 24-hour clock format. diff --git a/doc/content/articles/quickstart.md b/doc/content/articles/quickstart.md index b5e7522..45482f1 100644 --- a/doc/content/articles/quickstart.md +++ b/doc/content/articles/quickstart.md @@ -1,11 +1,11 @@ +++ title = 'Quick Start' -date = 2023-10-08T09:38:53+06:00 +date = 2023-11-03T09:38:53+06:00 weight = 2 +++ # Getting Started -This guide will walk you through the essential steps to quickly get up and running with New JSON Schema library. It is also assumes a modest familiarity with the Java SDK and Java command-line interface including basic familiarity with Maven packages. Additionally, it considers a certain level of knowledge in Java language. +This guide will walk you through the essential steps to quickly get up and running with the new JSON Schema library. It is also assumed a modest familiarity with the Java language, Java SDK, and Java command-line interface, including basic familiarity with Maven packages. ## Maven Library Package To get started, launch your preferred IDE (such as IntelliJ IDEA, NetBeans IDE, Eclipse IDE, or VS Code) and open the Java project where you intend to include this library package. If you are using a build tool like Maven or Gradle, adding the library to your project is straightforward. For example in Maven project, navigate to the Maven `pom.xml` file and locate the section named `` and add the following XML snippet within the section of the file, replacing `1.x.x` with either the latest version or your preferred version: @@ -19,7 +19,7 @@ To get started, launch your preferred IDE (such as IntelliJ IDEA, NetBeans IDE, For additional information regarding this library package, you can visit the Maven repository page of this library [here](https://central.sonatype.com/artifact/com.relogiclabs.json/relogiclabs-json-schema), and files are also available [here](https://repo1.maven.org/maven2/com/relogiclabs/json/relogiclabs-json-schema/). ## Write a Sample to Test -With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a Java class featuring a method designed for validating a sample JSON based on a provided schema. +With all the necessary components in place, you are now ready to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a Java class featuring a method designed for validating a sample JSON based on a provided schema. If you are working with Java 17 or above, you can enhance the code further by utilizing new language features. ```java import com.relogiclabs.json.schema.JsonSchema; @@ -38,9 +38,11 @@ public class SampleSchema { /*currently only one role is allowed by system*/ "role": "user" #string, "isActive": #boolean, //user account current status + "registeredAt": #time, "profile": { "firstName": @regex("[A-Za-z ]{3,50}") #string, "lastName": @regex("[A-Za-z ]{3,50}") #string, + "dateOfBirth": #date, "age": @range(18, 130) #integer, "email": @email #string, "pictureURL": @url #string, @@ -57,13 +59,15 @@ public class SampleSchema { """ { "user": { - "id": 1234, + "id": 1111, "username": "johndoe", "role": "user", "isActive": true, + "registeredAt": "2023-09-06T15:10:30.639Z", "profile": { "firstName": "John", "lastName": "Doe", + "dateOfBirth": "1993-06-17", "age": 30, "email": "john.doe@example.com", "pictureURL": "https://example.com/picture.jpg", @@ -107,7 +111,6 @@ Let's intentionally introduce a few errors by modifying the previous JSON docume } ``` To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the `writeError` method to display the errors if validation fails is as follows: - ```java ... @@ -117,13 +120,12 @@ if(!jsonSchema.isValid(json)) jsonSchema.writeError(); ... ``` Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. - ```json Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by "not number". -Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of "not number" +Schema (Line: 6:14) Json (Line: 3:14) [FUNC03]: Function @range(1, 10000) is incompatible with the target data type. Applying to a supported data type such as #number is expected but applied to an unsupported data type #string of "not number". Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern "[a-z_]{3,30}" is expected but found "john doe" that mismatches with pattern. -Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "profile"...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": "Doe", "a...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. -Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. +Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "register...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "registeredAt": "2023-09-06T15:10:30.639Z", "profile":...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. +Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "registeredAt": "2023-09-06T15:10:30.639Z", "... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. ``` ## Assertion for Validation @@ -145,17 +147,17 @@ com.relogiclabs.json.schema.exception.JsonSchemaException: DTYP04: Data type mis Expected (Schema Line: 6:31): data type #integer Actual (Json Line: 3:14): found #string inferred by "not number" - at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:85) - at com.relogiclabs.json.schema.types.JValidator.lambda$match$0(JValidator.java:82) - at java.base/java.lang.Iterable.forEach(Iterable.java:75) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:82) - at com.relogiclabs.json.schema.types.JObject.match(JObject.java:63) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:76) - at com.relogiclabs.json.schema.types.JObject.match(JObject.java:63) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:76) - at com.relogiclabs.json.schema.types.JRoot.match(JRoot.java:73) + at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:86) + at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:68) + at com.relogiclabs.json.schema.types.JValidator.matchDataType(JValidator.java:67) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:57) + at com.relogiclabs.json.schema.types.JObject.match(JObject.java:55) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:52) + at com.relogiclabs.json.schema.types.JObject.match(JObject.java:55) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:52) + at com.relogiclabs.json.schema.types.JRoot.match(JRoot.java:47) at com.relogiclabs.json.schema.JsonAssert.isValid(JsonAssert.java:54) - at org.example.SampleSchema.checkIsValid(SampleSchema.java:61) + at org.example.SampleSchema.checkIsValid(SampleSchema.java:64) at org.example.Main.main(Main.java:5) ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-Java/api/index.html). \ No newline at end of file +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-Java/api/index.html). diff --git a/doc/content/articles/sourcebuild.md b/doc/content/articles/sourcebuild.md index b2b0749..061a927 100644 --- a/doc/content/articles/sourcebuild.md +++ b/doc/content/articles/sourcebuild.md @@ -1,11 +1,11 @@ +++ title = 'Source Build' -date = 2023-10-10T09:38:53+06:00 +date = 2023-11-03T09:38:53+06:00 weight = 9 +++ # Build from Source Code -This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. It is important to have a foundational understanding of the Java language, as well as a modest level of familiarity with the Java SDK and command-line interface. You should also have a basic knowledge of how to work with Maven packages. +This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. It is important to have a foundational understanding of the Java language, as well as a modest level of familiarity with the Java SDK and command-line interface. You also need a basic knowledge of how to work with Maven packages. ## Build the Library To get started, clone the project from the following URL using your preferred Git client (command line or GUI). You can open a terminal and enter the following Git clone command as shown below: @@ -30,7 +30,7 @@ To integrate the library into your project, open it in your preferred IDE (such ``` ## Write a Sample to Test -With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a Java class featuring a method designed for validating a sample JSON based on a provided schema. +With all the necessary components in place, you are now ready to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a Java class featuring a method designed for validating a sample JSON based on a provided schema. If you are working with Java 17 or above, you can enhance the code further by utilizing new language features. ```java import com.relogiclabs.json.schema.JsonSchema; @@ -49,9 +49,11 @@ public class SampleSchema { /*currently only one role is allowed by system*/ "role": "user" #string, "isActive": #boolean, //user account current status + "registeredAt": #time, "profile": { "firstName": @regex("[A-Za-z ]{3,50}") #string, "lastName": @regex("[A-Za-z ]{3,50}") #string, + "dateOfBirth": #date, "age": @range(18, 130) #integer, "email": @email #string, "pictureURL": @url #string, @@ -68,13 +70,15 @@ public class SampleSchema { """ { "user": { - "id": 1234, + "id": 1111, "username": "johndoe", "role": "user", "isActive": true, + "registeredAt": "2023-09-06T15:10:30.639Z", "profile": { "firstName": "John", "lastName": "Doe", + "dateOfBirth": "1993-06-17", "age": 30, "email": "john.doe@example.com", "pictureURL": "https://example.com/picture.jpg", @@ -129,14 +133,14 @@ if(!jsonSchema.isValid(json)) jsonSchema.writeError(); Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. ```json Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by "not number". -Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of "not number" +Schema (Line: 6:14) Json (Line: 3:14) [FUNC03]: Function @range(1, 10000) is incompatible with the target data type. Applying to a supported data type such as #number is expected but applied to an unsupported data type #string of "not number". Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern "[a-z_]{3,30}" is expected but found "john doe" that mismatches with pattern. -Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "profile"...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": "Doe", "a...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. -Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. +Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "register...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "registeredAt": "2023-09-06T15:10:30.639Z", "profile":...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. +Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "registeredAt": "2023-09-06T15:10:30.639Z", "... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. ``` ## Assertion for Validation -To utilize this library for test automation and API testing, you can employ the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: +To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: ```java ... @@ -154,17 +158,17 @@ com.relogiclabs.json.schema.exception.JsonSchemaException: DTYP04: Data type mis Expected (Schema Line: 6:31): data type #integer Actual (Json Line: 3:14): found #string inferred by "not number" - at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:85) - at com.relogiclabs.json.schema.types.JValidator.lambda$match$0(JValidator.java:82) - at java.base/java.lang.Iterable.forEach(Iterable.java:75) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:82) - at com.relogiclabs.json.schema.types.JObject.match(JObject.java:63) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:76) - at com.relogiclabs.json.schema.types.JObject.match(JObject.java:63) - at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:76) - at com.relogiclabs.json.schema.types.JRoot.match(JRoot.java:73) + at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:86) + at com.relogiclabs.json.schema.types.JDataType.matchForReport(JDataType.java:68) + at com.relogiclabs.json.schema.types.JValidator.matchDataType(JValidator.java:67) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:57) + at com.relogiclabs.json.schema.types.JObject.match(JObject.java:55) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:52) + at com.relogiclabs.json.schema.types.JObject.match(JObject.java:55) + at com.relogiclabs.json.schema.types.JValidator.match(JValidator.java:52) + at com.relogiclabs.json.schema.types.JRoot.match(JRoot.java:47) at com.relogiclabs.json.schema.JsonAssert.isValid(JsonAssert.java:54) - at org.example.SampleSchema.checkIsValid(SampleSchema.java:61) + at org.example.SampleSchema.checkIsValid(SampleSchema.java:64) at org.example.Main.main(Main.java:5) ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-Java/api/index.html). \ No newline at end of file +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-Java/api/index.html). diff --git a/doc/layouts/partials/head.html b/doc/layouts/partials/head.html index 5a005b6..64a734a 100644 --- a/doc/layouts/partials/head.html +++ b/doc/layouts/partials/head.html @@ -1,3 +1,5 @@ + + \ No newline at end of file diff --git a/doc/layouts/partials/header.html b/doc/layouts/partials/header.html index 05dcdce..e8fbf6a 100644 --- a/doc/layouts/partials/header.html +++ b/doc/layouts/partials/header.html @@ -1,7 +1,15 @@