JsonSchemaLoader.java
package org.wikimedia.eventutilities.core.json;
import java.net.URI;
import java.util.concurrent.ConcurrentHashMap;
import org.wikimedia.eventutilities.core.util.ResourceLoader;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jsonschema.core.load.SchemaLoader;
/**
* Uses a {@link JsonLoader} to fetch JSON schemas from URIs and cache them.
* Usage:
*
* <pre>{@code
* JsonSchemaLoader schemaLoader = JsonSchemaLoader(schemaBaseURLs);
* JsonNode schema = schemaLoader.load("http://my.schemas.org/schemas/test/event/schema/0.0.2")
* }</pre>
*/
public class JsonSchemaLoader {
/**
* Cache of schema URI to JsonNode JSON schemas.
*/
private final ConcurrentHashMap<URI, com.fasterxml.jackson.databind.JsonNode> cache = new ConcurrentHashMap<>();
/**
* fge SchemaLoader, used to resolve JSON $ref pointers.
*/
private final SchemaLoader schemaLoader = new SchemaLoader();
/**
* Underlying JsonLoader.
*/
private final JsonLoader jsonLoader;
/**
* Make a new JsonSchemaLoader using {@link JsonLoader}.
*/
public JsonSchemaLoader(JsonLoader loader) {
this.jsonLoader = loader;
}
/**
* Creates a new JsonLoader using resourceLoader and uses that to create a new JsonSchemaLoader.
*/
public static JsonSchemaLoader build(ResourceLoader resourceLoader) {
return new JsonSchemaLoader(new JsonLoader(resourceLoader));
}
/**
* Given a schemaUri, this will request the JSON or YAML content at that URI and
* parse it into a JsonNode. $refs will be resolved.
* The compiled schema will be cached by schemaURI, and only looked up once per schemaURI.
*
* @return the jsonschema at schemaURI.
*/
public JsonNode load(URI schemaUri) throws JsonLoadingException {
if (this.cache.containsKey(schemaUri)) {
return this.cache.get(schemaUri);
}
// Use SchemaLoader so we resolve any JsonRefs in the JSONSchema.
JsonNode schema = this.schemaLoader.load(jsonLoader.load(schemaUri)).getBaseNode();
this.cache.put(schemaUri, schema);
return schema;
}
/**
* Parses the JSON or YAML string into a JsonNode.
* @param data JSON or YAML string to parse into a JsonNode.
*/
public JsonNode parse(String data) throws JsonLoadingException {
return jsonLoader.parse(data);
}
/**
* Proxy method to see if the schemaUri is currently cached.
*/
public boolean isCached(URI schemaUri) {
return this.cache.containsKey(schemaUri);
}
/**
* Proxy method to get a schema by schemaUri directly from the local cache.
*/
public JsonNode cacheGet(URI schemaUri) {
return this.cache.get(schemaUri);
}
/**
* Proxy method to put a schema by schemaUri directly in the local cache.
*/
public JsonNode cachePut(URI schemaUri, JsonNode schema) {
return this.cache.put(schemaUri, schema);
}
/**
* Return the underlying JsonLoader.
*/
public JsonLoader getJsonLoader() {
return jsonLoader;
}
}