You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2002/10/17 09:51:31 UTC

cvs commit: jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/bean suite.jelly

jstrachan    2002/10/17 00:51:31

  Modified:    jelly/src/java/org/apache/commons/jelly/tags/bean
                        BeanTagLibrary.java BeanPropertyTag.java
               jelly/src/java/org/apache/commons/jelly/tags/core
                        UseListTag.java
               jelly/src/test/org/apache/commons/jelly/bean suite.jelly
  Added:       jelly/src/java/org/apache/commons/jelly/tags/bean
                        BeanTag.java
               jelly/src/java/org/apache/commons/jelly/impl
                        CollectionTag.java
  Log:
  Added support for CollectionTag so that the bean tag library can be used to make collections of beans easily.
  
  Also refactored the bean tag library implementation a little so that both bean and property based tags work share the processing code (adding themselves to their parent via a setter, adder or a parent CollectionTag)
  
  Revision  Changes    Path
  1.2       +1 -2      jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/bean/BeanTagLibrary.java
  
  Index: BeanTagLibrary.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/bean/BeanTagLibrary.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BeanTagLibrary.java	16 Oct 2002 18:17:57 -0000	1.1
  +++ BeanTagLibrary.java	17 Oct 2002 07:51:31 -0000	1.2
  @@ -68,7 +68,6 @@
   import org.apache.commons.jelly.TagLibrary;
   import org.apache.commons.jelly.impl.TagFactory;
   import org.apache.commons.jelly.impl.TagScript;
  -import org.apache.commons.jelly.tags.core.UseBeanTag;
   
   import org.xml.sax.Attributes;
   
  @@ -135,7 +134,7 @@
           // is the name bound to a specific class
           Class beanType = getBeanType(name, attributes);
           if (beanType != null) {
  -            return new UseBeanTag(beanType);
  +            return new BeanTag(beanType, name);
           }
           
           // its a property tag
  
  
  
  1.2       +9 -79     jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/bean/BeanPropertyTag.java
  
  Index: BeanPropertyTag.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/bean/BeanPropertyTag.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BeanPropertyTag.java	16 Oct 2002 18:17:57 -0000	1.1
  +++ BeanPropertyTag.java	17 Oct 2002 07:51:31 -0000	1.2
  @@ -73,8 +73,6 @@
   import org.apache.commons.jelly.MissingAttributeException;
   import org.apache.commons.jelly.TagSupport;
   import org.apache.commons.jelly.XMLOutput;
  -import org.apache.commons.jelly.impl.BeanSource;
  -import org.apache.commons.jelly.tags.core.UseBeanTag;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  @@ -88,7 +86,7 @@
    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
    * @version $Revision$
    */
  -public class BeanPropertyTag extends UseBeanTag {
  +public class BeanPropertyTag extends BeanTag {
   
       /** empty arguments constant */
       private static final Object[] EMPTY_ARGS = {};
  @@ -100,34 +98,22 @@
       private static final Log log = LogFactory.getLog(BeanPropertyTag.class);
   
   
  -    /** the name of the property to create */
  -    private String propertyName;
  -
       /** the name of the create method */
       private String createMethodName;
   
  -    /** the name of the adder method */
  -    private String addMethodName;
  -
       
  -    public BeanPropertyTag(String propertyName) {
  -        super(Object.class);
  -        
  -        this.propertyName = propertyName;
  -        
  -        int length = propertyName.length();
  -        if (length > 0) {
  +    public BeanPropertyTag(String tagName) {
  +        super(Object.class, tagName);
  +
  +        if (tagName.length() > 0) {
               createMethodName = "create" 
  -                + propertyName.substring(0,1).toUpperCase() 
  -                + propertyName.substring(1);
  -            addMethodName = "add" 
  -                + propertyName.substring(0,1).toUpperCase() 
  -                + propertyName.substring(1);
  +                + tagName.substring(0,1).toUpperCase() 
  +                + tagName.substring(1);
           }
       }
       
       /**
  -     * Creates a new instance, try finding a parent property.
  +     * Creates a new instance by calling a create method on the parent bean
        */
       protected Object newInstance(Class theClass, Map attributes, XMLOutput output) throws Exception {
           Object parentObject = getParentObject();
  @@ -145,43 +131,12 @@
               }
           }
           else {
  -            throw new JellyException( "The " + propertyName + " tag must be nested within a tag which maps to a bean property" );
  +            throw new JellyException( "The " + getTagName() + " tag must be nested within a tag which maps to a bean property" );
           }
           return null;
       }
       
       /**
  -     * By default this will export the bean using the given variable if it is defined.
  -     * This Strategy method allows derived tags to process the beans in different ways
  -     * such as to register this bean with its parent tag etc.
  -     */
  -    protected void processBean(String var, Object bean) throws Exception {
  -        if (var != null) {
  -            context.setVariable(var, bean);
  -        }
  -        
  -        // now lets try set the parent property via calling the adder or the setter method
  -        Object parentObject = getParentObject();
  -        if (parentObject != null && bean != null) {
  -            // lets see if there's a setter method...
  -            Method method = findAddMethod(parentObject.getClass(), bean.getClass());
  -            if (method != null) {
  -                Object[] args = { bean };
  -                try {
  -                    method.invoke(parentObject, args);
  -                }
  -                catch (Exception e) {
  -                    throw new JellyException( "failed to invoke method: " + method + " on bean: " + parentObject + " reason: " + e, e );
  -                }
  -            }
  -            else {
  -                BeanUtils.setProperty(parentObject, propertyName, bean);
  -            }
  -            
  -        }
  -    }
  -
  -    /**
        * Finds the Method to create a new property object
        */
       protected Method findCreateMethod(Class theClass) {
  @@ -192,29 +147,4 @@
               theClass, createMethodName, EMPTY_ARG_TYPES
           );
       }    
  -
  -    /**
  -     * Finds the Method to add the new bean
  -     */
  -    protected Method findAddMethod(Class beanClass, Class valueClass) {
  -        if (addMethodName == null) {
  -            return null;
  -        }
  -        Class[] argTypes = { valueClass };
  -        return MethodUtils.getAccessibleMethod(
  -            beanClass, addMethodName, argTypes
  -        );
  -    }
  -        
  -        
  -    /**
  -     * @return the parent bean object
  -     */
  -    protected Object getParentObject() throws Exception {
  -        BeanSource tag = (BeanSource) findAncestorWithClass(BeanSource.class);
  -        if (tag != null) {
  -            return tag.getBean();
  -        }
  -        return null;
  -    }        
   }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/bean/BeanTag.java
  
  Index: BeanTag.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/taglibs/beanshell/src/java/org/apache/commons/jelly/tags/beanshell/BeanShellExpressionFactory.java,v 1.1 2002/05/21 07:58:55 jstrachan Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/21 07:58:55 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 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", "Commons", 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/>.
   * 
   * $Id: BeanShellExpressionFactory.java,v 1.1 2002/05/21 07:58:55 jstrachan Exp $
   */
  
  package org.apache.commons.jelly.tags.bean;
  
  import java.lang.reflect.Method;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.apache.commons.beanutils.BeanUtils;
  import org.apache.commons.beanutils.MethodUtils;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.MissingAttributeException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.impl.BeanSource;
  import org.apache.commons.jelly.impl.CollectionTag;
  import org.apache.commons.jelly.tags.core.UseBeanTag;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  
  /** 
   * Creates a bean for the given tag which is then either output as a variable
   * or can be added to a parent tag.
   * 
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
   * @version $Revision: 1.1 $
   */
  public class BeanTag extends UseBeanTag {
  
      /** empty arguments constant */
      private static final Object[] EMPTY_ARGS = {};
      
      /** empty argument types constant */
      private static final Class[] EMPTY_ARG_TYPES = {};
  
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(BeanTag.class);
  
  
      /** the name of the property to create */
      private String tagName;
  
      /** the name of the adder method */
      private String addMethodName;
  
      
      public BeanTag(Class defaultClass, String tagName) {
          super(defaultClass);
          this.tagName = tagName;
          
          if (tagName.length() > 0) {
              addMethodName = "add" 
                  + tagName.substring(0,1).toUpperCase() 
                  + tagName.substring(1);
          }
      }
  
      /**
       * @return the local name of the XML tag to which this tag is bound
       */
      public String getTagName() {
          return tagName;
      }
  
      /**
       * Output the tag as a named variable. If the parent bean has an adder or setter
       * method then invoke that to register this bean with its parent.
       */
      protected void processBean(String var, Object bean) throws Exception {
          if (var != null) {
              context.setVariable(var, bean);
          }
          
          // now lets try set the parent property via calling the adder or the setter method
          if (bean != null) {
              Object parentObject = getParentObject();
              if (parentObject != null) {
                  if (parentObject instanceof Collection) {
                      Collection collection = (Collection) parentObject;
                      collection.add(bean);
                  }
                  else {
                      // lets see if there's a setter method...
                      Method method = findAddMethod(parentObject.getClass(), bean.getClass());
                      if (method != null) {
                          Object[] args = { bean };
                          try {
                              method.invoke(parentObject, args);
                          }
                          catch (Exception e) {
                              throw new JellyException( "failed to invoke method: " + method + " on bean: " + parentObject + " reason: " + e, e );
                          }
                      }
                      else {
                          BeanUtils.setProperty(parentObject, tagName, bean);
                      }
                  }
                  
              }
              else {
                  // lets try find a parent List to add this bean to
                  CollectionTag tag = (CollectionTag) findAncestorWithClass(CollectionTag.class);
                  if (tag != null) {
                      tag.addItem(bean);
                  }
                  else {
                      log.warn( "Could not add bean to parent for bean: " + bean );
                  }
              }
          }
              
      }
  
      /**
       * Finds the Method to add the new bean
       */
      protected Method findAddMethod(Class beanClass, Class valueClass) {
          if (addMethodName == null) {
              return null;
          }
          Class[] argTypes = { valueClass };
          return MethodUtils.getAccessibleMethod(
              beanClass, addMethodName, argTypes
          );
      }
          
          
      /**
       * @return the parent bean object
       */
      protected Object getParentObject() throws Exception {
          BeanSource tag = (BeanSource) findAncestorWithClass(BeanSource.class);
          if (tag != null) {
              return tag.getBean();
          }
          return null;
      }        
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/impl/CollectionTag.java
  
  Index: CollectionTag.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/IfTag.java,v 1.6 2002/05/17 15:18:08 jstrachan Exp $
   * $Revision: 1.6 $
   * $Date: 2002/05/17 15:18:08 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 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", "Commons", 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/>.
   * 
   * $Id: IfTag.java,v 1.6 2002/05/17 15:18:08 jstrachan Exp $
   */
  package org.apache.commons.jelly.impl;
  
  /** 
   * A tag which is capable of consuming objects, such as a &lt;useList&gt; tag
   * such that nested objects will be added to the parent tag.
   *
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
   * @version $Revision: 1.6 $
   */
  public interface CollectionTag {
  
      /** 
       * @return adds an item to the tags collection
       */
      public void addItem(Object value);
  }
  
  
  
  1.3       +8 -1      jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/UseListTag.java
  
  Index: UseListTag.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/UseListTag.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- UseListTag.java	30 Sep 2002 17:46:59 -0000	1.2
  +++ UseListTag.java	17 Oct 2002 07:51:31 -0000	1.3
  @@ -62,6 +62,7 @@
   import java.util.Map;
   
   import org.apache.commons.jelly.expression.Expression;
  +import org.apache.commons.jelly.impl.CollectionTag;
   
   /** 
    * A tag which creates a List implementation and optionally 
  @@ -73,7 +74,7 @@
    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
    * @version $Revision$
    */
  -public class UseListTag extends UseBeanTag {
  +public class UseListTag extends UseBeanTag implements CollectionTag {
   
       private Expression items;
       
  @@ -85,6 +86,12 @@
       }
       
   
  +    // CollectionTag interface
  +    //-------------------------------------------------------------------------                    
  +    public void addItem(Object value) {
  +        getList().add(value);
  +    }
  +    
       // DynaTag interface
       //-------------------------------------------------------------------------                    
       public Class getAttributeType(String name) throws Exception {
  
  
  
  1.2       +50 -1     jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/bean/suite.jelly
  
  Index: suite.jelly
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/bean/suite.jelly,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- suite.jelly	16 Oct 2002 18:17:57 -0000	1.1
  +++ suite.jelly	17 Oct 2002 07:51:31 -0000	1.2
  @@ -6,7 +6,7 @@
   	xmlns:test="jelly:junit" 
   	xmlns:log="jelly:log">
   
  -<test:case name="simpleBean">
  +<test:case name="testNestedBean">
   
   	<customer var="c1" name="James" location="London" >
   		<order amount="100" price="2.99">
  @@ -41,6 +41,55 @@
   	<test:assertEquals expected="Pizza" actual="${c1.orders[1].product.name}"/>
   	
   	
  +</test:case>
  +
  +
  +<test:case name="testBeanList">
  +
  +	<j:useList var="list">
  +		<customer name="James" location="London">
  +			<order amount="100" price="2.99">
  +				<product id="p1" name="Beer"/>
  +			</order>
  +			<order amount="200" price="4.99">
  +				<product id="p2" name="Pizza"/>
  +			</order>
  +	  </customer>
  +		<customer name="Bob" location="Atlanta">
  +			<order amount="200" price="2.99">
  +				<product id="p1" name="Beer"/>
  +			</order>
  +	  </customer>
  +	</j:useList>
  +	  
  +	<log:info>Created a list of customers ${list}</log:info>
  +
  +	<test:assertTrue test="${size(list) == 2}"/>
  +
  +	<test:assertEquals expected="James" actual="${list[0].name}"/>
  +	<test:assertEquals expected="London" actual="${list[0].location}"/>
  +
  +	<test:assertTrue test="${size(list[0].orders) == 2}"/>
  +
  +	<test:assertTrue test="${list[0].orders[0].amount == 100}"/>
  +	<test:assertTrue test="${list[0].orders[0].price == 2.99}"/>
  +	
  +	<test:assertTrue test="${list[0].orders[1].amount == 200}"/>
  +	<test:assertTrue test="${list[0].orders[1].price == 4.99}"/>
  +
  +	<test:assertTrue test="${list[0].orders[0].product != null}"/>
  +	<test:assertTrue test="${list[0].orders[1].product != null}"/>
  +	
  +	<test:assertEquals expected="p1" actual="${list[0].orders[0].product.id}"/>
  +	<test:assertEquals expected="Beer" actual="${list[0].orders[0].product.name}"/>
  +
  +	<test:assertEquals expected="p2" actual="${list[0].orders[1].product.id}"/>
  +	<test:assertEquals expected="Pizza" actual="${list[0].orders[1].product.name}"/>
  +	
  +	
  +	<test:assertEquals expected="Bob" actual="${list[1].name}"/>
  +	<test:assertEquals expected="Atlanta" actual="${list[1].location}"/>
  +
   </test:case>
   
   </test:suite>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>