
com.strategicgains.hyperexpress.builder.DefaultLinkBuilder Maven / Gradle / Ivy
The newest version!
package com.strategicgains.hyperexpress.builder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.strategicgains.hyperexpress.domain.Link;
import com.strategicgains.hyperexpress.domain.LinkDefinition;
/**
* Build LinkDefinition instances from a URL pattern, binding URL tokens to
* actual values. Uses UrlBuilder to build the href or URL portion of the
* Link.
*
* @author toddf
* @since May 5, 2014
* @see UrlBuilder
*/
public class DefaultLinkBuilder
implements LinkBuilder
{
private static final String REL_TYPE = "rel";
private static final String TITLE = "title";
private static final String TYPE = "type";
private UrlBuilder urlBuilder;
private Map attributes = new HashMap();
/**
* Create an empty LinkBuilder, with no URL pattern. Using this constructor
* mandates that you MUST use the build(String) form of build instead of the
* parameterless, build() or other forms, as the latter will throw
* IllegalStateException in this state, due to not having a URL in the
* generated link.
*/
public DefaultLinkBuilder()
{
super();
urlBuilder = new DefaultUrlBuilder();
}
/**
* Create a new LinkBuilder, passing in the URL pattern in which to
* substitute tokens. This URL pattern may represent the entire URL or just
* the path portion (relative path).
*
* The URL pattern is templated, in that it contains tokens to be later
* substituted for actual values. The tokens are delimited with beginning
* and trailing curly-braces (e.g. '{token}').
*
* If used in conjunction with baseUrl(), this URL pattern must be just the
* path portion of the URL and should be prefixed with a leading slash
* ('/').
*
* For example: '/users/{userId}' or
* 'http://www.example.com/api/users/{userId}'
*
* @param urlPattern a URL path with optional tokens of the form '{tokenName}'
*/
public DefaultLinkBuilder(String urlPattern)
{
super();
urlBuilder = new DefaultUrlBuilder(urlPattern);
}
public DefaultLinkBuilder(DefaultLinkBuilder that)
{
super();
this.urlBuilder = that.urlBuilder.clone();
this.attributes = new HashMap(that.attributes);
}
/**
* Set the prefix portion of the URL which is to be pre-pended to the URL
* pattern.
*
* Optional, as the URL pattern may contain everything. However, this is
* provided as a convenience so consumers don't have to perform their own
* concatenation to pass in the entire URL pattern string to the constructor.
*
* For example: 'http://www.example.com:8080'
*
* @param baseUrl the string that will prefix the URL pattern
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder baseUrl(String url)
{
urlBuilder.baseUrl(url);
return this;
}
/**
* Add an optional query-string segment to this LinkBuilder.
*
* If all of the tokens in the query-string are bound, the segment is included
* in the generated URL string during build(). However, if there are unbound
* tokens in the resulting query-string segment, it is not included in the
* generated URL string.
*
* Do not include any question mark ("?") or ampersand ("&") in the query-string
* segment.
*
* @param query a query-string segment to optionally include.
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder withQuery(String query)
{
urlBuilder.withQuery(query);
return this;
}
/**
* Remove all attribute settings from this UrlBuilder.
* Properties such as 'rel', 'href', 'type' and 'title'
* are removed. Does not clear queries or URL-related
* properties, namely baseUrl or URl pattern.
*/
public void clearAttributes()
{
attributes.clear();
}
/**
* Remove the query-string segments from this UrlBuilder.
*/
public void clearQueries()
{
urlBuilder.clearQueries();
}
/**
* Retrieve the URL pattern associated with this link builder.
*
* @return the URL pattern or null.
*/
public String urlPattern()
{
return urlBuilder.urlPattern();
}
public DefaultLinkBuilder urlPattern(String pattern)
{
urlBuilder.urlPattern(pattern);
return this;
}
/**
* Set the 'rel' or relation-type value for links generated by this LinkBuilder.
*
* @param rel the relation-type name.
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder rel(String rel)
{
return set(REL_TYPE, rel);
}
/**
* Retrieve the 'rel' or relation-type name.
*
* @return the relation-type name, or null if the value is not set.
*/
public String rel()
{
return get(REL_TYPE);
}
/**
* Set the 'title' value of links generated by this LinkBuilder.
*
* @param title the title for generated links.
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder title(String title)
{
return set(TITLE, title);
}
/**
* Retrieve the 'title' value.
*
* @return the link title, or null if the value is not set.
*/
public String title()
{
return get(TITLE);
}
/**
* Set the 'type' value of links generated by this LinkBuilder.
*
* @param type the type for generated links.
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder type(String type)
{
return set(TYPE, type);
}
/**
* Retrieve the 'type'.
*
* @return the type of links, or null if the value is not set.
*/
public String type()
{
return get(TYPE);
}
/**
* Retrieve the value of an arbitrary named property value.
*
* @param name the name of the property to retrieve.
* @return the value for the give name, or null if the property is not set.
*/
public String get(String name)
{
return attributes.get(name);
}
/**
* Set an arbitrary named value for links generated by this LinkBuilder.
* If a property of the same name was previously-set, including 'rel', 'title'
* or 'type', it will be overwritten.
*
* If the value is null, the property is removed, if it was set before.
*
* @param name the name of a property.
* @param value the value of the property given by name.
* @return this LinkBuilder instance to facilitate method chaining.
*/
public DefaultLinkBuilder set(String name, String value)
{
if (value == null)
{
attributes.remove(name);
}
else
{
attributes.put(name, value);
}
return this;
}
public Link build()
{
return build(null);
}
public Link build(TokenResolver tokenResolver)
{
return createLink(urlBuilder.build(tokenResolver));
}
/**
* Build a Link instance.
*
* @param tokenResolver a TokenResolver with token bindings.
* @return a new Link instance
* @throws LinkBuilderException if the LinkBuilder is in a state to build an invalid
* LinkDefintion.
*/
public Link build(Object object, TokenResolver tokenResolver)
{
return createLink(urlBuilder.build(object, tokenResolver));
}
@Override
public String toString()
{
StringBuilder s = new StringBuilder();
s.append(this.getClass().getSimpleName());
s.append("{");
boolean isFirst = true;
for (Entry entry : attributes.entrySet())
{
if (!isFirst)
{
s.append(", ");
}
else
{
isFirst = false;
}
s.append(entry.getKey());
s.append("=");
s.append(entry.getValue());
}
s.append("}");
return s.toString();
}
private Link createLink(String url)
{
Link link = new LinkDefinition(attributes.get(REL_TYPE), url);
for (Entry entry : attributes.entrySet())
{
if (!entry.getKey().equalsIgnoreCase(REL_TYPE))
{
link.set(entry.getKey(), entry.getValue());
}
}
return link;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy