/*
 * Copyright (c) 2011, 2017 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package javax.ws.rs.core;

import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ws.rs.ext.RuntimeDelegate;

import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;

Class representing hypermedia links. A hypermedia link may include additional parameters beyond its underlying URI. Parameters such as rel or type provide additional meta-data. Links in responses can be followed by creating an Builder or a WebTarget.

The methods toString and valueOf can be used to serialize and de-serialize a link into a link header (RFC 5988).

Author:Marek Potociar, Santiago Pericas-Geertsen
See Also:
Since:2.0
/** * <p>Class representing hypermedia links. A hypermedia link may include additional * parameters beyond its underlying URI. Parameters such as {@code rel} or {@code type} * provide additional meta-data. Links in responses can be <em>followed</em> by * creating an {@link javax.ws.rs.client.Invocation.Builder} or a * {@link javax.ws.rs.client.WebTarget}.</p> * * <p>The methods {@link #toString} and {@link #valueOf} can be used to serialize * and de-serialize a link into a link header (RFC 5988).</p> * * @author Marek Potociar * @author Santiago Pericas-Geertsen * @see javax.ws.rs.client.Client#invocation * @see javax.ws.rs.client.Client#target(javax.ws.rs.core.Link) * @see javax.ws.rs.core.Response#getLink(java.lang.String) * @since 2.0 */
public abstract class Link {
Title link param from RFC 5988.
/** * Title link param from RFC 5988. */
public static final String TITLE = "title";
Rel link param from RFC 5988.
/** * Rel link param from RFC 5988. */
public static final String REL = "rel";
Type link param from RFC 5988.
/** * Type link param from RFC 5988. */
public static final String TYPE = "type";
Returns the underlying URI associated with this link.
Returns:underlying URI.
/** * Returns the underlying URI associated with this link. * * @return underlying URI. */
public abstract URI getUri();
Convenience method that returns a UriBuilder initialized with this link's underlying URI.
Returns:UriBuilder initialized using underlying URI.
/** * Convenience method that returns a {@link javax.ws.rs.core.UriBuilder} * initialized with this link's underlying URI. * * @return UriBuilder initialized using underlying URI. */
public abstract UriBuilder getUriBuilder();
Returns the value associated with the link rel param, or null if this param is not specified.
Returns:relation types as string or null.
/** * Returns the value associated with the link {@code rel} param, or * {@code null} if this param is not specified. * * @return relation types as string or {@code null}. */
public abstract String getRel();
Returns the value associated with the link rel param as a list of strings or the empty list if rel is not defined.
Returns:relation types as list of strings or empty list.
/** * Returns the value associated with the link {@code rel} param as a list * of strings or the empty list if {@code rel} is not defined. * * @return relation types as list of strings or empty list. */
public abstract List<String> getRels();
Returns the value associated with the link title param, or null if this param is not specified.
Returns:value of title parameter or null.
/** * Returns the value associated with the link {@code title} param, or * {@code null} if this param is not specified. * * @return value of title parameter or {@code null}. */
public abstract String getTitle();
Returns the value associated with the link type param, or null if this param is not specified.
Returns:value of type parameter or null.
/** * Returns the value associated with the link {@code type} param, or * {@code null} if this param is not specified. * * @return value of type parameter or {@code null}. */
public abstract String getType();
Returns an immutable map that includes all the link parameters defined on this link. If defined, this map will include entries for rel, title and type.
Returns:immutable map of link parameters.
/** * Returns an immutable map that includes all the link parameters * defined on this link. If defined, this map will include entries * for {@code rel}, {@code title} and {@code type}. * * @return immutable map of link parameters. */
public abstract Map<String, String> getParams();
Returns a string representation as a link header (RFC 5988). All link params are serialized as link-param="value" where value is a quoted-string. For example, ; title="employee"; rel="manager friend"
Returns:string link header representation for this link.
/** * Returns a string representation as a link header (RFC 5988). * All link params are serialized as link-param="value" where value * is a quoted-string. For example, * * <http://foo.bar/employee/john>; title="employee"; rel="manager friend" * * @return string link header representation for this link. */
@Override public abstract String toString();
Simple parser to convert link header string representations into a link.
link ::= '<' uri '>' (';' link-param)*
link-param ::= name '=' quoted-string
See RFC 5988 for more information.
Params:
  • value – String representation.
Throws:
See Also:
Returns:newly parsed link.
/** * Simple parser to convert link header string representations into a link. * <pre> * link ::= '<' uri '>' (';' link-param)* * link-param ::= name '=' quoted-string * </pre> * * See <a href="http://tools.ietf.org/html/rfc5988">RFC 5988</a> for more information. * * @param value String representation. * @return newly parsed link. * @throws IllegalArgumentException if a syntax error is found. * @see Link.Builder#link(java.lang.String) */
public static Link valueOf(String value) { Builder b = RuntimeDelegate.getInstance().createLinkBuilder(); b.link(value); return b.build(); }
Create a new builder instance initialized from an existing URI.
Params:
  • uri – a URI that will be used to initialize the builder.
Throws:
Returns:a new builder.
/** * Create a new builder instance initialized from an existing URI. * * @param uri a URI that will be used to initialize the builder. * @return a new builder. * @throws IllegalArgumentException if uri is {@code null}. */
public static Builder fromUri(URI uri) { Builder b = RuntimeDelegate.getInstance().createLinkBuilder(); b.uri(uri); return b; }
Create a new builder instance initialized from an existing URI represented as a string.
Params:
  • uri – a URI that will be used to initialize the builder.
Throws:
Returns:a new builder.
/** * Create a new builder instance initialized from an existing URI represented as a string. * * @param uri a URI that will be used to initialize the builder. * @return a new builder. * @throws IllegalArgumentException if uri is {@code null}. */
public static Builder fromUri(String uri) { Builder b = RuntimeDelegate.getInstance().createLinkBuilder(); b.uri(uri); return b; }
Create a new builder instance initialized from a URI builder.
Params:
  • uriBuilder – instance of URI builder.
Returns:a new builder.
/** * Create a new builder instance initialized from a URI builder. * * @param uriBuilder instance of URI builder. * @return a new builder. */
public static Builder fromUriBuilder(UriBuilder uriBuilder) { Builder b = RuntimeDelegate.getInstance().createLinkBuilder(); b.uriBuilder(uriBuilder); return b; }
Create a new builder instance initialized from another link.
Params:
  • link – other link used for initialization.
Returns:a new builder.
/** * Create a new builder instance initialized from another link. * * @param link other link used for initialization. * @return a new builder. */
public static Builder fromLink(Link link) { Builder b = RuntimeDelegate.getInstance().createLinkBuilder(); b.link(link); return b; }
Convenience method to build a link from a path. Equivalent to fromUriBuilder(UriBuilder.fromPath(path)).
Params:
  • path – a URI path that will be used to initialize the Link, may contain URI template parameters.
Throws:
Returns:a new Link.Builder.
/** * Convenience method to build a link from a path. Equivalent to * {@code fromUriBuilder(UriBuilder.fromPath(path))}. * * @param path a URI path that will be used to initialize the Link, may contain * URI template parameters. * @return a new Link.Builder. * @throws IllegalArgumentException if path is {@code null}. */
public static Builder fromPath(String path) { return fromUriBuilder(UriBuilder.fromPath(path)); }
Convenience method to build a link from a resource. Equivalent to Link.fromUriBuilder({@link UriBuilder#fromResource UriBuilder.fromResource(resource)}). Note that the link URI passed to the Link.Builder instance returned by this method is relative. Should the link be built as absolute, a base URI has to be specified in the builder prior to building the new link instance. For example, on a server side a UriInfo.getBaseUri() may be typically used to define the base URI of a link created using this method.
Params:
  • resource – a root resource whose Path value will be used to initialize the builder.
Throws:
See Also:
Returns:a new link builder instance.
/** * Convenience method to build a link from a resource. Equivalent to * {@code Link.fromUriBuilder({@link UriBuilder#fromResource UriBuilder.fromResource(resource)})}. * Note that the link URI passed to the {@code Link.Builder} instance returned by this * method is relative. Should the link be built as absolute, a {@link Link.Builder#baseUri(URI) * base URI} has to be specified in the builder prior to building the new link instance. * For example, on a server side a {@link UriInfo#getBaseUri()} may be typically used to define * the base URI of a link created using this method. * * @param resource a root resource whose {@link javax.ws.rs.Path} value will be used * to initialize the builder. * @return a new {@link Link.Builder link builder} instance. * @throws IllegalArgumentException if resource is not annotated with {@link javax.ws.rs.Path} * or resource is {@code null}. * @see UriInfo#getBaseUri() */
public static Builder fromResource(Class<?> resource) { return fromUriBuilder(UriBuilder.fromResource(resource)); }
Convenience method to build a link from a resource. Equivalent to Link.fromUriBuilder({@link UriBuilder#fromMethod(Class, String) UriBuilder.fromMethod(resource, method)}). Note that the link URI passed to the Link.Builder instance returned by this method is relative. Should the link be built as absolute, a base URI has to be specified in the builder prior to building the new link instance. For example, on a server side a UriInfo.getBaseUri() may be typically used to define the base URI of a link created using this method.
Params:
  • resource – the resource containing the method.
  • method – the name of the method whose Path value will be used to obtain the path to append.
Throws:
  • IllegalArgumentException – if resource or method is null, or there is more than or less than one variant of the method annotated with Path.
See Also:
Returns:the updated Link.Builder.
/** * Convenience method to build a link from a resource. Equivalent to * {@code Link.fromUriBuilder({@link UriBuilder#fromMethod(Class, String) UriBuilder.fromMethod(resource, method)})}. * Note that the link URI passed to the {@code Link.Builder} instance returned by this * method is relative. Should the link be built as absolute, a {@link Link.Builder#baseUri(URI) * base URI} has to be specified in the builder prior to building the new link instance. * For example, on a server side a {@link UriInfo#getBaseUri()} may be typically used to define * the base URI of a link created using this method. * * @param resource the resource containing the method. * @param method the name of the method whose {@link javax.ws.rs.Path} value will be used * to obtain the path to append. * @return the updated Link.Builder. * @throws IllegalArgumentException if resource or method is {@code null}, or there is more * than or less than one variant of the method annotated with * {@link javax.ws.rs.Path}. * @see UriInfo#getBaseUri() */
public static Builder fromMethod(Class<?> resource, String method) { return fromUriBuilder(UriBuilder.fromMethod(resource, method)); }
Builder class for hypermedia links.
See Also:
  • Link
Since:2.0
/** * Builder class for hypermedia links. * * @see Link * @since 2.0 */
public interface Builder {
Initialize builder using another link. Sets underlying URI and copies all parameters.
Params:
  • link – other link from which to initialize.
Returns:the updated builder.
/** * Initialize builder using another link. Sets underlying URI and copies * all parameters. * * @param link other link from which to initialize. * @return the updated builder. */
public Builder link(Link link);
Initialize builder using another link represented as a string. Uses simple parser to convert string representation into a link.
link ::= '<' uri '>' (';' link-param)*
link-param ::= name '=' quoted-string
See RFC 5988 for more information.
Params:
  • link – other link in string representation.
Throws:
Returns:the updated builder.
/** * Initialize builder using another link represented as a string. Uses * simple parser to convert string representation into a link. * <pre> * link ::= '<' uri '>' (';' link-param)* * link-param ::= name '=' quoted-string * </pre> * * See <a href="http://tools.ietf.org/html/rfc5988">RFC 5988</a> for more information. * * @param link other link in string representation. * @return the updated builder. * @throws IllegalArgumentException if string representation of URI is invalid. */
public Builder link(String link);
Set underlying URI template for the link being constructed.
Params:
  • uri – underlying URI for link
Returns:the updated builder.
/** * Set underlying URI template for the link being constructed. * * @param uri underlying URI for link * @return the updated builder. */
public Builder uri(URI uri);
Set underlying string representing URI template for the link being constructed.
Params:
  • uri – underlying URI for link.
Throws:
Returns:the updated builder.
/** * Set underlying string representing URI template for the link being constructed. * * @param uri underlying URI for link. * @return the updated builder. * @throws IllegalArgumentException if string representation of URI is invalid. */
public Builder uri(String uri);
Set the base URI for resolution of relative URIs. If the underlying URI is already absolute, the base URI is ignored.
Params:
  • uri – base URI for relative links.
See Also:
Returns:the updated builder.
/** * Set the base URI for resolution of relative URIs. If the underlying URI is already * absolute, the base URI is ignored. * * @param uri base URI for relative links. * @return the updated builder. * @see Link#fromPath(java.lang.String) * @see Link#fromResource(java.lang.Class) * @see Link#fromMethod(java.lang.Class, java.lang.String) */
public Builder baseUri(URI uri);
Set the base URI as a string for resolution of relative URIs. If the underlying URI is already absolute, the base URI is ignored.
Params:
  • uri – base URI for relative links.
Throws:
See Also:
Returns:the updated builder.
/** * Set the base URI as a string for resolution of relative URIs. If the underlying URI * is already absolute, the base URI is ignored. * * @param uri base URI for relative links. * @return the updated builder. * @throws IllegalArgumentException if string representation of URI is invalid. * @see Link#fromPath(java.lang.String) * @see Link#fromResource(java.lang.Class) * @see Link#fromMethod(java.lang.Class, java.lang.String) */
public Builder baseUri(String uri);
Set underlying URI builder representing the URI template for the link being constructed.
Params:
  • uriBuilder – underlying URI builder.
Returns:the updated builder.
/** * Set underlying URI builder representing the URI template for the link being constructed. * * @param uriBuilder underlying URI builder. * @return the updated builder. */
public Builder uriBuilder(UriBuilder uriBuilder);
Convenience method to set a link relation. More than one rel value can be specified by using one or more whitespace characters as delimiters according to RFC 5988. The effect of calling this method is cumulative; relations are appended using a single space character as separator.
Params:
  • rel – relation name.
Throws:
Returns:the updated builder.
/** * Convenience method to set a link relation. More than one {@code rel} value can * be specified by using one or more whitespace characters as delimiters * according to RFC 5988. The effect of calling this method is cumulative; * relations are appended using a single space character as separator. * * @param rel relation name. * @return the updated builder. * @throws IllegalArgumentException if the name is {@code null}. */
public Builder rel(String rel);
Convenience method to set a title on this link.
Params:
  • title – title parameter of this link.
Throws:
Returns:the updated builder.
/** * Convenience method to set a {@code title} on this link. * * @param title title parameter of this link. * @return the updated builder. * @throws IllegalArgumentException if the title is {@code null}. */
public Builder title(String title);
Convenience method to set a type on this link.
Params:
  • type – type parameter of this link.
Throws:
Returns:the updated builder.
/** * Convenience method to set a {@code type} on this link. * * @param type type parameter of this link. * @return the updated builder. * @throws IllegalArgumentException if the type is {@code null}. */
public Builder type(String type);
Set an arbitrary parameter on this link. Note that link parameters are those defined in RFC 5988 and should not be confused with URI parameters which can be specified when calling build(Object...).
Params:
  • name – the name of the parameter.
  • value – the value set for the parameter.
Throws:
Returns:the updated builder.
/** * Set an arbitrary parameter on this link. Note that link parameters are those * defined in RFC 5988 and should not be confused with URI parameters which can * be specified when calling {@link #build(Object...)}. * * @param name the name of the parameter. * @param value the value set for the parameter. * @return the updated builder. * @throws IllegalArgumentException if either the name or value are {@code null}. */
public Builder param(String name, String value);
Finish building this link using the supplied values as URI parameters. The state of the builder is unaffected; this method may be called multiple times on the same builder instance.
Params:
  • values – parameters used to build underlying URI.
Throws:
  • IllegalArgumentException – if there are any URI template parameters without a supplied value, or if a value is null.
  • UriBuilderException – if a URI cannot be constructed based on the current state of the underlying URI builder.
Returns:newly built link.
/** * Finish building this link using the supplied values as URI parameters. * * The state of the builder is unaffected; this method may be called * multiple times on the same builder instance. * * @param values parameters used to build underlying URI. * @return newly built link. * @throws IllegalArgumentException if there are any URI template parameters * without a supplied value, or if a value is {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the * current state of the underlying URI builder. */
public Link build(Object... values);
Finish building this link using the supplied values as URI parameters and relativize the result with respect to the supplied URI. If the underlying link is already relative or if it is absolute but does not share a prefix with the supplied URI, this method is equivalent to calling build(Object[]). Note that a base URI can be set on a relative link using baseUri(URI). The state of the builder is unaffected; this method may be called multiple times on the same builder instance.
Params:
  • uri – URI used for relativization.
  • values – parameters used to build underlying URI.
Throws:
  • IllegalArgumentException – if there are any URI template parameters without a supplied value, or if a value is null.
  • UriBuilderException – if a URI cannot be constructed based on the current state of the underlying URI builder.
See Also:
Returns:newly built link.
/** * Finish building this link using the supplied values as URI parameters * and relativize the result with respect to the supplied URI. * * If the underlying link is already relative or if it is absolute but does * not share a prefix with the supplied URI, this method is equivalent to calling * {@link Link.Builder#build(java.lang.Object[])}. Note that a base URI can * be set on a relative link using {@link Link.Builder#baseUri(java.net.URI)}. * The state of the builder is unaffected; this method may be called * multiple times on the same builder instance. * * @param uri URI used for relativization. * @param values parameters used to build underlying URI. * @return newly built link. * @throws IllegalArgumentException if there are any URI template parameters * without a supplied value, or if a value is {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current * state of the underlying URI builder. * @see #baseUri(java.lang.String) * @see #baseUri(java.net.URI) */
public Link buildRelativized(URI uri, Object... values); }
Value type for Link that can be marshalled and unmarshalled by JAXB.
See Also:
Since:2.0
/** * Value type for {@link javax.ws.rs.core.Link} that can be marshalled and * unmarshalled by JAXB. * * @see javax.ws.rs.core.Link.JaxbAdapter * @since 2.0 */
public static class JaxbLink { private URI uri; private Map<QName, Object> params;
Default constructor needed during unmarshalling.
/** * Default constructor needed during unmarshalling. */
public JaxbLink() { }
Construct an instance from a URI and no parameters.
Params:
  • uri – underlying URI.
/** * Construct an instance from a URI and no parameters. * * @param uri underlying URI. */
public JaxbLink(URI uri) { this.uri = uri; }
Construct an instance from a URI and some parameters.
Params:
  • uri – underlying URI.
  • params – parameters of this link.
/** * Construct an instance from a URI and some parameters. * * @param uri underlying URI. * @param params parameters of this link. */
public JaxbLink(URI uri, Map<QName, Object> params) { this.uri = uri; this.params = params; }
Get the underlying URI for this link.
Returns:underlying URI.
/** * Get the underlying URI for this link. * * @return underlying URI. */
@XmlAttribute(name = "href") public URI getUri() { return uri; }
Get the parameter map for this link.
Returns:parameter map.
/** * Get the parameter map for this link. * * @return parameter map. */
@XmlAnyAttribute public Map<QName, Object> getParams() { if (params == null) { params = new HashMap<QName, Object>(); } return params; }
Set the underlying URI for this link. This setter is needed for JAXB unmarshalling.
/** * Set the underlying URI for this link. * * This setter is needed for JAXB unmarshalling. */
void setUri(URI uri) { this.uri = uri; }
Set the parameter map for this link. This setter is needed for JAXB unmarshalling.
/** * Set the parameter map for this link. * * This setter is needed for JAXB unmarshalling. */
void setParams(Map<QName, Object> params) { this.params = params; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof JaxbLink)) return false; JaxbLink jaxbLink = (JaxbLink) o; if (uri != null ? !uri.equals(jaxbLink.uri) : jaxbLink.uri != null) { return false; } if (params == jaxbLink.params) { return true; } if (params == null) { // if this.params is 'null', consider other.params equal to empty return jaxbLink.params.isEmpty(); } if (jaxbLink.params == null) { // if other.params is 'null', consider this.params equal to empty return params.isEmpty(); } return params.equals(jaxbLink.params); } @Override public int hashCode() { int result = uri != null ? uri.hashCode() : 0; result = 31 * result + (params != null && !params.isEmpty() ? params.hashCode() : 0); return result; } }
An implementation of JAXB XmlAdapter that maps the Link type to a value that can be marshalled and unmarshalled by JAXB. The following example shows how to use this adapter on a JAXB bean class:
@XmlRootElement
public class MyModel {
  private Link link;
  @XmlElement(name="link")
  @XmlJavaTypeAdapter(JaxbAdapter.class)
  public Link getLink() {
    return link;
  }
  ...
}
See Also:
Since:2.0
/** * An implementation of JAXB {@link javax.xml.bind.annotation.adapters.XmlAdapter} * that maps the {@link javax.ws.rs.core.Link} type to a value that can be * marshalled and unmarshalled by JAXB. The following example shows how to use * this adapter on a JAXB bean class: * * <pre> * &#64;XmlRootElement * public class MyModel { * * private Link link; * * &#64;XmlElement(name="link") * &#64;XmlJavaTypeAdapter(JaxbAdapter.class) * public Link getLink() { * return link; * } * ... * } * </pre> * * @see javax.ws.rs.core.Link.JaxbLink * @since 2.0 */
public static class JaxbAdapter extends XmlAdapter<JaxbLink, Link> {
Convert a JaxbLink into a Link.
Params:
Returns:mapped instance of type JaxbLink
/** * Convert a {@link JaxbLink} into a {@link Link}. * * @param v instance of type {@link JaxbLink}. * @return mapped instance of type {@link JaxbLink} */
@Override public Link unmarshal(JaxbLink v) { Link.Builder lb = Link.fromUri(v.getUri()); for (Entry<QName, Object> e : v.getParams().entrySet()) { lb.param(e.getKey().getLocalPart(), e.getValue().toString()); } return lb.build(); }
Convert a Link into a JaxbLink.
Params:
  • v – instance of type Link.
Returns:mapped instance of type JaxbLink.
/** * Convert a {@link Link} into a {@link JaxbLink}. * * @param v instance of type {@link Link}. * @return mapped instance of type {@link JaxbLink}. */
@Override public JaxbLink marshal(Link v) { JaxbLink jl = new JaxbLink(v.getUri()); for (Entry<String, String> e : v.getParams().entrySet()) { final String name = e.getKey(); jl.getParams().put(new QName("", name), e.getValue()); } return jl; } } }