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 <useList> 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>