rwaldhoff 2002/11/29 23:41:21
Modified: jelly/src/java/org/apache/commons/jelly/tags/core
ArgTag.java InvokeTag.java NewTag.java
UseBeanTag.java
jelly/src/test/org/apache/commons/jelly/core TestNewTag.java
Added: jelly/src/test/org/apache/commons/jelly/core TestArgTag.java
Log:
cleanup ArgTag
add tests
Revision Changes Path
1.2 +184 -80
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/ArgTag.java
Index: ArgTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/ArgTag.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ArgTag.java 28 Nov 2002 00:22:23 -0000 1.1
+++ ArgTag.java 30 Nov 2002 07:41:21 -0000 1.2
@@ -2,7 +2,6 @@
* $Header$
* $Revision$
* $Date$
- *
* ====================================================================
*
* The Apache Software License, Version 1.1
@@ -61,122 +60,98 @@
*/
package org.apache.commons.jelly.tags.core;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+import org.apache.commons.beanutils.converters.BooleanConverter;
+import org.apache.commons.beanutils.converters.ByteConverter;
+import org.apache.commons.beanutils.converters.CharacterConverter;
+import org.apache.commons.beanutils.converters.DoubleConverter;
+import org.apache.commons.beanutils.converters.FloatConverter;
+import org.apache.commons.beanutils.converters.IntegerConverter;
+import org.apache.commons.beanutils.converters.LongConverter;
+import org.apache.commons.beanutils.converters.ShortConverter;
import org.apache.commons.jelly.JellyException;
import org.apache.commons.jelly.XMLOutput;
-import org.apache.commons.jelly.expression.Expression;
-/** An argument to a {@link NewTag} or {@link InvokeTag}.
- * This tag MUST be enclosed within an {@link ArgTagParent}
- * implementation.
- *
- * @author Rodney Waldhoff
- * @version $Revision$
- */
+/**
+ * An argument to a {@link NewTag} or {@link InvokeTag}.
+ * This tag MUST be enclosed within an {@link ArgTagParent}
+ * implementation.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision$
+ */
public class ArgTag extends BaseClassLoaderTag {
+
+ // constructors
+ //-------------------------------------------------------------------------
- /** The name of the parameter type, if any. */
- private String typeString;
-
- /** An {@link Expression} describing the parameter value. */
- private Expression valueExpression;
-
- /** The parameter value as {@link #setValueObject set} by some child tag (if
any). */
- private Object valueObject;
-
public ArgTag() {
}
- /** The name of the parameter type, if any. */
+ // attribute setters
+ //-------------------------------------------------------------------------
+
+ /**
+ * The name of the argument class or type, if any.
+ * This may be a fully specified class name or
+ * a primitive type name
+ * (<code>boolean<code>, <code>int</code>, <code>double</code>, etc.).
+ */
public void setType(String type) {
this.typeString = type;
}
- /** The parameter value. */
- public void setValue(Expression value) {
- this.valueExpression= value;
- }
-
- /** (used by child tags) */
- public void setValueObject(Object object) {
- this.valueObject = object;
+ /** The (possibly null) value of this argument. */
+ public void setValue(Object value) {
+ this.value= value;
}
- // Tag interface
- //-------------------------------------------------------------------------
+ // tag methods
+ //-------------------------------------------------------------------------
+
public void doTag(XMLOutput output) throws Exception {
invokeBody(output);
- if(null != valueObject && null != valueExpression) {
- throw new JellyException("Either the value parameter or a value-setting
child element can be provided, but not both.");
- }
+
Class klass = null;
- Object value = valueObject;
- if(null == value && null != valueExpression) {
- value = valueExpression.evaluate(context);
- }
if("boolean".equals(typeString)) {
klass = Boolean.TYPE;
- assertNotNull(value);
- if(!(value instanceof Boolean) && null != valueExpression) {
- value = new Boolean(valueExpression.evaluateAsBoolean(context));
- }
- assertInstanceOf(Boolean.class,value);
+ assertNotNull(value);
} else if("byte".equals(typeString)) {
klass = Byte.TYPE;
assertNotNull(value);
- if(!(value instanceof Byte) && null != valueExpression) {
- value = new Byte(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Byte.class,value);
} else if("short".equals(typeString)) {
klass = Short.TYPE;
assertNotNull(value);
- if(!(value instanceof Short) && null != valueExpression) {
- value = new Short(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Short.class,value);
} else if("int".equals(typeString)) {
klass = Integer.TYPE;
assertNotNull(value);
- if(!(value instanceof Integer) && null != valueExpression) {
- value = new Integer(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Integer.class,value);
} else if("char".equals(typeString)) {
klass = Character.TYPE;
assertNotNull(value);
- if(!(value instanceof Character) && null != valueExpression) {
- value = new
Character(valueExpression.evaluateAsString(context).charAt(0));
- }
- assertInstanceOf(Character.class,value);
} else if("float".equals(typeString)) {
klass = Float.TYPE;
assertNotNull(value);
- if(!(value instanceof Float) && null != valueExpression) {
- value = new Float(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Float.class,value);
} else if("long".equals(typeString)) {
klass = Long.TYPE;
assertNotNull(value);
- if(!(value instanceof Long) && null != valueExpression) {
- value = new Long(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Long.class,value);
} else if("double".equals(typeString)) {
klass = Double.TYPE;
assertNotNull(value);
- if(!(value instanceof Double) && null != valueExpression) {
- value = new Double(valueExpression.evaluateAsString(context));
- }
- assertInstanceOf(Double.class,value);
} else if(null != typeString) {
klass = getClassLoader().loadClass(typeString);
- assertInstanceOf(klass,value);
- } else if(null == value) {
+ } else if(null == value) { // and (by construction) null == typeString
klass = Object.class;
} else {
klass = value.getClass();
}
+
+ if(!isInstanceOf(klass,value)) {
+ value = convert(klass,value);
+ }
ArgTagParent parent =
(ArgTagParent)findAncestorWithClass(ArgTagParent.class);
if(null == parent) {
@@ -186,19 +161,148 @@
}
}
+ // private methods
+ //-------------------------------------------------------------------------
+
private void assertNotNull(Object value) throws JellyException {
if(null == value) {
throw new JellyException("A " + typeString + " instance cannot be
null.");
}
}
- private void assertInstanceOf(Class klass, Object value) throws JellyException {
- if(null != klass && null != value && (!klass.isInstance(value))) {
- if(null != valueExpression) {
- throw new JellyException("Can't create a " + typeString + "
instance from the expression " + valueExpression);
+ private boolean isInstanceOf(Class klass, Object value) {
+ return (null == value || (klass.isInstance(value)));
+ }
+
+ // attibutes
+ //-------------------------------------------------------------------------
+
+ /** The name of the parameter type, if any. */
+ private String typeString;
+
+ /** The value of the parameter, if any */
+ private Object value;
+
+ // static stuff
+ //-------------------------------------------------------------------------
+
+ private static Object convert(Class klass, Object value) throws JellyException {
+ if(null == value) {
+ return null;
+ } else if(!klass.isInstance(value)) {
+ Converter converter = (Converter)(converterMap.get(klass));
+ if(null == converter) {
+ throw new JellyException("Can't convert " + value + " to " + klass);
} else {
- throw new JellyException("Can't create a " + typeString + "
instance from the object " + valueObject);
+ try {
+ return converter.convert(klass,value);
+ } catch(ConversionException e) {
+ throw new JellyException("Can't convert " + value + " to " +
klass + " (" + e.toString() + ")",e);
+ }
}
+ } else {
+ return value;
+ }
+
+ }
+
+ /** My bag of converters, by target Class */
+ private static Map converterMap = new HashMap();
+ // these inner classes should probably move to beanutils
+ static {
+ {
+ Converter c = new BooleanConverter();
+ converterMap.put(Boolean.TYPE,c);
+ converterMap.put(Boolean.class,c);
+ }
+ {
+ Converter c = new CharacterConverter();
+ converterMap.put(Character.TYPE,c);
+ converterMap.put(Character.class,c);
+ }
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Byte(((Number)value).byteValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new ByteConverter();
+ };
+ converterMap.put(Byte.TYPE,c);
+ converterMap.put(Byte.class,c);
+ }
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Short(((Number)value).shortValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new ShortConverter();
+ };
+ converterMap.put(Short.TYPE,c);
+ converterMap.put(Short.class,c);
+ }
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Integer(((Number)value).intValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new IntegerConverter();
+ };
+ converterMap.put(Integer.TYPE,c);
+ converterMap.put(Integer.class,c);
+ }
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Long(((Number)value).longValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new LongConverter();
+ };
+ converterMap.put(Long.TYPE,c);
+ converterMap.put(Long.class,c);
+ }
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Float(((Number)value).floatValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new FloatConverter();
+ };
+ converterMap.put(Float.TYPE,c);
+ converterMap.put(Float.class,c);
}
+ {
+ Converter c = new Converter() {
+ public Object convert(Class klass, Object value) {
+ if(value instanceof Number) {
+ return new Double(((Number)value).doubleValue());
+ } else {
+ return inner.convert(klass,value);
+ }
+ }
+ private Converter inner = new DoubleConverter();
+ };
+ converterMap.put(Double.TYPE,c);
+ converterMap.put(Double.class,c);
+ }
}
}
1.2 +6 -6
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/InvokeTag.java
Index: InvokeTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/InvokeTag.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- InvokeTag.java 29 Nov 2002 15:53:10 -0000 1.1
+++ InvokeTag.java 30 Nov 2002 07:41:21 -0000 1.2
@@ -129,7 +129,7 @@
ArgTag parentArg = (ArgTag)(findAncestorWithClass(ArgTag.class));
if(null != parentArg) {
- parentArg.setValueObject(result);
+ parentArg.setValue(result);
}
if(null != var) {
context.setVariable(var, result);
1.6 +1 -1
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/NewTag.java
Index: NewTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/NewTag.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- NewTag.java 29 Nov 2002 16:07:08 -0000 1.5
+++ NewTag.java 30 Nov 2002 07:41:21 -0000 1.6
@@ -131,7 +131,7 @@
if(null != var) {
context.setVariable(var, object);
} else {
- parentArg.setValueObject(object);
+ parentArg.setValue(object);
}
}
}
1.7 +1 -1
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/UseBeanTag.java
Index: UseBeanTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/UseBeanTag.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- UseBeanTag.java 28 Nov 2002 00:22:23 -0000 1.6
+++ UseBeanTag.java 30 Nov 2002 07:41:21 -0000 1.7
@@ -202,7 +202,7 @@
} else {
ArgTag parentArg = (ArgTag)(findAncestorWithClass(ArgTag.class));
if(null != parentArg) {
- parentArg.setValueObject(bean);
+ parentArg.setValue(bean);
}
}
}
1.2 +5 -6
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/core/TestNewTag.java
Index: TestNewTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/core/TestNewTag.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TestNewTag.java 28 Nov 2002 00:22:23 -0000 1.1
+++ TestNewTag.java 30 Nov 2002 07:41:21 -0000 1.2
@@ -205,5 +205,4 @@
assertEquals("Chicago",customer.getCity());
assertEquals("Location",customer.getLocation());
}
-
}
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/core/TestArgTag.java
Index: TestArgTag.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/core/TestArgTag.java,v
1.1 2002/11/30 07:41:21 rwaldhoff Exp $
* $Revision: 1.1 $
* $Date: 2002/11/30 07:41:21 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 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 [EMAIL PROTECTED]
*
* 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: TestArgTag.java,v 1.1 2002/11/30 07:41:21 rwaldhoff Exp $
*/
package org.apache.commons.jelly.core;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestSuite;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyException;
import org.apache.commons.jelly.Script;
import org.apache.commons.jelly.TagSupport;
import org.apache.commons.jelly.XMLOutput;
import org.apache.commons.jelly.tags.core.ArgTag;
import org.apache.commons.jelly.tags.core.ArgTagParent;
/**
* @author Rodney Waldhoff
* @version $Revision: 1.1 $ $Date: 2002/11/30 07:41:21 $
*/
public class TestArgTag extends BaseJellyTest {
public TestArgTag(String name) {
super(name);
}
public static TestSuite suite() throws Exception {
return new TestSuite(TestArgTag.class);
}
public void setUp() throws Exception {
super.setUp();
parentTag = new MockArgTagParent();
argTag = new ArgTag();
argTag.setContext(getJellyContext());
argTag.setParent(parentTag);
argTag.setBody(new MockScript());
}
public void tearDown() throws Exception {
super.tearDown();
parentTag = null;
argTag = null;
}
public void testToBooleanFromString() throws Exception {
argTag.setType("boolean");
argTag.setValue("true");
argTag.doTag(getXMLOutput());
assertEquals(Boolean.TYPE,parentTag.getType(0));
assertEquals(Boolean.TRUE,parentTag.getValue(0));
}
public void testToCharFromString() throws Exception {
argTag.setType("char");
argTag.setValue("X");
argTag.doTag(getXMLOutput());
assertEquals(Character.TYPE,parentTag.getType(0));
assertEquals(new Character('X'),parentTag.getValue(0));
}
public void testToByteFromString() throws Exception {
argTag.setType("byte");
argTag.setValue("17");
argTag.doTag(getXMLOutput());
assertEquals(Byte.TYPE,parentTag.getType(0));
assertEquals(new Byte((byte)17),parentTag.getValue(0));
}
public void testToByteFromNumber() throws Exception {
argTag.setType("byte");
argTag.setValue(new Double(17.3d));
argTag.doTag(getXMLOutput());
assertEquals(Byte.TYPE,parentTag.getType(0));
assertEquals(new Byte((byte)17),parentTag.getValue(0));
}
public void testToShortFromString() throws Exception {
argTag.setType("short");
argTag.setValue("17");
argTag.doTag(getXMLOutput());
assertEquals(Short.TYPE,parentTag.getType(0));
assertEquals(new Short((short)17),parentTag.getValue(0));
}
public void testToShortFromNumber() throws Exception {
argTag.setType("short");
argTag.setValue(new Double(17.3d));
argTag.doTag(getXMLOutput());
assertEquals(Short.TYPE,parentTag.getType(0));
assertEquals(new Short((short)17),parentTag.getValue(0));
}
public void testToIntFromString() throws Exception {
argTag.setType("int");
argTag.setValue("17");
argTag.doTag(getXMLOutput());
assertEquals(Integer.TYPE,parentTag.getType(0));
assertEquals(new Integer((int)17),parentTag.getValue(0));
}
public void testToIntFromNumber() throws Exception {
argTag.setType("int");
argTag.setValue(new Double(17.3d));
argTag.doTag(getXMLOutput());
assertEquals(Integer.TYPE,parentTag.getType(0));
assertEquals(new Integer((int)17),parentTag.getValue(0));
}
public void testToFloatFromString() throws Exception {
argTag.setType("float");
argTag.setValue("17.3");
argTag.doTag(getXMLOutput());
assertEquals(Float.TYPE,parentTag.getType(0));
assertEquals(new Float((float)17.3),parentTag.getValue(0));
}
public void testToFloatFromNumber() throws Exception {
argTag.setType("float");
argTag.setValue(new Double(17.3d));
argTag.doTag(getXMLOutput());
assertEquals(Float.TYPE,parentTag.getType(0));
assertEquals(new Float((float)17.3),parentTag.getValue(0));
}
public void testToLongFromString() throws Exception {
argTag.setType("long");
argTag.setValue("17");
argTag.doTag(getXMLOutput());
assertEquals(Long.TYPE,parentTag.getType(0));
assertEquals(new Long((int)17),parentTag.getValue(0));
}
public void testToLongFromNumber() throws Exception {
argTag.setType("long");
argTag.setValue(new Double(17.3d));
argTag.doTag(getXMLOutput());
assertEquals(Long.TYPE,parentTag.getType(0));
assertEquals(new Long((long)17),parentTag.getValue(0));
}
public void testToDoubleFromString() throws Exception {
argTag.setType("double");
argTag.setValue("17.3");
argTag.doTag(getXMLOutput());
assertEquals(Double.TYPE,parentTag.getType(0));
assertEquals(new Double((double)17.3),parentTag.getValue(0));
}
public void testToDoubleFromNumber() throws Exception {
argTag.setType("double");
argTag.setValue(new Long(17L));
argTag.doTag(getXMLOutput());
assertEquals(Double.TYPE,parentTag.getType(0));
assertEquals(new Double((double)17),parentTag.getValue(0));
}
public void testToPrimitiveFromNull() throws Exception {
String[] types = { "boolean", "char", "byte", "short", "int", "float",
"long", "double" };
for(int i=0;i<types.length;i++) {
argTag.setType(types[i]);
argTag.setValue(null);
try {
argTag.doTag(getXMLOutput());
fail("Expected JellyException");
} catch (JellyException e) {
// expected
}
}
}
public void testFromNull() throws Exception {
Class[] types = { Boolean.class, Character.class, Byte.class, Short.class,
Integer.class, Float.class, Long.class, Double.class, String.class, Object.class };
for(int i=0;i<types.length;i++) {
argTag.setType(types[i].getName());
argTag.setValue(null);
argTag.doTag(getXMLOutput());
assertEquals(types[i],parentTag.getType(i));
assertNull(parentTag.getValue(i));
}
}
private MockArgTagParent parentTag = null;
private ArgTag argTag = null;
class MockArgTagParent extends TagSupport implements ArgTagParent {
public void addArgument(Class type, Object value) {
typeList.add(type);
valueList.add(value);
}
public void doTag(XMLOutput output) throws Exception {
}
private Class getType(int i) {
return (Class)(typeList.get(i));
}
private Object getValue(int i) {
return valueList.get(i);
}
private List typeList = new ArrayList();
private List valueList = new ArrayList();
}
class MockScript implements Script {
public Script compile() throws Exception {
return this;
}
public void run(JellyContext context, XMLOutput output) throws Exception {
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>