Author: jcarman Date: Sat May 24 07:56:53 2008 New Revision: 659831 URL: http://svn.apache.org/viewvc?rev=659831&view=rev Log: Implemented a "chain" invoker. Also moved getDefaultValue() method to ProxyUtils to avoid code duplication.
Added: commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/ChainInvoker.java commons/proper/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestChainInvoker.java Modified: commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/ProxyUtils.java commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java Modified: commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/ProxyUtils.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/ProxyUtils.java?rev=659831&r1=659830&r2=659831&view=diff ============================================================================== --- commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/ProxyUtils.java (original) +++ commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/ProxyUtils.java Sat May 24 07:56:53 2008 @@ -39,6 +39,7 @@ public static final Object[] EMPTY_ARGUMENTS = new Object[0]; public static final Class[] EMPTY_ARGUMENT_TYPES = new Class[0]; private static final Map wrapperClassMap = new HashMap(); + public static Map defaultValueMap = new HashMap(); //********************************************************************************************************************** // Static Methods @@ -56,6 +57,18 @@ wrapperClassMap.put(Byte.TYPE, Byte.class); } + static + { + defaultValueMap.put(Integer.TYPE, new Integer(0)); + defaultValueMap.put(Long.TYPE, new Long(0)); + defaultValueMap.put(Short.TYPE, new Short(( short ) 0)); + defaultValueMap.put(Byte.TYPE, new Byte(( byte ) 0)); + defaultValueMap.put(Float.TYPE, new Float(0.0f)); + defaultValueMap.put(Double.TYPE, new Double(0.0)); + defaultValueMap.put(Character.TYPE, new Character(( char ) 0)); + defaultValueMap.put(Boolean.TYPE, Boolean.FALSE); + } + /** * Creates a "null object" which implements the <code>proxyClasses</code>. * @@ -152,5 +165,22 @@ { return ( Class ) wrapperClassMap.get(primitiveType); } + + /** + * Returns the default value (null, zero, false) for a specified type. + * @param type the type + * @return the default value + */ + public static Object getDefaultValue(Class type) + { + if( type.isPrimitive() ) + { + return defaultValueMap.get(type); + } + else + { + return null; + } + } } Added: commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/ChainInvoker.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/ChainInvoker.java?rev=659831&view=auto ============================================================================== --- commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/ChainInvoker.java (added) +++ commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/ChainInvoker.java Sat May 24 07:56:53 2008 @@ -0,0 +1,38 @@ +package org.apache.commons.proxy.invoker; + +import org.apache.commons.proxy.Invoker; +import org.apache.commons.proxy.ProxyUtils; + +import java.lang.reflect.Method; + +/** + * A chain invoker will invoke the method on each object in the chain until one of them + * returns a non-default value + * + * @author James Carman + * @since 1.1 + */ +public class ChainInvoker implements Invoker +{ + private final Object[] targets; + + public ChainInvoker(Object[] targets) + { + this.targets = targets; + } + + public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable + { + for (int i = 0; i < targets.length; i++) + { + Object target = targets[i]; + Object value = method.invoke(target, arguments); + if (value != null && !value.equals(ProxyUtils.getDefaultValue(method.getReturnType()))) + { + return value; + } + } + return ProxyUtils.getDefaultValue(method.getReturnType()); + } +} + Modified: commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java?rev=659831&r1=659830&r2=659831&view=diff ============================================================================== --- commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java (original) +++ commons/proper/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/NullInvoker.java Sat May 24 07:56:53 2008 @@ -18,11 +18,10 @@ package org.apache.commons.proxy.invoker; import org.apache.commons.proxy.Invoker; +import org.apache.commons.proxy.ProxyUtils; import java.io.Serializable; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; /** * An [EMAIL PROTECTED] Invoker} implementation which merely returns null for all method invocations. This class is @@ -34,42 +33,14 @@ public class NullInvoker implements Invoker, Serializable { //********************************************************************************************************************** -// Fields -//********************************************************************************************************************** - - private static Map primitiveValueMap = new HashMap(); - -//********************************************************************************************************************** -// Static Methods -//********************************************************************************************************************** - - static - { - primitiveValueMap.put(Integer.TYPE, new Integer(0)); - primitiveValueMap.put(Long.TYPE, new Long(0)); - primitiveValueMap.put(Short.TYPE, new Short(( short ) 0)); - primitiveValueMap.put(Byte.TYPE, new Byte(( byte ) 0)); - primitiveValueMap.put(Float.TYPE, new Float(0.0f)); - primitiveValueMap.put(Double.TYPE, new Double(0.0)); - primitiveValueMap.put(Character.TYPE, new Character(( char ) 0)); - primitiveValueMap.put(Boolean.TYPE, Boolean.FALSE); - } - -//********************************************************************************************************************** // Invoker Implementation //********************************************************************************************************************** public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable { final Class returnType = method.getReturnType(); - if( returnType.isPrimitive() ) - { - return primitiveValueMap.get(returnType); - } - else - { - return null; - } + return ProxyUtils.getDefaultValue(returnType); } + } Added: commons/proper/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestChainInvoker.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestChainInvoker.java?rev=659831&view=auto ============================================================================== --- commons/proper/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestChainInvoker.java (added) +++ commons/proper/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestChainInvoker.java Sat May 24 07:56:53 2008 @@ -0,0 +1,157 @@ +package org.apache.commons.proxy.invoker; + +import org.apache.commons.proxy.util.AbstractTestCase; +import org.apache.commons.proxy.ProxyFactory; + +/** + * @since 1.1 + */ +public class TestChainInvoker extends AbstractTestCase +{ + public void testSkipDefaultValues() + { + final ChainInvoker invoker = new ChainInvoker(new Object[]{new DefaultTester(), new NonDefaultTester()}); + Tester tester = (Tester)new ProxyFactory().createInvokerProxy(invoker, new Class[] { Tester.class }); + assertEquals(true,tester.booleanMethod()); + assertEquals(1, tester.byteMethod()); + assertEquals('1', tester.charMethod()); + assertEquals(1.0, tester.doubleMethod(), 0.0); + assertEquals(1.0f, tester.floatMethod(), 0.0f); + assertEquals(1, tester.intMethod()); + assertEquals(1, tester.longMethod()); + assertEquals(1, tester.shortMethod()); + assertEquals("One", tester.objectMethod()); + } + + public void testReturnDefaultValue() + { + final ChainInvoker invoker = new ChainInvoker(new Object[]{new DefaultTester(), new DefaultTester()}); + Tester tester = (Tester)new ProxyFactory().createInvokerProxy(invoker, new Class[] { Tester.class }); + assertEquals(false,tester.booleanMethod()); + assertEquals(0, tester.byteMethod()); + assertEquals(0, tester.charMethod()); + assertEquals(0.0, tester.doubleMethod(), 0.0); + assertEquals(0.0f, tester.floatMethod(), 0.0f); + assertEquals(0, tester.intMethod()); + assertEquals(0, tester.longMethod()); + assertEquals(0, tester.shortMethod()); + assertEquals(null, tester.objectMethod()); + } + + public static interface Tester + { + public int intMethod(); + + public long longMethod(); + + public short shortMethod(); + + public byte byteMethod(); + + public double doubleMethod(); + + public float floatMethod(); + + public boolean booleanMethod(); + + public char charMethod(); + + public Object objectMethod(); + } + + public class NonDefaultTester implements Tester + { + public boolean booleanMethod() + { + return true; + } + + public byte byteMethod() + { + return 1; + } + + public char charMethod() + { + return '1'; + } + + public double doubleMethod() + { + return 1.0; + } + + public float floatMethod() + { + return 1.0f; + } + + public int intMethod() + { + return 1; + } + + public long longMethod() + { + return 1; + } + + public Object objectMethod() + { + return "One"; + } + + public short shortMethod() + { + return 1; + } + } + + public class DefaultTester implements Tester + { + public boolean booleanMethod() + { + return false; + } + + public byte byteMethod() + { + return 0; + } + + public char charMethod() + { + return 0; + } + + public double doubleMethod() + { + return 0; + } + + public float floatMethod() + { + return 0; + } + + public int intMethod() + { + return 0; + } + + public long longMethod() + { + return 0; + } + + public Object objectMethod() + { + return null; + } + + public short shortMethod() + { + return 0; + } + } +}