Skip to content

Commit

Permalink
get default locator from reader method
Browse files Browse the repository at this point in the history
  • Loading branch information
redmitry committed Oct 23, 2024
1 parent 5bd0eac commit fce4e30
Show file tree
Hide file tree
Showing 25 changed files with 241 additions and 40 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import via maven:
<dependency>
<groupId>es.elixir.bsc.json.schema</groupId>
<artifactId>jaronuinga</artifactId>
<version>0.5.5</version>
<version>0.5.6</version>
</dependency>
...
<repositories>
Expand All @@ -24,7 +24,7 @@ import via maven:
The simplest usage:
```java
JsonSchema schema = JsonSchemaReader.getReader().read(url); // parse JsonSchema from the URL location
List<ValidationError> errors = new ArrayList<>(); // array to collect errors
List<ValidationError> errors = new ArrayList(); // array to collect errors
schema.validate(json, errors); // validate JsonObject
```
Note that instead of URL users could provide their own schema locators.
Expand All @@ -34,7 +34,7 @@ to resolve "$ref" Json Pointers.
To provide flexibility it is possible to get callbacks during the validation process.
```java
schema.validate(json, errors, (
PrimitiveSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
JsonSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
});
```
Here above we have:
Expand All @@ -44,19 +44,19 @@ Here above we have:
- parent - a parent of currently validating Json value
- err - collected validation errors so far

Note, that providing ExtendedJsonSchemaLocator (which collects all subschemas as originated jsons), we can
associate validated JsonValue with corresponding Json Object which describes the schema:
```java
JsonSchema schema = JsonSchemaReader.getReader().read(locator);
JsonSchemaReader reader = JsonSchemaReader.getReader();
JsonSchemaLocator locator = reader.getJsonSchemaLocator(uri);
JsonSchema schema = reader.read(locator);
schema.validate(json, errors, (
PrimitiveSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
JsonSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
JsonObject subschemaJsonObject = locator.getSchema(subschema.getId(), subschema.getJsonPointer());
});
```
We can also stop further parsing on error via the callback:
```java
schema.validate(json, errors, (
PrimitiveSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
JsonSchema subschema, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
throw new ValidationException(new ValidationError(subschema.getId(), subschema.getJsonPointer(), ""));
});
```
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

<groupId>es.elixir.bsc.json.schema</groupId>
<artifactId>jaronuinga</artifactId>
<version>0.5.5</version>
<version>0.5.6</version>
<packaging>jar</packaging>

<organization>
Expand Down
60 changes: 55 additions & 5 deletions src/main/java/es/elixir/bsc/json/schema/JsonSchemaReader.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* *****************************************************************************
* Copyright (C) 2023 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
Expand All @@ -26,6 +26,7 @@
package es.elixir.bsc.json.schema;

import es.elixir.bsc.json.schema.model.JsonSchema;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.Iterator;
Expand All @@ -39,21 +40,70 @@
public interface JsonSchemaReader {

/**
* Read JSON Schema located by the provided URL.
* The reader uses a new instance of JsonSchemaLocator.
*
* @param url the URL to read Json Schema from.
* @param url the URL to read a JSON Schema from.
* @return parsed JsonSchema object
*
* @throws JsonSchemaException
*/
JsonSchema read(URL url) throws JsonSchemaException;

/**
* Read JSON Schema located by the provided JsonSchemaLocator.
* This allows reuse the same JsonSchemaLocator instance between calls.
*
* @param locator JsonSchemaLocator to locate parsed JSON Schema.
* @return parsed JsonSchema object
*
* @throws JsonSchemaException
*/
JsonSchema read(JsonSchemaLocator locator) throws JsonSchemaException;

/**
* Creates new instance of default implementation of the JsonSchemaLocator.
*
* @param uri the JSON Schema location URI
*
* @return JsonSchemaLocator
*/
JsonSchemaLocator getJsonSchemaLocator(URI uri);

/**
* Set configuration property for this JsonSchemaReader.
*
* @param name configuration property name
* @param property configuration property value
*/
void setJsonSchemaParserProperty(String name, Object property);

public static JsonSchemaReader getReader() {

/**
* Create JsonSchemaReader with no configuration parameters.
*
* @return new instance of the JsonSchemaReader
*/
static JsonSchemaReader getReader() {
return getReader(Collections.EMPTY_MAP);
}

public static JsonSchemaReader getReader(Map<String, Object> config) {
/**
* Create JsonSchemaReader with provided configuration properties.
*
* <pre>
* example:
* {@code
* JsonSchemaParserConfig config =
* new JsonSchemaParserConfig()
* .setJsonSchemaVersion(JsonSchemaVersion.SCHEMA_DRAFT_2020_12);
* JsonSchemaReader reader = JsonSchemaReader.getReader(config);
* }</pre>
*
* @param config the map of configuration properties
*
* @return new instance of the JsonSchemaReader
*/
static JsonSchemaReader getReader(Map<String, Object> config) {
ServiceLoader<JsonSchemaReader> loader = ServiceLoader.load(JsonSchemaReader.class);
Iterator<JsonSchemaReader> iterator = loader.iterator();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* *****************************************************************************
* Copyright (C) 2022 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
Expand All @@ -25,7 +25,7 @@

package es.elixir.bsc.json.schema;

import es.elixir.bsc.json.schema.model.PrimitiveSchema;
import es.elixir.bsc.json.schema.model.JsonSchema;
import java.util.List;

/**
Expand All @@ -39,8 +39,11 @@
public interface JsonSchemaValidationCallback<T> {

/**
* Callback method called by the validator after the value is validated.Implementations may include custom validation errors into the errors list
or stop validation process by throwing the ValidationException.
* Callback method called by the validator after the value is validated.
* Implementations may include custom validation errors into the errors list
* or stop validation process by throwing the ValidationException.
* Note that validation errors not necessary mean the schema is invalid -
* this may be a part of evaluation of 'oneOf', for example.
*
* @param schema json schema model to validate json value.
* @param pointer json pointer to the validated value
Expand All @@ -50,5 +53,6 @@ public interface JsonSchemaValidationCallback<T> {
*
* @throws ValidationException the exception to be thrown by the validator.
*/
void validated(PrimitiveSchema schema, String pointer, T value, T parent, List<ValidationError> errors) throws ValidationException;
void validated(JsonSchema schema, String pointer, T value, T parent,
List<ValidationError> errors) throws ValidationException;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* *****************************************************************************
* Copyright (C) 2022 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
Expand Down Expand Up @@ -59,7 +59,7 @@ public class DefaultJsonSchemaLocator extends JsonSchemaLocator {
protected final Map<URI, JsonValue> schemas;

public DefaultJsonSchemaLocator(URI uri) {
this(uri, new HashMap<>());
this(uri, new HashMap());
}

protected DefaultJsonSchemaLocator(URI uri, Map<URI, JsonValue> schemas) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public AbstractJsonSchema parse(JsonSchemaLocator locator, AbstractJsonSchemaEle
String jsonPointer, JsonValue value, JsonType type)
throws JsonSchemaException {

// much easily catch 'invalid' root json pointer here than check for the '/' root in callers.
jsonPointer = jsonPointer.startsWith("//") ? jsonPointer.substring(1) : jsonPointer;

AbstractJsonSchema schema = cache.get(locator, jsonPointer);
if (schema != null) {
return schema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public void setJsonSchemaParserProperty(String name, Object property) {
properties.put(name, property);
}

@Override
public JsonSchemaLocator getJsonSchemaLocator(URI uri) {
return new DefaultJsonSchemaLocator(uri);
}

@Override
public JsonSchema read(URL url) throws JsonSchemaException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ public AbstractJsonSchemaElement(AbstractJsonSchemaElement parent,
JsonSchemaLocator locator, String jsonPointer) {

this.parent = parent;

this.locator = locator;
this.jsonPointer = jsonPointer.startsWith("//") ? jsonPointer.substring(1) : jsonPointer;
this.jsonPointer = jsonPointer;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public boolean validate(String jsonPointer, JsonValue value, JsonValue parent,

return nerrors == errors.size();
}

private void validate(String jsonPointer, BigDecimal dec, List<ValidationError> errors) {

if (minimum != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
package es.elixir.bsc.json.schema;

import es.elixir.bsc.json.schema.model.JsonSchema;
import es.elixir.bsc.json.schema.model.PrimitiveSchema;
import javax.json.Json;
import javax.json.JsonStructure;
import javax.json.JsonValue;
Expand Down Expand Up @@ -62,7 +61,8 @@ public void test_01() {

final AtomicInteger counter = new AtomicInteger();
List<ValidationError> errors = new ArrayList<>();
schema.validate(json, errors, (PrimitiveSchema model, String pointer, JsonValue value, JsonValue parent, List<ValidationError> err) -> {
schema.validate(json, errors, (JsonSchema model, String pointer,
JsonValue value, JsonValue parent, List<ValidationError> err) -> {
counter.incrementAndGet();
});

Expand Down
10 changes: 10 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft3/subSchemas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"definitions": {
"integer": {
"type": "integer"
},
"refToInteger": {
"$ref": "#/definitions/integer"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"definitions": {
"refToInteger": {
"$ref": "#foo"
},
"A": {
"id": "#foo",
"type": "integer"
}
}
}
15 changes: 15 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft4/name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"definitions": {
"orNull": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#"
}
]
}
},
"type": "string"
}
10 changes: 10 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft4/subSchemas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"definitions": {
"integer": {
"type": "integer"
},
"refToInteger": {
"$ref": "#/definitions/integer"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"definitions": {
"refToInteger": {
"$ref": "#foo"
},
"A": {
"$id": "#foo",
"type": "integer"
}
}
}
15 changes: 15 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft6/name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"definitions": {
"orNull": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#"
}
]
}
},
"type": "string"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$id": "http://localhost:1234/draft6/ref-and-definitions.json",
"definitions": {
"inner": {
"properties": {
"bar": { "type": "string" }
}
}
},
"allOf": [ { "$ref": "#/definitions/inner" } ]
}
10 changes: 10 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft6/subSchemas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"definitions": {
"integer": {
"type": "integer"
},
"refToInteger": {
"$ref": "#/definitions/integer"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"definitions": {
"refToInteger": {
"$ref": "#foo"
},
"A": {
"$id": "#foo",
"type": "integer"
}
}
}
15 changes: 15 additions & 0 deletions src/test/resources/json-schema-org/remotes/draft7/name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"definitions": {
"orNull": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#"
}
]
}
},
"type": "string"
}
Loading

0 comments on commit fce4e30

Please sign in to comment.