com.networknt.schema.ValidationMessage Maven / Gradle / Ivy
Show all versions of json-schema-validator Show documentation
/*
* Copyright (c) 2016 Network New Technologies Inc.
*
* 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.
*/
package com.networknt.schema;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.networknt.schema.i18n.MessageFormatter;
import com.networknt.schema.utils.CachingSupplier;
import com.networknt.schema.utils.StringUtils;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;
/**
* The output format.
*
* @see JSON
* Schema
*/
@JsonIgnoreProperties({ "messageSupplier", "schemaNode", "instanceNode", "valid" })
@JsonPropertyOrder({ "type", "code", "message", "instanceLocation", "property", "evaluationPath", "schemaLocation",
"messageKey", "arguments", "details" })
@JsonInclude(Include.NON_NULL)
public class ValidationMessage {
private final String type;
private final String code;
@JsonSerialize(using = ToStringSerializer.class)
private final JsonNodePath evaluationPath;
@JsonSerialize(using = ToStringSerializer.class)
private final SchemaLocation schemaLocation;
@JsonSerialize(using = ToStringSerializer.class)
private final JsonNodePath instanceLocation;
private final String property;
private final Object[] arguments;
private final String messageKey;
private final Supplier messageSupplier;
private final Map details;
private final JsonNode instanceNode;
private final JsonNode schemaNode;
ValidationMessage(String type, String code, JsonNodePath evaluationPath, SchemaLocation schemaLocation,
JsonNodePath instanceLocation, String property, Object[] arguments, Map details,
String messageKey, Supplier messageSupplier, JsonNode instanceNode, JsonNode schemaNode) {
super();
this.type = type;
this.code = code;
this.instanceLocation = instanceLocation;
this.schemaLocation = schemaLocation;
this.evaluationPath = evaluationPath;
this.property = property;
this.arguments = arguments;
this.details = details;
this.messageKey = messageKey;
this.messageSupplier = messageSupplier;
this.instanceNode = instanceNode;
this.schemaNode = schemaNode;
}
public String getCode() {
return code;
}
/**
* The instance location is the location of the JSON value within the root
* instance being validated.
*
* @return The path to the input json
*/
public JsonNodePath getInstanceLocation() {
return instanceLocation;
}
/**
* The evaluation path is the set of keys, starting from the schema root,
* through which evaluation passes to reach the schema object that produced a
* specific result.
*
* @return the evaluation path
*/
public JsonNodePath getEvaluationPath() {
return evaluationPath;
}
/**
* The schema location is the canonical IRI of the schema object plus a JSON
* Pointer fragment indicating the subschema that produced a result. In contrast
* with the evaluation path, the schema location MUST NOT include by-reference
* applicators such as $ref or $dynamicRef.
*
* @return the schema location
*/
public SchemaLocation getSchemaLocation() {
return schemaLocation;
}
/**
* Returns the instance node which was evaluated.
*
* This corresponds with the instance location.
*
* @return the instance node
*/
public JsonNode getInstanceNode() {
return instanceNode;
}
/**
* Returns the schema node which was evaluated.
*
* This corresponds with the schema location.
*
* @return the schema node
*/
public JsonNode getSchemaNode() {
return schemaNode;
}
/**
* Returns the property with the error.
*
* For instance, for the required validator the instance location does not
* contain the missing property name as the instance must refer to the input
* data.
*
* @return the property name
*/
public String getProperty() {
return property;
}
public Object[] getArguments() {
return arguments;
}
public Map getDetails() {
return details;
}
public String getMessage() {
return messageSupplier.get();
}
public String getMessageKey() {
return messageKey;
}
public boolean isValid() {
return messageSupplier != null;
}
@Override
public String toString() {
return messageSupplier.get();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ValidationMessage that = (ValidationMessage) o;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
if (code != null ? !code.equals(that.code) : that.code != null) return false;
if (instanceLocation != null ? !instanceLocation.equals(that.instanceLocation) : that.instanceLocation != null) return false;
if (evaluationPath != null ? !evaluationPath.equals(that.evaluationPath) : that.evaluationPath != null) return false;
if (details != null ? !details.equals(that.details) : that.details != null) return false;
if (messageKey != null ? !messageKey.equals(that.messageKey) : that.messageKey != null) return false;
if (!Arrays.equals(arguments, that.arguments)) return false;
return true;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (code != null ? code.hashCode() : 0);
result = 31 * result + (instanceLocation != null ? instanceLocation.hashCode() : 0);
result = 31 * result + (evaluationPath != null ? evaluationPath.hashCode() : 0);
result = 31 * result + (details != null ? details.hashCode() : 0);
result = 31 * result + (arguments != null ? Arrays.hashCode(arguments) : 0);
result = 31 * result + (messageKey != null ? messageKey.hashCode() : 0);
return result;
}
public String getType() {
return type;
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends BuilderSupport {
@Override
public Builder self() {
return this;
}
}
public static abstract class BuilderSupport {
public abstract S self();
protected String type;
protected String code;
protected JsonNodePath evaluationPath;
protected SchemaLocation schemaLocation;
protected JsonNodePath instanceLocation;
protected String property;
protected Object[] arguments;
protected Map details;
protected MessageFormat format;
protected String message;
protected Supplier messageSupplier;
protected MessageFormatter messageFormatter;
protected String messageKey;
protected JsonNode instanceNode;
protected JsonNode schemaNode;
public S type(String type) {
this.type = type;
return self();
}
public S code(String code) {
this.code = code;
return self();
}
/**
* The instance location is the location of the JSON value within the root
* instance being validated.
*
* @param instanceLocation the instance location
* @return the builder
*/
public S instanceLocation(JsonNodePath instanceLocation) {
this.instanceLocation = instanceLocation;
return self();
}
/**
* The schema location is the canonical URI of the schema object plus a JSON
* Pointer fragment indicating the subschema that produced a result. In contrast
* with the evaluation path, the schema location MUST NOT include by-reference
* applicators such as $ref or $dynamicRef.
*
* @param schemaLocation the schema location
* @return the builder
*/
public S schemaLocation(SchemaLocation schemaLocation) {
this.schemaLocation = schemaLocation;
return self();
}
/**
* The evaluation path is the set of keys, starting from the schema root,
* through which evaluation passes to reach the schema object that produced a
* specific result.
*
* @param evaluationPath the evaluation path
* @return the builder
*/
public S evaluationPath(JsonNodePath evaluationPath) {
this.evaluationPath = evaluationPath;
return self();
}
public S property(String property) {
this.property = property;
return self();
}
public S arguments(Object... arguments) {
this.arguments = arguments;
return self();
}
public S details(Map details) {
this.details = details;
return self();
}
public S format(MessageFormat format) {
this.format = format;
return self();
}
@Deprecated
public S customMessage(String message) {
return message(message);
}
/**
* Explicitly sets the message pattern to be used.
*
* If set the message supplier and message formatter will be ignored.
*
* @param message the message pattern
* @return the builder
*/
public S message(String message) {
this.message = message;
return self();
}
public S messageSupplier(Supplier messageSupplier) {
this.messageSupplier = messageSupplier;
return self();
}
public S messageFormatter(MessageFormatter messageFormatter) {
this.messageFormatter = messageFormatter;
return self();
}
public S messageKey(String messageKey) {
this.messageKey = messageKey;
return self();
}
public S instanceNode(JsonNode instanceNode) {
this.instanceNode = instanceNode;
return self();
}
public S schemaNode(JsonNode schemaNode) {
this.schemaNode = schemaNode;
return self();
}
public ValidationMessage build() {
Supplier messageSupplier = this.messageSupplier;
String messageKey = this.messageKey;
if (StringUtils.isNotBlank(this.message)) {
messageKey = this.message;
if (this.message.contains("{")) {
Object[] objs = getMessageArguments();
MessageFormat format = new MessageFormat(this.message);
messageSupplier = new CachingSupplier<>(() -> format.format(objs));
} else {
messageSupplier = message::toString;
}
} else if (messageSupplier == null) {
Object[] objs = getMessageArguments();
MessageFormatter formatter = this.messageFormatter != null ? this.messageFormatter : format::format;
messageSupplier = new CachingSupplier<>(() -> formatter.format(objs));
}
return new ValidationMessage(type, code, evaluationPath, schemaLocation, instanceLocation,
property, arguments, details, messageKey, messageSupplier, this.instanceNode, this.schemaNode);
}
protected Object[] getMessageArguments() {
Object[] objs = new Object[(arguments == null ? 0 : arguments.length) + 1];
objs[0] = instanceLocation;
if (arguments != null) {
for (int i = 1; i < objs.length; i++) {
objs[i] = arguments[i - 1];
}
}
return objs;
}
protected String getType() {
return type;
}
protected String getCode() {
return code;
}
protected JsonNodePath getEvaluationPath() {
return evaluationPath;
}
protected SchemaLocation getSchemaLocation() {
return schemaLocation;
}
protected JsonNodePath getInstanceLocation() {
return instanceLocation;
}
protected String getProperty() {
return property;
}
protected Object[] getArguments() {
return arguments;
}
protected Map getDetails() {
return details;
}
protected MessageFormat getFormat() {
return format;
}
protected String getMessage() {
return message;
}
protected Supplier getMessageSupplier() {
return messageSupplier;
}
protected MessageFormatter getMessageFormatter() {
return messageFormatter;
}
protected String getMessageKey() {
return messageKey;
}
}
}