You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/03/22 04:30:23 UTC
svn commit: r925946 - in /tapestry/tapestry5/trunk/tapestry-ioc/src:
main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java
test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java
Author: hlship
Date: Mon Mar 22 03:30:23 2010
New Revision: 925946
URL: http://svn.apache.org/viewvc?rev=925946&view=rev
Log:
TAP5-1064: Extend PropertyAccess to understand Scala style properties (which use a different naming convention than JavaBeans)
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java?rev=925946&r1=925945&r2=925946&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImpl.java Mon Mar 22 03:30:23 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,11 +22,14 @@ import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+@SuppressWarnings("unchecked")
public class PropertyAccessImpl implements PropertyAccess
{
private final Map<Class, ClassPropertyAdapter> adapters = CollectionFactory.newConcurrentMap();
@@ -42,7 +45,7 @@ public class PropertyAccessImpl implemen
}
/**
- * Clears the cache of adapters and asks the Introspector to clear its cache.
+ * Clears the cache of adapters and asks the {@link Introspector} to clear its cache.
*/
public synchronized void clearCache()
{
@@ -81,15 +84,18 @@ public class PropertyAccessImpl implemen
try
{
- BeanInfo info = Introspector.getBeanInfo(forClass);
+ BeanInfo info = Introspector.getBeanInfo(forClass);
- List<PropertyDescriptor> descriptors = CollectionFactory.newList();
+ List<PropertyDescriptor> descriptors = CollectionFactory.newList();
- addAll(descriptors, info.getPropertyDescriptors());
+ addAll(descriptors, info.getPropertyDescriptors());
+
+ if (forClass.isInterface())
+ addPropertiesFromExtendedInterfaces(forClass, descriptors);
- if (forClass.isInterface()) addPropertiesFromExtendedInterfaces(forClass, descriptors);
+ addPropertiesFromScala(forClass, descriptors);
- return new ClassPropertyAdapterImpl(forClass, descriptors);
+ return new ClassPropertyAdapterImpl(forClass, descriptors);
}
catch (Throwable ex)
{
@@ -121,4 +127,76 @@ public class PropertyAccessImpl implemen
}
}
+ private void addPropertiesFromScala(Class forClass, List<PropertyDescriptor> descriptors)
+ throws IntrospectionException
+ {
+ for (Method method : forClass.getMethods())
+ {
+ addPropertyIfScalaGetterMethod(forClass, descriptors, method);
+ }
+ }
+
+ private void addPropertyIfScalaGetterMethod(Class forClass, List<PropertyDescriptor> descriptors, Method method)
+ throws IntrospectionException
+ {
+ if (!isScalaGetterMethod(method))
+ return;
+
+ PropertyDescriptor propertyDescriptor = new PropertyDescriptor(method.getName(), forClass, method.getName(),
+ null);
+
+ // found a getter, looking for the setter now
+ try
+ {
+ Method setterMethod = findScalaSetterMethod(forClass, method);
+
+ propertyDescriptor.setWriteMethod(setterMethod);
+ }
+ catch (NoSuchMethodException e)
+ {
+ // ignore
+ }
+
+ // check if the same property was already discovered with java bean accessors
+
+ addScalaPropertyIfNoJavaBeansProperty(descriptors, propertyDescriptor, method);
+ }
+
+ private void addScalaPropertyIfNoJavaBeansProperty(List<PropertyDescriptor> descriptors,
+ PropertyDescriptor propertyDescriptor, Method getterMethod)
+ {
+ boolean found = false;
+
+ for (PropertyDescriptor currentPropertyDescriptor : descriptors)
+ {
+ if (currentPropertyDescriptor.getName().equals(getterMethod.getName()))
+ {
+ found = true;
+
+ break;
+ }
+ }
+
+ if (!found)
+ descriptors.add(propertyDescriptor);
+ }
+
+ private Method findScalaSetterMethod(Class forClass, Method getterMethod) throws NoSuchMethodException
+ {
+ return forClass.getMethod(getterMethod.getName() + "_$eq", getterMethod.getReturnType());
+ }
+
+ private boolean isScalaGetterMethod(Method method)
+ {
+ try
+ {
+ return Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0
+ && !method.getReturnType().equals(Void.TYPE)
+ && method.getDeclaringClass().getDeclaredField(method.getName()) != null;
+ }
+ catch (NoSuchFieldException ex)
+ {
+ return false;
+ }
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java?rev=925946&r1=925945&r2=925946&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java Mon Mar 22 03:30:23 2010
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -145,6 +145,44 @@ public class PropertyAccessImplTest exte
}
+ public static class ScalaBean {
+ private String value;
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+ public String value()
+ {
+ return value;
+ }
+
+ public void value_$eq(String value)
+ {
+ this.value = value;
+ }
+ }
+
+ public static class ScalaClass {
+ private String value;
+
+ public String value()
+ {
+ return value;
+ }
+
+ public void value_$eq(String value)
+ {
+ this.value = value;
+ }
+ }
+
public static class BooleanHolder
{
private boolean flag;
@@ -523,4 +561,21 @@ public class PropertyAccessImplTest exte
assertFalse(pa2.isCastRequired());
}
+
+ @Test
+ public void get_scala_properties_with_bean_accessors() {
+ PropertyAdapter pa = access.getAdapter(ScalaBean.class).getPropertyAdapter("value");
+
+ // even thought scala accessors are present the java bean ones should be the ones used by Tapestry
+ assertEquals(pa.getReadMethod().getName(), "getValue");
+ assertEquals(pa.getWriteMethod().getName(), "setValue");
+ }
+
+ @Test
+ public void get_scala_properties() {
+ PropertyAdapter pa = access.getAdapter(ScalaClass.class).getPropertyAdapter("value");
+
+ assertEquals(pa.getReadMethod().getName(), "value");
+ assertEquals(pa.getWriteMethod().getName(), "value_$eq");
+ }
}