You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by th...@apache.org on 2014/06/28 15:37:18 UTC

git commit: TAP5-1885: Error in PropertyAccess service TAP5-1548: Property expressions fails when using a supertype that implements an interface with a matching method

Repository: tapestry-5
Updated Branches:
  refs/heads/master 4400d5dd3 -> af6518b97


TAP5-1885: Error in PropertyAccess service
TAP5-1548: Property expressions fails when using a supertype that
implements an interface with a matching method

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/af6518b9
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/af6518b9
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/af6518b9

Branch: refs/heads/master
Commit: af6518b97e1ef307e64c1664115d67345a68d274
Parents: 4400d5d
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Sat Jun 28 10:37:05 2014 -0300
Committer: Thiago H. de Paula Figueiredo <th...@apache.org>
Committed: Sat Jun 28 10:37:05 2014 -0300

----------------------------------------------------------------------
 .../services/ClassPropertyAdapterImpl.java      | 52 ++++++++++++++++-
 .../ioc/specs/PropertyAccessImplSpec.groovy     | 60 ++++++++++++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6518b9/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
index 939fa54..c916cd9 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
@@ -48,7 +48,8 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter
             // Indexed properties will have a null propertyType (and a non-null
             // indexedPropertyType). We ignore indexed properties.
 
-            if (pd.getPropertyType() == null)
+            final Class<?> thisPropertyType = pd.getPropertyType();
+            if (thisPropertyType == null)
                 continue;
 
             Method readMethod = pd.getReadMethod();
@@ -63,6 +64,27 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter
             	}
             	readMethod = findMethodWithSameNameAndParamCount(readMethod, nonBridgeMethods); 
             }
+            
+            // TAP5-1548, TAP5-1885: trying to find a getter which Introspector missed
+            if (readMethod == null) {
+                final String prefix = thisPropertyType != boolean.class ? "get" : "is";
+                try
+                {
+                    Method method = beanType.getMethod(prefix + capitalize(pd.getName()));
+                    final Class<?> returnType = method.getReturnType();
+                    if (returnType.equals(thisPropertyType) || returnType.isInstance(thisPropertyType)) {
+                        readMethod = method;
+                    }
+                }
+                catch (SecurityException e) {
+                    // getter not usable.
+                }
+                catch (NoSuchMethodException e)
+                {
+                    // getter doesn't exist.
+                }
+            }
+            
             if (writeMethod != null && writeMethod.isBridge())
             {
             	if (nonBridgeMethods == null)
@@ -71,8 +93,29 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter
             	}
             	writeMethod = findMethodWithSameNameAndParamCount(writeMethod, nonBridgeMethods);
             }
+            
+            // TAP5-1548, TAP5-1885: trying to find a setter which Introspector missed
+            if (writeMethod == null) {
+                try
+                {
+                    Method method = beanType.getMethod("set" + capitalize(pd.getName()), pd.getPropertyType());
+                    final Class<?> returnType = method.getReturnType();
+                    if (returnType.equals(void.class)) {
+                        writeMethod = method;
+                    }
+                }
+                catch (SecurityException e) {
+                    // setter not usable.
+                    e.printStackTrace();
+                }
+                catch (NoSuchMethodException e)
+                {
+                    // setter doesn't exist.
+                    e.printStackTrace();
+                }
+            }
 
-            Class propertyType = readMethod == null ? pd.getPropertyType() : GenericsUtils.extractGenericReturnType(
+            Class propertyType = readMethod == null ? thisPropertyType : GenericsUtils.extractGenericReturnType(
                     beanType, readMethod);
 
             PropertyAdapter pa = new PropertyAdapterImpl(this, pd.getName(), propertyType, readMethod, writeMethod);
@@ -96,6 +139,11 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter
         }
     }
 
+    private static String capitalize(String name)
+    {
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+    }
+
     /**
      * Find a replacement for the method (if one exists)
      * @param method A method

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6518b9/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy
index f0ac187..5e62147 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy
@@ -12,6 +12,7 @@ import org.apache.tapestry5.ioc.internal.util.Pair
 import org.apache.tapestry5.ioc.internal.util.StringLongPair
 import org.apache.tapestry5.ioc.services.ClassPropertyAdapter
 import org.apache.tapestry5.ioc.services.PropertyAccess
+import org.apache.tapestry5.ioc.internal.PropertyAccessImplClasses
 
 import spock.lang.*
 
@@ -709,6 +710,65 @@ class PropertyAccessImplSpec extends Specification {
     pa.type == String
     pa.declaringClass == GenericBean
   }
+  
+  interface GetterInterface {
+    int getValue();
+  }
+        
+  interface SetterGetterInterface extends GetterInterface {
+    void setValue(int value);
+  }
+  
+  interface SetterInterface {
+    void setValue(int value);
+  }
+          
+  interface GetterSetterInterface extends SetterInterface {
+    int getValue();
+  }
+  
+  final class GetterSetterClass implements GetterSetterInterface {
+    public void setValue(int value) {}
+    public int getValue() {}
+  }
+    
+  // TAP5-1885
+  def "split properties (getter in one supertype, setter in another)"() {
+        
+    when:
+    def pa1 = getPropertyAdapter SetterGetterInterface, "value";
+    def pa2 = getPropertyAdapter GetterSetterInterface, "value";
+    def pa3 = getPropertyAdapter GetterSetterClass, "value";
+      
+    then:
+    pa1.isRead();
+    pa1.isUpdate();
+    pa2.isRead();
+    pa2.isUpdate();
+    pa3.isRead();
+    pa3.isUpdate();
+  }
+  
+  public interface Baz { String getBar(); }
+ 
+  public class AbstractFoo implements Baz {
+    private String bar;
+    public String getBar() { return bar; }
+    public void setBar(String bar){ this.bar =bar; }
+  }
+  
+  public class Foo extends AbstractFoo {}
+  
+  // TAP5-1548
+  def "property expressions fails when using a supertype that implements an interface with a matching method"() {
+        
+    when:
+    def pa = getPropertyAdapter AbstractFoo, "bar";
+      
+    then:
+    pa.isRead();
+    pa.isUpdate();
+  }
 
 
   def getPropertyAdapter(clazz, name) {