Commits

Anonymous committed 1fa9f0f

Issue number: XW-313, XW-314
Obtained from:
Submitted by:
Reviewed by:
CVS: ----------------------------------------------------------------------
CVS: Issue number: XW-313, XW-314
CVS: If this change addresses one or more issues,
CVS: then enter the issue number(s) here.
CVS: Obtained from:
CVS: If this change has been taken from another system,
CVS: then name the system in this line, otherwise delete it.
CVS: Submitted by:
CVS: If this code has been contributed to the project by someone else; i.e.,
CVS: they sent us a patch or a set of diffs, then include their name/email
CVS: address here. If this is your work then delete this line.
CVS: Reviewed by:
CVS: If we are doing pre-commit code reviews and someone else has
CVS: reviewed your changes, include their name(s) here.
CVS: If you have not had it reviewed then delete this line.

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

Comments (0)

Files changed (8)

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

  */
 package com.opensymphony.xwork.util;
 
+import java.util.Map;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
     public static final String KEY_PREFIX = "Key_";
     public static final String ELEMENT_PREFIX = "Element_";
     public static final String KEY_PROPERTY_PREFIX = "KeyProperty_";
+    public static final String CREATE_IF_NULL_PREFIX = "CreateIfNull_";
     public static final String DEPRECATED_ELEMENT_PREFIX = "Collection_";
 
 
                 .getConverter(parentClass, KEY_PROPERTY_PREFIX + property);
 
     }
-
+    
+    public boolean shouldCreateIfNew(Class parentClass, 
+            String property, 
+            Object target,
+            String keyProperty,
+            boolean isIndexAccessed) {
+        
+        	String configValue=(String) XWorkConverter.getInstance()
+            .getConverter(parentClass, CREATE_IF_NULL_PREFIX + property);
+        	//check if a value is in the config
+        	if (configValue!=null) {
+        	    if (configValue.equals("true")) {
+        	        return true;
+        	    }
+        	    if (configValue.equals("false")) {
+        	        return false;
+        	    }        	      
+        	}
+        	
+        	//default values depend on target type 
+        	//and whether this is accessed by an index
+        	//in the case of List
+        	if ((target instanceof Map) || isIndexAccessed) {
+        	    return true;
+        	}	else {
+        	    return false;
+        	}
+    }
 }

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

     public Class getElementClass(Class parentClass, String property, Object key);
 
     public String getKeyProperty(Class parentClass, String property);
+    
+    public boolean shouldCreateIfNew(Class parentClass, 
+            String property, 
+            Object target,
+            String keyProperty,
+            boolean isIndexAccessed);
 }

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

 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import com.opensymphony.xwork.ObjectFactory;
+
 import java.util.*;
 
 /**
             OgnlContextState.updateCurrentPropertyPath(context, key);
             return super.getProperty(context, target, key);
         }
-
+        
+        ObjectTypeDeterminer objTypeDeterminer=XWorkConverter.getInstance()
+        .getObjectTypeDeterminer();
+        
         //get the key property to index the
         //collection with from the ObjectTypeDeterminer
-        String keyProperty = XWorkConverter.getInstance()
-                .getObjectTypeDeterminer()
+        String keyProperty = objTypeDeterminer
                 .getKeyProperty(lastBeanClass, lastPropertyClass);
 
         //get the collection class of the
                 return collMap.get(null);
             }
             Object realKey = XWorkConverter.getInstance().convertValue(context, key, keyType);
-            return collMap.get(realKey);
+            Object value = collMap.get(realKey);
+            if (value == null
+                    && OgnlContextState.isCreatingNullObjects(context)
+                    && objTypeDeterminer
+                    .shouldCreateIfNew(lastBeanClass,lastPropertyClass,c,keyProperty,false)) {
+                	//create a new element and 
+                    //set the value of keyProperty
+                    //to be the given value
+                	try {
+                	    value=ObjectFactory
+                		.getObjectFactory()
+                		.buildBean(collClass, context);
+                	    
+                	    //set the value of the keyProperty
+                	    _accessor.setProperty(context,value,keyProperty,realKey);
+                	    
+                	    //add the new object to the collection 
+                	    c.add(value);
+                	    
+                	    //add to the Map if accessed later
+                	    collMap.put(realKey, value);
+                	    
+                	    
+                	}	catch (Exception exc) {
+                	    throw new OgnlException("Error adding new element to collection", exc);
+                	    
+                	}
+                
+            }
+            return value;
         } else {
             if (key.toString().equals(KEY_PROPERTY_FOR_CREATION)) {
                 return null;

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

                         LOG.debug(key + ":" + entry.getValue());
                     }
 
-                    if (key.startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX)) {
+                    if (key.startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX)
+                            || key.startsWith(DefaultObjectTypeDeterminer.CREATE_IF_NULL_PREFIX)) {
                         mapping.put(key, entry.getValue());
                     }
                     //for properties of classes

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

         }
         OgnlContextState.updateCurrentPropertyPath(context, name);
         //System.out.println("Entering XWorkListPropertyAccessor. Name: " + name);
+        Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
+        String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
+        
         if (name instanceof Number
-                && context.get(InstantiatingNullHandler.CREATE_NULL_OBJECTS) != null) {
+                && OgnlContextState.isCreatingNullObjects(context)
+                && XWorkConverter.getInstance()
+                .getObjectTypeDeterminer().shouldCreateIfNew(lastClass,lastProperty,target,null,true)) {
 
             //System.out.println("Getting index from List");
             List list = (List) target;
             int index = ((Number) name).intValue();
             int listSize = list.size();
-            Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
-            String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
+
             if (lastClass == null || lastProperty == null) {
                 return super.getProperty(context, target, name);
             }
                     OgnlUtil.setValue((String) name, context, o, v);
                     c.add(o);
                 } catch (Exception e) {
-                    // what to do?
+                    throw new OgnlException("Error converting given String values for Collection.", e);
                 }
             }
 

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

             result = map.get(key);
 
             if (result == null &&
-                    context.get(InstantiatingNullHandler.CREATE_NULL_OBJECTS) != null) {
+                    context.get(InstantiatingNullHandler.CREATE_NULL_OBJECTS) != null
+                    &&  XWorkConverter.getInstance()
+                    .getObjectTypeDeterminer().shouldCreateIfNew(lastClass,lastProperty,target,null,false)) {
                 Class valueClass = _converter.getObjectTypeDeterminer().getElementClass(lastClass, lastProperty, key);
 
                 try {

src/test/com/opensymphony/xwork/config/providers/MockConfigurationProvider.java

 
     public static final String FOO_ACTION_NAME = "foo";
     public static final String MODEL_DRIVEN_PARAM_TEST = "modelParamTest";
+    public static final String MODEL_DRIVEN_PARAM_FILTER_TEST  = "modelParamFilterTest";
     public static final String PARAM_INTERCEPTOR_ACTION_NAME = "parametersInterceptorTest";
     public static final String VALIDATION_ACTION_NAME = "validationInterceptorTest";
     public static final String VALIDATION_ALIAS_NAME = "validationAlias";
 
         ActionConfig modelParamActionConfig = new ActionConfig(null, ModelDrivenAction.class, null, null, interceptors);
         defaultPackageContext.addActionConfig(MODEL_DRIVEN_PARAM_TEST, modelParamActionConfig);
+        
+        //List paramFilterInterceptor=new ArrayList();
+        //paramFilterInterceptor.add(new ParameterFilterInterC)
+        //ActionConfig modelParamFilterActionConfig = new ActionConfig(null, ModelDrivenAction.class, null, null, interceptors);
+        
 
         results = new HashMap();
         successParams = new HashMap();

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

 
 
 /**
- * @author CameronBraid
+ * @author CameronBraid and Gabe
  */
 public class SetPropertiesTest extends TestCase {
 
         assertNull(bar.getId());
         assertEquals(0, bar.getFieldErrors().size());
     }
-
     public void testAddingToListsWithObjects() {
+        doTestAddingToListsWithObjects(true);
+        doTestAddingToListsWithObjects(false);
+        
+    }
+    public void doTestAddingToListsWithObjects(boolean allowAdditions) {
+        
+        MockObjectTypeDeterminer determiner
+        =new MockObjectTypeDeterminer(null,Cat.class,null,allowAdditions);
+        XWorkConverter.getInstance().setKeyElementDeterminer(determiner);
+        
         Foo foo = new Foo();
         foo.setMoreCats(new ArrayList());
         String spielname = "Spielen";
         vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
         vs.getContext().put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.TRUE);
         vs.push(foo);
+        try {
         vs.setValue("moreCats[2].name", spielname);
-        Object setCat = foo.getMoreCats().get(2);
-        assertNotNull(setCat);
-        assertTrue(setCat instanceof Cat);
-        assertTrue(((Cat) setCat).getName().equals(spielname));
+        } catch (IndexOutOfBoundsException e) {
+            if (allowAdditions) {
+                throw e;
+            }
+        }
+        Object setCat = null;
+        if (allowAdditions) {
+             setCat = foo.getMoreCats().get(2);
+        
+        
+	        assertNotNull(setCat);
+	        assertTrue(setCat instanceof Cat);
+	        assertTrue(((Cat) setCat).getName().equals(spielname));
+        }	else {
+            assertTrue(foo.getMoreCats()==null || foo.getMoreCats().size()==0);
+        }
+        
         //now try to set a lower number
         //to test setting after a higher one
         //has been created
-        spielname = "paws";
-        vs.setValue("moreCats[0].name", spielname);
-        setCat = foo.getMoreCats().get(0);
-        assertNotNull(setCat);
-        assertTrue(setCat instanceof Cat);
-        assertTrue(((Cat) setCat).getName().equals(spielname));
-
+        if (allowAdditions) {
+	        spielname = "paws";
+	        vs.setValue("moreCats[0].name", spielname);
+	        setCat = foo.getMoreCats().get(0);
+	        assertNotNull(setCat);
+	        assertTrue(setCat instanceof Cat);
+	        assertTrue(((Cat) setCat).getName().equals(spielname));
+        }
 
     }
-
+    
     public void testAddingToMapsWithObjects() {
+        doTestAddingToMapsWithObjects(true);
+        doTestAddingToMapsWithObjects(false);
+        
+    }
+    
+    public void doTestAddingToMapsWithObjects(boolean allowAdditions) {
+        
+        MockObjectTypeDeterminer determiner
+        =new MockObjectTypeDeterminer(Long.class,Cat.class,null,allowAdditions);
+        XWorkConverter.getInstance().setKeyElementDeterminer(determiner);
+        
         Foo foo = new Foo();
         foo.setAnotherCatMap(new HashMap());
         String spielname = "Spielen";
         vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
         vs.setValue("anotherCatMap[\"3\"].name", spielname);
         Object setCat = foo.getAnotherCatMap().get(new Long(3));
-        assertNotNull(setCat);
-        assertTrue(setCat instanceof Cat);
-        assertTrue(((Cat) setCat).getName().equals(spielname));
+        if (allowAdditions) {
+	        assertNotNull(setCat);
+	        assertTrue(setCat instanceof Cat);
+	        assertTrue(((Cat) setCat).getName().equals(spielname));
+        }	else {
+            assertNull(setCat);
+        }
 
 
     }
     
     public void testAddingAndModifyingCollectionWithObjects() {
         doTestAddingAndModifyingCollectionWithObjects(new HashSet());
-        doTestAddingAndModifyingCollectionWithObjects(new ArrayList());
+        doTestAddingAndModifyingCollectionWithObjects(new ArrayList());      
         
     }
     public void doTestAddingAndModifyingCollectionWithObjects(Collection barColl) {
+
+        XWorkConverter.getInstance().setKeyElementDeterminer(new DefaultObjectTypeDeterminer());
         OgnlValueStack vs = new OgnlValueStack();
         Foo foo = new Foo();
         
                 assertEquals(bar1Title, next.getTitle());
             }
         }
-        //now test adding
+        //now test adding to a collection
         String bar3Title = "Revenge of the Sith";
         String bar4Title = "A New Hope";
         vs.setValue("barCollection.makeNew[4].title", bar4Title, true);
         vs.setValue("barCollection.makeNew[0].title", bar3Title, true);
+
         assertEquals(4, barColl.size());
         barSetIter = barColl.iterator();
 
         }
 
     }
+    
+    public void testAddingToCollectionBasedOnPermission() {
+        
+        MockObjectTypeDeterminer determiner
+        =new MockObjectTypeDeterminer(Long.class,Bar.class,"id",true);
+        XWorkConverter.getInstance().setKeyElementDeterminer(determiner);
+        
+        Collection barColl=new HashSet();
+        
+        OgnlValueStack vs = new OgnlValueStack();
+        OgnlContextState.setCreatingNullObjects(vs.getContext(), true);
+        OgnlContextState.setReportingConversionErrors(vs.getContext(), true);
+        Foo foo = new Foo();
+        
+        foo.setBarCollection(barColl);
+        
+        vs.push(foo);
+        
+        String bar1Title="title";
+        vs.setValue("barCollection(11).title", bar1Title);
+        
+        assertEquals(1, barColl.size());
+        Object bar=barColl.iterator().next();
+        assertTrue(bar instanceof Bar);
+        assertEquals(((Bar)bar).getTitle(), bar1Title);
+        assertEquals(((Bar)bar).getId(), new Long(11));
+        
+        //now test where there is no permission
+        determiner.setShouldCreateIfNew(false);
+        
+        String bar2Title="another title";
+        vs.setValue("barCollection(22).title", bar1Title);
+        
+        assertEquals(1, barColl.size());
+        bar=barColl.iterator().next();
+        assertTrue(bar instanceof Bar);
+        assertEquals(((Bar)bar).getTitle(), bar1Title);
+        assertEquals(((Bar)bar).getId(), new Long(11));
+        
+        
+    }
 
 
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.