/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos 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 General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.utils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Collection; import java.util.concurrent.Callable; import nl.strohalm.cyclos.entities.Entity; import nl.strohalm.cyclos.entities.accounts.guarantees.Certification; import nl.strohalm.cyclos.entities.accounts.guarantees.Guarantee; import nl.strohalm.cyclos.entities.accounts.guarantees.PaymentObligation; import nl.strohalm.cyclos.entities.accounts.loans.Loan; import nl.strohalm.cyclos.entities.accounts.transactions.Invoice; import nl.strohalm.cyclos.entities.accounts.transactions.ScheduledPayment; import nl.strohalm.cyclos.entities.accounts.transactions.Transfer; import nl.strohalm.cyclos.entities.ads.Ad; import nl.strohalm.cyclos.entities.alerts.ErrorLogEntry; import nl.strohalm.cyclos.entities.exceptions.EntityNotFoundException; import nl.strohalm.cyclos.entities.groups.Group; import nl.strohalm.cyclos.entities.groups.GroupFilter; import nl.strohalm.cyclos.entities.groups.MemberGroup; import nl.strohalm.cyclos.entities.groups.SystemGroup; import nl.strohalm.cyclos.entities.members.Element; import nl.strohalm.cyclos.entities.members.GeneralReference; import nl.strohalm.cyclos.entities.members.Member; import nl.strohalm.cyclos.entities.members.Operator; import nl.strohalm.cyclos.entities.members.PendingEmailChange; import nl.strohalm.cyclos.entities.members.TransactionFeedback; import nl.strohalm.cyclos.entities.members.TransactionFeedbackRequest; import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContract; import nl.strohalm.cyclos.services.groups.GroupService; import nl.strohalm.cyclos.services.settings.SettingsService; import nl.strohalm.cyclos.utils.access.LoggedUser; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Implementation for link generator * @author jefferson */ public class LinkGeneratorImpl implements LinkGenerator { private static final Log LOG = LogFactory.getLog(LinkGeneratorImpl.class); private SettingsService settingsService; private MessageHelper messageHelper; private GroupService groupService; @Override public String generateForApplicationRoot(final Element element) { return buildTagFor(getRootUrl(element)); } @Override public String generateLinkFor(final Element element, final Entity entity) throws EntityNotFoundException { String relativePath = ""; if (entity instanceof Ad) { relativePath = "viewAd?id="; } else if (entity instanceof Member) { relativePath = "profile?memberId="; } else if (entity instanceof Invoice) { relativePath = "invoiceDetails?invoiceId="; } else if (entity instanceof Transfer) { relativePath = "viewTransaction?transferId="; } else if (entity instanceof GeneralReference) { relativePath = "generalReferenceDetails?referenceId="; } else if (entity instanceof TransactionFeedback) { relativePath = "transactionFeedbackDetails?referenceId="; } else if (entity instanceof TransactionFeedbackRequest) { final TransactionFeedbackRequest transactionFeedbackRequest = (TransactionFeedbackRequest) entity; String paramName; if (transactionFeedbackRequest.getPayment() instanceof ScheduledPayment) { paramName = "scheduledPaymentId"; } else { paramName = "transferId"; } relativePath = "transactionFeedbackDetails?" + paramName + "="; } else if (entity instanceof Loan) { relativePath = "loanDetails?loanId="; } else if (entity instanceof ErrorLogEntry) { relativePath = "viewErrorLogEntry?entryId="; } else if (entity instanceof BrokerCommissionContract) { relativePath = "editBrokerCommissionContract?brokerCommissionContractId="; } else if (entity instanceof Certification) { relativePath = "editCertification?certificationId="; } else if (entity instanceof Guarantee) { relativePath = "guaranteeDetails?guaranteeId="; } else if (entity instanceof PaymentObligation) { relativePath = "editPaymentObligation?paymentObligationId="; } else { throw new EntityNotFoundException(entity.getClass()); } final String path = "do/" + element.getNature().name().toLowerCase() + "/" + relativePath + entity.getId(); final String baseUrl = getBaseUrl(element); final String pathPart = "/do/redirectFromMessage?userId=" + element.getId() + "&path=" + StringHelper.encodeUrl("/" + path); return buildTagFor(resolveUrl(baseUrl, pathPart)); } @Override public String generateLinkForMailChangeValidation(final PendingEmailChange change) { return buildTagFor(getMailChangeValidationUrl(change)); } @Override public String generateLinkForMailValidation(final MemberGroup group, final String key) { return buildTagFor(getMailValidationUrl(group, key)); } @Override public String getMailChangeValidationUrl(final PendingEmailChange change) { final String baseUrl = getBaseUrl(change.getMember()); final String pathPart = "/do/redirectFromMessage?userId=" + change.getMember().getId() + "&path=/do/member/validateEmailChange?key=" + change.getValidationKey(); return resolveUrl(baseUrl, pathPart); } @Override public String getMailValidationUrl(final MemberGroup group, final String key) { final String baseUrl = getBaseUrl(group); final String pathPart = "/do/validateRegistration?key=" + key; return resolveUrl(baseUrl, pathPart); } @Override public String getRootUrl(final Element element) { return getBaseUrl(element) + "/"; } public void setGroupService(final GroupService groupService) { this.groupService = groupService; } public void setMessageHelper(final MessageHelper messageHelper) { this.messageHelper = messageHelper; } public void setSettingsService(final SettingsService settingsService) { this.settingsService = settingsService; } /** * Build the anchor tag for the given url, using a message key 'message.link.label' to retrieve the label */ private String buildTagFor(final String url) { final String label = messageHelper.message("message.link.label"); return buildTagFor(url, label); } /** * Build the anchor tag for the given url, with a given label key */ private String buildTagFor(final String url, final String label) { return "<a class=\"default\" href=\"" + url + "\">" + label + "</a>"; } private String getBaseUrl(final Element element) { SystemGroup group; if (element instanceof Operator) { group = (SystemGroup) loadGroup(((Operator) element).getMember().getGroup().getId()); } else { group = (SystemGroup) loadGroup(element.getGroup().getId()); } return getBaseUrl(group); } private String getBaseUrl(SystemGroup group) { // As there is no FetchServiceLocal here, load the group again with the correct relationships group = (SystemGroup) loadGroup(group.getId()); // Attempt by group String url = group.getRootUrl(); if (StringUtils.isEmpty(url)) { // Not found on group. Attempt on group filters final Collection<GroupFilter> groupFilters = group.getGroupFilters(); for (final GroupFilter groupFilter : groupFilters) { if (StringUtils.isNotEmpty(groupFilter.getRootUrl())) { url = groupFilter.getRootUrl(); break; } } } if (StringUtils.isEmpty(url)) { // Get the system default url = settingsService.getLocalSettings().getRootUrl(); } if (StringUtils.isEmpty(url)) { // None found?!? Should be required on settings!!! LOG.error("No root url was found when generating a link"); return ""; } // Make sure the trailing / is removed return StringUtils.removeEnd(url, "/"); } private Group loadGroup(final Long id) { return LoggedUser.runAsSystem(new Callable<Group>() { @Override public Group call() throws Exception { return groupService.load(id, Group.Relationships.GROUP_FILTERS); } }); } private String resolveUrl(final String baseUrl, String pathPart) { if (baseUrl.contains("?")) { // As the base url already contains a '?', it is assumed that the rest is a parameter to it, like: // http://baseUrl?param=<the rest of the path should be escaped> try { pathPart = URLEncoder.encode(pathPart, "UTF-8"); } catch (final UnsupportedEncodingException e) { throw new IllegalStateException(e); } } return baseUrl + pathPart; } }