Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for relative-json-pointer format #198

Merged
merged 1 commit into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ final class Formats {
Map.entry("ipv6", Map.entry(4291, "IPv6address")),
Map.entry("json-pointer", Map.entry(6901, "json-pointer")),
Map.entry("iri", Map.entry(3987, "IRI")),
Map.entry("iri-reference", Map.entry(3987, "IRI-reference"))
Map.entry("iri-reference", Map.entry(3987, "IRI-reference")),
Map.entry("relative-json-pointer", Map.entry(20180723, "relative-json-pointer"))
);

Format findByName(final String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,19 @@ public final class Rfcs {
Map.entry(
6901,
Map.of("json-pointer", new RegExRule(Pattern.compile("^(/([\\x00-.0-}\\x7f-\\u010ffff]|\\~[01])*)*$")))
),
//draft -> use expired date as number :)
Map.entry(
20180723,
Map.of(
"relative-json-pointer",
new RegExRule(
Pattern.compile(
"^(0|[1-9][0-9]*)((/([\\x00-.0-}\\x7f-\\u010ffff]|\\~[01])*)*|#)$",
Pattern.CASE_INSENSITIVE
)
)
)
)
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
relative-json-pointer = non-negative-integer json-pointer
relative-json-pointer =/ non-negative-integer "#"
non-negative-integer = %x30 / %x31-39 *( %x30-39 )
; "0", or digits without a leading "0"

json-pointer = *( "/" reference-token )
reference-token = *( unescaped / escaped )
unescaped = %x00-2E / %x30-7D / %x7F-10FFFF
; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
escaped = "~" ( "0" / "1" )
; representing '~' and '/', respectively

97 changes: 97 additions & 0 deletions vocabulary/format-assertion/src/main/resources/rfc/rfc3987
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
IRI = scheme ":" ihier-part [ "?" iquery ]
[ "#" ifragment ]

ihier-part = "//" iauthority ipath-abempty
/ ipath-absolute
/ ipath-rootless
/ ipath-empty

IRI-reference = IRI / irelative-ref

absolute-IRI = scheme ":" ihier-part [ "?" iquery ]

irelative-ref = irelative-part [ "?" iquery ] [ "#" ifragment ]

irelative-part = "//" iauthority ipath-abempty
/ ipath-absolute
/ ipath-noscheme
/ ipath-empty

iauthority = [ iuserinfo "@" ] ihost [ ":" port ]
iuserinfo = *( iunreserved / pct-encoded / sub-delims / ":" )
ihost = IP-literal / IPv4address / ireg-name

ireg-name = *( iunreserved / pct-encoded / sub-delims )

ipath = ipath-abempty ; begins with "/" or is empty
/ ipath-absolute ; begins with "/" but not "//"
/ ipath-noscheme ; begins with a non-colon segment
/ ipath-rootless ; begins with a segment
/ ipath-empty ; zero characters

ipath-abempty = *( "/" isegment )
ipath-absolute = "/" [ isegment-nz *( "/" isegment ) ]
ipath-noscheme = isegment-nz-nc *( "/" isegment )
ipath-rootless = isegment-nz *( "/" isegment )
ipath-empty = 0<ipchar>

isegment = *ipchar
isegment-nz = 1*ipchar
isegment-nz-nc = 1*( iunreserved / pct-encoded / sub-delims
/ "@" )
; non-zero-length segment without any colon ":"

ipchar = iunreserved / pct-encoded / sub-delims / ":"
/ "@"

iquery = *( ipchar / iprivate / "/" / "?" )

ifragment = *( ipchar / "/" / "?" )

iunreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" / ucschar

ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD

iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD

scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

port = *DIGIT

IP-literal = "[" ( IPv6address / IPvFuture ) "]"

IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )

IPv6address = 6( h16 ":" ) ls32
/ "::" 5( h16 ":" ) ls32
/ [ h16 ] "::" 4( h16 ":" ) ls32
/ [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
/ [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
/ [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
/ [ *4( h16 ":" ) h16 ] "::" ls32
/ [ *5( h16 ":" ) h16 ] "::" h16
/ [ *6( h16 ":" ) h16 ] "::"

h16 = 1*4HEXDIG
ls32 = ( h16 ":" h16 ) / IPv4address

IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet

dec-octet = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255

pct-encoded = "%" HEXDIG HEXDIG

unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
reserved = gen-delims / sub-delims
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void should_found_uuidformat() {
@Test
void should_found_jsonpointerformat() {
assertThat(new Formats().findByName("json-pointer").applyTo("/abc"), is(true));
assertThat(new Formats().findByName("json-pointer:").applyTo("abc"), is(false));
assertThat(new Formats().findByName("json-pointer").applyTo("abc"), is(false));
}

@Test
Expand All @@ -157,4 +157,14 @@ void should_found_irireferenceformat() {
assertThat(new Formats().findByName("iri-reference").applyTo("http://www.myfictionαlbank.com"), is(true));
assertThat(new Formats().findByName("iri-reference").applyTo("1://noIri"), is(false));
}

@Test
void should_found_relativejsonpointerformat() {
assertThat(new Formats().findByName("relative-json-pointer").applyTo("0"), is(true));
assertThat(new Formats().findByName("relative-json-pointer").applyTo("1/0"), is(true));
assertThat(new Formats().findByName("relative-json-pointer").applyTo("2/highly/nested/objects"), is(true));
assertThat(new Formats().findByName("relative-json-pointer").applyTo("0#"), is(true));
assertThat(new Formats().findByName("relative-json-pointer").applyTo("1#"), is(true));
assertThat(new Formats().findByName("relative-json-pointer").applyTo("nopointer"), is(false));
}
}
Loading