/* * Copyright 2013-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.hateoas; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.util.StringUtils; /** * Value object to represent a list of {@link Link}s. * * @author Oliver Gierke */ public class Links implements Iterable<Link> { private static final Pattern LINK_HEADER_PATTERN = Pattern.compile("(<[^>]*>;rel=\"[^\"]*\")"); static final Links NO_LINKS = new Links(Collections.<Link> emptyList()); private final List<Link> links; /** * Creates a new {@link Links} instance from the given {@link Link}s. * * @param links */ public Links(List<Link> links) { this.links = links == null ? Collections.<Link> emptyList() : Collections.unmodifiableList(links); } /** * Creates a new {@link Links} instance from the given {@link Link}s. * * @param links */ public Links(Link... links) { this(Arrays.asList(links)); } /** * Returns the {@link Link} with the given rel. * * @param rel the relation type to lookup a link for. * @return the {@link Link} with the given rel or {@literal null} if none found. */ public Link getLink(String rel) { for (Link link : links) { if (link.getRel().equals(rel)) { return link; } } return null; } /** * Returns all {@link Links} with the given relation type. * * @return the links */ public List<Link> getLinks(String rel) { List<Link> result = new ArrayList<Link>(); for (Link link : links) { if (link.getRel().endsWith(rel)) { result.add(link); } } return result; } /** * Returns whether the {@link Links} container contains a {@link Link} with the given rel. * * @param rel * @return */ public boolean hasLink(String rel) { return getLink(rel) != null; } /** * Creates a {@link Links} instance from the given RFC5988-compatible link format. * * @param source a comma separated list of {@link Link} representations. * @return the {@link Links} represented by the given {@link String}. */ public static Links valueOf(String source) { if (!StringUtils.hasText(source)) { return NO_LINKS; } Matcher matcher = LINK_HEADER_PATTERN.matcher(source); List<Link> links = new ArrayList<Link>(); while (matcher.find()) { Link link = Link.valueOf(matcher.group()); if (link != null) { links.add(link); } } return new Links(links); } /** * Returns whether the {@link Links} containter is empty. * * @return */ public boolean isEmpty() { return links.isEmpty(); } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return StringUtils.collectionToCommaDelimitedString(links); } /* * (non-Javadoc) * @see java.lang.Iterable#iterator() */ @Override public Iterator<Link> iterator() { return links.iterator(); } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object arg0) { if (!(arg0 instanceof Links)) { return false; } Links that = (Links) arg0; return this.links.equals(that.links); } /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int result = 17; result += 31 * links.hashCode(); return result; } }