You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2009/11/09 23:10:43 UTC
svn commit: r834255 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl/JexlArithmetic.java
test/java/org/apache/commons/jexl/ArrayLiteralTest.java
Author: henrib
Date: Mon Nov 9 22:10:42 2009
New Revision: 834255
URL: http://svn.apache.org/viewvc?rev=834255&view=rev
Log:
Made array literals strongly typed; the code will attempt to find a common class for all elements of an array literal. Thus a ['foo', 'bar'] will create a String[ ] . If all elements are primitives of the same type, the returned array will be of that primitive type; [1, 2] will create an int[ ]. If all elements are Number (but of different classes), a Number[ ] will be returned. If all attempts fail, an Object[ ] is returned.
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/JexlArithmetic.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/ArrayLiteralTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/JexlArithmetic.java?rev=834255&r1=834254&r2=834255&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl/JexlArithmetic.java Mon Nov 9 22:10:42 2009
@@ -16,6 +16,8 @@
*/
package org.apache.commons.jexl;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -182,6 +184,59 @@
}
/**
+ * Given an array of objects, attempt to type it more strictly.
+ * <ul>
+ * <li>If all objects are of the same type, the array returned will be an array of that same type</li>
+ * <li>If all objects are Numbers, the array returned will be an array of Numbers</li>
+ * <li>If all objects are convertible to a primitive type, the array returned will be an array
+ * of the primitive type</li>
+ * </ul>
+ * @param untyped an untyped array
+ * @return the original array if the attempt to strictly type the array fails, a typed array otherwise
+ */
+ protected Object narrowArrayType(Object[] untyped) {
+ final int size = untyped.length;
+ Class<?> commonClass = null;
+ if (size > 0) {
+ // base common class on first entry
+ commonClass = untyped[0].getClass();
+ final boolean isNumber = Number.class.isAssignableFrom(commonClass);
+ // for all children after first...
+ for (int i = 1; i < size; i++) {
+ Class<?> eclass = untyped[i].getClass();
+ // detect same type for all elements in array
+ if (!Object.class.equals(commonClass) && !commonClass.equals(eclass)) {
+ // if both are numbers...
+ if (isNumber && Number.class.isAssignableFrom(eclass)) {
+ commonClass = Number.class;
+ } else {
+ commonClass = Object.class;
+ }
+ }
+ }
+ // convert array to the common class if not Object.class
+ if (!Object.class.equals(commonClass)) {
+ // if the commonClass has an equivalent primitive type, get it
+ if (isNumber) {
+ try {
+ Field TYPE = commonClass.getField("TYPE");
+ commonClass = (Class<?>) TYPE.get(null);
+ } catch (Exception xany) {
+ // ignore
+ }
+ }
+ // allocate and fill up the typed array
+ Object typed = Array.newInstance(commonClass, size);
+ for(int i = 0; i < size; ++i) {
+ Array.set(typed, i, untyped[i]);
+ }
+ return typed;
+ }
+ }
+ return untyped;
+ }
+
+ /**
* Add two values together.
* <p>
* If any numeric add fails on coercion to the appropriate type,
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/ArrayLiteralTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/ArrayLiteralTest.java?rev=834255&r1=834254&r2=834255&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/ArrayLiteralTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl/ArrayLiteralTest.java Mon Nov 9 22:10:42 2009
@@ -19,7 +19,7 @@
import java.util.Arrays;
/**
- * Tests for map literals
+ * Tests for array literals
* @since 2.0
*/
public class ArrayLiteralTest extends JexlTestCase {
@@ -43,14 +43,23 @@
}
public void testLiteralWithNumbers() throws Exception {
- Expression e = JEXL.createExpression( "[ 5 , 10 ]" );
+ Expression e = JEXL.createExpression( "[ 5.0 , 10 ]" );
JexlContext jc = JexlHelper.createContext();
Object o = e.evaluate( jc );
- Object[] check = { Integer.valueOf(5), Integer.valueOf(10) };
+ Object[] check = { new Float(5), new Integer(10) };
assertTrue( Arrays.equals(check, (Object[])o) );
}
+ public void testLiteralWithIntegers() throws Exception {
+ Expression e = JEXL.createExpression( "[ 5 , 10 ]" );
+ JexlContext jc = JexlHelper.createContext();
+
+ Object o = e.evaluate( jc );
+ int[] check = { 5, 10 };
+ assertTrue( Arrays.equals(check, (int[])o) );
+ }
+
public void testSizeOfSimpleArrayLiteral() throws Exception {
Expression e = JEXL.createExpression( "size([ 'foo' , 'bar' ])" );
JexlContext jc = JexlHelper.createContext();