Commits

Anonymous committed cdc5997

MUCH better implementation of Null handler -- uses ognl now

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@239e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (2)

src/java/com/opensymphony/xwork/util/InstantiatingNullHandler.java

 
 import com.opensymphony.xwork.ObjectFactory;
 import ognl.NullHandler;
+import ognl.Ognl;
+import ognl.OgnlContext;
+import ognl.OgnlRuntime;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import java.lang.reflect.Method;
-import java.util.*;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 
 /**
     public static final String CREATE_NULL_OBJECTS = "xwork.NullHandler.createNullObjects";
     private static final Log LOG = LogFactory.getLog(InstantiatingNullHandler.class);
 
-    //~ Instance fields ////////////////////////////////////////////////////////
-
-    HashMap mappings = new HashMap();
-    HashSet noMapping = new HashSet();
-    private Map clazzMap = new HashMap();
-
     //~ Methods ////////////////////////////////////////////////////////////////
 
     public Object nullMethodResult(Map context, Object target, String methodName, Object[] args) {
             return null;
         }
 
-        Method method = null;
-
-        if (target instanceof CompoundRoot) {
-            // sometimes the null object may be at the root, so we need to check all of them
-            CompoundRoot root = (CompoundRoot) target;
-
-            for (Iterator iterator = root.iterator(); iterator.hasNext();) {
-                Object o = iterator.next();
-                Map methodMap = getMethodMap(o);
-                method = getMethod(methodMap, property.toString(), o);
-
-                if (method != null) {
-                    target = o;
-
-                    break;
+        try {
+            Class clazz = null;
+            Object o = target;
+            if (target instanceof CompoundRoot) {
+                CompoundRoot root = (CompoundRoot) target;
+                for (Iterator iterator = root.iterator(); iterator.hasNext();) {
+                    o = iterator.next();
+                    if (OgnlRuntime.hasSetProperty((OgnlContext) context, o, property.toString())) {
+                        clazz = OgnlRuntime.getPropertyDescriptor(o.getClass(), property.toString()).getPropertyType();
+                        break;
+                    }
                 }
+            } else {
+                clazz = OgnlRuntime.getPropertyDescriptor(o.getClass(), property.toString()).getPropertyType();
             }
-        } else {
-            Map methodMap = getMethodMap(target);
-            method = getMethod(methodMap, property.toString(), target);
-        }
 
-        /**
-         * if we didn't find any single parameter setters for this method, then there's nothing we can do.
-         */
-        if (method == null) {
-            return null;
-        }
+            Object param = createObject(clazz, o, property.toString());
 
-        try {
-            Class clazz = method.getParameterTypes()[0];
-            Object param = createObject(context, clazz, target, property.toString());
-            method.invoke(target, new Object[]{param});
+            Ognl.setValue(property.toString(), context, o, param);
+            //OgnlRuntime.setProperty((OgnlContext) context, target, property.toString(), param);
+            //method.invoke(target, new Object[]{param});
 
             return param;
         } catch (Exception e) {
+            e.printStackTrace();
             LOG.error("Could not create and/or set value back on to object", e);
         }
 
         return (Class) XWorkConverter.getInstance().getConverter(clazz, "Collection_" + property);
     }
 
-    /**
-     * Attempt to find the setter associated with the provided instance and propertyName.  If we do find it, place that
-     * Method into the methodMap keyed by property name
-     *
-     * @param propertyName the name of the property we're looking up
-     * @param instance     of instance of the Class we're attempting to find the setter for
-     */
-    private Method getMethod(Map methodMap, String propertyName, Object instance) {
-        synchronized (methodMap) {
-            Method method = (Method) methodMap.get(propertyName);
-
-            if (method == null) {
-                String getter = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
-                Method[] methods = instance.getClass().getDeclaredMethods();
-
-                for (int i = 0; i < methods.length; i++) {
-                    String name = methods[i].getName();
-
-                    if (!getter.equals(name) || (methods[i].getParameterTypes().length != 1)) {
-                        continue;
-                    } else {
-                        method = methods[i];
-                        methodMap.put(propertyName, method);
-
-                        break;
-                    }
-                }
-            }
-
-            return method;
-        }
-    }
-
-    /**
-     * returns the Map associated with a given Class of Objects
-     *
-     * @param instance an instance of the Class we're interested in
-     * @return a Map of Method instances keyed by property name
-     */
-    private Map getMethodMap(Object instance) {
-        synchronized (clazzMap) {
-            Map methodMap = (Map) clazzMap.get(instance.getClass());
-
-            if (methodMap == null) {
-                methodMap = new HashMap();
-                clazzMap.put(instance.getClass(), methodMap);
-            }
-
-            return methodMap;
-        }
-    }
-
-    private Object createObject(Map context, Class clazz, Object target, String property) throws Exception {
+    private Object createObject(Class clazz, Object target, String property) throws Exception {
         if ((clazz == Collection.class) || (clazz == List.class)) {
             Class collectionType = getCollectionType(target.getClass(), property);
 

src/test/com/opensymphony/xwork/util/InstantiatingNullHandlerTest.java

 package com.opensymphony.xwork.util;
 
 import junit.framework.TestCase;
+import ognl.OgnlContext;
+
+import java.util.List;
+import java.util.Map;
 
 public class InstantiatingNullHandlerTest extends TestCase {
     public void testInheritance() {
         Tiger t = new Tiger();
+        CompoundRoot root = new CompoundRoot();
+        root.add(t);
+
+        Map context = new OgnlContext();
+        context.put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.TRUE);
         InstantiatingNullHandler nh = new InstantiatingNullHandler();
 
+        Object dogList = nh.nullPropertyValue(context, root, "dogs");
         Class clazz = nh.getCollectionType(Tiger.class, "dogs");
         assertEquals(Dog.class, clazz);
+        assertNotNull(dogList);
+        assertTrue(dogList instanceof List);
+
 
+        Object kittenList = nh.nullPropertyValue(context, root, "kittens");
         clazz = nh.getCollectionType(Tiger.class, "kittens");
         assertEquals(Cat.class, clazz);
+        assertNotNull(kittenList);
+        assertTrue(kittenList instanceof List);
     }
 }