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

Custom format validators now have access to the unprocessed properties #301

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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<String> 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<String> validate(String subject, Map<String, Object> unprocessedProperties);

/**
* Provides the name of this format.
* <p>
* Unless specified otherwise the {@link org.everit.json.schema.loader.SchemaLoader} will use this
* name to recognize string schemas using this format.
* </p>
* 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";
}

}
Original file line number Diff line number Diff line change
@@ -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<String> validate(String subject) {
return validate(subject,null);
}

}
25 changes: 8 additions & 17 deletions core/src/main/java/org/everit/json/schema/FormatValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,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 -> Optional.empty();
FormatValidator NONE = (subject) -> Optional.empty();

/**
* Static factory method for {@code FormatValidator} implementations supporting the
Expand Down Expand Up @@ -67,24 +68,14 @@ 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<String> validate(String subject);

/**
* Provides the name of this format.
* <p>
* Unless specified otherwise the {@link org.everit.json.schema.loader.SchemaLoader} will use this
* name to recognize string schemas using this format.
* </p>
* 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<String> validate(String subject, Map<String, Object> unprocessedProperties) {
return validate(subject);
}

}
8 changes: 4 additions & 4 deletions core/src/main/java/org/everit/json/schema/StringSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static class Builder extends Schema.Builder<StringSchema> {

private boolean requiresString = true;

private FormatValidator formatValidator = NONE;
private AbstractFormatValidator formatValidator = NONE;

@Override
public StringSchema build() {
Expand All @@ -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;
}
Expand Down Expand Up @@ -86,7 +86,7 @@ public static Builder builder() {

private final boolean requiresString;

private final FormatValidator formatValidator;
private final AbstractFormatValidator formatValidator;

public StringSchema() {
this(builder());
Expand Down Expand Up @@ -149,7 +149,7 @@ public boolean equals(Object o) {
}
}

public FormatValidator getFormatValidator() {
public AbstractFormatValidator getFormatValidator() {
return formatValidator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public StringSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
}
}

@Override void visitFormat(FormatValidator formatValidator) {
Optional<String> failure = formatValidator.validate(stringSubject);
@Override void visitFormat(AbstractFormatValidator formatValidator, Schema schema) {
Optional<String> failure = formatValidator.validate(stringSubject, schema.getUnprocessedProperties());
if (failure.isPresent()) {
owner.failure(failure.get(), "format");
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/everit/json/schema/Visitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -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(AbstractFormatValidator formatValidator, Schema schema) {
}

void visitPattern(Regexp pattern) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static java.lang.String.format;

import java.util.Map;
import java.util.Optional;

import org.everit.json.schema.FormatValidator;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.everit.json.schema.internal;

import java.util.Map;
import java.util.Optional;

import org.everit.json.schema.FormatValidator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import java.net.URI;
import java.net.URISyntaxException;

import java.util.Map;
import java.util.Optional;

import org.everit.json.schema.FormatValidator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static java.lang.String.format;

import java.util.Map;
import java.util.Optional;

import org.everit.json.schema.FormatValidator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Optional;
import org.everit.json.schema.FormatValidator;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,7 +26,7 @@ static LoaderConfig defaultV4Config() {

final SchemaClient schemaClient;

final Map<String, FormatValidator> formatValidators;
final Map<String, AbstractFormatValidator> formatValidators;

final Map<URI, Object> schemasByURI;

Expand All @@ -38,12 +38,12 @@ static LoaderConfig defaultV4Config() {

final RegexpFactory regexpFactory;

LoaderConfig(SchemaClient schemaClient, Map<String, FormatValidator> formatValidators,
LoaderConfig(SchemaClient schemaClient, Map<String, AbstractFormatValidator> formatValidators,
SpecificationVersion specVersion, boolean useDefaults) {
this(schemaClient, formatValidators, emptyMap(), specVersion, useDefaults, false, new JavaUtilRegexpFactory());
}

LoaderConfig(SchemaClient schemaClient, Map<String, FormatValidator> formatValidators,
LoaderConfig(SchemaClient schemaClient, Map<String, AbstractFormatValidator> formatValidators,
Map<URI, Object> schemasByURI,
SpecificationVersion specVersion, boolean useDefaults, boolean nullableSupport,
RegexpFactory regexpFactory) {
Expand Down