Bug 11857

Summary: Enhancement on FormatTagSupport
Product: Taglibs Reporter: Bruno Blaise <bruno.blaise>
Component: I18N TaglibAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED WONTFIX    
Severity: enhancement    
Priority: P3    
Version: 1.0   
Target Milestone: ---   
Hardware: All   
OS: All   

Description Bruno Blaise 2002-08-20 13:49:33 UTC
Hi,

I have a proposition for you to lookup in a bean (same technics use in struts).


Example in JSP:

  <i18n:formatDate name="ligne" property="DatePrestation" style="short"/>

The i18n.tld have to be modified: value Not Mandatory and introduce two new
attributes:

        <attribute>
            <name>name</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
            <type>String</type>
        </attribute>
        <attribute>
            <name>property</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>String</type>
        </attribute>


Into FormatTagSupport.java, I have introduced two String _name and _property and
two protected methods "lookup" and getValue has been modified.

I did some tests with FormatNumber and FormatDate and It works... :-) I hope
that you will be interested by this enhancement.

Kind regards.

Bruno Blaise

Please see the following code:

/*
 * $Header:
/home/cvs/jakarta-taglibs/i18n/src/org/apache/taglibs/i18n/FormatTagSupport.java,v
1.4 2001/10/14 22:01:25 tdawson Exp $
 * $Revision: 1.4 $
 * $Date: 2001/10/14 22:01:25 $
 *
 * ====================================================================
 * 
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:  
 *       "This product includes software developed by the 
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */ 

package org.apache.taglibs.i18n;

import java.io.IOException;
import java.text.Format;
import java.text.DateFormat;
import java.util.Enumeration;
import java.util.Locale;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.commons.beanutils.PropertyUtils;

/** An abstract base class for the formatting tags to provide 
  * implementation inheritence.
  *
  * @author James Strachan
  * @version $Revision: 1.4 $
  */
public abstract class FormatTagSupport extends TagSupport {
    
    String _name     = null;
    String _property = null;
  
    /** the value to be formatted */
    private Object value;    
    /** the locale used to format the value */
    private Locale locale;
    /** the text output if the value is null */
    private String defaultText = "";


    public FormatTagSupport() {
    }
    

    // Tag interface
    //-------------------------------------------------------------------------
    public int doStartTag() throws JspException {
        return EVAL_BODY_INCLUDE;
    }
    
    public int doEndTag() throws JspException {
        try {
            Object value = getValue();
            JspWriter out = pageContext.getOut();
            String text = null;
            if ( value != null ) {
                Format formatter = getFormat();
                if ( formatter == null ) {
                    throw new JspException( "Could not find valid Format
instance" );
                }
                text = formatter.format( value );
            }
            else {
                text = getDefaultText();
            }
            if ( text != null ) {
                out.print( text );
            }
        }
        catch ( IOException e ) {
            handleIOException( e );
        }
        return EVAL_PAGE;
    }
    
    public void release() {
        super.release();
        value = null;
        locale = null;
        defaultText = "";
        _name = null;
        _property = null;
    }
    
    // Properties
    //-------------------------------------------------------------------------    

    public void setName(String name) {
      _name = name;
    }
  
    public void setProperty(String property) {
      _property = property;
    }
  
    public Object getValue() {
        if ( _name == null ) {
            return value;
        }
        
        Object o = lookup( pageContext, _name, _property, null);
        
        return (o==null) ? value : o;
    }
    
    public void setValue( Object value ) {
        this.value = value;
    }

    /** If no {@link java.util.Locale} has been explicitly configured then use the
      * parent LocaleTag if present else the Locale from the ServletRequest
      * else use the default JVM {@link java.util.Locale}.
      */
    public Locale getLocale() {
        if ( locale == null ) {
            return findLocale();
        }
        return locale;
    }
    
    public void setLocale( Locale locale ) {
        this.locale = locale;
    }

    public String getDefaultText() {
        return defaultText;
    }
    
    public void setDefaultText( String defaultText ) {
        this.defaultText = defaultText;
    }

    
    // Implementation methods
    //-------------------------------------------------------------------------
    
    /** Abstract class to return the value formatter 
      */
    protected abstract Format getFormat();    
    
    protected void handleIOException( IOException e ) throws JspException {
        pageContext.getServletContext().log( "Caught: IOException: " + e );
        throw new JspException( "IOException: " + e );
    }

    /** finds the current locale from either an outer LocaleTag or the 
      * current SerlvetRequest or the current JVM.
      *
      * @return a Locale instance
      */
    protected Locale findLocale() {
        // lets try find a LocaleTag first
        LocaleTag localeTag = (LocaleTag) findAncestorWithClass( this,
LocaleTag.class );
        if ( localeTag != null ) {
            return localeTag.getLocale();
        }
        else {
            return pageContext.getResponse().getLocale();
        }
    }
    
    
    /** A helper method for date, datetime & time based formatting tags.
      * This method converts a string into a DateFormat style code.
      */
    protected int getStyleCode( String style ) {
        if ( "short".equalsIgnoreCase( style ) ) {
            return DateFormat.SHORT; 
        }
        else if ( "medium".equalsIgnoreCase( style ) ) {
            return DateFormat.MEDIUM; 
        }
        else if ( "long".equalsIgnoreCase( style ) ) {
            return DateFormat.LONG; 
        }
        else if ( "full".equalsIgnoreCase( style ) ) {
            return DateFormat.FULL; 
        }
        else {
            return DateFormat.SHORT;
        }
    }
    
        /**
     * Locate and return the specified bean, from an optionally specified
     * scope, in the specified page context.  If no such bean is found,
     * return <code>null</code> instead.  If an exception is thrown, it will
     * have already been saved via a call to <code>saveException()</code>.
     *
     * @param pageContext Page context to be searched
     * @param name Name of the bean to be retrieved
     * @param scope Scope to be searched (page, request, session, application)
     *  or <code>null</code> to use <code>findAttribute()</code> instead
     *
     * @exception JspException if an invalid scope name
     *  is requested
     */
    protected Object lookup(PageContext pageContext, String name,
                                String scope) {

        Object bean = null;
        if (scope == null)
            bean = pageContext.findAttribute(name);
        else if (scope.equalsIgnoreCase("page"))
            bean = pageContext.getAttribute(name, PageContext.PAGE_SCOPE);
        else if (scope.equalsIgnoreCase("request"))
            bean = pageContext.getAttribute(name, PageContext.REQUEST_SCOPE);
        else if (scope.equalsIgnoreCase("session"))
            bean = pageContext.getAttribute(name, PageContext.SESSION_SCOPE);
        else if (scope.equalsIgnoreCase("application"))
            bean = pageContext.getAttribute(name, PageContext.APPLICATION_SCOPE);
        return (bean);

    }


    /**
     * Locate and return the specified property of the specified bean, from
     * an optionally specified scope, in the specified page context.  If an
     * exception is thrown, it will have already been saved via a call to
     * <code>saveException()</code>.
     *
     * @param pageContext Page context to be searched
     * @param name Name of the bean to be retrieved
     * @param property Name of the property to be retrieved, or
     *  <code>null</code> to retrieve the bean itself
     * @param scope Scope to be searched (page, request, session, application)
     *  or <code>null</code> to use <code>findAttribute()</code> instead
     *
     * @exception JspException if an invalid scope name
     *  is requested
     * @exception JspException if the specified bean is not found
     * @exception JspException if accessing this property causes an
     *  IllegalAccessException, IllegalArgumentException,
     *  InvocationTargetException, or NoSuchMethodException
     */
    protected Object lookup(PageContext pageContext, String name,
                                String property, String scope) {

        // Look up the requested bean, and return if requested
        Object bean = lookup(pageContext, name, scope);
        if (bean == null) {
            return null;
        }
        if (property == null)
            return (bean);

        // Locate and return the specified property
        try {
            return (PropertyUtils.getProperty(bean, property));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

}
Comment 1 Bruno Blaise 2002-08-20 14:02:45 UTC
I have to be honnest with the Struts's team. This technic (and the majority of
this methods: lookup, setName and setProperty, thus 99% of the code) has been
extracted from this beautiful framework.

And I did, as well, the following imports: 

  import java.beans.BeanInfo; 
  import java.beans.Introspector;
  import java.beans.IntrospectionException;
  import java.beans.PropertyDescriptor;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;

  import org.apache.commons.beanutils.PropertyUtils;

I don't know if you agree to import theses packages?
Comment 2 Henri Yandell 2009-07-10 00:33:41 UTC
JSTL replaced the i18n taglib, so this won't be worked on.