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

com.github.fge.jsonschema.ref.JsonRef 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.ref;

import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jackson.jsonpointer.JsonPointerException;
import com.github.fge.jsonschema.CoreMessageBundle;
import com.github.fge.jsonschema.exceptions.JsonReferenceException;
import com.github.fge.jsonschema.report.ProcessingMessage;

import javax.annotation.concurrent.Immutable;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * Representation of a JSON Reference
 *
 * 

JSON * Reference, currently a draft, is a way to define a path within a JSON * document.

* *

To quote the draft, "A JSON Reference is a JSON object, which contains * a member named "$ref", which has a JSON string value." This string value * must be a URI. Example:

* *
 *     {
 *         "$ref": "http://example.com/example.json#/foo/bar"
 *     }
 * 
* *

This class differs from the JSON Reference draft in that it accepts to * process illegal references, in the sense that they are URIs, but their * fragment parts are not JSON Pointers (in which case {@link #isLegal()} * returns {@code false}.

* *

The implementation is a wrapper over Java's {@link URI}, with the * following characteristics:

* *
    *
  • all URIs are normalized from the get go;
  • *
  • an empty fragment is equivalent to no fragment at all, and stands for * a root JSON Pointer, as required by the draft;
  • *
  • a reference is taken to be absolute if the underlying URI is absolute * and it has no fragment, or an empty fragment.
  • *
* *

It also special cases the following:

* *
    *
  • an empty reference (for instance, used in anonymouns schemas);
  • *
  • URIs with the {@code jar} scheme (the resolving algorithm differs -- * please note that this breaks URI resolution rules).
  • *
* */ @Immutable public abstract class JsonRef { private static final CoreMessageBundle BUNDLE = CoreMessageBundle.getInstance(); /** * The empty URI */ private static final URI EMPTY_URI = URI.create(""); /** * A "hash only" URI -- used by {@link EmptyJsonRef} */ protected static final URI HASHONLY_URI = URI.create("#"); /** * Whether this JSON Reference is legal */ protected final boolean legal; /** * The URI, as provided by the input, with an appended empty fragment if * no fragment was provided */ protected final URI uri; /** * The locator of this reference. This is the URI with an empty fragment * part. */ protected final URI locator; /** * The pointer of this reference, if any * *

Initialized to null if the fragment part is not a JSON Pointer.

* * @see #isLegal() */ protected final JsonPointer pointer; /** * String representation */ private final String asString; /** * Hashcode */ private final int hashCode; /** * Main constructor, {@code protected} by design * * @param uri the URI to build that reference */ protected JsonRef(final URI uri) { final String scheme = uri.getScheme(); final String ssp = uri.getSchemeSpecificPart(); final String uriFragment = uri.getFragment(); /* * Account for URIs with no fragment: substitute an empty one */ final String realFragment = uriFragment == null ? "" : uriFragment; /* * Compute the fragment */ boolean isLegal = true; JsonPointer ptr; try { ptr = realFragment.isEmpty() ? JsonPointer.empty() : new JsonPointer(realFragment); } catch (JsonPointerException ignored) { ptr = null; isLegal = false; } legal = isLegal; pointer = ptr; try { this.uri = new URI(scheme, ssp, realFragment); locator = new URI(scheme, ssp, ""); asString = this.uri.toString(); hashCode = asString.hashCode(); } catch (URISyntaxException e) { /* * Can't happen: we did have a legal URI to start with */ throw new RuntimeException("WTF??", e); } } /** * Build a JSON Reference from a URI * * @param uri the provided URI * @return the JSON Reference * @throws NullPointerException the provided URI is null */ public static JsonRef fromURI(final URI uri) { BUNDLE.checkNotNull(uri, "jsonRef.nullURI"); final URI normalized = uri.normalize(); if (HASHONLY_URI.equals(normalized) || EMPTY_URI.equals(normalized)) return EmptyJsonRef.getInstance(); return "jar".equals(normalized.getScheme()) ? new JarJsonRef(normalized) : new HierarchicalJsonRef(normalized); } /** * Build a JSON Reference from a string input * * @param s the string * @return the reference * @throws JsonReferenceException string is not a valid URI * @throws NullPointerException provided string is null */ public static JsonRef fromString(final String s) throws JsonReferenceException { BUNDLE.checkNotNull(s, "jsonRef.nullInput"); try { return fromURI(new URI(s)); } catch (URISyntaxException e) { throw new JsonReferenceException(new ProcessingMessage() .message(BUNDLE.getKey("jsonRef.invalidURI")) .put("input", s), e); } } /** * Return an empty reference * *

An empty reference is a reference which only has an empty fragment. *

* * @return a statically allocated empty reference */ public static JsonRef emptyRef() { return EmptyJsonRef.getInstance(); } /** * Return the underlying URI for this JSON Reference * * @return the URI */ public final URI toURI() { return uri; } /** * Tell whether this reference is an absolute reference * *

See description.

* * @return {@code true} if the JSON Reference is absolute */ public abstract boolean isAbsolute(); /** * Resolve this reference against another reference * * @param other the reference to resolve * @return the resolved reference */ public abstract JsonRef resolve(final JsonRef other); /** * Return this JSON Reference's locator * *

This returns the reference with an empty fragment, ie the URI of the * document itself.

* * @return an URI */ public final URI getLocator() { return locator; } /** * Tell whether this JSON Reference is legal * *

Recall: it is legal if and only if its fragment part is a JSON * pointer.

* * @return {@code true} if legal * @see JsonPointer */ public final boolean isLegal() { return legal; } /** * Return the fragment part of this JSON Reference as a JSON Pointer * *

If the reference is not legal, this returns {@code null} without * further notice, so beware!

* * @return a JSON Pointer * @see JsonPointer */ public final JsonPointer getPointer() { return pointer; } /** * Tell whether the current JSON Reference "contains" another * *

This is considered true iif both references have the same locator, * in other words, if they differ only by their fragment part.

* * @param other the other reference * @return see above */ public final boolean contains(final JsonRef other) { return locator.equals(other.locator); } @Override public final int hashCode() { return hashCode; } @Override public final boolean equals(final Object obj) { if (obj == null) return false; if (this == obj) return true; if (!(obj instanceof JsonRef)) return false; final JsonRef that = (JsonRef) obj; return asString.equals(that.asString); } @Override public final String toString() { return asString; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy