Commits

Anonymous committed d5cce11

Fix for XW-367: Improve GenericsObjectTypeDeterminer to work on method level as well

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/xwork_1-2@1052e221344d-f017-0410-9bd5-d282ab1896d7

  • Participants
  • Parent commits 0698dc2
  • Branches xwork_1-2

Comments (0)

Files changed (1)

File tiger/src/java/com/opensymphony/xwork/util/GenericsObjectTypeDeterminer.java

 
 package com.opensymphony.xwork.util;
 
-import ognl.OgnlRuntime;
-
+import java.beans.IntrospectionException;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Map;
 
+import ognl.OgnlException;
+import ognl.OgnlRuntime;
+
 /**
- * GenericsObjectTypeDeterminer
+ * GenericsObjectTypeDeterminer use the following algorithm for determining the types: looks for 
+ * a field annotation, than for the corresponding setter annotation, and for special cases falls
+ * back to generic types.
  *
  * @author Patrick Lightbody
  * @author Rainer Hermanns
+ * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
  */
 public class GenericsObjectTypeDeterminer extends DefaultObjectTypeDeterminer {
 
      * @see com.opensymphony.xwork.util.ObjectTypeDeterminer#getKeyClass(Class, String)
      */
     public Class getKeyClass(Class parentClass, String property) {
+        Key annotation = getAnnotation(parentClass, property, Key.class);
 
-        Field field = OgnlRuntime.getField(parentClass, property);
-
-        if (field != null) {
-            Key annotation = field.getAnnotation(Key.class);
-            if (annotation != null) {
-                return annotation.value();
-            }
+        if (annotation != null) {
+            return annotation.value();
+        }
 
-            Class clazz = getClass(field, false);
+        Class clazz = getClass(OgnlRuntime.getField(parentClass, property), false);
 
-            if (clazz != null) {
-                return clazz;
-            }
+        if (clazz != null) {
+            return clazz;
         }
 
         return super.getKeyClass(parentClass, property);
      * @see com.opensymphony.xwork.util.ObjectTypeDeterminer#getElementClass(Class, String, Object)
      */
     public Class getElementClass(Class parentClass, String property, Object key) {
+        Element annotation = getAnnotation(parentClass, property, Element.class);
 
-        Field field = OgnlRuntime.getField(parentClass, property);
-
-        if (field != null) {
-            Element annotation = field.getAnnotation(Element.class);
-            if (annotation != null) {
-                return annotation.value();
-            }
+        if (annotation != null) {
+            return annotation.value();
+        }
 
-            Class clazz = getClass(field, true);
+        Class clazz = getClass(OgnlRuntime.getField(parentClass, property), true);
 
-            if (clazz != null) {
-                return clazz;
-            }
+        if (clazz != null) {
+            return clazz;
         }
 
         return super.getElementClass(parentClass, property, key);
      * @see com.opensymphony.xwork.util.ObjectTypeDeterminer#getKeyProperty(Class, String)
      */
     public String getKeyProperty(Class parentClass, String property) {
-
-        Field field = OgnlRuntime.getField(parentClass, property);
-
-        if (field != null) {
-            KeyProperty annotation = field.getAnnotation(KeyProperty.class);
-
-            if (annotation != null) {
-                return annotation.value();
-            }
+        KeyProperty annotation = getAnnotation(parentClass, property, KeyProperty.class);
+        
+        if (annotation != null) {
+            return annotation.value();
         }
 
-
         return super.getKeyProperty(parentClass, property);
     }
 
                                      String keyProperty,
                                      boolean isIndexAccessed) {
 
-        Field field = OgnlRuntime.getField(parentClass, property);
+        CreateIfNull annotation = getAnnotation(parentClass, property, CreateIfNull.class);
 
-        if (field != null) {
-            CreateIfNull annotation = field.getAnnotation(CreateIfNull.class);
-            if (annotation != null) {
-                return annotation.value();
-            }
+        if (annotation != null) {
+            return annotation.value();
         }
 
         return super.shouldCreateIfNew(parentClass, property, target, keyProperty, isIndexAccessed);
-
     }
 
     /**
+     * Retrieves an annotation for the specified field of setter.
+     * 
+     * @param <T> the annotation type to be retrieved
+     * @param parentClass the class
+     * @param property the property
+     * @param annotationClass the annotation 
+     * @return the field or setter annotation or <code>null</code> if not found
+     */
+    protected <T extends Annotation> T getAnnotation(Class parentClass, String property, Class<T> annotationClass) {
+        T annotation = null;
+        Field field = OgnlRuntime.getField(parentClass, property);
+
+        if (field != null) {
+            annotation = field.getAnnotation(annotationClass);
+        }
+        if (annotation == null) { // HINT: try with setter
+            try {
+                Method setter = OgnlRuntime.getSetMethod(null, parentClass, property);
+                
+                if (setter != null) {
+                    annotation = setter.getAnnotation(annotationClass);                    
+                }
+            }
+            catch(OgnlException ognle) {
+                ; // ignore
+            }
+            catch(IntrospectionException ie) {
+                ; // ignore
+            }
+        }
+        
+        return annotation;
+    }
+    
+    /**
      * Returns the class for the given field via generic type check.
      *
      * @param field The field to check for generic types.