package com.temenos.useragent.generic;
/*
* #%L
* useragent-generic-java
* %%
* Copyright (C) 2012 - 2016 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import com.temenos.useragent.generic.internal.ActionableLink;
import com.temenos.useragent.generic.internal.LinkWrapper;
import com.temenos.useragent.generic.internal.SessionContext;
/**
* This class maps {@link Link links} against some of their attributes to
* provide convenient access.
*
* @author ssethupathi
*
*/
public class Links {
private List<Link> links = new ArrayList<Link>();
private Map<String, List<Link>> linksByRel = new HashMap<String, List<Link>>();
private Map<String, List<Link>> linksByHref = new HashMap<String, List<Link>>();
private Map<String, List<Link>> linksByTitle = new HashMap<String, List<Link>>();
private Map<String, List<Link>> linksById = new HashMap<String, List<Link>>();
private Map<String, List<Link>> linksByDesc = new LinkedHashMap<String, List<Link>>();
private SessionContext sessionContext;
private Links(List<Link> links, SessionContext sessionCallback) {
this.sessionContext = sessionCallback;
for (Link link : links) {
this.links.add(link);
}
mapLinks();
}
private Links() {
}
/**
* Returns the first {@link ActionableLink link} from the mapping for a
* supplied attribute <i>rel</i>.
*
* @param rel
* @return {@link ActionableLink link}
* @throws IllegalStateException
* if no mapping found for the supplied attribute
*/
public ActionableLink byRel(String rel) {
return buildFromFirstLink(linksByRel.get(rel), "rel", rel);
}
/**
* Returns all the {@link ActionableLink links} from the mapping for a
* supplied attribute <i>rel</i>.
*
* @param rel
* @return {@link ActionableLink links} list
*/
public List<ActionableLink> allByRel(String rel) {
return buildFromAllLinks(linksByRel.get(rel));
}
/**
* Returns the first {@link ActionableLink link} from the mapping for a
* supplied attribute <i>href</i>.
*
* @param href
* @return {@link ActionableLink link}
* @throws IllegalStateException
* if no mapping found for the supplied attribute
*/
public ActionableLink byHref(String href) {
return buildFromFirstLink(linksByHref.get(href), "href", href);
}
/**
* Returns all the {@link ActionableLink links} from the mapping for a
* supplied attribute <i>href</i>.
*
* @param href
* @return {@link ActionableLink links} list
*/
public List<ActionableLink> allByHref(String href) {
return buildFromAllLinks(linksByHref.get(href));
}
/**
* Returns the first {@link ActionableLink link} from the mapping for a
* matching supplied attribute <i>title</i>.
*
* @param regex
* @return {@link ActionableLink link}
* @throws IllegalStateException
* if no mapping found for the supplied attribute
*/
public ActionableLink byTitle(String regex) {
for (String title : linksByTitle.keySet()) {
if (Pattern.compile(regex).matcher(title).matches()) {
List<Link> matchingLinks = linksByTitle.get(title);
if (!matchingLinks.isEmpty()) {
return new LinkWrapper(matchingLinks.get(0), sessionContext);
}
}
}
throw new IllegalStateException("No link found matching title '"
+ regex + "'");
}
/**
* Returns all the {@link ActionableLink links} from the mapping for a
* supplied attribute <i>title</i>.
*
* @param regex
* @return {@link ActionableLink links} list
*/
public List<ActionableLink> allByTitle(String regex) {
List<ActionableLink> allLinks = new ArrayList<ActionableLink>();
for (String title : linksByTitle.keySet()) {
if (Pattern.compile(regex).matcher(title).matches()) {
allLinks.addAll(buildFromAllLinks(linksByTitle.get(title)));
}
}
return allLinks;
}
/**
* Returns the first {@link ActionableLink link} from the mapping for a
* supplied attribute <i>id</i>.
*
* @param id
* @return {@link ActionableLink link}
* @throws IllegalStateException
* if no mapping found for the supplied attribute
*/
public ActionableLink byId(String id) {
return buildFromFirstLink(linksById.get(id), "id", id);
}
/**
* Returns all the {@link ActionableLink links} from the mapping for a
* supplied attribute <i>id</i>.
*
* @param id
* @return {@link ActionableLink links} list
*/
public List<ActionableLink> allById(String id) {
return buildFromAllLinks(linksById.get(id));
}
/**
* Returns the first {@link ActionableLink link} from the mapping for a
* matching supplied attribute <i>description</i>.
*
* @param regex
* @return {@link ActionableLink link}
* @throws IllegalStateException
* if no mapping found for the supplied attribute
*/
public ActionableLink byDescription(String regex) {
for (String description : linksByDesc.keySet()) {
if (Pattern.compile(regex).matcher(description).matches()) {
List<Link> matchingLinks = linksByDesc.get(description);
if (!matchingLinks.isEmpty()) {
return new LinkWrapper(matchingLinks.get(0), sessionContext);
}
}
}
throw new IllegalStateException("No link found matching description '"
+ regex + "'");
}
/**
* Returns all the {@link ActionableLink links} from the mapping for a
* supplied attribute <i>description</i>.
*
* @param regex
* @return {@link ActionableLink links} list
*/
public List<ActionableLink> allByDescription(String regex) {
List<ActionableLink> allLinks = new ArrayList<ActionableLink>();
for (String description : linksByDesc.keySet()) {
if (Pattern.compile(regex).matcher(description).matches()) {
allLinks.addAll(buildFromAllLinks(linksByDesc.get(description)));
}
}
return allLinks;
}
/**
* Returns "read-only" view of all {@link Link links} from this mapping.
*
* @return all links
*/
public List<Link> all() {
return Collections.unmodifiableList(links);
}
public static Links create(List<Link> links, SessionContext sessionContext) {
return new Links(links, sessionContext);
}
public static Links empty() {
return new Links();
}
private void mapLinks() {
for (Link link : links) {
mapLinksByAttribute(link.rel(), linksByRel, link);
mapLinksByAttribute(link.id(), linksById, link);
mapLinksByAttribute(link.title(), linksByTitle, link);
mapLinksByAttribute(link.href(), linksByHref, link);
mapLinksByAttribute(link.description(), linksByDesc, link);
}
}
private void mapLinksByAttribute(String attributeValue,
Map<String, List<Link>> mapping, Link link) {
if (attributeValue.isEmpty()) {
return;
}
List<Link> links = mapping.get(attributeValue);
if (links == null) {
links = new ArrayList<Link>();
links.add(link);
mapping.put(attributeValue, links);
} else {
mapping.get(attributeValue).add(link);
}
}
private ActionableLink buildFromFirstLink(List<Link> links,
String attribute, String value) {
if (links == null || links.isEmpty()) {
throw new IllegalStateException("No link found for " + attribute
+ " '" + value + "'");
} else {
return new LinkWrapper(links.get(0), sessionContext);
}
}
private List<ActionableLink> buildFromAllLinks(List<Link> links) {
List<ActionableLink> allActionableLinks = new ArrayList<ActionableLink>();
if (links == null) {
return allActionableLinks;
}
for (Link link : links) {
allActionableLinks.add(new LinkWrapper(link, sessionContext));
}
return allActionableLinks;
}
}