diff --git a/README.md b/README.md index 4f3c12e46..3cdc21370 100644 --- a/README.md +++ b/README.md @@ -430,6 +430,84 @@ Schema schema = schemaLoader.load().build(); // the schema is created using the schema.validate(jsonDocument); // the document validation happens here ``` +### Custom Provider Validators +The library use `DefaultProviderValidators` that collects all the validators used in the process of validation of json. +To use a custom Provider of Validators basically you: + + * create your own ProviderValidators in a class implementing the `org.everit.json.schema.loader.ProviderValidators` interface + * bind your ProviderValidators in a `org.everit.json.schema.loader.SchemaLoader.SchemaLoaderBuilder.builder(IstanceOfNewProviderValidators` instance before loading the actual schema + +#### Example for validate a field with a function javascript + +Assume a schema with a simple function of validation that return true if the subject is equals to number 5: +```java +.... + "age": { + ... + "format": "javascript: subject == 5" + }, +... +``` + +Let's create a custom ProviderValidators that catch the intent of launch a javascript function and istantiate a new custom validator +```java +class ExampleDefaultProviderValidators extends DefaultProviderValidators { + @Override + public FormatValidator getFormatValidator(String formatName) { + + if (!this.getFormatValidators().containsKey(formatName) + && formatName.startsWith("javascript:")) { + String script = formatName.substring(formatName.lastIndexOf("javascript:"),formatName.length()); + this.addFormatValidator(formatName, new JavascriptFormatValidator(formatName, script)); + } + return super.getFormatValidator(formatName); + } +} + +class JavascriptFormatValidator implements FormatValidator { + + String script; + String formatName; + + public JavascriptFormatValidator(String formatName, String script) { + this.formatName = formatName; + this.script = script; + } + + @Override + public Optional validate(String subject) { + + ScriptEngine javaScriptEngine = new ScriptEngineManager().getEngineByName("js"); + javaScriptEngine.put("subject",subject); + try { + Boolean result = (Boolean) javaScriptEngine.eval(script); + if (!result) { + return Optional.of(String.format("the length of string [%s] is not equal 5", subject)); + } + } catch (ScriptException e) { + e.printStackTrace(); + return Optional.of(String.format("Error on evalutation of [%s] ", subject)); + } + return Optional.empty(); + } + + @Override + public String formatName() { + return formatName; + } +} +``` + +In the builder we can set this new ProviderValidators and launch the validation process. +```java +ExampleDefaultProviderValidators customProviderValidators = new ExampleDefaultProviderValidators(); +SchemaLoader schemaLoader = SchemaLoader.builder(customProviderValidators) + ....... + .build(); +Schema schema = schemaLoader.load().build(); // the schema is created using the above created configuration +schema.validate(jsonDocument); // the document validation happens here +``` + ## $ref resolution 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..290f2b275 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 @@ -11,6 +11,7 @@ import java.util.Map; import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.everit.json.schema.regexp.JavaUtilRegexpFactory; import org.everit.json.schema.regexp.RegexpFactory; @@ -21,12 +22,13 @@ class LoaderConfig { static LoaderConfig defaultV4Config() { - return new LoaderConfig(new DefaultSchemaClient(), DRAFT_4.defaultFormatValidators(), DRAFT_4, false); + return new LoaderConfig(new DefaultSchemaClient(), new DefaultProviderValidators(DRAFT_4.defaultFormatValidators()), DRAFT_4, false); } final SchemaClient schemaClient; - final Map formatValidators; + //final Map formatValidators; + final ProviderValidators providerValidators; final Map schemasByURI; @@ -38,17 +40,17 @@ static LoaderConfig defaultV4Config() { final RegexpFactory regexpFactory; - LoaderConfig(SchemaClient schemaClient, Map formatValidators, + LoaderConfig(SchemaClient schemaClient, ProviderValidators providerValidators, SpecificationVersion specVersion, boolean useDefaults) { - this(schemaClient, formatValidators, emptyMap(), specVersion, useDefaults, false, new JavaUtilRegexpFactory()); + this(schemaClient, providerValidators, emptyMap(), specVersion, useDefaults, false, new JavaUtilRegexpFactory()); } - LoaderConfig(SchemaClient schemaClient, Map formatValidators, + LoaderConfig(SchemaClient schemaClient, ProviderValidators providerValidators, Map schemasByURI, SpecificationVersion specVersion, boolean useDefaults, boolean nullableSupport, RegexpFactory regexpFactory) { this.schemaClient = requireNonNull(schemaClient, "schemaClient cannot be null"); - this.formatValidators = requireNonNull(formatValidators, "formatValidators cannot be null"); + this.providerValidators = requireNonNull(providerValidators, "providerValidators cannot be null"); if (schemasByURI == null) { this.schemasByURI = new HashMap<>(); } else { @@ -71,7 +73,7 @@ SchemaLoader.SchemaLoaderBuilder initLoader() { .useDefaults(this.useDefaults) .regexpFactory(this.regexpFactory) .nullableSupport(this.nullableSupport) - .formatValidators(new HashMap<>(this.formatValidators)); + .formatValidators(new HashMap<>(this.providerValidators.getFormatValidators())); loaderBuilder.schemasByURI = schemasByURI; if (DRAFT_6.equals(specVersion)) { loaderBuilder.draftV6Support(); diff --git a/core/src/main/java/org/everit/json/schema/loader/ProviderValidators.java b/core/src/main/java/org/everit/json/schema/loader/ProviderValidators.java new file mode 100644 index 000000000..0d2973bfc --- /dev/null +++ b/core/src/main/java/org/everit/json/schema/loader/ProviderValidators.java @@ -0,0 +1,56 @@ +package org.everit.json.schema.loader; + +import org.everit.json.schema.FormatValidator; +import java.util.Map; + +/** + * Interface for the provider of validators used in Schema + */ +public interface ProviderValidators { + + /** + * Return a FormatValidator with a name + * + * @param formatName Name of the FormatValidator + * @return + */ + FormatValidator getFormatValidator(String formatName); + + /** + * Add a FormatValidator with a name + * + * @param formatName Name of the FormatValidator + * @param formatValidator The FormatValidator to add + */ + void addFormatValidator(String formatName, FormatValidator formatValidator); + + /** + * Add a FormatValidator with a name if is or is not present + * + * @param formatName Name of the FormatValidator + * @param formatValidator The FormatValidator to add + * @param addIfAbsent If true, the FormatValidator can add on map + */ + void addFormatValidator(String formatName, FormatValidator formatValidator, boolean addIfAbsent); + + /** + * Add a map of FormatValidator to the base map + * + * @param formatValidators All the FormatValidator to add on a base map + */ + void addAllFormatValidators(Map formatValidators); + + /** + * Initialize the map of FormatValidator + * + * @param formatValidators the map of FormatValidator + */ + void initAllFormatValidators(Map formatValidators); + + /** + * Return all the validators + * + * @return The map of all Validators + */ + Map getFormatValidators(); +} diff --git a/core/src/main/java/org/everit/json/schema/loader/SchemaExtractor.java b/core/src/main/java/org/everit/json/schema/loader/SchemaExtractor.java index 8bd604163..c1add7d08 100644 --- a/core/src/main/java/org/everit/json/schema/loader/SchemaExtractor.java +++ b/core/src/main/java/org/everit/json/schema/loader/SchemaExtractor.java @@ -156,7 +156,7 @@ NumberSchema.Builder buildNumberSchema() { StringSchema.Builder buildStringSchema() { PropertySnifferSchemaExtractor.STRING_SCHEMA_PROPS.forEach(consumedKeys::keyConsumed); - return new StringSchemaLoader(schemaJson.ls, config().formatValidators).load(); + return new StringSchemaLoader(schemaJson.ls, config().providerValidators).load(); } abstract List> extract(); 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 17090aa78..868ba3067 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 @@ -27,6 +27,7 @@ import org.everit.json.schema.SchemaException; import org.everit.json.schema.SchemaLocation; import org.everit.json.schema.TrueSchema; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.everit.json.schema.loader.internal.WrappingFormatValidator; import org.everit.json.schema.regexp.JavaUtilRegexpFactory; @@ -61,7 +62,8 @@ public static class SchemaLoaderBuilder { SchemaLocation pointerToCurrentObj = SchemaLocation.empty(); - Map formatValidators = new HashMap<>(); + //Map formatValidators = new HashMap<>(); + ProviderValidators providerValidators = new DefaultProviderValidators(); SpecificationVersion specVersion; @@ -81,6 +83,11 @@ public SchemaLoaderBuilder() { setSpecVersion(DRAFT_4); } + public SchemaLoaderBuilder(final ProviderValidators providerValidators) { + setSpecVersion(DRAFT_4); + this.providerValidators = providerValidators; + } + /** * Registers a format validator with the name returned by {@link FormatValidator#formatName()}. * @@ -89,7 +96,7 @@ public SchemaLoaderBuilder() { * @return {@code this} */ public SchemaLoaderBuilder addFormatValidator(FormatValidator formatValidator) { - formatValidators.put(formatValidator.formatName(), formatValidator); + providerValidators.addFormatValidator(formatValidator.formatName(), formatValidator); return this; } @@ -106,9 +113,9 @@ public SchemaLoaderBuilder addFormatValidator(FormatValidator formatValidator) { public SchemaLoaderBuilder addFormatValidator(String formatName, final FormatValidator formatValidator) { if (!Objects.equals(formatName, formatValidator.formatName())) { - formatValidators.put(formatName, new WrappingFormatValidator(formatName, formatValidator)); + providerValidators.addFormatValidator(formatName, new WrappingFormatValidator(formatName, formatValidator)); } else { - formatValidators.put(formatName, formatValidator); + providerValidators.addFormatValidator(formatName, formatValidator); } return this; } @@ -154,10 +161,10 @@ private void addBuiltInFormatValidators() { if (enableOverrideOfBuiltInFormatValidators) { for (Entry entry : defaultFormatValidators.entrySet()) { - formatValidators.putIfAbsent(entry.getKey(), entry.getValue()); + providerValidators.addFormatValidator(entry.getKey(), entry.getValue(), true); } } else { - formatValidators.putAll(defaultFormatValidators); + providerValidators.addAllFormatValidators(defaultFormatValidators); } } @Deprecated @@ -229,7 +236,7 @@ public SchemaLoaderBuilder schemaJson(Object schema) { } SchemaLoaderBuilder formatValidators(Map formatValidators) { - this.formatValidators = formatValidators; + this.providerValidators.initAllFormatValidators(formatValidators); return this; } @@ -279,6 +286,10 @@ public static SchemaLoaderBuilder builder() { return new SchemaLoaderBuilder(); } + public static SchemaLoaderBuilder builder(ProviderValidators providerValidators) { + return new SchemaLoaderBuilder(providerValidators); + } + /** * Loads a JSON schema to a schema validator using a {@link DefaultSchemaClient default HTTP * client}. @@ -342,7 +353,8 @@ public SchemaLoader(SchemaLoaderBuilder builder) { specVersion = builder.specVersion; } this.config = new LoaderConfig(builder.schemaClient, - builder.formatValidators, + //builder.formatValidators, + builder.providerValidators, builder.schemasByURI, specVersion, builder.useDefaults, @@ -477,7 +489,7 @@ SpecificationVersion specVersion() { */ @Deprecated Optional getFormatValidator(String formatName) { - return Optional.ofNullable(config.formatValidators.get(formatName)); + return Optional.ofNullable(config.providerValidators.getFormatValidator(formatName)); } } 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 bbc003616..d33ba7280 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 @@ -8,6 +8,7 @@ import org.everit.json.schema.FormatValidator; import org.everit.json.schema.StringSchema; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; /** * @author erosb @@ -16,21 +17,22 @@ public class StringSchemaLoader { private LoadingState ls; - private Map formatValidators; + //private Map formatValidators; + private ProviderValidators providerValidators; /** * Creates an instance with {@link SpecificationVersion#defaultFormatValidators()} draft v4 format validators}. * - * @deprecated explicitly specify the format validators with {@link #StringSchemaLoader(LoadingState, Map)} instead + * @deprecated explicitly specify the format validators with {@link #StringSchemaLoader(LoadingState, ProviderValidators)} instead */ @Deprecated public StringSchemaLoader(LoadingState ls) { - this(ls, DRAFT_4.defaultFormatValidators()); + this(ls, new DefaultProviderValidators(DRAFT_4.defaultFormatValidators())); } - StringSchemaLoader(LoadingState ls, Map formatValidators) { + StringSchemaLoader(LoadingState ls, ProviderValidators providerValidators) { this.ls = requireNonNull(ls, "ls cannot be null"); - this.formatValidators = unmodifiableMap(requireNonNull(formatValidators, "formatValidators cannot be null")); + this.providerValidators = requireNonNull(providerValidators, "providerValidators cannot be null"); } public StringSchema.Builder load() { @@ -46,7 +48,7 @@ public StringSchema.Builder load() { } private void addFormatValidator(StringSchema.Builder builder, String formatName) { - FormatValidator formatValidator = formatValidators.get(formatName); + FormatValidator formatValidator = providerValidators.getFormatValidator(formatName); if (formatValidator != null) { builder.formatValidator(formatValidator); } diff --git a/core/src/main/java/org/everit/json/schema/loader/internal/DefaultProviderValidators.java b/core/src/main/java/org/everit/json/schema/loader/internal/DefaultProviderValidators.java new file mode 100644 index 000000000..3b8f6e77b --- /dev/null +++ b/core/src/main/java/org/everit/json/schema/loader/internal/DefaultProviderValidators.java @@ -0,0 +1,57 @@ +package org.everit.json.schema.loader.internal; + +import org.everit.json.schema.FormatValidator; +import org.everit.json.schema.loader.ProviderValidators; +import org.everit.json.schema.loader.SchemaClient; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +/** + * The Default {@link ProviderValidators} implementation which useful for collect all default and custom validators + */ +public class DefaultProviderValidators implements ProviderValidators { + + Map formatValidators = new HashMap<>(); + + public DefaultProviderValidators() { } + + public DefaultProviderValidators(Map formatValidators) { + this.initAllFormatValidators(formatValidators); + } + + @Override + public FormatValidator getFormatValidator(String formatName) { + return this.formatValidators.get(formatName); + } + + @Override + public void addFormatValidator(String formatName, FormatValidator formatValidator) { + this.formatValidators.put(formatName, formatValidator); + } + + @Override + public void addFormatValidator(String formatName, FormatValidator formatValidator, boolean addIfAbsent) { + if (addIfAbsent) { + this.formatValidators.putIfAbsent(formatName, formatValidator); + } else { + this.addFormatValidator(formatName, formatValidator); + } + } + + @Override + public void addAllFormatValidators(Map formatValidators) { + this.formatValidators.putAll(formatValidators); + } + + @Override + public void initAllFormatValidators(Map formatValidators) { + this.formatValidators = formatValidators; + } + + @Override + public Map getFormatValidators() { + return formatValidators; + } +} diff --git a/core/src/test/java/org/everit/json/schema/loader/JsonPointerEvaluatorTest.java b/core/src/test/java/org/everit/json/schema/loader/JsonPointerEvaluatorTest.java index b33c26287..86f7eaa7b 100644 --- a/core/src/test/java/org/everit/json/schema/loader/JsonPointerEvaluatorTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/JsonPointerEvaluatorTest.java @@ -20,6 +20,7 @@ import org.everit.json.schema.ResourceLoader; import org.everit.json.schema.SchemaException; import org.everit.json.schema.SchemaLocation; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.json.JSONObject; import org.junit.Test; @@ -71,7 +72,7 @@ public void escaping() { } private LoadingState createLoadingState(SchemaClient schemaClient, String ref) { - LoaderConfig config = new LoaderConfig(schemaClient, emptyMap(), SpecificationVersion.DRAFT_4, false); + LoaderConfig config = new LoaderConfig(schemaClient, new DefaultProviderValidators(), SpecificationVersion.DRAFT_4, false); URI parentScopeId = null; Object rootSchemaJson = this.rootSchemaJson; HashMap schemaJson = new HashMap<>(); diff --git a/core/src/test/java/org/everit/json/schema/loader/JsonValueTest.java b/core/src/test/java/org/everit/json/schema/loader/JsonValueTest.java index e5d312947..d9720c59b 100644 --- a/core/src/test/java/org/everit/json/schema/loader/JsonValueTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/JsonValueTest.java @@ -21,6 +21,7 @@ import org.everit.json.schema.SchemaException; import org.everit.json.schema.SchemaLocation; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.json.JSONArray; import org.json.JSONObject; @@ -39,13 +40,13 @@ public class JsonValueTest { static final JsonValue asV6Value(Object o) { - LoaderConfig v6Config = new LoaderConfig(new DefaultSchemaClient(), emptyMap(), SpecificationVersion.DRAFT_6, false); + LoaderConfig v6Config = new LoaderConfig(new DefaultSchemaClient(), new DefaultProviderValidators(), SpecificationVersion.DRAFT_6, false); LoadingState ls = new LoadingState(v6Config, emptyMap(), JsonValue.of(o), JsonValue.of(o), null, SchemaLocation.empty()); return ls.schemaJson; } static final JsonValue withLs(Object o) { - LoaderConfig v4Config = new LoaderConfig(new DefaultSchemaClient(), emptyMap(), SpecificationVersion.DRAFT_4, false); + LoaderConfig v4Config = new LoaderConfig(new DefaultSchemaClient(), new DefaultProviderValidators(), SpecificationVersion.DRAFT_4, false); LoadingState ls = new LoadingState(v4Config, new HashMap<>(), o, o, null, SchemaLocation.empty()); return ls.schemaJson; } diff --git a/core/src/test/java/org/everit/json/schema/loader/LoadingStateTest.java b/core/src/test/java/org/everit/json/schema/loader/LoadingStateTest.java index 221377cb8..84d9a54af 100644 --- a/core/src/test/java/org/everit/json/schema/loader/LoadingStateTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/LoadingStateTest.java @@ -16,6 +16,7 @@ import org.everit.json.schema.Schema; import org.everit.json.schema.SchemaException; import org.everit.json.schema.SchemaLocation; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.json.JSONPointer; import org.junit.Test; @@ -25,7 +26,7 @@ */ public class LoadingStateTest { - private static final LoaderConfig CONFIG = new LoaderConfig(new DefaultSchemaClient(), emptyMap(), SpecificationVersion.DRAFT_4, false); + private static final LoaderConfig CONFIG = new LoaderConfig(new DefaultSchemaClient(),new DefaultProviderValidators(), SpecificationVersion.DRAFT_4, false); private LoadingState emptySubject() { return new LoadingState(CONFIG, emptyMap(), new HashMap<>(), diff --git a/core/src/test/java/org/everit/json/schema/loader/ReferenceLookupTest.java b/core/src/test/java/org/everit/json/schema/loader/ReferenceLookupTest.java index 40dbc6454..c6965e675 100644 --- a/core/src/test/java/org/everit/json/schema/loader/ReferenceLookupTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/ReferenceLookupTest.java @@ -18,6 +18,7 @@ import org.everit.json.schema.ResourceLoader; import org.everit.json.schema.Schema; import org.everit.json.schema.SchemaLocation; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; @@ -64,7 +65,7 @@ public void sameDocumentLookup() { } private JsonValue query(String pointer) { - LoadingState rootLs = new LoadingState(new LoaderConfig(schemaClient, emptyMap(), SpecificationVersion.DRAFT_6, false), + LoadingState rootLs = new LoadingState(new LoaderConfig(schemaClient, new DefaultProviderValidators(), SpecificationVersion.DRAFT_6, false), new HashMap<>(), rootSchemaJson, rootSchemaJson, 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 0828568f0..46cd144e7 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 @@ -28,26 +28,7 @@ import java.util.Map; import java.util.Optional; -import org.everit.json.schema.ArraySchema; -import org.everit.json.schema.BooleanSchema; -import org.everit.json.schema.CombinedSchema; -import org.everit.json.schema.ConditionalSchema; -import org.everit.json.schema.ConstSchema; -import org.everit.json.schema.EmptySchema; -import org.everit.json.schema.EnumSchema; -import org.everit.json.schema.FalseSchema; -import org.everit.json.schema.NotSchema; -import org.everit.json.schema.NullSchema; -import org.everit.json.schema.NumberSchema; -import org.everit.json.schema.ObjectSchema; -import org.everit.json.schema.ReferenceSchema; -import org.everit.json.schema.ResourceLoader; -import org.everit.json.schema.Schema; -import org.everit.json.schema.SchemaException; -import org.everit.json.schema.SchemaLocation; -import org.everit.json.schema.StringSchema; -import org.everit.json.schema.TestSupport; -import org.everit.json.schema.TrueSchema; +import org.everit.json.schema.*; import org.everit.json.schema.internal.DateTimeFormatValidator; import org.everit.json.schema.internal.EmailFormatValidator; import org.everit.json.schema.internal.HostnameFormatValidator; @@ -55,6 +36,7 @@ import org.everit.json.schema.internal.IPV6Validator; import org.everit.json.schema.internal.URIV4FormatValidator; import org.everit.json.schema.loader.SchemaLoader.SchemaLoaderBuilder; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.json.JSONArray; import org.json.JSONObject; @@ -63,6 +45,10 @@ import org.junit.Ignore; import org.junit.Test; +import javax.script.ScriptEngineManager; +import javax.script.ScriptEngine; +import javax.script.ScriptException; + import com.google.common.collect.ImmutableMap; public class SchemaLoaderTest { @@ -123,6 +109,14 @@ public void customFormat() { TestSupport.expectFailure(subject, "asd"); } + @Test + public void dynamicFormat() { + Schema subject = SchemaLoader.builder(new ExampleDefaultProviderValidators()) + .schemaJson(get("dynamicFormat")) + .build().load().build(); + TestSupport.expectFailure(subject, "6"); + } + @Test public void emptyPatternProperties() { ObjectSchema actual = (ObjectSchema) SchemaLoader.load(get("emptyPatternProperties")); @@ -521,7 +515,7 @@ public void constLoadingV4() { public void automaticSchemaVersionRecognition() { SchemaLoaderBuilder builder = SchemaLoader.builder(); SchemaLoader loader = builder.schemaJson(get("explicitSchemaVersion")).build(); - assertEquals(DRAFT_6.defaultFormatValidators(), builder.formatValidators); + assertEquals(DRAFT_6.defaultFormatValidators(), builder.providerValidators.getFormatValidators()); assertEquals(DRAFT_6, loader.specVersion()); } @@ -825,4 +819,52 @@ public void explicitlySetResolutionScope_isMappedToSchemaLocation() throws URISy assertEquals(new SchemaLocation(new URI("http://example.org"), emptyList()), actual.getLocation()); } + + private class ExampleDefaultProviderValidators extends DefaultProviderValidators { + @Override + public FormatValidator getFormatValidator(String formatName) { + + if (!this.getFormatValidators().containsKey(formatName) + && formatName.startsWith("javascript:")) { + String script = formatName.substring(formatName.lastIndexOf("javascript:"),formatName.length()); + this.addFormatValidator(formatName, new JavascriptFormatValidator(formatName, script)); + } + return super.getFormatValidator(formatName); + } + } + + private class JavascriptFormatValidator implements FormatValidator { + + String script; + String formatName; + + public JavascriptFormatValidator(String formatName, String script) { + this.formatName = formatName; + this.script = script; + } + + @Override + public Optional validate(String subject) { + + ScriptEngine javaScriptEngine = new ScriptEngineManager().getEngineByName("js"); + javaScriptEngine.put("subject",subject); + try { + Boolean result = (Boolean) javaScriptEngine.eval(script); + if (!result) { + return Optional.of(String.format("the length of string [%s] is not equal 5", subject)); + } + } catch (ScriptException e) { + e.printStackTrace(); + return Optional.of(String.format("Error on evalutation of [%s] ", subject)); + } + return Optional.empty(); + } + + @Override + public String formatName() { + return formatName; + } + } + + } diff --git a/core/src/test/java/org/everit/json/schema/loader/SubschemaRegistryTest.java b/core/src/test/java/org/everit/json/schema/loader/SubschemaRegistryTest.java index 594ef632b..f0529d26a 100644 --- a/core/src/test/java/org/everit/json/schema/loader/SubschemaRegistryTest.java +++ b/core/src/test/java/org/everit/json/schema/loader/SubschemaRegistryTest.java @@ -6,12 +6,13 @@ import org.everit.json.schema.ResourceLoader; import org.everit.json.schema.SchemaLocation; +import org.everit.json.schema.loader.internal.DefaultProviderValidators; import org.everit.json.schema.loader.internal.DefaultSchemaClient; import org.junit.Test; public class SubschemaRegistryTest { - static final LoaderConfig CONFIG = new LoaderConfig(new DefaultSchemaClient(), emptyMap(), SpecificationVersion.DRAFT_6, false); + static final LoaderConfig CONFIG = new LoaderConfig(new DefaultSchemaClient(), new DefaultProviderValidators(), SpecificationVersion.DRAFT_6, false); @Test public void emptySchemaContainsNoElems() { diff --git a/core/src/test/resources/org/everit/jsonvalidator/testschemas.json b/core/src/test/resources/org/everit/jsonvalidator/testschemas.json index c2209affb..245845da9 100644 --- a/core/src/test/resources/org/everit/jsonvalidator/testschemas.json +++ b/core/src/test/resources/org/everit/jsonvalidator/testschemas.json @@ -38,6 +38,9 @@ "customFormat": { "format": "custom" }, + "dynamicFormat": { + "format": "javascript: subject == 5" + }, "unknown": { "type": "unknown" },