All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fge.jsonschema.main.JsonSchemaFactory Maven / Gradle / Ivy

There is a newer version: 2.2.6
Show newest version
/*
 * Copyright (c) 2012, Francis Galiegue 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Lesser GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * Lesser GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

package com.github.fge.jsonschema.main;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.github.fge.jsonschema.metaschema.BuiltinSchemas;
import com.github.fge.jsonschema.metaschema.KeywordRegistry;
import com.github.fge.jsonschema.metaschema.MetaSchema;
import com.github.fge.jsonschema.metaschema.SchemaURIs;
import com.github.fge.jsonschema.ref.JsonFragment;
import com.github.fge.jsonschema.ref.JsonPointer;
import com.github.fge.jsonschema.ref.JsonRef;
import com.github.fge.jsonschema.schema.AddressingMode;
import com.github.fge.jsonschema.schema.SchemaBundle;
import com.github.fge.jsonschema.schema.SchemaContainer;
import com.github.fge.jsonschema.schema.SchemaNode;
import com.github.fge.jsonschema.schema.SchemaRegistry;
import com.github.fge.jsonschema.uri.URIDownloader;
import com.github.fge.jsonschema.uri.URIManager;
import com.github.fge.jsonschema.validator.JsonValidatorCache;

import java.net.URI;
import java.util.Map;

/**
 * Factory to build JSON Schema validating instances
 *
 * 

You can create a factory with all default settings using {@link * JsonSchemaFactory#defaultFactory()}. This is what you will do in the vast * majority of cases.

* *

If you want to customize it, you need to go through {@link * JsonSchemaFactory.Builder}.

* *

This class is thread safe and immutable.

* * @see JsonSchema * @see com.github.fge.jsonschema.examples */ public final class JsonSchemaFactory { /** * Schema registry */ private final SchemaRegistry registry; /** * Default schema URI */ private final JsonRef defaultSchemaURI; /** * Map of schema URIs and validator caches */ private final Map validatorCaches; /** * Build a factory with all default settings * * @return a schema factory instance */ public static JsonSchemaFactory defaultFactory() { return new Builder().build(); } public static Builder builder() { return new Builder(); } /** * Constructor, private by design * * @see JsonSchemaFactory.Builder * @param builder the builder */ private JsonSchemaFactory(final Builder builder) { registry = new SchemaRegistry(builder.uriManager, builder.namespace, builder.addressingMode); registry.addBundle(builder.bundle); defaultSchemaURI = builder.defaultSchemaURI; final ImmutableMap.Builder cacheBuilder = ImmutableMap.builder(); final Map map = builder.metaSchemas; JsonRef ref; JsonValidatorCache validatorCache; for (final Map.Entry entry: map.entrySet()) { ref = entry.getKey(); validatorCache = new JsonValidatorCache(entry.getValue(), registry); cacheBuilder.put(ref, validatorCache); } validatorCaches = cacheBuilder.build(); } /** * Create a schema instance from a JSON Schema, at a certain path * *

For instance, if you submit this schema:

* *
     *     {
     *         "schema1": { ... },
     *         "schema2": { ... }
     *     }
     * 
* *

then you can create a validator for {@code schema1} using:

* *
     *     final JsonSchema schema = factory.create(schema, "#/schema1");
     * 
* *

The path can be a {@link JsonPointer} as above, but also an id * reference.

* * @see JsonFragment * * @param schema the schema * @param path the pointer/id reference into the schema * @return a {@link JsonSchema} instance */ public JsonSchema fromSchema(final JsonNode schema, final String path) { final SchemaContainer container = registry.register(schema); final JsonNode subSchema = JsonFragment.fromFragment(path) .resolve(container.getSchema()); return createSchema(container, subSchema); } /** * Create a schema instance from a JSON Schema * *

This calls {@link #fromSchema(JsonNode, String)} with {@code ""} as * a path.

* * @param schema the schema * @return a {@link JsonSchema} instance */ public JsonSchema fromSchema(final JsonNode schema) { return fromSchema(schema, ""); } /** * Create a schema instance from a JSON Schema located at a given URI, and * at a given path * *

This allows you, for instance, to load a schema using HTTP. Or, in * fact, any other URI scheme that is supported.

* * @see URIManager * @see SchemaRegistry * * @param uri the URI * @param path the JSON Pointer/id reference into the downloaded schema * @return a {@link JsonSchema} instance * @throws JsonSchemaException unable to get content from that URI */ public JsonSchema fromURI(final URI uri, final String path) throws JsonSchemaException { final SchemaContainer container = registry.get(uri); final JsonNode subSchema = JsonFragment.fromFragment(path) .resolve(container.getSchema()); return createSchema(container, subSchema); } /** * Create a schema instance from a JSON Schema located at a given URI * * @see #fromSchema(JsonNode, String) * * @param uri the URI * @return a {@link JsonSchema} instance * @throws JsonSchemaException unable to get content from that URI */ public JsonSchema fromURI(final URI uri) throws JsonSchemaException { return fromURI(uri, ""); } /** * Create a schema instance from a JSON Schema located at a given URI * * @see URI#create(String) * @see #fromURI(URI, String) * * @param str the URI as a string * @return a {@link JsonSchema} instance * @throws JsonSchemaException unable to get content from that URI * @throws IllegalArgumentException URI is invalid */ public JsonSchema fromURI(final String str) throws JsonSchemaException { return fromURI(URI.create(str), ""); } /** * Create a schema instance from a JSON Schema located at a given URI and * at a given path * * @see URI#create(String) * @see #fromURI(URI, String) * * @param str the URI as a string * @param path the JSON Pointer/id reference into the downloaded schema * @return a {@link JsonSchema} instance * @throws JsonSchemaException unable to get content from that URI * @throws IllegalArgumentException URI is invalid */ public JsonSchema fromURI(final String str, final String path) throws JsonSchemaException { return fromURI(URI.create(str), path); } /** * Create a {@link JsonSchema} instance * * @param container the schema container * @param schema the subschema * @return a {@link JsonSchema} instance */ private JsonSchema createSchema(final SchemaContainer container, final JsonNode schema) { final SchemaNode schemaNode = new SchemaNode(container, schema); final JsonValidatorCache cache = getValidatorCache(container.getSchema()); return new JsonSchema(cache, schemaNode); } private JsonValidatorCache getValidatorCache(final JsonNode schema) { final JsonNode node = schema.path("$schema"); if (!node.isTextual()) return validatorCaches.get(defaultSchemaURI); JsonRef ref; try { ref = JsonRef.fromString(node.textValue()); if (!validatorCaches.containsKey(ref)) ref = defaultSchemaURI; } catch (JsonSchemaException ignored) { ref = defaultSchemaURI; } return validatorCaches.get(ref); } /** * Builder class for a {@link JsonSchemaFactory} */ public static final class Builder { /** * Addressing mode */ private AddressingMode addressingMode = AddressingMode.CANONICAL; /** * Default schema URI */ private JsonRef defaultSchemaURI = SchemaURIs.draftV3HyperSchema(); /** * Keyword registries */ private final Map metaSchemas; /** * The URI manager */ private final URIManager uriManager = new URIManager(); /** * The namespace */ private URI namespace = URI.create(""); /** * Schema bundle */ private final SchemaBundle bundle = new SchemaBundle(); /** * Constructor */ public Builder() { // Build keyword registries metaSchemas = Maps.newHashMap(); JsonRef ref; MetaSchema metaSchema; for (final BuiltinSchemas builtin: BuiltinSchemas.values()) { ref = JsonRef.fromURI(builtin.getURI()); metaSchema = MetaSchema.copyOf(builtin); metaSchemas.put(ref, metaSchema); } } /** * Register a {@link URIDownloader} for a given scheme * * @param scheme the URI scheme * @param downloader the downloader * @return the builder * @throws NullPointerException scheme is null * @throws IllegalArgumentException illegal scheme */ public Builder registerScheme(final String scheme, final URIDownloader downloader) { uriManager.registerScheme(scheme, downloader); return this; } /** * Unregister a scheme * * @param scheme the scheme to desupport * @return the builder */ public Builder unregisterScheme(final String scheme) { uriManager.unregisterScheme(scheme); return this; } /** * Sets the addressing mode for this factory * * @param addressingMode the addressing mode * @return the builder */ public Builder addressingMode(final AddressingMode addressingMode) { this.addressingMode = addressingMode; return this; } /** * Set the schema registry's namespace * * @see SchemaRegistry * * @param namespace the namespace, as a string * @return the builder * @throws IllegalArgumentException invalid URI (see {@link * URI#create(String)}) */ public Builder setNamespace(final String namespace) { this.namespace = URI.create(namespace); return this; } /** * Add an URI redirection * *

This allows you to add an alias for a schema location so that it * point to another of your choice. It may be useful if you have to * resolve absolute JSON References normally unreachable, but you have * a copy of this schema locally.

* *

Note that both URIs must be absolute.

* * @see JsonRef * * @param from the source URI, as a string * @param to the target URI, as a string * @return the builder * @throws IllegalArgumentException either {@code from} or {@code to} * is an invalid URI, or it is not an absolute JSON Reference */ public Builder addRedirection(final String from, final String to) { uriManager.addRedirection(from, to); return this; } /** * Add a keyword registry to the factory * * @param schemaURI the URI for the new registry * @param keywordRegistry the keyword registry * @param byDefault whether this registry will be the default * @return the builder * @throws NullPointerException the URI or registry are null * * @deprecated */ @Deprecated public Builder addKeywordRegistry(final JsonRef schemaURI, final KeywordRegistry keywordRegistry, final boolean byDefault) { Preconditions.checkNotNull(schemaURI, "schema URI cannot be null"); Preconditions.checkNotNull(keywordRegistry, "keyword registry cannot be null"); final MetaSchema metaSchema = MetaSchema.builder() .withURI(schemaURI.toString()) .addKeywordRegistry(keywordRegistry).build(); metaSchemas.put(schemaURI, metaSchema); if (byDefault) defaultSchemaURI = schemaURI; return this; } public Builder addMetaSchema(final MetaSchema metaSchema, final boolean byDefault) { final JsonRef dollarSchema = metaSchema.getDollarSchema(); metaSchemas.put(dollarSchema, metaSchema); if (byDefault) defaultSchemaURI = dollarSchema; return this; } /** * Register a schema * * @param uri the URI of this schema * @param schema the schema * @return the builder * * @see SchemaBundle#addSchema(URI, JsonNode) */ public Builder addSchema(final URI uri, final JsonNode schema) { bundle.addSchema(uri, schema); return this; } /** * Register a schema * * @param uri the URI of this schema * @param schema the schema * @return the builder * * @see SchemaBundle#addSchema(String, JsonNode) */ public Builder addSchema(final String uri, final JsonNode schema) { bundle.addSchema(uri, schema); return this; } /** * Build the factory * * @return the factory */ public JsonSchemaFactory build() { return new JsonSchemaFactory(this); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy