Joachim,
Thanks for reporting this problem. I incorporates your fix, slightly
modified. To avoid checking all those conditions twice, I simply
re-ordered clauses of the big if statement.
Thank you very much for tracking this problem.
- Dmitri
--- Joachim Maes <[EMAIL PROTECTED]> wrote:
> Hi,
>
> I started using JXPath last week (and I am very excited about it!),
> and
> think found a problem in the conversions to String types in
> BasicTypeConverter.
> I ran into it using an extension function that refers to the commons
> StringUtils class. Basically I use the expression
> "stringutils:getChomp(type,'.')". Due to a problem in the type
> conversion from a NodeSet to a String, the actual method gets called
> with String arguments
> "[EMAIL PROTECTED]" and
> ".".
>
> I added tests to the BasicTypeConverterTest class to illustrate the
> problem, and then I made a simple change to BasicTypeConverter to
> make
> the adapted test succeed. Presumably there are other approaches
> possible to resolve the problem (like implementing toString in
> EvalContext$SimpleNodeSet).
>
> Please find both classes/changes in attachment.
>
> Regards,
> Joachim Maes
>
>
> 1) added tests BasicTypeConverterTest :
>
> public void testSingletonCollectionToString() {
> assertConversion(Collections.singleton("Earth"),
> String.class,
> "Earth");
> }
>
> public void testSingletonArrayToString() {
> assertConversion(new String[] {"Earth"}, String.class,
> "Earth");
> }
>
> public void testPointerToString() {
> assertConversion(
> new Pointer() {
> public Object getValue() {
> return "value";
> }
> public Object getNode() {
> return null;
> }
> public void setValue(Object value) {
> }
> public Object getRootNode() {
> return null;
> }
> public String asPath() {
> return null;
> }
> public Object clone() {
> return null;
> }
> public int compareTo(Object o) {
> return 0;
> }
> },
> String.class,
> "value");
> }
>
> public void testNodeSetToString() {
> assertConversion(
> new NodeSet() {
> public List getNodes() {
> return null;
> }
> public List getPointers() {
> return null;
> }
> public List getValues() {
> return Collections.singletonList("hello");
> }
> },
> String.class,
> "hello");
> }
>
> // succeeds in current version
> public void testNodeSetToInteger() {
> assertConversion(
> new NodeSet() {
> public List getNodes() {
> return null;
> }
> public List getPointers() {
> return null;
> }
> public List getValues() {
> return Collections.singletonList("9");
> }
> },
> Integer.class,
> new Integer(9));
> }
>
>
>
> 2) change to BasicTypeConverter at line 223:
>
> if (toType == String.class
> && !(object instanceof Collection)
> && !fromType.isArray()
> && !(object instanceof NodeSet)
> && !(object instanceof Pointer)) {
>
> return object.toString();
> }
>
>
>
> > /*
> * $Header:
>
/home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/util/BasicTypeConverter.java,v
> 1.7 2003/03/11 00:59:34 dmitri Exp $
> * $Revision: 1.7 $
> * $Date: 2003/03/11 00:59:34 $
> *
> *
> ====================================================================
> * The Apache Software License, Version 1.1
> *
> *
> * Copyright (c) 1999-2003 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 and was
> * originally based on software copyright (c) 2001, Plotnix, Inc,
> * <http://www.plotnix.com/>.
> * For more information on the Apache Software Foundation, please see
> * <http://www.apache.org/>.
> */
> package org.apache.commons.jxpath.util;
>
> import java.lang.reflect.Array;
> import java.lang.reflect.Modifier;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.Collections;
> import java.util.HashSet;
> import java.util.Iterator;
> import java.util.List;
> import java.util.Set;
>
> import org.apache.commons.jxpath.JXPathException;
> import org.apache.commons.jxpath.Pointer;
> import org.apache.commons.jxpath.NodeSet;
>
> /**
> * The default implementation of TypeConverter.
> *
> * @author Dmitri Plotnikov
> * @version $Revision: 1.7 $ $Date: 2003/03/11 00:59:34 $
> */
> public class BasicTypeConverter implements TypeConverter {
>
> /**
> * Returns true if it can convert the supplied
> * object to the specified class.
> */
> public boolean canConvert(Object object, Class toType) {
> if (object == null) {
> return true;
> }
>
> if (toType == Object.class) {
> return true;
> }
>
> Class fromType = object.getClass();
> if (fromType.equals(toType)) {
> return true;
> }
>
> if (toType.isAssignableFrom(fromType)) {
> return true;
> }
>
> if (toType == String.class) {
> return true;
> }
>
> if (object instanceof Boolean) {
> if (toType == boolean.class
> || Number.class.isAssignableFrom(toType)) {
> return true;
> }
> }
> else if (object instanceof Number) {
> if (toType.isPrimitive()
> || Number.class.isAssignableFrom(toType)) {
> return true;
> }
> }
> else if (object instanceof Character) {
> if (toType == char.class) {
> return true;
> }
> }
> else if (object instanceof String) {
> if (toType.isPrimitive()) {
> return true;
> }
> if (toType == Boolean.class
> || toType == Character.class
> || toType == Byte.class
> || toType == Short.class
> || toType == Integer.class
> || toType == Long.class
> || toType == Float.class
> || toType == Double.class) {
> return true;
> }
> }
> else if (fromType.isArray()) {
> // Collection -> array
> if (toType.isArray()) {
> Class cType = toType.getComponentType();
> int length = Array.getLength(object);
> for (int i = 0; i < length; i++) {
> Object value = Array.get(object, i);
> if (!canConvert(value, cType)) {
> return false;
> }
> }
> return true;
> }
> else if (Collection.class.isAssignableFrom(toType)) {
> return canCreateCollection(toType);
> }
> else if (Array.getLength(object) == 1) {
> Object value = Array.get(object, 0);
> return canConvert(value, toType);
> }
> }
> else if (object instanceof Collection) {
> // Collection -> array
> if (toType.isArray()) {
> Class cType = toType.getComponentType();
> Iterator it = ((Collection) object).iterator();
> while (it.hasNext()) {
> Object value = it.next();
> if (!canConvert(value, cType)) {
> return false;
> }
> }
> return true;
> }
> else if (Collection.class.isAssignableFrom(toType)) {
> return canCreateCollection(toType);
> }
> else if (((Collection) object).size() == 1) {
> Object value;
> if (object instanceof List) {
> value = ((List) object).get(0);
> }
> else {
> Iterator it = ((Collection) object).iterator();
> value = it.next();
> }
>
=== message truncated ===> /*
> * $Header:
>
/home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/util/BasicTypeConverterTest.java,v
> 1.3 2003/03/11 00:59:40 dmitri Exp $
> * $Revision: 1.3 $
> * $Date: 2003/03/11 00:59:40 $
> *
> *
> ====================================================================
> * The Apache Software License, Version 1.1
> *
> *
> * Copyright (c) 1999-2003 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 and was
> * originally based on software copyright (c) 2001, Plotnix, Inc,
> * <http://www.plotnix.com/>.
> * For more information on the Apache Software Foundation, please see
> * <http://www.apache.org/>.
> */
>
> package org.apache.commons.jxpath.util;
>
> import java.lang.reflect.Array;
> import java.util.*;
>
> import junit.framework.TestCase;
> import org.apache.commons.jxpath.NodeSet;
> import org.apache.commons.jxpath.Pointer;
>
> /**
> * Tests BasicTypeConverter
> *
> * @author Dmitri Plotnikov
> * @version $Revision: 1.3 $ $Date: 2003/03/11 00:59:40 $
> */
>
> public class BasicTypeConverterTest extends TestCase {
> /**
> * Construct a new instance of this test case.
> *
> * @param name Name of the test case
> */
> public BasicTypeConverterTest(String name) {
> super(name);
> }
>
> public void testPrimitiveToString() {
> assertConversion(new Integer(1), String.class, "1");
> }
>
> public void testArrayToList() {
> assertConversion(
> new int[] { 1, 2 },
> List.class,
> Arrays.asList(new Object[] { new Integer(1), new
> Integer(2)}));
> }
>
> public void testArrayToArray() {
> assertConversion(
> new int[] { 1, 2 },
> String[].class,
> Arrays.asList(new String[] { "1", "2" }));
> }
>
> public void testListToArray() {
> assertConversion(
> Arrays.asList(new Integer[] { new Integer(1), new
> Integer(2)}),
> String[].class,
> Arrays.asList(new String[] { "1", "2" }));
>
> assertConversion(
> Arrays.asList(new String[] { "1", "2" }),
> int[].class,
> Arrays.asList(new Integer[] { new Integer(1), new
> Integer(2)}));
> }
>
> public void testInvalidConversion() {
> boolean exception = false;
> try {
> TypeUtils.convert("'foo'", Date.class);
> }
> catch (Throwable ex) {
> exception = true;
> }
> assertTrue("Type conversion exception", exception);
> }
>
> public void testSingletonCollectionToString() {
> assertConversion(Collections.singleton("Earth"),
> String.class, "Earth");
> }
>
> public void testSingletonArrayToString() {
> assertConversion(new String[] {"Earth"}, String.class,
> "Earth");
> }
>
> public void testPointerToString() {
> assertConversion(
> new Pointer() {
> public Object getValue() {
> return "value";
> }
> public Object getNode() {
> return null;
> }
> public void setValue(Object value) {
> }
> public Object getRootNode() {
> return null;
> }
> public String asPath() {
> return null;
> }
> public Object clone() {
> return null;
> }
> public int compareTo(Object o) {
> return 0;
> }
> },
> String.class,
> "value");
> }
>
> public void testNodeSetToString() {
> assertConversion(
> new NodeSet() {
> public List getNodes() {
> return null;
> }
> public List getPointers() {
> return null;
> }
> public List getValues() {
> return Collections.singletonList("hello");
> }
> },
> String.class,
> "hello");
> }
>
> // succeeds in current version
> public void testNodeSetToInteger() {
>
=== message truncated ===>
---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]