From c8795e513f36a2d651e0f7d3f0046e2047de873c Mon Sep 17 00:00:00 2001 From: Sebastian Toepfer <61313468+sebastian-toepfer@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:19:16 +0100 Subject: [PATCH 1/2] replace map with map.entry to define mapping between format an their rfc rule --- .../vocabulary/formatassertion/Formats.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java index 271a4f1..407dae2 100644 --- a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java +++ b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java @@ -28,41 +28,39 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; final class Formats { - private static final Map> RFCS = Map.of( + private static final Map> RFCS = Map.of( "hostname", - Map.of(1123, "hostname"), + Map.entry(1123, "hostname"), "date-time", - Map.of(3339, "date-time"), + Map.entry(3339, "date-time"), "date", - Map.of(3339, "full-date"), + Map.entry(3339, "full-date"), "time", - Map.of(3339, "full-time"), + Map.entry(3339, "full-time"), "duration", - Map.of(3339, "duration"), + Map.entry(3339, "duration"), "uri", - Map.of(3986, "URI"), + Map.entry(3986, "URI"), "email", - Map.of(5321, "mailbox"), + Map.entry(5321, "mailbox"), "ipv4", - Map.of(2673, "dotted-quad"), + Map.entry(2673, "dotted-quad"), "ipv6", - Map.of(4291, "IPv6address") + Map.entry(4291, "IPv6address") ); Format findByName(final String name) { return Optional.ofNullable(RFCS.get(name)) .stream() - .map(Map::entrySet) - .flatMap(Set::stream) - .findFirst() - .flatMap(entry -> + .map(entry -> Rfcs.findRfcByNumber(entry.getKey()).map(rfc -> new RfcBasedFormat(name, rfc, entry.getValue())) ) + .flatMap(Optional::stream) .map(Format.class::cast) + .findFirst() .orElseGet(() -> new UnknownFormat(name)); } From d0a80aef1ac8c97b6a84f632f4b1b7ae60f72ff3 Mon Sep 17 00:00:00 2001 From: Sebastian Toepfer <61313468+sebastian-toepfer@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:03:53 +0100 Subject: [PATCH 2/2] add support for uri-reference format --- .../vocabulary/formatassertion/Formats.java | 2 + .../vocabulary/formatassertion/rfc/Rfcs.java | 76 +++++++++++++++++++ .../formatassertion/FormatsTest.java | 7 ++ 3 files changed, 85 insertions(+) diff --git a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java index 407dae2..a1231ca 100644 --- a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java +++ b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/Formats.java @@ -44,6 +44,8 @@ final class Formats { Map.entry(3339, "duration"), "uri", Map.entry(3986, "URI"), + "uri-reference", + Map.entry(3986, "URI-reference"), "email", Map.entry(5321, "mailbox"), "ipv4", diff --git a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/rfc/Rfcs.java b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/rfc/Rfcs.java index 81acea7..9fa0970 100644 --- a/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/rfc/Rfcs.java +++ b/vocabulary/format-assertion/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/rfc/Rfcs.java @@ -114,6 +114,82 @@ public final class Rfcs { "\\:|@)|/|\\?)*))?(#(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|" + "\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)|/|\\?)*))?$" ) + ), + "URI-reference", + new RegExRule( + Pattern.compile( + "^(([A-Za-z]([A-Za-z0-9]|\\+|\\-|\\.)*)\\:(//(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|" + + "(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:)*)@)?((\\[((([0-9A-Fa-f]{1,4}\\:){6}(([0-9A-Fa-f]" + + "{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|" + + "2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4" + + "]\\d|25[0-5]))|\\:\\:([0-9A-Fa-f]{1,4}\\:){5}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1" + + "-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]" + + "\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|([0-9A-Fa-f]{1,4" + + "})?\\:\\:([0-9A-Fa-f]{1,4}\\:){4}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{" + + "2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[" + + "0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A-Fa-f]{1,4}\\:)?[0-9A-F" + + "a-f]{1,4})?\\:\\:([0-9A-Fa-f]{1,4}\\:){3}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1-9]" + + "\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1" + + "\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A-Fa-f]{1,4}\\:" + + "){0,2}[0-9A-Fa-f]{1,4})?\\:\\:([0-9A-Fa-f]{1,4}\\:){2}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4}" + + ")|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(" + + "\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A" + + "-Fa-f]{1,4}\\:){0,3}[0-9A-Fa-f]{1,4})?\\:\\:[0-9A-Fa-f]{1,4}\\:(([0-9A-Fa-f]{1,4}\\:[0-9A-F" + + "a-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-" + + "5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|" + + "(([0-9A-Fa-f]{1,4}\\:){0,4}[0-9A-Fa-f]{1,4})?\\:\\:(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(" + + "\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[" + + "1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A-Fa-f" + + "]{1,4}\\:){0,5}[0-9A-Fa-f]{1,4})?\\:\\:[0-9A-Fa-f]{1,4}|(([0-9A-Fa-f]{1,4}\\:){0,6}[0-9A-Fa" + + "-f]{1,4})?\\:\\:)|([Vv][0-9A-Fa-f]+\\.(([-A-Z._a-z0-9]|~)|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|" + + "\\=)|\\:)+))\\])|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d" + + "|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0" + + "-5])|((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=))*))" + + "(\\:\\d*)?(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|" + + "\\=)|\\:|@)*)*|/((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|," + + "|;|\\=)|\\:|@)+(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|," + + "|;|\\=)|\\:|@)*)*)?|(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\" + + "+|,|;|\\=)|\\:|@)+(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\" + + "+|,|;|\\=)|\\:|@)*)*|MISSING-0(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|" + + "\\)|\\*|\\+|,|;|\\=)|\\:|@))(\\?(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|" + + "\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)|/|\\?)*))?(#(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(" + + "\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)|/|\\?)*))?|(//(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f" + + "][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:)*)@)?((\\[((([0-9A-Fa-f]{1,4}\\:){6}" + + "(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9" + + "]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|" + + "1\\d{2}|2[0-4]\\d|25[0-5]))|\\:\\:([0-9A-Fa-f]{1,4}\\:){5}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{" + + "1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])" + + "\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|([0" + + "-9A-Fa-f]{1,4})?\\:\\:([0-9A-Fa-f]{1,4}\\:){4}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4})|(\\d|[" + + "1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]" + + "\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A-Fa-f]{1," + + "4}\\:)?[0-9A-Fa-f]{1,4})?\\:\\:([0-9A-Fa-f]{1,4}\\:){3}(([0-9A-Fa-f]{1,4}\\:[0-9A-Fa-f]{1,4" + + "})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(" + + "\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]))|(([0-9A" + + "-Fa-f]{1,4}\\:){0,2}[0-9A-Fa-f]{1,4})?\\:\\:([0-9A-Fa-f]{1,4}\\:){2}(([0-9A-Fa-f]{1,4}\\:[0" + + "-9A-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|" + + "25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-" + + "5]))|(([0-9A-Fa-f]{1,4}\\:){0,3}[0-9A-Fa-f]{1,4})?\\:\\:[0-9A-Fa-f]{1,4}\\:(([0-9A-Fa-f]{1," + + "4}\\:[0-9A-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0" + + "-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]" + + "\\d|25[0-5]))|(([0-9A-Fa-f]{1,4}\\:){0,4}[0-9A-Fa-f]{1,4})?\\:\\:(([0-9A-Fa-f]{1,4}\\:[0-9A" + + "-Fa-f]{1,4})|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[" + + "0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])" + + ")|(([0-9A-Fa-f]{1,4}\\:){0,5}[0-9A-Fa-f]{1,4})?\\:\\:[0-9A-Fa-f]{1,4}|(([0-9A-Fa-f]{1,4}\\:" + + "){0,6}[0-9A-Fa-f]{1,4})?\\:\\:)|([Vv][0-9A-Fa-f]+\\.(([-A-Z._a-z0-9]|~)|(\\!|\\$|&|'|\\(|\\" + + ")|\\*|\\+|,|;|\\=)|\\:)+))\\])|(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\" + + "d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|" + + "2[0-4]\\d|25[0-5])|((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|" + + "\\+|,|;|\\=))*))(\\:\\d*)?(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|" + + "\\)|\\*|\\+|,|;|\\=)|\\:|@)*)*|/((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|" + + "\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)+(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'|" + + "\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)*)*)?|((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|" + + "&|'|\\(|\\)|\\*|\\+|,|;|\\=)|@)+)(/(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(\\!|\\$|&|'" + + "|\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)*)*|MISSING-0(([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-f]|(" + + "\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@))(\\?(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa-f][0-9A-Fa-" + + "f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)|/|\\?)*))?(#(((([-A-Z._a-z0-9]|~)|%[0-9A-Fa" + + "-f][0-9A-Fa-f]|(\\!|\\$|&|'|\\(|\\)|\\*|\\+|,|;|\\=)|\\:|@)|/|\\?)*))?)$" + ) ) ) ), diff --git a/vocabulary/format-assertion/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/FormatsTest.java b/vocabulary/format-assertion/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/FormatsTest.java index 4e9a591..c2f9553 100644 --- a/vocabulary/format-assertion/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/FormatsTest.java +++ b/vocabulary/format-assertion/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/formatassertion/FormatsTest.java @@ -108,4 +108,11 @@ void should_found_uriformat() { assertThat(new Formats().findByName("uri").applyTo("http://www.example.com"), is(true)); assertThat(new Formats().findByName("uri").applyTo("1://noUri"), is(false)); } + + @Test + void should_found_urireferenceformat() { + assertThat(new Formats().findByName("uri-reference").applyTo("http://www.example.com"), is(true)); + assertThat(new Formats().findByName("uri-reference").applyTo("/json-schema"), is(true)); + assertThat(new Formats().findByName("uri-reference").applyTo("1://noUri"), is(false)); + } }