You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by cl...@apache.org on 2008/10/06 21:29:47 UTC

svn commit: r702237 - in /jackrabbit/trunk/jackrabbit-ocm/src: main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/ main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ main/java/org/apache/jackrabbit/ocm/manager/objectconverte...

Author: clombart
Date: Mon Oct  6 12:29:47 2008
New Revision: 702237

URL: http://svn.apache.org/viewvc?rev=702237&view=rev
Log:
Patch provided by Boni Gopalan for issue JCR-1784 (The UUID of the collection elements changes on update). I didn't modify the class AbstractMapperImpl. This modification is not necessary.
I also added unit tests for the annotation support. 

Added:
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AnnotationPersonListTest.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/DigesterPersonListTest.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/testmodel/collection/Person.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/test-config/jcrmapping-complex-collections.xml
Modified:
    jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/DefaultCollectionConverterImpl.java
    jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ObjectConverter.java
    jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java
    jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/mapper/model/ClassDescriptor.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/AnnotationTestBase.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/DigesterTestBase.java
    jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AllTests.java

Modified: jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/DefaultCollectionConverterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/DefaultCollectionConverterImpl.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/DefaultCollectionConverterImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/collectionconverter/impl/DefaultCollectionConverterImpl.java Mon Oct  6 12:29:47 2008
@@ -206,7 +206,7 @@
         Node collectionNode = parentNode.getNode(jcrName);
         //  If the collection elements have not an id, it is not possible to find the matching JCR nodes 
         //  => delete the complete collection
-        if (!elementClassDescriptor.hasIdField()) {
+        if (!elementClassDescriptor.hasIdField() && !elementClassDescriptor.hasUUIdField()) {
             collectionNode.remove();
             collectionNode = parentNode.addNode(jcrName);
         }
@@ -214,12 +214,31 @@
         Iterator collectionIterator = objects.getIterator();
 
         Map updatedItems = new HashMap();
+        List<String> validUuidsForTheNode = new ArrayList<String>();
         while (collectionIterator.hasNext()) {
             Object item = collectionIterator.next();
-
             String elementJcrName = null;
-
-            if (elementClassDescriptor.hasIdField()) {
+            
+            if (elementClassDescriptor.hasUUIdField()){
+            	elementJcrName = collectionDescriptor.getJcrElementName();
+            	elementJcrName = (elementJcrName == null)? COLLECTION_ELEMENT_NAME : elementJcrName;
+                String uuidFieldName = elementClassDescriptor.getUuidFieldDescriptor().getFieldName();
+                Object objUuid = ReflectionUtils.getNestedProperty(item, uuidFieldName);
+            	String currentItemUuid = (objUuid == null) ? null : objUuid.toString();
+            	if (currentItemUuid != null){
+            		//The Node already exists so we need to update the existing node 
+            		//rather than to replace it.
+            		Node nodeToUpdate = collectionNode.getSession().getNodeByUUID(currentItemUuid);
+            		objectConverter.update(session, currentItemUuid, item);
+            		validUuidsForTheNode.add(currentItemUuid);
+            	}
+            	else{
+            		objectConverter.insert(session, collectionNode, elementJcrName, item);
+            		validUuidsForTheNode.add(ReflectionUtils.getNestedProperty(item, uuidFieldName).toString());
+            	}
+            	
+            }
+            else if (elementClassDescriptor.hasIdField()) {
 
                 String idFieldName = elementClassDescriptor.getIdFieldDescriptor().getFieldName();
                 elementJcrName = ReflectionUtils.getNestedProperty(item, idFieldName).toString();
@@ -245,6 +264,22 @@
         }
 
         // Delete JCR nodes that are not present in the collection
+        if (elementClassDescriptor.hasUUIdField()) {
+            NodeIterator nodeIterator = collectionNode.getNodes();
+            List<Node> removeNodes = new ArrayList<Node>();
+            while (nodeIterator.hasNext()) {
+            	Node currentNode = nodeIterator.nextNode();
+            	if (!validUuidsForTheNode.contains(currentNode.getUUID())) {
+                    removeNodes.add(currentNode);
+                }
+            }
+            for (Node aNode : removeNodes){
+            	aNode.remove();
+            }
+            return;
+        }
+        
+        // Delete JCR nodes that are not present in the collection
         if (elementClassDescriptor.hasIdField()) {
             NodeIterator nodeIterator = collectionNode.getNodes();
             List removeNodes = new ArrayList();
@@ -348,4 +383,4 @@
         }
         return false;
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ObjectConverter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ObjectConverter.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ObjectConverter.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/ObjectConverter.java Mon Oct  6 12:29:47 2008
@@ -115,7 +115,16 @@
 	 */
     public void update(Session session, Node parentNode, String nodeName, Object object) throws ObjectContentManagerException;
 
-
+	/**
+	 * Update the object
+	 *
+	 * @param session the JCR session
+	 * @param uuId The UUID of the node to get updated.
+	 * @param object the object to update
+	 * @throws ObjectContentManagerException when it is not possible to update the object
+	 */
+    public void update(Session session, String uuId, Object object);
+    
     /**
      * Get the object JCR path
      *

Modified: jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java Mon Oct  6 12:29:47 2008
@@ -271,6 +271,32 @@
 	 * @see org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter#update(javax.jcr.Session,
 	 *      javax.jcr.Node, java.lang.String, java.lang.Object)
 	 */
+	public void update(Session session, String uuId, Object object) {
+		try {
+			ClassDescriptor classDescriptor = mapper.getClassDescriptorByClass(ReflectionUtils.getBeanClass(object));
+			Node objectNode = session.getNodeByUUID(uuId);
+
+			checkNodeType(session, classDescriptor);
+
+			checkCompatiblePrimaryNodeTypes(session, objectNode, classDescriptor, false);
+
+			simpleFieldsHelp.storeSimpleFields(session, object, classDescriptor, objectNode);
+			updateBeanFields(session, object, classDescriptor, objectNode);
+			updateCollectionFields(session, object, classDescriptor, objectNode);
+			simpleFieldsHelp.refreshUuidPath(session, classDescriptor, objectNode, object);
+		} catch (PathNotFoundException pnfe) {
+			throw new ObjectContentManagerException("Impossible to update the object with UUID: " + uuId , pnfe);
+		} catch (RepositoryException re) {
+			throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to update the object with UUID: " + uuId, re);
+		}
+	}
+	
+	
+	/**
+	 *
+	 * @see org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter#update(javax.jcr.Session,
+	 *      javax.jcr.Node, java.lang.String, java.lang.Object)
+	 */
 	public void update(Session session, Node parentNode, String nodeName, Object object) {
 		try {
 			ClassDescriptor classDescriptor = mapper.getClassDescriptorByClass(ReflectionUtils.getBeanClass(object));

Modified: jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/mapper/model/ClassDescriptor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/mapper/model/ClassDescriptor.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/mapper/model/ClassDescriptor.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/main/java/org/apache/jackrabbit/ocm/mapper/model/ClassDescriptor.java Mon Oct  6 12:29:47 2008
@@ -296,6 +296,16 @@
     }
 
     /**
+     * Check if this class has an UUID
+     * @return true if the class has an UUID
+     */
+    public boolean hasUUIdField(){
+        return (this.getUuidFieldDescriptor() != null
+        		&& this.getUuidFieldDescriptor().isUuid());
+    	
+    }
+
+    /**
      * Get the JCR name used for one of the object attributes
      * @param fieldName the object attribute name (can be an atomic field, bean field or a collection field)
      * @return the JCR name found
@@ -589,4 +599,4 @@
 	public String toString() {
 		return "Class Descriptor : " +  this.getClassName();
 	}
-}
\ No newline at end of file
+}

Modified: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/AnnotationTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/AnnotationTestBase.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/AnnotationTestBase.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/AnnotationTestBase.java Mon Oct  6 12:29:47 2008
@@ -52,6 +52,7 @@
 import org.apache.jackrabbit.ocm.testmodel.Residual.ResidualProperties;
 import org.apache.jackrabbit.ocm.testmodel.collection.Element;
 import org.apache.jackrabbit.ocm.testmodel.collection.Main;
+import org.apache.jackrabbit.ocm.testmodel.collection.Person;
 import org.apache.jackrabbit.ocm.testmodel.inheritance.Ancestor;
 import org.apache.jackrabbit.ocm.testmodel.inheritance.AnotherDescendant;
 import org.apache.jackrabbit.ocm.testmodel.inheritance.Descendant;
@@ -170,6 +171,7 @@
 		classes.add(SimpleAnnotedAbstractClass.class);
 		classes.add(SimpleAnnotedClass.class);
 		classes.add(SimpleInterface.class);
+		classes.add(Person.class);
 		
 		Mapper mapper = new AnnotationMapperImpl(classes);
 		ocm = new ObjectContentManagerImpl(session, mapper);

Modified: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/DigesterTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/DigesterTestBase.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/DigesterTestBase.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/DigesterTestBase.java Mon Oct  6 12:29:47 2008
@@ -57,10 +57,11 @@
                            "./src/test/test-config/jcrmapping-beandescriptor.xml",
                            "./src/test/test-config/jcrmapping-inheritance.xml",
                            "./src/test/test-config/jcrmapping-jcrnodetypes.xml",
-                           "./src/test/test-config/jcrmapping-uuid.xml"};
+                           "./src/test/test-config/jcrmapping-uuid.xml",
+                           "./src/test/test-config/jcrmapping-complex-collections.xml"};
 		session = RepositoryUtil.login(repository, "superuser", "superuser");
 		ocm = new ObjectContentManagerImpl(session, files);
 		
 	}
 
-}
\ No newline at end of file
+}

Modified: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AllTests.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AllTests.java?rev=702237&r1=702236&r2=702237&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AllTests.java (original)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AllTests.java Mon Oct  6 12:29:47 2008
@@ -41,6 +41,7 @@
         suite.addTestSuite(AnnotationHashMapTest.class);
         suite.addTestSuite(AnnotationMultiValueCollectionConverterImplTest.class);
         suite.addTestSuite(AnnotationNTCollectionConverterImplTest.class);
+        suite.addTestSuite(AnnotationPersonListTest.class);
         suite.addTestSuite(AnnotationResidualNodesCollectionConverterImplTest.class);
         suite.addTestSuite(AnnotationResidualPropertiesCollectionConverterImplTest.class);
         suite.addTestSuite(DigesterArrayListTest.class);
@@ -48,6 +49,7 @@
         suite.addTestSuite(DigesterHashMapTest.class);
         suite.addTestSuite(DigesterMultiValueCollectionConverterImplTest.class);
         suite.addTestSuite(DigesterNTCollectionConverterImplTest.class);
+        suite.addTestSuite(DigesterPersonListTest.class);
         suite.addTestSuite(DigesterResidualNodesCollectionConverterImplTest.class);
         suite.addTestSuite(DigesterResidualPropertiesCollectionConverterImplTest.class);
 

Added: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AnnotationPersonListTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AnnotationPersonListTest.java?rev=702237&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AnnotationPersonListTest.java (added)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/AnnotationPersonListTest.java Mon Oct  6 12:29:47 2008
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.ocm.manager.collectionconverter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.ocm.AnnotationTestBase;
+import org.apache.jackrabbit.ocm.RepositoryLifecycleTestSetup;
+import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
+import org.apache.jackrabbit.ocm.testmodel.collection.Person;
+
+/**
+ * @author <a href="mailto:boni.g@bioimagene.com">Boni Gopalan</a>
+ */
+public class AnnotationPersonListTest extends AnnotationTestBase
+{
+    private final static Log log = LogFactory.getLog(AnnotationPersonListTest.class);
+
+    /**
+     * <p>Defines the test case name for junit.</p>
+     * @param testName The test case name.
+     */
+    public AnnotationPersonListTest(String testName)  throws Exception
+    {
+        super(testName);
+    }
+
+    public static Test suite()
+    {
+        // All methods starting with "test" will be executed in the test suite.
+        return new RepositoryLifecycleTestSetup(new TestSuite(AnnotationPersonListTest.class));
+    }
+
+    public void testPersonList()
+    {
+        try
+        {
+        	ObjectContentManager ocm = getObjectContentManager();
+        	Person aPerson = buildPerson("PERSON1");
+        	aPerson.setPath("/person");
+        	ocm.insert(aPerson);
+        	ocm.save();
+        	assertNotNull(aPerson.getId());
+        	String oldParentId = new String(aPerson.getId().toCharArray());
+        	List<String> childIds = new ArrayList<String>(); 
+        	for (Person p : aPerson.getChildren()){
+        		assertNotNull(p.getId());
+        		childIds.add(new String(p.getId().toCharArray()));
+        	}
+        	aPerson.setName("UPDATED1");
+        	ocm.update(aPerson);
+        	Person fb1Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb1Person);
+        	assertEquals("UPDATED1", fb1Person.getName());
+        	assertEquals(oldParentId, fb1Person.getId());
+        	
+        	//To assert that the ids of the objects in the 
+        	//collection has not changed during update.
+        	for (Person p : fb1Person.getChildren()){
+        		assertTrue(childIds.contains(p.getId()));
+        	}
+        	
+        	Person newChild = new Person();
+        	newChild.setName("CHILD2");
+        	
+        	fb1Person.getChildren().add(newChild);
+        	ocm.update(fb1Person);
+        	
+        	Person fb2Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb2Person);
+        	assertEquals("UPDATED1", fb2Person.getName());
+        	assertEquals(oldParentId, fb2Person.getId());
+        	
+        	//To assert that the ids of the objects in the 
+        	//collection has not changed during update.
+        	String child2Id = null;
+        	for (Person p : fb2Person.getChildren()){
+        		if (!"CHILD2".equals(p.getName()))
+        			assertTrue(childIds.contains(p.getId()));
+        		else{
+        			assertNotNull(p.getId());
+        			child2Id = new String(p.getId().toCharArray());
+        			assertFalse(childIds.contains(p.getId()));
+        		}
+        	}
+        	
+        	//Now remove everyone but CHILD2 and do the update once again
+        	List<Person> peopleToRemove = new ArrayList<Person>();
+        	for (Person p : fb2Person.getChildren()){
+        		if (!"CHILD2".equals(p.getName()))
+        			peopleToRemove.add(p);
+        	}
+        	
+        	for (Person p : peopleToRemove){
+        		fb2Person.getChildren().remove(p);
+        	}
+        	
+        	ocm.update(fb2Person);
+        	
+        	Person fb3Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb3Person);
+        	assertEquals(1, fb3Person.getChildren().size());
+        	assertEquals(child2Id, fb3Person.getChildren().get(0).getId());
+        	
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            fail("Exception occurs during the unit test : " + e);
+        }
+    }
+    
+    public Person buildPerson(String name){
+    	Person p = new Person();
+    	p.setName(name);
+    	Person aChild = new Person();
+    	aChild.setName("CHILD1");
+    	List<Person> children = new ArrayList<Person>();
+    	children.add(aChild);
+    	p.setChildren(children);
+    	return p;
+    }
+
+
+
+}

Added: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/DigesterPersonListTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/DigesterPersonListTest.java?rev=702237&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/DigesterPersonListTest.java (added)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/manager/collectionconverter/DigesterPersonListTest.java Mon Oct  6 12:29:47 2008
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.ocm.manager.collectionconverter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.ocm.DigesterTestBase;
+import org.apache.jackrabbit.ocm.RepositoryLifecycleTestSetup;
+import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
+import org.apache.jackrabbit.ocm.testmodel.collection.ArrayListElement;
+import org.apache.jackrabbit.ocm.testmodel.collection.Element;
+import org.apache.jackrabbit.ocm.testmodel.collection.Main;
+import org.apache.jackrabbit.ocm.testmodel.collection.Person;
+
+/**
+ * @author <a href="mailto:boni.g@bioimagene.com">Boni Gopalan</a>
+ */
+public class DigesterPersonListTest extends DigesterTestBase
+{
+    private final static Log log = LogFactory.getLog(DigesterPersonListTest.class);
+
+    /**
+     * <p>Defines the test case name for junit.</p>
+     * @param testName The test case name.
+     */
+    public DigesterPersonListTest(String testName)  throws Exception
+    {
+        super(testName);
+    }
+
+    public static Test suite()
+    {
+        // All methods starting with "test" will be executed in the test suite.
+        return new RepositoryLifecycleTestSetup(new TestSuite(DigesterPersonListTest.class));
+    }
+
+    public void testPersonList()
+    {
+        try
+        {
+        	ObjectContentManager ocm = getObjectContentManager();
+        	Person aPerson = buildPerson("PERSON1");
+        	aPerson.setPath("/person");
+        	ocm.insert(aPerson);
+        	ocm.save();
+        	assertNotNull(aPerson.getId());
+        	String oldParentId = new String(aPerson.getId().toCharArray());
+        	List<String> childIds = new ArrayList<String>(); 
+        	for (Person p : aPerson.getChildren()){
+        		assertNotNull(p.getId());
+        		childIds.add(new String(p.getId().toCharArray()));
+        	}
+        	aPerson.setName("UPDATED1");
+        	ocm.update(aPerson);
+        	Person fb1Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb1Person);
+        	assertEquals("UPDATED1", fb1Person.getName());
+        	assertEquals(oldParentId, fb1Person.getId());
+        	
+        	//To assert that the ids of the objects in the 
+        	//collection has not changed during update.
+        	for (Person p : fb1Person.getChildren()){
+        		assertTrue(childIds.contains(p.getId()));
+        	}
+        	
+        	Person newChild = new Person();
+        	newChild.setName("CHILD2");
+        	
+        	fb1Person.getChildren().add(newChild);
+        	ocm.update(fb1Person);
+        	
+        	Person fb2Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb2Person);
+        	assertEquals("UPDATED1", fb2Person.getName());
+        	assertEquals(oldParentId, fb2Person.getId());
+        	
+        	//To assert that the ids of the objects in the 
+        	//collection has not changed during update.
+        	String child2Id = null;
+        	for (Person p : fb2Person.getChildren()){
+        		if (!"CHILD2".equals(p.getName()))
+        			assertTrue(childIds.contains(p.getId()));
+        		else{
+        			assertNotNull(p.getId());
+        			child2Id = new String(p.getId().toCharArray());
+        			assertFalse(childIds.contains(p.getId()));
+        		}
+        	}
+        	
+        	//Now remove everyone but CHILD2 and do the update once again
+        	List<Person> peopleToRemove = new ArrayList<Person>();
+        	for (Person p : fb2Person.getChildren()){
+        		if (!"CHILD2".equals(p.getName()))
+        			peopleToRemove.add(p);
+        	}
+        	
+        	for (Person p : peopleToRemove){
+        		fb2Person.getChildren().remove(p);
+        	}
+        	
+        	ocm.update(fb2Person);
+        	
+        	Person fb3Person = (Person)ocm.getObject("/person");
+        	assertNotNull(fb3Person);
+        	assertEquals(1, fb3Person.getChildren().size());
+        	assertEquals(child2Id, fb3Person.getChildren().get(0).getId());
+        	
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            fail("Exception occurs during the unit test : " + e);
+        }
+    }
+    
+    public Person buildPerson(String name){
+    	Person p = new Person();
+    	p.setName(name);
+    	Person aChild = new Person();
+    	aChild.setName("CHILD1");
+    	List<Person> children = new ArrayList<Person>();
+    	children.add(aChild);
+    	p.setChildren(children);
+    	return p;
+    }
+
+
+
+}

Added: jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/testmodel/collection/Person.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/testmodel/collection/Person.java?rev=702237&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/testmodel/collection/Person.java (added)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/java/org/apache/jackrabbit/ocm/testmodel/collection/Person.java Mon Oct  6 12:29:47 2008
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.ocm.testmodel.collection;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Collection;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
+
+@Node(jcrMixinTypes="mix:referenceable")
+public class Person {
+	@Field(uuid=true) String id;
+	@Field(jcrName="personName") String name;
+	@Field(path=true)  String path;
+	@Collection List<Person> children;
+	@Collection Map<String,Person> friends;
+	public String getId() {
+		return id;
+	}
+	public void setId(String id) {
+		this.id = id;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public List<Person> getChildren() {
+		return children;
+	}
+	public void setChildren(List<Person> children) {
+		this.children = children;
+	}
+	public Map<String, Person> getFriends() {
+		return friends;
+	}
+	public void setFriends(Map<String, Person> friends) {
+		this.friends = friends;
+	}
+	public String getPath() {
+		return path;
+	}
+	public void setPath(String path) {
+		this.path = path;
+	}
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		return result;
+	}
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		final Person other = (Person) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		return true;
+	}
+}

Added: jackrabbit/trunk/jackrabbit-ocm/src/test/test-config/jcrmapping-complex-collections.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-ocm/src/test/test-config/jcrmapping-complex-collections.xml?rev=702237&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-ocm/src/test/test-config/jcrmapping-complex-collections.xml (added)
+++ jackrabbit/trunk/jackrabbit-ocm/src/test/test-config/jcrmapping-complex-collections.xml Mon Oct  6 12:29:47 2008
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+
+<jackrabbit-ocm>
+	<class-descriptor
+		className="org.apache.jackrabbit.ocm.testmodel.collection.Person" jcrType="nt:unstructured"  jcrMixinTypes="mix:referenceable" >
+		<field-descriptor fieldName="path" path="true"/>
+		<field-descriptor fieldName="id" uuid="true" jcrName="jcr:uuid"/>
+		<field-descriptor fieldName="name" jcrName="personName"/>
+		<collection-descriptor 	fieldName="children" jcrName="children" 
+								elementClassName="org.apache.jackrabbit.ocm.testmodel.collection.Person"
+								/>
+	</class-descriptor>
+</jackrabbit-ocm>