Skip to content

Commit

Permalink
add support for regex format (#194)
Browse files Browse the repository at this point in the history
* add support for regex format
  • Loading branch information
sebastian-toepfer authored Dec 9, 2024
1 parent 56a6028 commit be9a982
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* The MIT License
*
* Copyright 2024 sebastian.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion;

public interface Format {
boolean applyTo(String value);

String name();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
final class FormatKeyword implements Assertion, Annotation {

static final String NAME = "format";
private final Formats.Format format;
private final Format format;

FormatKeyword(final Formats.Format format) {
FormatKeyword(final Format format) {
this.format = Objects.requireNonNull(format);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion;

import io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion.rfc.Rfc;
import io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion.rfc.Rfcs;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

final class Formats {

private static final Map<String, Format> CUSTOM_FORMAT = Map.of("regex", new RegExFormat());

private static final Map<String, Map.Entry<Integer, String>> RFCS = Map.ofEntries(
Map.entry("hostname", Map.entry(1123, "hostname")),
Map.entry("date-time", Map.entry(3339, "date-time")),
Expand All @@ -49,60 +49,12 @@ final class Formats {

Format findByName(final String name) {
return Optional.ofNullable(RFCS.get(name))
.stream()
.map(entry ->
.flatMap(entry ->
Rfcs.findRfcByNumber(entry.getKey()).map(rfc -> new RfcBasedFormat(name, rfc, entry.getValue()))
)
.flatMap(Optional::stream)
.map(Format.class::cast)
.findFirst()
.or(() -> Optional.ofNullable(CUSTOM_FORMAT.get(name)))
.map(Format.class::cast)
.orElseGet(() -> new UnknownFormat(name));
}

private static class RfcBasedFormat implements Format {

private final String formatName;
private final Rfc rfc;
private final String ruleName;

public RfcBasedFormat(final String formatName, final Rfc rfc, final String ruleName) {
this.formatName = Objects.requireNonNull(formatName);
this.rfc = Objects.requireNonNull(rfc);
this.ruleName = Objects.requireNonNull(ruleName);
}

@Override
public boolean applyTo(final String value) {
return rfc.findRuleByName(ruleName).map(r -> r.applyTo(value)).orElse(Boolean.FALSE);
}

@Override
public String name() {
return formatName;
}
}

interface Format {
boolean applyTo(String value);
String name();
}

private static class UnknownFormat implements Format {

private final String name;

public UnknownFormat(final String name) {
this.name = name;
}

@Override
public String name() {
return name;
}

@Override
public boolean applyTo(final String value) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* The MIT License
*
* Copyright 2024 sebastian.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion;

import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

final class RegExFormat implements Format {

private static final Logger LOG = Logger.getLogger(RegExFormat.class.getName());

@Override
public boolean applyTo(final String value) {
try {
Pattern.compile(value);
return true;
} catch (Exception e) {
LOG.log(Level.FINE, "invalid regex!", e);
return false;
}
}

@Override
public String name() {
return "regex";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* The MIT License
*
* Copyright 2024 sebastian.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion;

import io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion.rfc.Rfc;
import java.util.Objects;

public final class RfcBasedFormat implements Format {

private final String formatName;
private final Rfc rfc;
private final String ruleName;

public RfcBasedFormat(final String formatName, final Rfc rfc, final String ruleName) {
this.formatName = Objects.requireNonNull(formatName);
this.rfc = Objects.requireNonNull(rfc);
this.ruleName = Objects.requireNonNull(ruleName);
}

@Override
public boolean applyTo(final String value) {
return rfc.findRuleByName(ruleName).map(r -> r.applyTo(value)).orElse(Boolean.FALSE);
}

@Override
public String name() {
return formatName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* The MIT License
*
* Copyright 2024 sebastian.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.formatassertion;

public record UnknownFormat(String name) implements Format {
@Override
public boolean applyTo(final String value) {
return false;
}
}
1 change: 1 addition & 0 deletions vocabulary/format-assertion/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
requires io.github.sebastiantoepfer.jsonschema;
requires io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
requires io.github.sebastiantoepfer.ddd.common;
requires java.logging;
requires com.github.spotbugs.annotations;
requires jakarta.json;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,11 @@ void should_found_jsonpointerformat() {
assertThat(new Formats().findByName("json-pointer").applyTo("/abc"), is(true));
assertThat(new Formats().findByName("json-pointer:").applyTo("abc"), is(false));
}

@Test
void should_found_regexformat() {
assertThat(new Formats().findByName("regex").name(), is("regex"));
assertThat(new Formats().findByName("regex").applyTo("^[0-9]*"), is(true));
assertThat(new Formats().findByName("regex").applyTo("({"), is(false));
}
}
1 change: 1 addition & 0 deletions vocabulary/format-assertion/src/test/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
requires io.github.sebastiantoepfer.jsonschema;
requires io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
requires io.github.sebastiantoepfer.ddd.common;
requires java.logging;
requires jakarta.json;

requires org.junit.jupiter.api;
Expand Down

0 comments on commit be9a982

Please sign in to comment.