package com.psddev.cms.db; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.tagext.DynamicAttributes; import javax.servlet.jsp.tagext.TryCatchFinally; import com.psddev.dari.db.Recordable; import com.psddev.dari.db.State; import com.psddev.dari.util.JspUtils; import com.psddev.dari.util.ObjectUtils; import com.psddev.dari.util.StringUtils; /** * Equivalent to the HTML {@code A} tag where its {@code href} attribute * may be set to a URL or a Dari object. Note that the context path will * automatically be prepended to the final URL. */ public class AnchorTag extends BodyTagSupport implements DynamicAttributes, TryCatchFinally { private static final long serialVersionUID = 1L; private Object href; private final Map<String, String> attributes = new LinkedHashMap<String, String>(); public Object getHref() { return href; } public void setHref(Object href) { this.href = href; } // --- TagSupport support --- @Override public int doStartTag() throws JspException { return EVAL_BODY_BUFFERED; } @Override public int doEndTag() throws JspException { Object href = getHref(); String hrefString = null; if (href == null) { hrefString = null; } else if (href instanceof String || href instanceof URI || href instanceof URL) { hrefString = href.toString(); } else if (href instanceof Content) { hrefString = ((Content) href).getPermalink(); } else { hrefString = State.getInstance(href).as(Directory.ObjectModification.class).getPermalink(); } if (!ObjectUtils.isBlank(hrefString)) { hrefString = JspUtils.getAbsolutePath((HttpServletRequest) pageContext.getRequest(), hrefString); hrefString = StringUtils.escapeHtml(hrefString); } else { hrefString = ""; } try { JspWriter writer = pageContext.getOut(); if (!hrefString.isEmpty()) { writer.print("<a href=\""); writer.print(hrefString); writer.print("\""); for (Map.Entry<String, String> e : attributes.entrySet()) { String key = e.getKey(); String value = e.getValue(); if (!(ObjectUtils.isBlank(key) || ObjectUtils.isBlank(value))) { writer.print(" "); writer.print(StringUtils.escapeHtml(key)); writer.print("=\""); writer.print(StringUtils.escapeHtml(value)); writer.print("\""); } } writer.print(">"); } String body = null; if (bodyContent != null) { body = bodyContent.getString(); } if (ObjectUtils.isBlank(body)) { if (href instanceof Recordable) { body = ((Recordable) href).getState().getLabel(); if (ObjectUtils.isBlank(body)) { body = ""; } else { body = StringUtils.escapeHtml(body); } } else { body = ""; } } writer.print(body); if (!hrefString.isEmpty()) { writer.print("</a>"); } } catch (IOException ex) { throw new JspException(ex); } return EVAL_PAGE; } // --- DynamicAttribute support --- @Override public void setDynamicAttribute(String uri, String localName, Object value) { attributes.put(localName, value != null ? value.toString() : null); } // --- TryCatchFinally support --- @Override public void doCatch(Throwable error) throws Throwable { throw error; } @Override public void doFinally() { setHref(null); attributes.clear(); } }