com.rexsl.page.Link Maven / Gradle / Ivy
/**
* Copyright (c) 2011-2013, ReXSL.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met: 1) Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer. 2) Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution. 3) Neither the name of the ReXSL.com nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.rexsl.page;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* HATEOAS link.
*
* This is how it is supposed to be used, for example:
*
*
@Path("/alpha")
* public class MainRs {
* @GET
* @Produces(MediaTypes.APPLICATION_XML)
* public BasePage front() {
* return new PageBuilder()
* .stylesheet("/xsl/front.xsl")
* .build(BasePage.class)
* .link(new Link("search", "./s"))
* .link(new Link("start", "/start"));
* }
* }
*
* That is how an XML will look like (if the site is deployed to
* {@code http://example.com/foo/}):
*
*
<?xml version="1.0" ?>
* <?xml-stylesheet type='text/xsl' href='/xsl/front.xsl'?>
* <page>
* <links>
* <link rel="search" href="http://example.com/foo/alpha/s"
* type="application/xml"/>
* <link rel="start" href="http://example.com/foo/start"
* type="application/xml"/>
* </links>
* </page>
*
* Sometimes it's necessary to add more information to the link, besides the
* the mandatory {@code rel}, {@code href}, and {@code type} attributes. That's
* how you can specify more:
*
*
return new PageBuilder()
* .build(BasePage.class)
* .link(
* new Link("search", "./s")
* .with(new JaxbBundle("name", "John Doe"))
* )
*
* The result XML will look like:
*
*
<?xml version="1.0" ?>
* <?xml-stylesheet type='text/xsl' href='/xsl/front.xsl'?>
* <page>
* <links>
* <link rel="search" href="http://example.com/foo/alpha/s"
* type="application/xml"/>
* <name>John Doe</name>
* </link>
* </links>
* </page>
*
* URI provided as a second parameter of any constructor of this class
* may be absolute or relative. It is relative if it starts with a slash
* ({@code "/"}) or a dot ({@link "."}). URIs started with a slash are related
* to the absolute path of the deployed application. URIs started with a dot
* are related to the path of the currently rendered page. To get the
* information about current context {@link #attachTo(Resource)} method
* is used. It is being called by {@link BasePage#init(Resource)}.
*
*
The class is mutable and thread-safe.
*
* @author Yegor Bugayenko ([email protected])
* @version $Id$
*/
@XmlRootElement(name = "link")
@XmlAccessorType(XmlAccessType.NONE)
@ToString
@EqualsAndHashCode(of = { "rel", "type", "elements", "href" })
public final class Link {
/**
* Name of {@code rel} attribute.
*/
@NotNull
private final transient String rel;
/**
* The type of resource there.
*/
@NotNull
private final transient String type;
/**
* Optional sub-elements.
*/
private final transient List