You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jc...@apache.org on 2007/10/02 16:36:29 UTC

svn commit: r581265 - in /commons/sandbox/proxy/trunk/src: main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java

Author: jcarman
Date: Tue Oct  2 07:36:28 2007
New Revision: 581265

URL: http://svn.apache.org/viewvc?rev=581265&view=rev
Log:
Now checks return types to verify that they are compatible.

Modified:
    commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
    commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java

Modified: commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
URL: http://svn.apache.org/viewvc/commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java?rev=581265&r1=581264&r2=581265&view=diff
==============================================================================
--- commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java (original)
+++ commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java Tue Oct  2 07:36:28 2007
@@ -23,9 +23,32 @@
 import java.lang.reflect.Method;
 
 /**
- * An invoker which supports "duck typing", meaning that it finds a matching method
- * on the object returned from the target provider and invokes it.  This class is useful for
- * adapting an existing class to an interface it does not implement.
+ * An invoker which supports <a href="http://en.wikipedia.org/wiki/Duck_typing">&quot;duck typing&quot;</a>, meaning
+ * that it finds a matching method on the object returned from the target provider and invokes it.  This class is
+ * useful for adapting an existing class to an interface it does not implement.
+ * <p>
+ * <b>Example:</b>
+ * </p>
+ * <p>
+ * <pre>
+ * public class LegacyDuck // Does not implement interface!
+ * {
+ *   public void quack()
+ *   {
+ *     // Quacking logic...
+ *   }
+ * }
+ * <p/>
+ * public interface Duck
+ * {
+ *   public void quack();
+ * }
+ * <p/>
+ * ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck()); // Always returns a "legacy" duck
+ * DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
+ * Duck duck = ( Duck )proxyFactory.createInvokerProxy( invoker, new Class[] { Duck.class } );
+ * </pre>
+ * </p>
  */
 public class DuckTypingInvoker implements Invoker
 {
@@ -48,6 +71,11 @@
 // Interface Invoker
 //----------------------------------------------------------------------------------------------------------------------
 
+
+//----------------------------------------------------------------------------------------------------------------------
+// Interface Invoker
+//----------------------------------------------------------------------------------------------------------------------
+
     public Object invoke( final Object proxy, final Method method, final Object[] arguments ) throws Throwable
     {
         final Object target = targetProvider.getObject();
@@ -55,11 +83,17 @@
         try
         {
             final Method targetMethod = targetClass.getMethod( method.getName(), method.getParameterTypes() );
-            return targetMethod.invoke( target, arguments );
+            if ( method.getReturnType().isAssignableFrom( targetMethod.getReturnType() ) )
+            {
+                return targetMethod.invoke( target, arguments );
+            }
+            throw new UnsupportedOperationException(
+                    "Target type " + targetClass.getName() + " method has incompatible return type." );
         }
         catch ( NoSuchMethodException e )
         {
-            throw new UnsupportedOperationException("Target type " + targetClass.getName() + " does not have a method matching " + method + "." );
+            throw new UnsupportedOperationException(
+                    "Target type " + targetClass.getName() + " does not have a method matching " + method + "." );
         }
     }
 }

Modified: commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java
URL: http://svn.apache.org/viewvc/commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java?rev=581265&r1=581264&r2=581265&view=diff
==============================================================================
--- commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java (original)
+++ commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java Tue Oct  2 07:36:28 2007
@@ -22,9 +22,7 @@
 import org.apache.commons.proxy.ProxyFactory;
 import org.apache.commons.proxy.provider.ConstantProvider;
 
-import java.io.Externalizable;
-import java.io.IOException;
-import java.util.Comparator;
+import java.io.Serializable;
 
 /**
  *
@@ -37,46 +35,106 @@
 
     public void testExactSignatureMatch()
     {
-        final ObjectProvider targetProvider = new ConstantProvider(new DuckComparator());
+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
         final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
-        final Comparator c = ( Comparator )new ProxyFactory().createInvokerProxy( invoker, new Class[] { Comparator.class } );
-        assertEquals( 12345, c.compare( null, null ) );
+        final Duck duck = ( Duck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Duck.class } );
+        assertEquals( "Quack!", duck.sayQuack() );
     }
 
     public void testNoMatchingMethod()
     {
-        final ObjectProvider targetProvider = new ConstantProvider(new DuckComparator());
+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
         final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
-        final Externalizable externalizable = ( Externalizable )new ProxyFactory().createInvokerProxy( invoker, new Class[] {
-                Externalizable.class } );
+        final Goose goose = ( Goose ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Goose.class } );
         try
         {
-            externalizable.writeExternal( null );
-            fail("No matching method should be found.");
+            goose.sayHonk();
+            fail( "No matching method should be found." );
         }
-        catch(UnsupportedOperationException e )
+        catch ( UnsupportedOperationException e )
         {
             // Do nothing, expected behavior!
         }
-        catch ( IOException e )
+    }
+
+    public void testMismatchingParameterType()
+    {
+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
+        final ParameterizedDuck parameterizedDuck = ( ParameterizedDuck ) new ProxyFactory()
+                .createInvokerProxy( invoker, new Class[]{ ParameterizedDuck.class } );
+        try
         {
-            fail("No IOException should be thrown here.");
+            parameterizedDuck.sayQuack("Elmer");
+            fail( "No matching method should be found." );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            // Do nothing, expected behavior!
         }
     }
 
-//----------------------------------------------------------------------------------------------------------------------
-// Inner Classes
-//----------------------------------------------------------------------------------------------------------------------
+    public void testTargetHasCompatibleReturnType()
+    {
+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
+        final SerializableDuck duck = ( SerializableDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
+                SerializableDuck.class } );
+        assertEquals("Quack!", duck.sayQuack() );
 
-    public static class DuckComparator
+    }
+
+    public void testMismatchingReturnType()
     {
+        final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
+        final VoidReturnDuck voidDuck = ( VoidReturnDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
+                VoidReturnDuck.class } );
+        try
+        {
+            voidDuck.sayQuack();
+            fail( "No matching method should be found." );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            // Do nothing, expected behavior!
+        }
+    }
+
 //----------------------------------------------------------------------------------------------------------------------
-// Other Methods
+// Inner Classes
 //----------------------------------------------------------------------------------------------------------------------
 
-        public int compare( final Object o1, final Object o2 )
+    public static class LegacyDuck
+    {
+        public String sayQuack()
         {
-            return 12345;
+            return "Quack!";
         }
+    }
+
+    public interface Duck
+    {
+        public String sayQuack();
+    }
+
+    public interface SerializableDuck
+    {
+        public Serializable sayQuack();
+    }
+    
+    public interface ParameterizedDuck
+    {
+        public String sayQuack( String recipient );
+    }
+
+    public interface VoidReturnDuck
+    {
+        public void sayQuack();
+    }
+
+    public interface Goose
+    {
+        public void sayHonk();
     }
 }