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 4e4c0e9 commit 18be39b
Show file tree
Hide file tree
Showing 25 changed files with 264 additions and 57 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>jakarta.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(), ""));
});
```
42 changes: 24 additions & 18 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
~ and Barcelona Supercomputing Center (BSC)
~
~ 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.
-->
Copyright (C) 2024 Spanish National Bioinformatics Institute (INB) and
Barcelona Supercomputing Center
Modifications to the initial code base are copyright of their respective
authors, or their employers as appropriate.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
Expand All @@ -24,7 +30,7 @@

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

<organization>
Expand All @@ -51,7 +57,7 @@
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<jakarta.json.version>2.1.0</jakarta.json.version>
<jakarta.json.version>2.1.3</jakarta.json.version>
</properties>

<dependencies>
Expand All @@ -70,7 +76,7 @@
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>jakarta.json</artifactId>
<version>1.1.3</version>
<version>1.1.7</version>
<scope>test</scope>
</dependency>
</dependencies>
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 jakarta.json.Json;
import jakarta.json.JsonStructure;
import jakarta.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"
}
}
}
Loading

0 comments on commit 18be39b

Please sign in to comment.