From 627d9346382ae01497371b45dbaa00d017276975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Fern=C3=A1ndez?= Date: Thu, 9 May 2019 19:00:44 +0200 Subject: [PATCH 1/2] Custom format validators now have access to the unprocessed properties There can be some use cases where a custom format validator requires additional setup values in order to tweak its behaviour. So, now custom format validator have access to the unprocessed properties in the JSON Schema context where the subject is being evaluated. --- .../everit/json/schema/FormatValidator.java | 8 +- .../schema/StringSchemaValidatingVisitor.java | 4 +- .../java/org/everit/json/schema/Visitor.java | 4 +- .../internal/DateTimeFormatValidator.java | 5 +- .../schema/internal/EmailFormatValidator.java | 3 +- .../internal/HostnameFormatValidator.java | 3 +- .../json/schema/internal/IPV4Validator.java | 3 +- .../json/schema/internal/IPV6Validator.java | 3 +- .../internal/JsonPointerFormatValidator.java | 3 +- .../schema/internal/RegexFormatValidator.java | 3 +- .../RelativeJsonPointerFormatValidator.java | 3 +- .../internal/TemporalFormatValidator.java | 4 +- .../schema/internal/URIFormatValidator.java | 4 +- .../internal/URIReferenceFormatValidator.java | 4 +- .../internal/URITemplateFormatValidator.java | 3 +- .../schema/internal/URIV4FormatValidator.java | 3 +- .../internal/WrappingFormatValidator.java | 5 +- .../everit/json/schema/StringSchemaTest.java | 4 +- .../internal/DefaultFormatValidatorTest.java | 3 +- .../internal/URIV4FormatValidatorTest.java | 6 +- .../schema/internal/ValidatorTestSupport.java | 13 +- .../loader/CustomFormatValidatorExtTest.java | 123 ++++++++++++++++++ .../loader/CustomFormatValidatorTest.java | 3 +- .../json/schema/loader/SchemaLoaderTest.java | 2 +- .../customformat-ext-fail_data.json | 3 + .../customformat-ext-schema.json | 14 ++ .../customformat-ext-works_data.json | 3 + 27 files changed, 207 insertions(+), 32 deletions(-) create mode 100644 core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java create mode 100644 core/src/test/resources/org/everit/jsonvalidator/customformat-ext-fail_data.json create mode 100644 core/src/test/resources/org/everit/jsonvalidator/customformat-ext-schema.json create mode 100644 core/src/test/resources/org/everit/jsonvalidator/customformat-ext-works_data.json diff --git a/core/src/main/java/org/everit/json/schema/FormatValidator.java b/core/src/main/java/org/everit/json/schema/FormatValidator.java index 718743f7f..c9c93894c 100644 --- a/core/src/main/java/org/everit/json/schema/FormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/FormatValidator.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.internal.DateTimeFormatValidator; @@ -21,7 +22,7 @@ public interface FormatValidator { /** * No-operation implementation (never throws {always returns {@link Optional#empty()}). */ - FormatValidator NONE = subject -> Optional.empty(); + FormatValidator NONE = (subject, unprocessedProperties) -> Optional.empty(); /** * Static factory method for {@code FormatValidator} implementations supporting the @@ -67,10 +68,13 @@ static FormatValidator forFormat(final String formatName) { * * @param subject * the string to be validated + * @param unprocessedProperties + * the map of unprocessed properties, which can be useful for some custom complex format + * * @return an {@code Optional} wrapping the error message if a validation error occured, otherwise * {@link Optional#empty() an empty optional}. */ - Optional validate(String subject); + Optional validate(String subject, Map unprocessedProperties); /** * Provides the name of this format. diff --git a/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java b/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java index c32ebbe65..fb521ad75 100644 --- a/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java +++ b/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java @@ -51,8 +51,8 @@ public StringSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) { } } - @Override void visitFormat(FormatValidator formatValidator) { - Optional failure = formatValidator.validate(stringSubject); + @Override void visitFormat(FormatValidator formatValidator, Schema schema) { + Optional failure = formatValidator.validate(stringSubject, schema.getUnprocessedProperties()); if (failure.isPresent()) { owner.failure(failure.get(), "format"); } diff --git a/core/src/main/java/org/everit/json/schema/Visitor.java b/core/src/main/java/org/everit/json/schema/Visitor.java index 18d5d12a9..7c1e8e31b 100644 --- a/core/src/main/java/org/everit/json/schema/Visitor.java +++ b/core/src/main/java/org/everit/json/schema/Visitor.java @@ -167,10 +167,10 @@ void visitStringSchema(StringSchema stringSchema) { visitMinLength(stringSchema.getMinLength()); visitMaxLength(stringSchema.getMaxLength()); visitPattern(stringSchema.getRegexpPattern()); - visitFormat(stringSchema.getFormatValidator()); + visitFormat(stringSchema.getFormatValidator(),stringSchema); } - void visitFormat(FormatValidator formatValidator) { + void visitFormat(FormatValidator formatValidator, Schema schema) { } void visitPattern(Regexp pattern) { diff --git a/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java index db083fd63..b47932a16 100644 --- a/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java @@ -6,6 +6,7 @@ import java.time.format.DateTimeFormatterBuilder; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; import static org.everit.json.schema.internal.TemporalFormatValidator.SECONDS_FRACTION_FORMATTER; @@ -43,8 +44,8 @@ private static class Delegate extends TemporalFormatValidator { private Delegate delegate = new Delegate(); - @Override public Optional validate(String subject) { - return delegate.validate(subject); + @Override public Optional validate(String subject, final Map unprocessedProperties) { + return delegate.validate(subject, unprocessedProperties); } @Override diff --git a/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java index edf4fc3fd..5fe11c58e 100644 --- a/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java @@ -1,5 +1,6 @@ package org.everit.json.schema.internal; +import java.util.Map; import java.util.Optional; import org.apache.commons.validator.routines.EmailValidator; @@ -11,7 +12,7 @@ public class EmailFormatValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { if (EmailValidator.getInstance(false, true).isValid(subject)) { return Optional.empty(); } diff --git a/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java index 70ce2853b..5566d6a4b 100644 --- a/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java @@ -3,6 +3,7 @@ import org.apache.commons.validator.routines.DomainValidator; import org.everit.json.schema.FormatValidator; +import java.util.Map; import java.util.Optional; /** @@ -11,7 +12,7 @@ public class HostnameFormatValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { return DomainValidator.getInstance(true).isValid(subject) && !subject.contains("_") ? Optional.empty() : Optional.of(String.format("[%s] is not a valid hostname", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java b/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java index 7871aaed1..1ad08bc98 100644 --- a/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java +++ b/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java @@ -3,6 +3,7 @@ import org.apache.commons.validator.routines.InetAddressValidator; import org.everit.json.schema.FormatValidator; +import java.util.Map; import java.util.Optional; /** @@ -11,7 +12,7 @@ public class IPV4Validator extends IPAddressValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { return InetAddressValidator.getInstance().isValidInet4Address(subject) ? Optional.empty() : Optional.of(String.format("[%s] is not a valid ipv4 address", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java b/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java index ad629a1df..575e66037 100644 --- a/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java +++ b/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java @@ -3,6 +3,7 @@ import org.apache.commons.validator.routines.InetAddressValidator; import org.everit.json.schema.FormatValidator; +import java.util.Map; import java.util.Optional; /** @@ -11,7 +12,7 @@ public class IPV6Validator extends IPAddressValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { return (subject != null) && InetAddressValidator.getInstance().isValidInet6Address(subject) ? Optional.empty() : Optional.of(String.format("[%s] is not a valid ipv6 address", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java index 7a862363b..2854ebccb 100644 --- a/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java @@ -2,6 +2,7 @@ import static java.lang.String.format; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; @@ -9,7 +10,7 @@ public class JsonPointerFormatValidator implements FormatValidator { - @Override public Optional validate(String subject) { + @Override public Optional validate(String subject, final Map unprocessedProperties) { if ("".equals(subject)) { return Optional.empty(); } diff --git a/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java index 28fac7481..adbb17266 100644 --- a/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java @@ -1,5 +1,6 @@ package org.everit.json.schema.internal; +import java.util.Map; import java.util.Optional; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -8,7 +9,7 @@ public class RegexFormatValidator implements FormatValidator { - @Override public Optional validate(String subject) { + @Override public Optional validate(String subject, final Map unprocessedProperties) { try { Pattern.compile(subject); } catch (PatternSyntaxException e) { diff --git a/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java index 8cefbb4a8..bc8e1a8f4 100644 --- a/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java @@ -1,5 +1,6 @@ package org.everit.json.schema.internal; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; @@ -104,7 +105,7 @@ private void parseJsonPointer() throws ParseException { @Override - public Optional validate(String subject) { + public Optional validate(String subject, final Map unprocessedProperties) { try { new Parser(subject).parse(); } catch (ParseException e) { diff --git a/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java index 3b679c9c7..4615b7c57 100644 --- a/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java @@ -6,6 +6,8 @@ import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; + +import java.util.Map; import java.util.Optional; import static java.util.Objects.requireNonNull; @@ -28,7 +30,7 @@ public class TemporalFormatValidator implements FormatValidator { } @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { try { formatter.parse(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java index 7adc6c2b3..556ddbc1d 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java @@ -2,6 +2,8 @@ import java.net.URI; import java.net.URISyntaxException; + +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; @@ -22,7 +24,7 @@ public URIFormatValidator(boolean protocolRelativeURIPermitted) { } @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { try { if (subject != null) { URI uri = new URI(subject); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java index bee1a13ea..ecb82e906 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java @@ -4,13 +4,15 @@ import java.net.URI; import java.net.URISyntaxException; + +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; public class URIReferenceFormatValidator implements FormatValidator { - @Override public Optional validate(String subject) { + @Override public Optional validate(String subject, final Map unprocessedProperties) { try { new URI(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java index e144161b7..a36b76cd8 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java @@ -2,6 +2,7 @@ import static java.lang.String.format; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; @@ -11,7 +12,7 @@ public class URITemplateFormatValidator implements FormatValidator { - @Override public Optional validate(String subject) { + @Override public Optional validate(String subject, final Map unprocessedProperties) { try { UriTemplate.fromTemplate(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java index 6cca1b4bd..a81cc1bd4 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java @@ -2,13 +2,14 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; public class URIV4FormatValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { try { URI uri = new URI(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java b/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java index 92e1460b9..03b5c77f2 100644 --- a/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java @@ -2,6 +2,7 @@ import org.everit.json.schema.FormatValidator; +import java.util.Map; import java.util.Optional; import static java.util.Objects.requireNonNull; @@ -19,8 +20,8 @@ public WrappingFormatValidator(String formatName, FormatValidator wrappedValidat @Override - public Optional validate(String subject) { - return formatValidator.validate(subject); + public Optional validate(String subject, Map unprocessedProperties) { + return formatValidator.validate(subject, unprocessedProperties); } @Override diff --git a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java index 9c70cb28a..1f0d99dcf 100644 --- a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java +++ b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java @@ -28,7 +28,7 @@ private static Schema loadWithNullableSupport(JSONObject rawSchemaJson) { @Test public void formatFailure() { StringSchema subject = buildWithLocation(StringSchema.builder() - .formatValidator(subj -> Optional.of("violation"))); + .formatValidator((subj, props) -> Optional.of("violation"))); TestSupport.failureOf(subject) .expectedKeyword("format") .input("string") @@ -37,7 +37,7 @@ public void formatFailure() { @Test public void formatSuccess() { - StringSchema subject = StringSchema.builder().formatValidator(subj -> Optional.empty()).build(); + StringSchema subject = StringSchema.builder().formatValidator((subj, props) -> Optional.empty()).build(); subject.validate("string"); } diff --git a/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java b/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java index f70aead47..aeb2e3482 100644 --- a/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java +++ b/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java @@ -18,6 +18,7 @@ import org.everit.json.schema.FormatValidator; import org.junit.Test; +import java.util.Map; import java.util.Optional; import static org.everit.json.schema.internal.ValidatorTestSupport.assertFailure; @@ -270,7 +271,7 @@ public class IPV4ValidatorOld extends IPAddressValidator implements FormatValida private static final int IPV4_LENGTH = 4; @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { return checkIpAddress(subject, IPV4_LENGTH, "[%s] is not a valid ipv4 address"); } diff --git a/core/src/test/java/org/everit/json/schema/internal/URIV4FormatValidatorTest.java b/core/src/test/java/org/everit/json/schema/internal/URIV4FormatValidatorTest.java index fdb455f9b..c7f512a53 100644 --- a/core/src/test/java/org/everit/json/schema/internal/URIV4FormatValidatorTest.java +++ b/core/src/test/java/org/everit/json/schema/internal/URIV4FormatValidatorTest.java @@ -9,16 +9,16 @@ public class URIV4FormatValidatorTest { @Test public void relativeURI() { - assertFalse(new URIV4FormatValidator().validate("abc").isPresent()); + assertFalse(new URIV4FormatValidator().validate("abc",null).isPresent()); } @Test public void absoluteURI() { - assertFalse(new URIV4FormatValidator().validate("http://a.b.c").isPresent()); + assertFalse(new URIV4FormatValidator().validate("http://a.b.c",null).isPresent()); } @Test public void notURI() { - assertTrue(new URIV4FormatValidator().validate("\\\\\\\\WINDOWS\\\\fileshare").isPresent()); + assertTrue(new URIV4FormatValidator().validate("\\\\\\\\WINDOWS\\\\fileshare",null).isPresent()); } } diff --git a/core/src/test/java/org/everit/json/schema/internal/ValidatorTestSupport.java b/core/src/test/java/org/everit/json/schema/internal/ValidatorTestSupport.java index d434b557e..0351d9928 100644 --- a/core/src/test/java/org/everit/json/schema/internal/ValidatorTestSupport.java +++ b/core/src/test/java/org/everit/json/schema/internal/ValidatorTestSupport.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertTrue; +import java.util.Map; import java.util.Optional; import org.everit.json.schema.FormatValidator; @@ -10,13 +11,21 @@ public final class ValidatorTestSupport { static void assertSuccess(String subject, FormatValidator format) { - Optional opt = format.validate(subject); + assertSuccess(subject, format, null); + } + + static void assertSuccess(String subject, FormatValidator format, Map unprocessedProperties) { + Optional opt = format.validate(subject, unprocessedProperties); Assert.assertNotNull("the optional is not null", opt); Assert.assertFalse("failure not exist", opt.isPresent()); } static void assertFailure(String subject, FormatValidator format, String expectedFailure) { - Optional opt = format.validate(subject); + assertFailure(subject, format, null, expectedFailure); + } + + static void assertFailure(String subject, FormatValidator format, Map unprocessedProperties, String expectedFailure) { + Optional opt = format.validate(subject, unprocessedProperties); Assert.assertNotNull("the optional is not null", opt); assertTrue("failure exists", opt.isPresent()); Assert.assertEquals(expectedFailure, opt.get()); diff --git a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java new file mode 100644 index 000000000..e08529709 --- /dev/null +++ b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 Everit Kft. (http://www.everit.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.everit.json.schema.loader; + +import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.ResourceLoader; +import org.everit.json.schema.ValidationException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.junit.Assert.assertEquals; + +public class CustomFormatValidatorExtTest { + + private final ResourceLoader loader = ResourceLoader.DEFAULT; + + static class DivisibleValidator implements FormatValidator { + + @Override + public Optional validate(final String subject, final Map unprocessedProperties) { + if (unprocessedProperties.containsKey("factors")) { + try { + long divisible = Long.parseLong(subject); + try { + List factors = (List) unprocessedProperties.get("factors"); + for (String strFactor: factors) { + try { + long factor = Long.parseLong(strFactor); + if (divisible % factor != 0) { + return Optional.of(String.format("[%s] is not divisible by [%s]", subject, strFactor)); + } + } catch(NumberFormatException nfe) { + return Optional.of(String.format("the factor [%s] is not a parsable number", strFactor)); + } + } + return Optional.empty(); + } catch(ClassCastException cce) { + return Optional.of("'factors' is not an array in JSON Schema"); + } + } catch(NumberFormatException nfe) { + return Optional.of(String.format("the string [%s] is not a parsable number", subject)); + } + } else { + return Optional.of(String.format("no declared 'factors' in JSON Schema", subject)); + } + } + + @Override + public String formatName() { + return "divisible"; + } + } + + @Test + public void testWorks() { + SchemaLoader schemaLoader = SchemaLoader.builder() + .schemaJson(baseSchemaJson()) + .addFormatValidator("divisible", new DivisibleValidator()) + .build(); + + try { + schemaLoader.load().build().validate(loader.readObj("customformat-ext-works_data.json")); + } catch (ValidationException ve) { + Assert.fail("throwed exception"); + } + } + + @Test + public void testFail() { + SchemaLoader schemaLoader = SchemaLoader.builder() + .schemaJson(baseSchemaJson()) + .addFormatValidator("divisible", new DivisibleValidator()) + .build(); + + try { + schemaLoader.load().build().validate(loader.readObj("customformat-ext-fail_data.json")); + Assert.fail("did not throw exception"); + } catch (ValidationException ve) { + } + } + + @Test + public void nameOverride() { + JSONObject rawSchemaJson = baseSchemaJson(); + JSONObject idPropSchema = (JSONObject) rawSchemaJson.query("/properties/v"); + idPropSchema.put("format", "somethingelse"); + SchemaLoader schemaLoader = SchemaLoader.builder() + .schemaJson(rawSchemaJson) + .addFormatValidator("somethingelse", new DivisibleValidator()) + .build(); + Object actual = fetchFormatValueFromOutputJson(schemaLoader); + assertEquals("somethingelse", actual); + } + + private Object fetchFormatValueFromOutputJson(SchemaLoader schemaLoader) { + return new JSONObject(schemaLoader.load().build().toString()) + .query("/properties/v/format"); + } + + private JSONObject baseSchemaJson() { + return loader.readObj("customformat-ext-schema.json"); + } + +} diff --git a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java index 229debf1c..42556f4bb 100644 --- a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java @@ -22,6 +22,7 @@ import org.junit.Assert; import org.junit.Test; +import java.util.Map; import java.util.Optional; import static org.junit.Assert.assertEquals; @@ -33,7 +34,7 @@ public class CustomFormatValidatorTest { static class EvenCharNumValidator implements FormatValidator { @Override - public Optional validate(final String subject) { + public Optional validate(final String subject, final Map unprocessedProperties) { if (subject.length() % 2 == 0) { return Optional.empty(); } else { diff --git a/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java b/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java index 0928ae389..070221654 100644 --- a/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java @@ -97,7 +97,7 @@ public void builderUsesDefaultSchemaClient() { public void customFormat() { Schema subject = SchemaLoader.builder() .schemaJson(get("customFormat")) - .addFormatValidator("custom", obj -> Optional.of("failure")) + .addFormatValidator("custom", (obj, props) -> Optional.of("failure")) .build().load().build(); TestSupport.expectFailure(subject, "asd"); } diff --git a/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-fail_data.json b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-fail_data.json new file mode 100644 index 000000000..aef402027 --- /dev/null +++ b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-fail_data.json @@ -0,0 +1,3 @@ +{ + "v": "21" +} diff --git a/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-schema.json b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-schema.json new file mode 100644 index 000000000..f070b7c44 --- /dev/null +++ b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "v": { + "type": "string", + "format": "divisible", + "factors": [ "3", "5" ] + } + }, + "required": [ + "v" + ] +} diff --git a/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-works_data.json b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-works_data.json new file mode 100644 index 000000000..5342cbb45 --- /dev/null +++ b/core/src/test/resources/org/everit/jsonvalidator/customformat-ext-works_data.json @@ -0,0 +1,3 @@ +{ + "v": "15" +} From d4387f4383e37d32d16cc91499c75a2710f68211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Fern=C3=A1ndez?= Date: Fri, 17 May 2019 01:52:57 +0200 Subject: [PATCH 2/2] FormatValidator Interface backward compatibility In order to keep backward compatibility, the new code has been spread among AbstractFormatValidator, FormatValidator and ContextualFormatValidator --- .../json/schema/AbstractFormatValidator.java | 66 +++++++++++++++++++ .../schema/ContextualFormatValidator.java | 38 +++++++++++ .../everit/json/schema/FormatValidator.java | 21 ++---- .../org/everit/json/schema/StringSchema.java | 8 +-- .../schema/StringSchemaValidatingVisitor.java | 2 +- .../java/org/everit/json/schema/Visitor.java | 2 +- .../internal/DateTimeFormatValidator.java | 4 +- .../schema/internal/EmailFormatValidator.java | 2 +- .../internal/HostnameFormatValidator.java | 2 +- .../json/schema/internal/IPV4Validator.java | 2 +- .../json/schema/internal/IPV6Validator.java | 2 +- .../internal/JsonPointerFormatValidator.java | 2 +- .../schema/internal/RegexFormatValidator.java | 2 +- .../RelativeJsonPointerFormatValidator.java | 2 +- .../internal/TemporalFormatValidator.java | 2 +- .../schema/internal/URIFormatValidator.java | 2 +- .../internal/URIReferenceFormatValidator.java | 2 +- .../internal/URITemplateFormatValidator.java | 2 +- .../schema/internal/URIV4FormatValidator.java | 2 +- .../json/schema/loader/LoaderConfig.java | 8 +-- .../json/schema/loader/SchemaLoader.java | 14 ++-- .../schema/loader/SpecificationVersion.java | 19 +++--- .../schema/loader/StringSchemaLoader.java | 8 +-- .../internal/WrappingFormatValidator.java | 12 ++-- .../everit/json/schema/StringSchemaTest.java | 4 +- .../internal/DefaultFormatValidatorTest.java | 2 +- .../loader/CustomFormatValidatorExtTest.java | 4 +- .../loader/CustomFormatValidatorTest.java | 2 +- .../json/schema/loader/SchemaLoaderTest.java | 3 +- .../loader/SpecificationVersionTest.java | 6 +- 30 files changed, 172 insertions(+), 75 deletions(-) create mode 100644 core/src/main/java/org/everit/json/schema/AbstractFormatValidator.java create mode 100644 core/src/main/java/org/everit/json/schema/ContextualFormatValidator.java diff --git a/core/src/main/java/org/everit/json/schema/AbstractFormatValidator.java b/core/src/main/java/org/everit/json/schema/AbstractFormatValidator.java new file mode 100644 index 000000000..8433fd691 --- /dev/null +++ b/core/src/main/java/org/everit/json/schema/AbstractFormatValidator.java @@ -0,0 +1,66 @@ +package org.everit.json.schema; + +import static java.util.Objects.requireNonNull; + +import java.util.Map; +import java.util.Optional; + +import org.everit.json.schema.internal.DateTimeFormatValidator; +import org.everit.json.schema.internal.EmailFormatValidator; +import org.everit.json.schema.internal.HostnameFormatValidator; +import org.everit.json.schema.internal.IPV4Validator; +import org.everit.json.schema.internal.IPV6Validator; +import org.everit.json.schema.internal.URIFormatValidator; + +/** + * Implementations perform the validation against the "format" keyword (see JSON Schema spec section + * 7). + */ +public interface AbstractFormatValidator { + + /** + * Implementation-specific validation of {@code subject}. If a validation error occurs then + * implementations should return a programmer-friendly error message as a String wrapped in an + * Optional. If the validation succeeded then {@link Optional#empty() an empty optional} should be + * returned. + * + * @param subject + * the string to be validated + * + * @return an {@code Optional} wrapping the error message if a validation error occured, otherwise + * {@link Optional#empty() an empty optional}. + */ + Optional validate(String subject); + + /** + * Implementation-specific validation of {@code subject}. If a validation error occurs then + * implementations should return a programmer-friendly error message as a String wrapped in an + * Optional. If the validation succeeded then {@link Optional#empty() an empty optional} should be + * returned. + * + * @param subject + * the string to be validated + * @param unprocessedProperties + * the map of unprocessed properties, which can be useful for some custom complex format + * + * @return an {@code Optional} wrapping the error message if a validation error occured, otherwise + * {@link Optional#empty() an empty optional}. + */ + Optional validate(String subject, Map unprocessedProperties); + + /** + * Provides the name of this format. + *

+ * Unless specified otherwise the {@link org.everit.json.schema.loader.SchemaLoader} will use this + * name to recognize string schemas using this format. + *

+ * The default implementation of this method returns {@code "unnamed-format"}. It is strongly + * recommended for implementations to give a more meaningful name by overriding this method. + * + * @return the format name. + */ + default String formatName() { + return "unnamed-format"; + } + +} diff --git a/core/src/main/java/org/everit/json/schema/ContextualFormatValidator.java b/core/src/main/java/org/everit/json/schema/ContextualFormatValidator.java new file mode 100644 index 000000000..0d772682b --- /dev/null +++ b/core/src/main/java/org/everit/json/schema/ContextualFormatValidator.java @@ -0,0 +1,38 @@ +package org.everit.json.schema; + +import static java.util.Objects.requireNonNull; + +import java.util.Map; +import java.util.Optional; + +import org.everit.json.schema.internal.DateTimeFormatValidator; +import org.everit.json.schema.internal.EmailFormatValidator; +import org.everit.json.schema.internal.HostnameFormatValidator; +import org.everit.json.schema.internal.IPV4Validator; +import org.everit.json.schema.internal.IPV6Validator; +import org.everit.json.schema.internal.URIFormatValidator; + +/** + * Implementations perform the validation against the "format" keyword (see JSON Schema spec section + * 7). + */ +@FunctionalInterface +public interface ContextualFormatValidator extends AbstractFormatValidator { + + /** + * Implementation-specific validation of {@code subject}. If a validation error occurs then + * implementations should return a programmer-friendly error message as a String wrapped in an + * Optional. If the validation succeeded then {@link Optional#empty() an empty optional} should be + * returned. + * + * @param subject + * the string to be validated + * + * @return an {@code Optional} wrapping the error message if a validation error occured, otherwise + * {@link Optional#empty() an empty optional}. + */ + default Optional validate(String subject) { + return validate(subject,null); + } + +} diff --git a/core/src/main/java/org/everit/json/schema/FormatValidator.java b/core/src/main/java/org/everit/json/schema/FormatValidator.java index c9c93894c..e3fd6c3f0 100644 --- a/core/src/main/java/org/everit/json/schema/FormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/FormatValidator.java @@ -17,12 +17,12 @@ * 7). */ @FunctionalInterface -public interface FormatValidator { +public interface FormatValidator extends AbstractFormatValidator { /** * No-operation implementation (never throws {always returns {@link Optional#empty()}). */ - FormatValidator NONE = (subject, unprocessedProperties) -> Optional.empty(); + FormatValidator NONE = (subject) -> Optional.empty(); /** * Static factory method for {@code FormatValidator} implementations supporting the @@ -74,21 +74,8 @@ static FormatValidator forFormat(final String formatName) { * @return an {@code Optional} wrapping the error message if a validation error occured, otherwise * {@link Optional#empty() an empty optional}. */ - Optional validate(String subject, Map unprocessedProperties); - - /** - * Provides the name of this format. - *

- * Unless specified otherwise the {@link org.everit.json.schema.loader.SchemaLoader} will use this - * name to recognize string schemas using this format. - *

- * The default implementation of this method returns {@code "unnamed-format"}. It is strongly - * recommended for implementations to give a more meaningful name by overriding this method. - * - * @return the format name. - */ - default String formatName() { - return "unnamed-format"; + default Optional validate(String subject, Map unprocessedProperties) { + return validate(subject); } } diff --git a/core/src/main/java/org/everit/json/schema/StringSchema.java b/core/src/main/java/org/everit/json/schema/StringSchema.java index 68ea7099d..6096a87db 100644 --- a/core/src/main/java/org/everit/json/schema/StringSchema.java +++ b/core/src/main/java/org/everit/json/schema/StringSchema.java @@ -27,7 +27,7 @@ public static class Builder extends Schema.Builder { private boolean requiresString = true; - private FormatValidator formatValidator = NONE; + private AbstractFormatValidator formatValidator = NONE; @Override public StringSchema build() { @@ -43,7 +43,7 @@ public StringSchema build() { * the format validator * @return {@code this} */ - public Builder formatValidator(final FormatValidator formatValidator) { + public Builder formatValidator(final AbstractFormatValidator formatValidator) { this.formatValidator = requireNonNull(formatValidator, "formatValidator cannot be null"); return this; } @@ -86,7 +86,7 @@ public static Builder builder() { private final boolean requiresString; - private final FormatValidator formatValidator; + private final AbstractFormatValidator formatValidator; public StringSchema() { this(builder()); @@ -149,7 +149,7 @@ public boolean equals(Object o) { } } - public FormatValidator getFormatValidator() { + public AbstractFormatValidator getFormatValidator() { return formatValidator; } diff --git a/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java b/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java index fb521ad75..7e6adf4e4 100644 --- a/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java +++ b/core/src/main/java/org/everit/json/schema/StringSchemaValidatingVisitor.java @@ -51,7 +51,7 @@ public StringSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) { } } - @Override void visitFormat(FormatValidator formatValidator, Schema schema) { + @Override void visitFormat(AbstractFormatValidator formatValidator, Schema schema) { Optional failure = formatValidator.validate(stringSubject, schema.getUnprocessedProperties()); if (failure.isPresent()) { owner.failure(failure.get(), "format"); diff --git a/core/src/main/java/org/everit/json/schema/Visitor.java b/core/src/main/java/org/everit/json/schema/Visitor.java index 7c1e8e31b..a9843526a 100644 --- a/core/src/main/java/org/everit/json/schema/Visitor.java +++ b/core/src/main/java/org/everit/json/schema/Visitor.java @@ -170,7 +170,7 @@ void visitStringSchema(StringSchema stringSchema) { visitFormat(stringSchema.getFormatValidator(),stringSchema); } - void visitFormat(FormatValidator formatValidator, Schema schema) { + void visitFormat(AbstractFormatValidator formatValidator, Schema schema) { } void visitPattern(Regexp pattern) { diff --git a/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java index b47932a16..ef8519189 100644 --- a/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java @@ -44,8 +44,8 @@ private static class Delegate extends TemporalFormatValidator { private Delegate delegate = new Delegate(); - @Override public Optional validate(String subject, final Map unprocessedProperties) { - return delegate.validate(subject, unprocessedProperties); + @Override public Optional validate(String subject) { + return delegate.validate(subject); } @Override diff --git a/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java index 5fe11c58e..ec8d780cd 100644 --- a/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/EmailFormatValidator.java @@ -12,7 +12,7 @@ public class EmailFormatValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { if (EmailValidator.getInstance(false, true).isValid(subject)) { return Optional.empty(); } diff --git a/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java index 5566d6a4b..0d06d9750 100644 --- a/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/HostnameFormatValidator.java @@ -12,7 +12,7 @@ public class HostnameFormatValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { return DomainValidator.getInstance(true).isValid(subject) && !subject.contains("_") ? Optional.empty() : Optional.of(String.format("[%s] is not a valid hostname", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java b/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java index 1ad08bc98..b44ad0108 100644 --- a/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java +++ b/core/src/main/java/org/everit/json/schema/internal/IPV4Validator.java @@ -12,7 +12,7 @@ public class IPV4Validator extends IPAddressValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { return InetAddressValidator.getInstance().isValidInet4Address(subject) ? Optional.empty() : Optional.of(String.format("[%s] is not a valid ipv4 address", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java b/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java index 575e66037..034a50500 100644 --- a/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java +++ b/core/src/main/java/org/everit/json/schema/internal/IPV6Validator.java @@ -12,7 +12,7 @@ public class IPV6Validator extends IPAddressValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { return (subject != null) && InetAddressValidator.getInstance().isValidInet6Address(subject) ? Optional.empty() : Optional.of(String.format("[%s] is not a valid ipv6 address", subject)); diff --git a/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java index 2854ebccb..ca9287002 100644 --- a/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/JsonPointerFormatValidator.java @@ -10,7 +10,7 @@ public class JsonPointerFormatValidator implements FormatValidator { - @Override public Optional validate(String subject, final Map unprocessedProperties) { + @Override public Optional validate(String subject) { if ("".equals(subject)) { return Optional.empty(); } diff --git a/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java index adbb17266..cc9c77085 100644 --- a/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/RegexFormatValidator.java @@ -9,7 +9,7 @@ public class RegexFormatValidator implements FormatValidator { - @Override public Optional validate(String subject, final Map unprocessedProperties) { + @Override public Optional validate(String subject) { try { Pattern.compile(subject); } catch (PatternSyntaxException e) { diff --git a/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java index bc8e1a8f4..d008019a4 100644 --- a/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/RelativeJsonPointerFormatValidator.java @@ -105,7 +105,7 @@ private void parseJsonPointer() throws ParseException { @Override - public Optional validate(String subject, final Map unprocessedProperties) { + public Optional validate(String subject) { try { new Parser(subject).parse(); } catch (ParseException e) { diff --git a/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java index 4615b7c57..be06a126c 100644 --- a/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/TemporalFormatValidator.java @@ -30,7 +30,7 @@ public class TemporalFormatValidator implements FormatValidator { } @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { try { formatter.parse(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java index 556ddbc1d..05b04c61c 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIFormatValidator.java @@ -24,7 +24,7 @@ public URIFormatValidator(boolean protocolRelativeURIPermitted) { } @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { try { if (subject != null) { URI uri = new URI(subject); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java index ecb82e906..5d0c49bb1 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIReferenceFormatValidator.java @@ -12,7 +12,7 @@ public class URIReferenceFormatValidator implements FormatValidator { - @Override public Optional validate(String subject, final Map unprocessedProperties) { + @Override public Optional validate(String subject) { try { new URI(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java index a36b76cd8..6a3033b61 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URITemplateFormatValidator.java @@ -12,7 +12,7 @@ public class URITemplateFormatValidator implements FormatValidator { - @Override public Optional validate(String subject, final Map unprocessedProperties) { + @Override public Optional validate(String subject) { try { UriTemplate.fromTemplate(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java b/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java index a81cc1bd4..4d0b74f2f 100644 --- a/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/internal/URIV4FormatValidator.java @@ -9,7 +9,7 @@ public class URIV4FormatValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { try { URI uri = new URI(subject); return Optional.empty(); diff --git a/core/src/main/java/org/everit/json/schema/loader/LoaderConfig.java b/core/src/main/java/org/everit/json/schema/loader/LoaderConfig.java index dba904211..655d437ab 100644 --- a/core/src/main/java/org/everit/json/schema/loader/LoaderConfig.java +++ b/core/src/main/java/org/everit/json/schema/loader/LoaderConfig.java @@ -10,7 +10,7 @@ import java.util.HashMap; import java.util.Map; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.AbstractFormatValidator; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.everit.json.schema.regexp.JavaUtilRegexpFactory; import org.everit.json.schema.regexp.RegexpFactory; @@ -26,7 +26,7 @@ static LoaderConfig defaultV4Config() { final SchemaClient schemaClient; - final Map formatValidators; + final Map formatValidators; final Map schemasByURI; @@ -38,12 +38,12 @@ static LoaderConfig defaultV4Config() { final RegexpFactory regexpFactory; - LoaderConfig(SchemaClient schemaClient, Map formatValidators, + LoaderConfig(SchemaClient schemaClient, Map formatValidators, SpecificationVersion specVersion, boolean useDefaults) { this(schemaClient, formatValidators, emptyMap(), specVersion, useDefaults, false, new JavaUtilRegexpFactory()); } - LoaderConfig(SchemaClient schemaClient, Map formatValidators, + LoaderConfig(SchemaClient schemaClient, Map formatValidators, Map schemasByURI, SpecificationVersion specVersion, boolean useDefaults, boolean nullableSupport, RegexpFactory regexpFactory) { diff --git a/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java b/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java index 505586514..7afbc1201 100644 --- a/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java +++ b/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java @@ -21,7 +21,7 @@ import org.everit.json.schema.CombinedSchema; import org.everit.json.schema.EmptySchema; import org.everit.json.schema.FalseSchema; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.AbstractFormatValidator; import org.everit.json.schema.Schema; import org.everit.json.schema.SchemaException; import org.everit.json.schema.SchemaLocation; @@ -58,7 +58,7 @@ public static class SchemaLoaderBuilder { SchemaLocation pointerToCurrentObj = SchemaLocation.empty(); - Map formatValidators = new HashMap<>(); + Map formatValidators = new HashMap<>(); SpecificationVersion specVersion; @@ -77,13 +77,13 @@ public SchemaLoaderBuilder() { } /** - * Registers a format validator with the name returned by {@link FormatValidator#formatName()}. + * Registers a format validator with the name returned by {@link AbstractFormatValidator#formatName()}. * * @param formatValidator * the format validator to be registered with its name * @return {@code this} */ - public SchemaLoaderBuilder addFormatValidator(FormatValidator formatValidator) { + public SchemaLoaderBuilder addFormatValidator(AbstractFormatValidator formatValidator) { formatValidators.put(formatValidator.formatName(), formatValidator); return this; } @@ -99,7 +99,7 @@ public SchemaLoaderBuilder addFormatValidator(FormatValidator formatValidator) { */ @Deprecated public SchemaLoaderBuilder addFormatValidator(String formatName, - final FormatValidator formatValidator) { + final AbstractFormatValidator formatValidator) { if (!Objects.equals(formatName, formatValidator.formatName())) { formatValidators.put(formatName, new WrappingFormatValidator(formatName, formatValidator)); } else { @@ -206,7 +206,7 @@ public SchemaLoaderBuilder schemaJson(Object schema) { return this; } - SchemaLoaderBuilder formatValidators(Map formatValidators) { + SchemaLoaderBuilder formatValidators(Map formatValidators) { this.formatValidators = formatValidators; return this; } @@ -448,7 +448,7 @@ SpecificationVersion specVersion() { * @deprecated */ @Deprecated - Optional getFormatValidator(String formatName) { + Optional getFormatValidator(String formatName) { return Optional.ofNullable(config.formatValidators.get(formatName)); } diff --git a/core/src/main/java/org/everit/json/schema/loader/SpecificationVersion.java b/core/src/main/java/org/everit/json/schema/loader/SpecificationVersion.java index b60403ad7..ef8bf45d8 100644 --- a/core/src/main/java/org/everit/json/schema/loader/SpecificationVersion.java +++ b/core/src/main/java/org/everit/json/schema/loader/SpecificationVersion.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; +import org.everit.json.schema.AbstractFormatValidator; import org.everit.json.schema.FormatValidator; import org.everit.json.schema.internal.DateFormatValidator; import org.everit.json.schema.internal.DateTimeFormatValidator; @@ -48,7 +49,7 @@ enum SpecificationVersion { return "http://json-schema.org/draft-04/schema"; } - @Override Map defaultFormatValidators() { + @Override Map defaultFormatValidators() { return V4_VALIDATORS; } @@ -69,7 +70,7 @@ enum SpecificationVersion { return "http://json-schema.org/draft-06/schema"; } - @Override Map defaultFormatValidators() { + @Override Map defaultFormatValidators() { return V6_VALIDATORS; } @@ -90,7 +91,7 @@ enum SpecificationVersion { return "http://json-schema.org/draft-07/schema"; } - @Override Map defaultFormatValidators() { + @Override Map defaultFormatValidators() { return V7_VALIDATORS; } }; @@ -129,7 +130,7 @@ private static List keywords(String... keywords) { return unmodifiableList(asList(keywords)); } - private static final Map V4_VALIDATORS = formatValidators(null, + private static final Map V4_VALIDATORS = formatValidators(null, new DateTimeFormatValidator(), new URIV4FormatValidator(), new EmailFormatValidator(), @@ -138,14 +139,14 @@ private static List keywords(String... keywords) { new HostnameFormatValidator() ); - private static final Map V6_VALIDATORS = formatValidators(V4_VALIDATORS, + private static final Map V6_VALIDATORS = formatValidators(V4_VALIDATORS, new JsonPointerFormatValidator(), new URIFormatValidator(), new URIReferenceFormatValidator(), new URITemplateFormatValidator() ); - private static final Map V7_VALIDATORS = formatValidators(V6_VALIDATORS, + private static final Map V7_VALIDATORS = formatValidators(V6_VALIDATORS, new DateFormatValidator(), new URIFormatValidator(false), new TimeFormatValidator(), @@ -153,8 +154,8 @@ private static List keywords(String... keywords) { new RelativeJsonPointerFormatValidator() ); - private static Map formatValidators(Map parent, FormatValidator... validators) { - Map validatorMap = (parent == null) ? new HashMap<>() : new HashMap<>(parent); + private static Map formatValidators(Map parent, FormatValidator... validators) { + Map validatorMap = (parent == null) ? new HashMap<>() : new HashMap<>(parent); for (FormatValidator validator : validators) { validatorMap.put(validator.formatName(), validator); } @@ -169,7 +170,7 @@ private static Map formatValidators(Map defaultFormatValidators(); + abstract Map defaultFormatValidators(); public boolean isAtLeast(SpecificationVersion lowerInclusiveBound) { return this.ordinal() >= lowerInclusiveBound.ordinal(); diff --git a/core/src/main/java/org/everit/json/schema/loader/StringSchemaLoader.java b/core/src/main/java/org/everit/json/schema/loader/StringSchemaLoader.java index 1633f9f3e..d9f6bb229 100644 --- a/core/src/main/java/org/everit/json/schema/loader/StringSchemaLoader.java +++ b/core/src/main/java/org/everit/json/schema/loader/StringSchemaLoader.java @@ -6,7 +6,7 @@ import java.util.Map; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.AbstractFormatValidator; import org.everit.json.schema.StringSchema; /** @@ -16,7 +16,7 @@ public class StringSchemaLoader { private LoadingState ls; - private Map formatValidators; + private Map formatValidators; private boolean useDefault; @@ -30,7 +30,7 @@ public StringSchemaLoader(LoadingState ls) { this(ls, DRAFT_4.defaultFormatValidators()); } - StringSchemaLoader(LoadingState ls, Map formatValidators) { + StringSchemaLoader(LoadingState ls, Map formatValidators) { this.ls = requireNonNull(ls, "ls cannot be null"); this.formatValidators = unmodifiableMap(requireNonNull(formatValidators, "formatValidators cannot be null")); } @@ -48,7 +48,7 @@ public StringSchema.Builder load() { } private void addFormatValidator(StringSchema.Builder builder, String formatName) { - FormatValidator formatValidator = formatValidators.get(formatName); + AbstractFormatValidator formatValidator = formatValidators.get(formatName); if (formatValidator != null) { builder.formatValidator(formatValidator); } diff --git a/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java b/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java index 03b5c77f2..35c501914 100644 --- a/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java +++ b/core/src/main/java/org/everit/json/schema/loader/internal/WrappingFormatValidator.java @@ -1,23 +1,27 @@ package org.everit.json.schema.loader.internal; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.AbstractFormatValidator; import java.util.Map; import java.util.Optional; import static java.util.Objects.requireNonNull; -public class WrappingFormatValidator implements FormatValidator { +public class WrappingFormatValidator implements AbstractFormatValidator { private final String formatName; - private final FormatValidator formatValidator; + private final AbstractFormatValidator formatValidator; - public WrappingFormatValidator(String formatName, FormatValidator wrappedValidator) { + public WrappingFormatValidator(String formatName, AbstractFormatValidator wrappedValidator) { this.formatName = requireNonNull(formatName, "formatName cannot be null"); this.formatValidator = requireNonNull(wrappedValidator, "wrappedValidator cannot be null"); } + @Override + public Optional validate(String subject) { + return formatValidator.validate(subject); + } @Override public Optional validate(String subject, Map unprocessedProperties) { diff --git a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java index 1f0d99dcf..13d815164 100644 --- a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java +++ b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java @@ -28,7 +28,7 @@ private static Schema loadWithNullableSupport(JSONObject rawSchemaJson) { @Test public void formatFailure() { StringSchema subject = buildWithLocation(StringSchema.builder() - .formatValidator((subj, props) -> Optional.of("violation"))); + .formatValidator(((FormatValidator)((subj) -> Optional.of("violation"))))); TestSupport.failureOf(subject) .expectedKeyword("format") .input("string") @@ -37,7 +37,7 @@ public void formatFailure() { @Test public void formatSuccess() { - StringSchema subject = StringSchema.builder().formatValidator((subj, props) -> Optional.empty()).build(); + StringSchema subject = StringSchema.builder().formatValidator(((FormatValidator)((subj) -> Optional.empty()))).build(); subject.validate("string"); } diff --git a/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java b/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java index aeb2e3482..c7c6e42a3 100644 --- a/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java +++ b/core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java @@ -271,7 +271,7 @@ public class IPV4ValidatorOld extends IPAddressValidator implements FormatValida private static final int IPV4_LENGTH = 4; @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { return checkIpAddress(subject, IPV4_LENGTH, "[%s] is not a valid ipv4 address"); } diff --git a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java index e08529709..926469c50 100644 --- a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorExtTest.java @@ -15,7 +15,7 @@ */ package org.everit.json.schema.loader; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.ContextualFormatValidator; import org.everit.json.schema.ResourceLoader; import org.everit.json.schema.ValidationException; import org.json.JSONObject; @@ -33,7 +33,7 @@ public class CustomFormatValidatorExtTest { private final ResourceLoader loader = ResourceLoader.DEFAULT; - static class DivisibleValidator implements FormatValidator { + static class DivisibleValidator implements ContextualFormatValidator { @Override public Optional validate(final String subject, final Map unprocessedProperties) { diff --git a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java index 42556f4bb..b1b70bcb9 100644 --- a/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/CustomFormatValidatorTest.java @@ -34,7 +34,7 @@ public class CustomFormatValidatorTest { static class EvenCharNumValidator implements FormatValidator { @Override - public Optional validate(final String subject, final Map unprocessedProperties) { + public Optional validate(final String subject) { if (subject.length() % 2 == 0) { return Optional.empty(); } else { diff --git a/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java b/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java index 070221654..b0e2892ab 100644 --- a/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java @@ -33,6 +33,7 @@ import org.everit.json.schema.EmptySchema; import org.everit.json.schema.EnumSchema; import org.everit.json.schema.FalseSchema; +import org.everit.json.schema.FormatValidator; import org.everit.json.schema.NotSchema; import org.everit.json.schema.NullSchema; import org.everit.json.schema.NumberSchema; @@ -97,7 +98,7 @@ public void builderUsesDefaultSchemaClient() { public void customFormat() { Schema subject = SchemaLoader.builder() .schemaJson(get("customFormat")) - .addFormatValidator("custom", (obj, props) -> Optional.of("failure")) + .addFormatValidator("custom", ((FormatValidator)((obj) -> Optional.of("failure")))) .build().load().build(); TestSupport.expectFailure(subject, "asd"); } diff --git a/core/src/test/java/org/everit/json/schema/loader/SpecificationVersionTest.java b/core/src/test/java/org/everit/json/schema/loader/SpecificationVersionTest.java index dd008fd03..4df725ab1 100644 --- a/core/src/test/java/org/everit/json/schema/loader/SpecificationVersionTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/SpecificationVersionTest.java @@ -11,7 +11,7 @@ import java.util.Map; import java.util.Set; -import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.AbstractFormatValidator; import org.junit.Test; public class SpecificationVersionTest { @@ -24,14 +24,14 @@ public void v6ContainsAdditionalFormats() { @Test public void v4MapMatchesFormatNames() { - for (Map.Entry entry : DRAFT_4.defaultFormatValidators().entrySet()) { + for (Map.Entry entry : DRAFT_4.defaultFormatValidators().entrySet()) { assertEquals(entry.getKey(), entry.getValue().formatName()); } } @Test public void v6MapMatchesFormatNames() { - for (Map.Entry entry : DRAFT_6.defaultFormatValidators().entrySet()) { + for (Map.Entry entry : DRAFT_6.defaultFormatValidators().entrySet()) { assertEquals(entry.getKey(), entry.getValue().formatName()); } }