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

com.github.fge.jsonschema.tree.BaseSchemaTree Maven / Gradle / Ivy

There is a newer version: 1.2.5
Show newest version
/*
 * Copyright (c) 2013, 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.tree;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jackson.JacksonUtils;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jackson.jsonpointer.TokenResolver;
import com.github.fge.jsonschema.exceptions.JsonReferenceException;
import com.github.fge.jsonschema.ref.JsonRef;

import javax.annotation.concurrent.Immutable;

/**
 * Base implementation of a {@link SchemaTree}
 *
 * @see CanonicalSchemaTree
 * @see InlineSchemaTree
 */
@Immutable
public abstract class BaseSchemaTree
    implements SchemaTree
{
    private static final JsonNodeFactory FACTORY = JacksonUtils.nodeFactory();

    /**
     * The contents of {@code $schema} for that schema
     *
     * 

Note that it is required that if it is present, it be an absolute * JSON Reference. If no suitable {@code $schema} is found, an empty ref * is returned.

*/ private final JsonRef dollarSchema; /** * The initial node */ protected final JsonNode baseNode; /** * The current JSON Pointer into the node. Starts empty. */ protected final JsonPointer pointer; /** * The current node. */ private final JsonNode node; /** * The JSON Reference from which this node has been loaded * *

If loaded without a URI, this will be the empty reference.

*/ protected final JsonRef loadingRef; /** * The JSON Reference representing the context at the root of the schema * *

It will defer from {@link #loadingRef} if there is an {@code id} at * the top level.

*/ private final JsonRef startingRef; /** * The current resolution context */ private final JsonRef currentRef; protected BaseSchemaTree(final JsonRef loadingRef, final JsonNode baseNode, final JsonPointer pointer) { dollarSchema = extractDollarSchema(baseNode); this.baseNode = baseNode; this.pointer = pointer; node = pointer.path(baseNode); this.loadingRef = loadingRef; final JsonRef ref = idFromNode(baseNode); startingRef = ref == null ? loadingRef : loadingRef.resolve(ref); currentRef = nextRef(startingRef, pointer, baseNode); } protected BaseSchemaTree(final BaseSchemaTree other, final JsonPointer newPointer) { dollarSchema = other.dollarSchema; baseNode = other.baseNode; loadingRef = other.loadingRef; pointer = newPointer; node = newPointer.get(baseNode); startingRef = other.startingRef; currentRef = nextRef(startingRef, newPointer, baseNode); } @Override public final JsonNode getBaseNode() { return baseNode; } @Override public final JsonPointer getPointer() { return pointer; } @Override public final JsonNode getNode() { return node; } /** * Resolve a JSON Reference against the current resolution context * * @param other the JSON Reference to resolve * @return the resolved reference * @see JsonRef#resolve(JsonRef) */ @Override public final JsonRef resolve(final JsonRef other) { return currentRef.resolve(other); } @Override public final JsonRef getDollarSchema() { return dollarSchema; } /** * Get the loading URI for that schema * * @return the loading URI as a {@link JsonRef} */ @Override public final JsonRef getLoadingRef() { return loadingRef; } /** * Get the current resolution context * * @return the context as a {@link JsonRef} */ @Override public final JsonRef getContext() { return currentRef; } @Override public final JsonNode asJson() { final ObjectNode ret = FACTORY.objectNode(); ret.put("loadingURI", FACTORY.textNode(loadingRef.toString())); ret.put("pointer", FACTORY.textNode(pointer.toString())); return ret; } @Override public final String toString() { return "loading URI: " + loadingRef + "; current pointer: \"" + pointer + "\"; resolution context: " + currentRef; } /** * Build a JSON Reference from a node * *

This will return {@code null} if the reference could not be built. The * conditions for a successful build are as follows:

* *
    *
  • the node is an object;
  • *
  • it has a member named {@code id};
  • *
  • the value of this member is a string;
  • *
  • this string is a valid URI.
  • *
* * @param node the node * @return a JSON Reference, or {@code null} */ protected static JsonRef idFromNode(final JsonNode node) { if (!node.path("id").isTextual()) return null; try { return JsonRef.fromString(node.get("id").textValue()); } catch (JsonReferenceException ignored) { return null; } } /** * Calculate the next URI context from a starting reference and node * * @param startingRef the starting reference * @param ptr the JSON Pointer * @param startingNode the starting node * @return the calculated reference */ private static JsonRef nextRef(final JsonRef startingRef, final JsonPointer ptr, final JsonNode startingNode) { JsonRef ret = startingRef; JsonRef idRef; JsonNode node = startingNode; for (final TokenResolver resolver: ptr) { node = resolver.get(node); if (node == null) break; idRef = idFromNode(node); if (idRef != null) ret = ret.resolve(idRef); } return ret; } private static JsonRef extractDollarSchema(final JsonNode schema) { final JsonNode node = schema.path("$schema"); if (!node.isTextual()) return JsonRef.emptyRef(); try { final JsonRef ref = JsonRef.fromString(node.textValue()); return ref.isAbsolute() ? ref : JsonRef.emptyRef(); } catch (JsonReferenceException ignored) { return JsonRef.emptyRef(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy