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

com.github.fge.jsonschema.validator.JsonResolver Maven / Gradle / Ivy

/*
 * 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.validator;

import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jsonschema.main.JsonSchemaException;
import com.github.fge.jsonschema.ref.JsonRef;
import com.github.fge.jsonschema.report.Domain;
import com.github.fge.jsonschema.report.Message;
import com.github.fge.jsonschema.schema.SchemaContext;
import com.github.fge.jsonschema.schema.SchemaNode;
import com.github.fge.jsonschema.schema.SchemaRegistry;

import java.net.URI;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * Class responsible for JSON Reference resolution
 *
 * 

One instance of such class is created for each instance of {@link * JsonValidatorCache}.

*/ final class JsonResolver { private final SchemaRegistry registry; JsonResolver(final SchemaRegistry registry) { this.registry = registry; } /** * Resolve a schema node to the target schema node * * @see SchemaRegistry#get(URI) * * @param schemaNode the original schema node * @return the computed schema node * @throws JsonSchemaException ref resolution failure (dangling ref, ref * loop, etc) */ SchemaNode resolve(final SchemaNode schemaNode) throws JsonSchemaException { /* * All failures at this level are fatal */ final Message.Builder msg = Domain.REF_RESOLVING.newMessage() .setKeyword("$ref").setFatal(true); /* * These two elements might change during ref resolving. Set them to * their initial values. */ SchemaContext schemaContext = schemaNode.getSchemaContext(); JsonNode node = schemaNode.getNode(); /* * This set will store all ABSOLUTE JSON references we encounter * during ref resolution. If there is an attempt to store an already * existing reference, this means a ref loop. * * We want to preserve insertion order, therefore we have to use a * LinkedHashSet. */ final Set refs = new LinkedHashSet(); /* * All elements below are set during the ref resolution process. */ JsonRef source, ref, target; JsonNode refNode; while (true) { /* * We break out immediately if either there is no $ref node, * or there exists one but it is not a text node (syntax validation * will catch that). */ refNode = node.path("$ref"); if (!refNode.isTextual()) break; /* * Similarly, the constructor will fail at this point iif the text * value of the node is not an URI: break, we want this caught by * syntax validation. */ try { ref = JsonRef.fromString(refNode.textValue()); } catch (JsonSchemaException ignored) { break; } /* * Compute the target ref. Try and insert it into the set of refs * already seen: if it has been already seen, there is a ref loop. */ source = schemaContext.getLocator(); target = source.resolve(ref); if (!refs.add(target)) { msg.setMessage("ref loop detected").addInfo("path", refs); throw new JsonSchemaException(msg.build()); } /* * Should we change schema context? We should if the source ref (the * one in the current context) does not contain the target ref. In * this case, get the new context from our schema registry. If we * cannot do that, this is an error condition, bail out. */ if (!schemaContext.contains(target)) schemaContext = registry.get(target.getLocator()); /* * Finally, compute the next node in the process. If it is missing, * we have a dangling JSON Pointer: this is an error condition. */ node = schemaContext.resolve(target); if (node.isMissingNode()) { msg.setMessage("dangling JSON Reference") .addInfo("ref", target); throw new JsonSchemaException(msg.build()); } } return new SchemaNode(schemaContext, node); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy