You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Dan Allen <da...@mojavelinux.com> on 2003/03/20 15:23:26 UTC

logic tag addition proposal

While coding my new application in struts, I came across what I deam
to be a missing feature in the struts taglibs.  As I present the
problem and the solution I came up with, hopefully it will become
clear that this tag is a good idea.

On a particular page, call it a profile page, I was putting together
member information, which included a headshot, contact information
and a description.  My delimmea came when I created the <html:img>
tag to the headshot.  Since not every member had a headshot, the
image would appear broken in the browser if it was missing (the
headshot was just the member id + ".jpg" in the headshot directory.
The problem was, there was no way for me to know (unless i kept an
entry in the database and even that could get out of sync) whether
or not the image existed before displaying it.  If the image was
missing, I would want to do something else, like either put a
placeholder image in there or just display nothing.  So I came up
with an idea for a logic tag.  It would look like the following

<logic:exists page="/assets/graphics/headshots/${member.id}/.jpg">
    <html:img page="/assets/graphics/headshots/${member.id}/.jpg"/>
</logic:exists>

* I am also thinking it might be nice if the tag also did a "set"
call using the "id" and "toScope" like the bean define.

Right now I have it in a taglib called "file" and hence I use
<file:exists> but really, the view really shouldn't be moving around
files, so there is not real need for a whole set of file taglibs.
Below I have included the sourcecode, which I actually based off of
the struts-el library since that is what I use in my application.

Please provide any feedback and perhaps souce code changes to make
this better.  I really believe this should be part of the view and
if I am the only one that thinks that, so be it, I will use my
taglibs in silence.

Dan

p.s. I still need to do logic:notExists for this, but that is a
small step.  However, if someone feels it would be better to use
<core:choose> and make this a test expression, that could be good
too.  I only started with java and struts 2 weeks ago, so I am still
playing catchup understanding how the taglibs are made.

package net.creativerge.taglib.file;

import java.io.File;

import javax.servlet.jsp.JspException;

import org.apache.struts.taglib.logic.ConditionalTagBase;
import org.apache.taglibs.standard.tag.common.core.NullAttributeException;
import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

public class ELExistsTag extends ConditionalTagBase
{
	/**
	 * The module-relative path, starting with a slash character, of the
	 * file to be checked by this tag.
	 */
	protected String page = null;

	/**
	 * Getter method for "page" tag attribute
	 */
	public String getPage() { return this.page; }

	/**
	 * Setter method for "page" tag attribute
	 */
	public void setPage(String page) { this.page = page; }

	/**
	 * Instance variable mapped to "page" tag attribute
	 */
	private String pageExpr;

	/**
	 * Getter method for "page" tag attribute
	 */
	public String getPageExpr() { return pageExpr; }

	/**
	 * Setter method for "page" tag attribute
	 */
	public void setPageExpr(String pageExpr) { this.pageExpr = pageExpr; }

	/**
	 * Resets attribute values for reuse
	 */
	public void release()
	{
		super.release();
		setPageExpr(null);
	}

	/**
	 * Process the start tag.
	 *
	 * @execption JspException if a jsp exception has occured
	 */
	public int doStartTag() throws JspException
	{
		evaluateExpressions();
		return super.doStartTag();
	}

	/**
	 * Evaluates and returns a single attribute value, given the attribute
	 * name, attribute value, and attribute type.  It uses
	 * <code>ExpressionUtil.evalNotNull</code> to do the actual evaluation, and
	 * it passes to this the name of the current tag, the <code>this</code>
	 * pointer, and the current pageContext.
	 *
	 * @param attrName attribute name being evaluated
	 * @param attrValue String value of attribute to be evaluated using EL
	 * @param attrType Required resulting type of attribute value
	 * @exception NullAttributeException if either the <code>attrValue</code>
	 * was null, or the resulting evaluated value was null.
	 * @return Resulting attribute value
	 */
	private Object evalAttr(
		String attrName,
		String attrValue,
		Class attrType
	) throws JspException, NullAttributeException
	{
		return ExpressionUtil.evalNotNull("exists", attrName, attrValue, attrType, this, pageContext);
	}

	/**
	 * Processes all attribute values which use the JSTL expression evaluation
	 * engine to determine their values.  If any evaluation fails with a
	 * <code>NullAttributeException</code> it will just use <code>null</code>
	 * as the value.
	 *
	 * @exception JspException if a JSP exception has occurred
	 */
	public void evaluateExpressions() throws JspException
	{
		try
		{
			setPage((String) evalAttr("page", getPageExpr(), String.class));
		}
		catch (NullAttributeException e)
		{
		}
	}

	/**
	 * Evaluate the condition that is being tested by this particular tag,
	 * and return <code>true</code> if the nested body content of this tag
	 * should be evaluated, or <code>false</code> if it should be skipped.
	 * This method must be implemented by concrete subclasses.
	 *
	 * @exception JspException if a JSP exception occurs
	 */
	protected boolean condition() throws JspException
	{
		return condition(true);
	}

	/**
	 * Evaluate the condition that is being tested by this particular tag,
	 * and return <code>true</code> if the nested body content of this tag
	 * should be evaluated, or <code>false</code> if it should be skipped.
	 * This method must be implemented by concrete subclasses.
	 *
	 * @param desired Desired outcome for a true result
	 *
	 * @exception JspException if a JSP exception occurs
	 */
	protected boolean condition(boolean desired) throws JspException
	{
		boolean exists = false;

		if (page != null)
		{
			exists = new File(pageContext.getServletContext().getRealPath(page)).exists();
		}

		return (exists == desired);
	}
}

package net.creativerge.taglib.file;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;

/**
 * This is the <code>BeanInfo</code> descriptor for the
 * <code>net.creativerge.taglib.file.ELExistsTag</code> class.  It is
 * needed to override the default mapping of custom tag attribute names to
 * class attribute names.
 *<p>
 * In particular, it provides for the mapping of the custom tag attribute
 * <code>collection</code> to the class attribute <code>collectionExpr</code>.
 *<p>
 */
public class ELExistsTagBeanInfo extends SimpleBeanInfo
{
    public PropertyDescriptor[] getPropertyDescriptors()
    {
        PropertyDescriptor[] result = new PropertyDescriptor[1];
        try
		{
            result[0] = new PropertyDescriptor("page", ELExistsTag.class, null, "setPageExpr");
		}
		catch (IntrospectionException e)
		{
			e.printStackTrace();
		}

		return result;
	}
}

-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Daniel Allen, <da...@mojavelinux.com>
http://www.mojavelinux.com/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
"If you are going to play the game of trial and error, 
don't be suprised when the results are revealing. -- me"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org