com.github.fge.jsonschema.main.JsonValidator Maven / Gradle / Ivy
/*
* Copyright (c) 2014, Francis Galiegue ([email protected])
*
* This software is dual-licensed under:
*
* - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
* later version;
* - the Apache Software License (ASL) version 2.0.
*
* The text of this file and of both licenses is available at the root of this
* project or, if you have the jar distribution, in directory META-INF/, under
* the names LGPL-3.0.txt and ASL-2.0.txt respectively.
*
* Direct link to the sources:
*
* - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
* - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
*/
package com.github.fge.jsonschema.main;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jsonschema.core.exceptions.JsonReferenceException;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.load.SchemaLoader;
import com.github.fge.jsonschema.core.messages.JsonSchemaCoreMessageBundle;
import com.github.fge.jsonschema.core.processing.ProcessingResult;
import com.github.fge.jsonschema.core.processing.Processor;
import com.github.fge.jsonschema.core.ref.JsonRef;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.core.report.ReportProvider;
import com.github.fge.jsonschema.core.tree.JsonTree;
import com.github.fge.jsonschema.core.tree.SchemaTree;
import com.github.fge.jsonschema.core.tree.SimpleJsonTree;
import com.github.fge.jsonschema.processors.data.FullData;
import com.github.fge.jsonschema.processors.validation.ValidationProcessor;
import com.github.fge.msgsimple.bundle.MessageBundle;
import com.github.fge.msgsimple.load.MessageBundles;
import javax.annotation.concurrent.Immutable;
/**
* A generic schema/instance validator
*
* One such instance exists per {@link JsonSchemaFactory}. In fact, you have
* to go through a factory to obtain an instance.
*
* This class is also responsible for building {@link JsonSchema} instances.
*
*
* @see JsonSchemaFactory#getValidator()
*/
@Immutable
public final class JsonValidator
{
private static final MessageBundle BUNDLE
= MessageBundles.getBundle(JsonSchemaCoreMessageBundle.class);
private final SchemaLoader loader;
private final ValidationProcessor processor;
private final ReportProvider reportProvider;
/**
* Package private (and only) constructor
*
* @param loader the schema loader
* @param processor the validation processor
* @param reportProvider the report provider
*/
JsonValidator(final SchemaLoader loader,
final ValidationProcessor processor,
final ReportProvider reportProvider)
{
this.loader = loader;
this.processor = processor;
this.reportProvider = reportProvider;
}
/**
* Validate a schema/instance pair
*
* The third boolean argument instructs the validator as to whether it
* should validate children even if the container (array or object) fails
* to validate.
*
* @param schema the schema
* @param instance the instance
* @param deepCheck see description
* @return a validation report
* @throws ProcessingException an exception occurred during validation
* @throws NullPointerException the schema or instance is null
*
* @since 2.1.8
*/
public ProcessingReport validate(final JsonNode schema,
final JsonNode instance, final boolean deepCheck)
throws ProcessingException
{
final ProcessingReport report = reportProvider.newReport();
final FullData data = buildData(schema, instance, deepCheck);
return ProcessingResult.of(processor, report, data).getReport();
}
/**
* Validate a schema/instance pair, "fast" version
*
* This calls {@link #validate(JsonNode, JsonNode, boolean)} with {@code
* false} as the third argument.
*
* @param schema the schema
* @param instance the instance
* @return a validation report
* @throws ProcessingException an exception occurred during validation
* @throws NullPointerException the schema or instance is null
*/
public ProcessingReport validate(final JsonNode schema,
final JsonNode instance)
throws ProcessingException
{
return validate(schema, instance, false);
}
/**
* Validate a schema/instance pair (unchecked mode)
*
* The third boolean argument instructs the validator as to whether it
* should validate children even if the container (array or object) fails
* to validate.
*
* The same warnings as described in {@link
* JsonSchema#validateUnchecked(JsonNode)} apply
*
* @param schema the schema
* @param instance the instance
* @param deepCheck see description
* @return a validation report
* @throws NullPointerException the schema or instance is null
*
* @since 2.1.8
*/
public ProcessingReport validateUnchecked(final JsonNode schema,
final JsonNode instance, final boolean deepCheck)
{
final ProcessingReport report = reportProvider.newReport();
final FullData data = buildData(schema, instance, deepCheck);
return ProcessingResult.uncheckedResult(processor, report, data)
.getReport();
}
/**
* Validate a schema/instance pair (unchecked mode), "fast" version
*
* This calls {@link #validateUnchecked(JsonNode, JsonNode, boolean)}
* with {@code false} as a third argument.
*
* The same warnings as described in {@link
* JsonSchema#validateUnchecked(JsonNode)} apply
*
* @param schema the schema
* @param instance the instance
* @return a validation report
* @throws NullPointerException the schema or instance is null
*/
public ProcessingReport validateUnchecked(final JsonNode schema,
final JsonNode instance)
{
return validateUnchecked(schema, instance, false);
}
/**
* Build a {@link JsonSchema} instance
*
* @param schema the schema
* @param pointer the pointer into the schema
* @return a new {@link JsonSchema}
* @throws ProcessingException resolving the pointer against the schema
* leads to a {@link MissingNode}
* @throws NullPointerException the schema or pointer is null
*/
JsonSchema buildJsonSchema(final JsonNode schema, final JsonPointer pointer)
throws ProcessingException
{
final SchemaTree tree = loader.load(schema).setPointer(pointer);
if (tree.getNode().isMissingNode())
throw new JsonReferenceException(new ProcessingMessage()
.setMessage(BUNDLE.getMessage("danglingRef")));
return new JsonSchema(processor, tree, reportProvider);
}
/**
* Build a {@link JsonSchema} instance
*
* @param uri the URI to load the schema from
* @return a {@link JsonSchema}
* @throws ProcessingException invalid URI, or URI did not resolve to a
* JSON Schema
* @throws NullPointerException URI is null
*/
JsonSchema buildJsonSchema(final String uri)
throws ProcessingException
{
final JsonRef ref = JsonRef.fromString(uri);
if (!ref.isLegal())
throw new JsonReferenceException(new ProcessingMessage()
.setMessage(BUNDLE.getMessage("illegalJsonRef")));
final SchemaTree tree
= loader.get(ref.getLocator()).setPointer(ref.getPointer());
if (tree.getNode().isMissingNode())
throw new JsonReferenceException(new ProcessingMessage()
.setMessage(BUNDLE.getMessage("danglingRef")));
return new JsonSchema(processor, tree, reportProvider);
}
/**
* Get the raw processor for this validator (package private)
*
* @return the processor (a {@link ValidationProcessor}
*/
Processor getProcessor()
{
return processor;
}
private FullData buildData(final JsonNode schema, final JsonNode instance,
final boolean deepCheck)
{
BUNDLE.checkNotNull(schema, "nullSchema");
BUNDLE.checkNotNull(instance, "nullInstance");
final SchemaTree schemaTree = loader.load(schema);
final JsonTree tree = new SimpleJsonTree(instance);
return new FullData(schemaTree, tree, deepCheck);
}
}