[weld-commits] Weld SVN: r6361 - extensions/trunk/src/main/java/org/jboss/weld/extensions/util.

weld-commits at lists.jboss.org weld-commits at lists.jboss.org
Sun May 30 22:50:10 EDT 2010


Author: shane.bryzak at jboss.com
Date: 2010-05-30 22:50:10 -0400 (Sun, 30 May 2010)
New Revision: 6361

Added:
   extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AbstractBeanProperty.java
   extensions/trunk/src/main/java/org/jboss/weld/extensions/util/TypedBeanProperty.java
Modified:
   extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AnnotatedBeanProperty.java
Log:
WELDX-106

Added: extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AbstractBeanProperty.java
===================================================================
--- extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AbstractBeanProperty.java	                        (rev 0)
+++ extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AbstractBeanProperty.java	2010-05-31 02:50:10 UTC (rev 6361)
@@ -0,0 +1,356 @@
+package org.jboss.weld.extensions.util;
+
+import java.beans.Introspector;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * Base class for bean property wrappers
+ * 
+ * @author Shane Bryzak
+ */
+public abstract class AbstractBeanProperty
+{
+   /**
+    * Property field
+    */
+   private Field propertyField;
+   
+   /**
+    * Property getter method
+    */
+   private Method propertyGetter;
+   
+   /**
+    * Property setter method
+    */
+   private Method propertySetter;
+   
+   /**
+    * Property name
+    */
+   private String name;
+   
+   /**
+    * The class containing the property
+    */
+   private Class<?> targetClass;
+   
+   /**
+    * Flag indicating whether the target class has been scanned
+    */
+   private boolean scanned = false;   
+   
+   private boolean isFieldProperty;
+   
+   /**
+    * Flag indicating whether a valid property has been found
+    */
+   private boolean valid = false;
+   
+   private Type propertyType;   
+   
+   /**
+    * 
+    * @param targetClass
+    */
+   public AbstractBeanProperty(Class<?> targetClass)
+   {
+      this.targetClass = targetClass;
+   }
+   
+   protected void scan()
+   {
+      if (scanned) return;
+      
+      scanned = true;
+      
+      // First check declared fields
+      for (Field f : targetClass.getDeclaredFields())
+      {
+         if (fieldMatches(f))
+         {
+            setupFieldProperty(f);            
+            valid = true;
+            return;
+         }
+      }      
+      
+      // Then check public fields, in case it's inherited
+      for (Field f : targetClass.getFields())
+      {
+         if (fieldMatches(f)) 
+         {
+            setupFieldProperty(f);
+            valid = true;
+            return;
+         }
+      }
+      
+      // Then check public methods (we ignore private methods)
+      for (Method m : targetClass.getMethods())
+      {
+         if (methodMatches(m))
+         {
+            String methodName = m.getName();
+            
+            if ( m.getName().startsWith("get") )
+            {
+               this.name = Introspector.decapitalize( m.getName().substring(3) );
+            }
+            else if ( methodName.startsWith("is") )
+            {
+               this.name = Introspector.decapitalize( m.getName().substring(2) );
+            }            
+            
+            if (this.name != null)
+            {
+               this.propertyGetter = getGetterMethod(targetClass, this.name);
+               this.propertySetter = getSetterMethod(targetClass, this.name);
+               this.propertyType = this.propertyGetter.getGenericReturnType();
+               isFieldProperty = false;               
+               valid = true;
+            }
+            else
+            {
+               throw new IllegalStateException("Invalid accessor method, must start with 'get' or 'is'.  " +
+                     "Method: " + m + " in class: " + targetClass);
+            }
+         }
+      }        
+   }
+   
+   protected abstract boolean fieldMatches(Field f);
+   
+   protected abstract boolean methodMatches(Method m);
+      
+   private void setupFieldProperty(Field propertyField)
+   {
+      this.propertyField = propertyField;
+      isFieldProperty = true;
+      this.name = propertyField.getName();
+      this.propertyType = propertyField.getGenericType();
+   }     
+   
+   /**
+    * This method sets the property value for a specified bean to the specified 
+    * value.  The property to be set is either a field or setter method that
+    * matches the specified annotation class and returns true for the isMatch() 
+    * method.
+    * 
+    * @param bean The bean containing the property to set
+    * @param value The new property value
+    * @throws Exception
+    */
+   public void setValue(Object bean, Object value) throws Exception
+   {
+      scan();
+      
+      if (isFieldProperty)
+      {
+         setFieldValue(propertyField, bean, value);        
+      }
+      else
+      {
+         invokeMethod(propertySetter, bean, value);
+      }
+   }
+    
+   /**
+    * Returns the property value for the specified bean.  The property to be
+    * returned is either a field or getter method that matches the specified
+    * annotation class and returns true for the isMatch() method.
+    * 
+    * @param bean The bean to read the property from
+    * @return The property value
+    * @throws Exception
+    */
+   public Object getValue(Object bean) throws Exception
+   {
+      scan();
+      
+      if (isFieldProperty)
+      {
+         return getFieldValue(propertyField, bean);  
+      }
+      else
+      {
+         return invokeMethod(propertyGetter, bean);
+      }
+   }      
+   
+   /**
+    * Returns the property type
+    * 
+    * @return The property type
+    */
+   public Type getPropertyType()
+   {
+      scan();
+      return propertyType;
+   }
+   
+   /**
+    * Returns true if the property has been successfully located, otherwise
+    * returns false.
+    * 
+    * @return
+    */
+   public boolean isValid()
+   {
+      scan();
+      return valid;
+   }      
+   
+   /**
+    * Returns the name of the property. If the property is a field, then the
+    * field name is returned.  Otherwise, if the property is a method, then the
+    * name that is returned is the getter method name without the "get" or "is"
+    * prefix, and a lower case first letter.
+    * 
+    * @return The name of the property
+    */
+   public String getName()
+   {
+      scan();      
+      return name;
+   }
+   
+   private Object getFieldValue(Field field, Object obj)
+   {
+      field.setAccessible(true);
+      try
+      {
+         return field.get(obj);
+      }
+      catch (IllegalAccessException e)
+      {
+         throw new RuntimeException(buildGetFieldValueErrorMessage(field, obj), e);        
+      }      
+      catch (NullPointerException ex)
+      {         
+         NullPointerException ex2 = new NullPointerException(
+               buildGetFieldValueErrorMessage(field, obj));
+         ex2.initCause(ex.getCause());
+         throw ex2;
+      }   
+   }
+   
+   private String buildGetFieldValueErrorMessage(Field field, Object obj)
+   {
+      return String.format("Exception reading [%s] field from object [%s].",
+            field.getName(), obj);
+   }
+   
+   private void setFieldValue(Field field, Object obj, Object value)
+   {
+      field.setAccessible(true);
+      try
+      {
+         field.set(obj, value);
+      }
+      catch (IllegalAccessException e)
+      {
+         throw new RuntimeException(buildSetFieldValueErrorMessage(field, obj, value), e);
+      }
+      catch (NullPointerException ex)
+      {         
+         NullPointerException ex2 = new NullPointerException(
+               buildSetFieldValueErrorMessage(field, obj, value));
+         ex2.initCause(ex.getCause());
+         throw ex2;
+      }
+   }
+   
+   private String buildSetFieldValueErrorMessage(Field field, Object obj, Object value)
+   {
+      return String.format("Exception setting [%s] field on object [%s] to value [%s]",
+            field.getName(), obj, value);
+   }   
+   
+   private Object invokeMethod(Method method, Object obj, Object... args)
+   {
+      try
+      {
+         return method.invoke(obj, args);
+      }
+      catch (IllegalAccessException ex)
+      {
+         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), ex);
+      }
+      catch (IllegalArgumentException ex)
+      {
+         throw new IllegalArgumentException(buildInvokeMethodErrorMessage(method, obj, args), ex.getCause()); 
+      }
+      catch (InvocationTargetException ex)
+      {
+         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), ex);
+      }
+      catch (NullPointerException ex)
+      {         
+         NullPointerException ex2 = new NullPointerException(buildInvokeMethodErrorMessage(method, obj, args));
+         ex2.initCause(ex.getCause());
+         throw ex2;
+      }
+      catch (ExceptionInInitializerError e)
+      {
+         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), e);
+      }
+   }   
+   
+   private String buildInvokeMethodErrorMessage(Method method, Object obj, Object... args)
+   {
+      StringBuilder message = new StringBuilder(String.format(
+            "Exception invoking method [%s] on object [%s], using arguments [",
+            method.getName(), obj));
+      if (args != null) for (int i = 0; i < args.length; i++) message.append((i > 0 ? "," : "") + args[i]);
+      message.append("]");
+      return message.toString();
+   }
+   
+   private Method getSetterMethod(Class<?> clazz, String name)
+   {
+      Method[] methods = clazz.getMethods();
+      for (Method method: methods)
+      {
+         String methodName = method.getName();
+         if ( methodName.startsWith("set") && method.getParameterTypes().length==1 )
+         {
+            if ( Introspector.decapitalize( methodName.substring(3) ).equals(name) )
+            {
+               return method;
+            }
+         }
+      }
+      throw new IllegalArgumentException("no such setter method: " + clazz.getName() + '.' + name);
+   }
+   
+   private Method getGetterMethod(Class<?> clazz, String name)
+   {
+      Method[] methods = clazz.getMethods();
+      for (Method method: methods)
+      {
+         String methodName = method.getName();
+         if ( method.getParameterTypes().length==0 )
+         {
+            if ( methodName.startsWith("get") )
+            {
+               if ( Introspector.decapitalize( methodName.substring(3) ).equals(name) )
+               {
+                  return method;
+               }
+            }
+            else if ( methodName.startsWith("is") )
+            {
+               if ( Introspector.decapitalize( methodName.substring(2) ).equals(name) )
+               {
+                  return method;
+               }
+            }
+         }
+      }
+      throw new IllegalArgumentException("no such getter method: " + clazz.getName() + '.' + name);
+   }     
+}

Modified: extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AnnotatedBeanProperty.java
===================================================================
--- extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AnnotatedBeanProperty.java	2010-05-30 11:54:06 UTC (rev 6360)
+++ extensions/trunk/src/main/java/org/jboss/weld/extensions/util/AnnotatedBeanProperty.java	2010-05-31 02:50:10 UTC (rev 6361)
@@ -1,36 +1,22 @@
 package org.jboss.weld.extensions.util;
 
-import java.beans.Introspector;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.lang.ExceptionInInitializerError;
 
 /**
- * A convenience class for working with an annotated property (either a field or method) of
- * a JavaBean class.  By providing an isMatch() method in a concrete implementation
- * of this class, annotations may be matched on their attribute values or other
- * conditions.
+ * A convenience class for working with an annotated property (either a field or 
+ * method) of a JavaBean class.  By providing an overridden annotationMatches() 
+ * method in a subclass, annotations may be matched on their attribute values or 
+ * other conditions.
  *  
  * @author Shane Bryzak
  */
-public class AnnotatedBeanProperty<T extends Annotation>
-{
-   private Field propertyField;
-   private Method propertyGetter;
-   private Method propertySetter;
-   private String name;
-   private Type propertyType;
+public class AnnotatedBeanProperty<T extends Annotation> extends AbstractBeanProperty
+{   
    private T annotation;
    
-   private boolean isFieldProperty;
-   private boolean set = false;
-   
-   private Class<?> targetClass;
    private Class<T> annotationClass;
-   private boolean scanned = false;
    
    /**
     * Default constructor
@@ -41,150 +27,49 @@
     */
    public AnnotatedBeanProperty(Class<?> cls, Class<T> annotationClass)
    {            
-      this.targetClass = cls;
+      super(cls);
       this.annotationClass = annotationClass;
    }   
    
-   /**
-    * Scans the target class to locate the annotated property
-    */
-   private void scan()
+   protected boolean fieldMatches(Field f)
    {      
-      // First check declared fields
-      for (Field f : targetClass.getDeclaredFields())
-      {
-         if (f.isAnnotationPresent(annotationClass) && 
-               isMatch(f.getAnnotation(annotationClass))) 
-         {
-            setupFieldProperty(f);
-            this.annotation = f.getAnnotation(annotationClass);            
-            set = true;
-            return;
-         }
-      }      
-      
-      // Then check public fields, in case it's inherited
-      for (Field f : targetClass.getFields())
-      {
-         if (f.isAnnotationPresent(annotationClass) &&
-               isMatch(f.getAnnotation(annotationClass))) 
-         {
-            this.annotation = f.getAnnotation(annotationClass);
-            setupFieldProperty(f);
-            set = true;
-            return;
-         }
+      if (f.isAnnotationPresent(annotationClass) && 
+            annotationMatches(f.getAnnotation(annotationClass)))
+      {      
+         this.annotation = f.getAnnotation(annotationClass);
+         return true;
       }
-      
-      // Then check public methods (we ignore private methods)
-      for (Method m : targetClass.getMethods())
-      {
-         if (m.isAnnotationPresent(annotationClass) &&
-               isMatch(m.getAnnotation(annotationClass)))
-         {
-            this.annotation = m.getAnnotation(annotationClass);
-            String methodName = m.getName();
-            
-            if ( m.getName().startsWith("get") )
-            {
-               this.name = Introspector.decapitalize( m.getName().substring(3) );
-            }
-            else if ( methodName.startsWith("is") )
-            {
-               this.name = Introspector.decapitalize( m.getName().substring(2) );
-            }            
-            
-            if (this.name != null)
-            {
-               this.propertyGetter = getGetterMethod(targetClass, this.name);
-               this.propertySetter = getSetterMethod(targetClass, this.name);
-               this.propertyType = this.propertyGetter.getGenericReturnType();
-               isFieldProperty = false;               
-               set = true;
-            }
-            else
-            {
-               throw new IllegalStateException("Invalid accessor method, must start with 'get' or 'is'.  " +
-                     "Method: " + m + " in class: " + targetClass);
-            }
-         }
-      }   
-      
-      scanned = true;
-   }
-   
-   /**
-    * This method may be overridden by a subclass. It can be used to scan 
-    * for an annotation with particular attribute values, or to allow a match
-    * based on more complex logic.  
-    * 
-    * @param annotation The potential match
-    * @return true if the specified annotation is a match
-    */
-   protected boolean isMatch(T annotation)
-   {
-      return true;
-   }
-
-   /**
-    * This method sets the property value for a specified bean to the specified 
-    * value.  The property to be set is either a field or setter method that
-    * matches the specified annotation class and returns true for the isMatch() 
-    * method.
-    * 
-    * @param bean The bean containing the property to set
-    * @param value The new property value
-    * @throws Exception
-    */
-   public void setValue(Object bean, Object value) throws Exception
-   {
-      if (!scanned) scan();
-      
-      if (isFieldProperty)
-      {
-         setFieldValue(propertyField, bean, value);        
-      }
       else
       {
-         invokeMethod(propertySetter, bean, value);
+         return false;
       }
    }
-    
-   /**
-    * Returns the property value for the specified bean.  The property to be
-    * returned is either a field or getter method that matches the specified
-    * annotation class and returns true for the isMatch() method.
-    * 
-    * @param bean The bean to read the property from
-    * @return The property value
-    * @throws Exception
-    */
-   public Object getValue(Object bean) throws Exception
+   
+   protected boolean methodMatches(Method m)
    {
-      if (!scanned) scan();
-      
-      if (isFieldProperty)
+      if (m.isAnnotationPresent(annotationClass) &&
+            annotationMatches(m.getAnnotation(annotationClass)))
       {
-         return getFieldValue(propertyField, bean);  
+         this.annotation = m.getAnnotation(annotationClass);
+         return true;
       }
       else
       {
-         return invokeMethod(propertyGetter, bean);
+         return false;
       }
    }
    
    /**
-    * Returns the name of the property. If the property is a field, then the
-    * field name is returned.  Otherwise, if the property is a method, then the
-    * name that is returned is the getter method name without the "get" or "is"
-    * prefix, and a lower case first letter.
+    * This method may be overridden by a subclass. It can be used to scan 
+    * for an annotation with particular attribute values, or to allow a match
+    * based on more complex logic.  
     * 
-    * @return The name of the property
+    * @param annotation The potential match
+    * @return true if the specified annotation is a match
     */
-   public String getName()
+   protected boolean annotationMatches(T annotation)
    {
-      if (!scanned) scan();      
-      return name;
+      return true;
    }
    
    /**
@@ -194,174 +79,11 @@
     */
    public T getAnnotation()
    {
-      if (!scanned) scan();
+      scan();
       return annotation;
    }
+
+    
    
-   /**
-    * Returns the property type
-    * 
-    * @return The property type
-    */
-   public Type getPropertyType()
-   {
-      if (!scanned) scan();
-      return propertyType;
-   }
-   
-   /**
-    * Returns true if the property has been successfully located, otherwise
-    * returns false.
-    * 
-    * @return
-    */
-   public boolean isSet()
-   {
-      if (!scanned) scan();
-      return set;
-   }
-   
-   private void setupFieldProperty(Field propertyField)
-   {
-      this.propertyField = propertyField;
-      isFieldProperty = true;
-      this.name = propertyField.getName();
-      this.propertyType = propertyField.getGenericType();
-   }   
-   
-   private Object getFieldValue(Field field, Object obj)
-   {
-      field.setAccessible(true);
-      try
-      {
-         return field.get(obj);
-      }
-      catch (IllegalAccessException e)
-      {
-         throw new RuntimeException(buildGetFieldValueErrorMessage(field, obj), e);        
-      }      
-      catch (NullPointerException ex)
-      {         
-         NullPointerException ex2 = new NullPointerException(
-               buildGetFieldValueErrorMessage(field, obj));
-         ex2.initCause(ex.getCause());
-         throw ex2;
-      }   
-   }
-   
-   private String buildGetFieldValueErrorMessage(Field field, Object obj)
-   {
-      return String.format("Exception reading [%s] field from object [%s].",
-            field.getName(), obj);
-   }
-   
-   private void setFieldValue(Field field, Object obj, Object value)
-   {
-      field.setAccessible(true);
-      try
-      {
-         field.set(obj, value);
-      }
-      catch (IllegalAccessException e)
-      {
-         throw new RuntimeException(buildSetFieldValueErrorMessage(field, obj, value), e);
-      }
-      catch (NullPointerException ex)
-      {         
-         NullPointerException ex2 = new NullPointerException(
-               buildSetFieldValueErrorMessage(field, obj, value));
-         ex2.initCause(ex.getCause());
-         throw ex2;
-      }
-   }
-   
-   private String buildSetFieldValueErrorMessage(Field field, Object obj, Object value)
-   {
-      return String.format("Exception setting [%s] field on object [%s] to value [%s]",
-            field.getName(), obj, value);
-   }
-   
-   private Object invokeMethod(Method method, Object obj, Object... args)
-   {
-      try
-      {
-         return method.invoke(obj, args);
-      }
-      catch (IllegalAccessException ex)
-      {
-         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), ex);
-      }
-      catch (IllegalArgumentException ex)
-      {
-         throw new IllegalArgumentException(buildInvokeMethodErrorMessage(method, obj, args), ex.getCause()); 
-      }
-      catch (InvocationTargetException ex)
-      {
-         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), ex);
-      }
-      catch (NullPointerException ex)
-      {         
-         NullPointerException ex2 = new NullPointerException(buildInvokeMethodErrorMessage(method, obj, args));
-         ex2.initCause(ex.getCause());
-         throw ex2;
-      }
-      catch (ExceptionInInitializerError e)
-      {
-         throw new RuntimeException(buildInvokeMethodErrorMessage(method, obj, args), e);
-      }
-   }   
-   
-   private String buildInvokeMethodErrorMessage(Method method, Object obj, Object... args)
-   {
-      StringBuilder message = new StringBuilder(String.format(
-            "Exception invoking method [%s] on object [%s], using arguments [",
-            method.getName(), obj));
-      if (args != null) for (int i = 0; i < args.length; i++) message.append((i > 0 ? "," : "") + args[i]);
-      message.append("]");
-      return message.toString();
-   }
-   
-   private Method getSetterMethod(Class<?> clazz, String name)
-   {
-      Method[] methods = clazz.getMethods();
-      for (Method method: methods)
-      {
-         String methodName = method.getName();
-         if ( methodName.startsWith("set") && method.getParameterTypes().length==1 )
-         {
-            if ( Introspector.decapitalize( methodName.substring(3) ).equals(name) )
-            {
-               return method;
-            }
-         }
-      }
-      throw new IllegalArgumentException("no such setter method: " + clazz.getName() + '.' + name);
-   }
-   
-   private Method getGetterMethod(Class<?> clazz, String name)
-   {
-      Method[] methods = clazz.getMethods();
-      for (Method method: methods)
-      {
-         String methodName = method.getName();
-         if ( method.getParameterTypes().length==0 )
-         {
-            if ( methodName.startsWith("get") )
-            {
-               if ( Introspector.decapitalize( methodName.substring(3) ).equals(name) )
-               {
-                  return method;
-               }
-            }
-            else if ( methodName.startsWith("is") )
-            {
-               if ( Introspector.decapitalize( methodName.substring(2) ).equals(name) )
-               {
-                  return method;
-               }
-            }
-         }
-      }
-      throw new IllegalArgumentException("no such getter method: " + clazz.getName() + '.' + name);
-   }   
+ 
 }
\ No newline at end of file

Added: extensions/trunk/src/main/java/org/jboss/weld/extensions/util/TypedBeanProperty.java
===================================================================
--- extensions/trunk/src/main/java/org/jboss/weld/extensions/util/TypedBeanProperty.java	                        (rev 0)
+++ extensions/trunk/src/main/java/org/jboss/weld/extensions/util/TypedBeanProperty.java	2010-05-31 02:50:10 UTC (rev 6361)
@@ -0,0 +1,39 @@
+package org.jboss.weld.extensions.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A convenience class for working with a typed property (either a field or
+ * method) of a JavaBean class.
+ * 
+ * @author Shane Bryzak
+ */
+public class TypedBeanProperty<T> extends AbstractBeanProperty
+{
+   private Class<?> propertyClass;
+   
+   public TypedBeanProperty(Class<?> cls, Class<?> propertyClass)
+   {            
+      super(cls);
+      
+      if (propertyClass == null)
+      {
+         throw new IllegalArgumentException("propertyClass can not be null.");
+      }
+      
+      this.propertyClass = propertyClass;
+   }
+
+   @Override
+   protected boolean fieldMatches(Field f)
+   {
+      return propertyClass.equals(f.getType());
+   }
+
+   @Override
+   protected boolean methodMatches(Method m)
+   {
+      return propertyClass.equals(m.getReturnType());
+   }   
+}



More information about the weld-commits mailing list