You are viewing a plain text version of this content. The canonical link for it is here.
Posted to graffito-commits@incubator.apache.org by cl...@apache.org on 2006/10/19 18:58:28 UTC

svn commit: r465724 - in /incubator/graffito/trunk/jcr/jcr-mapping/src: java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ test-config/ test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ test/org/apache/portal...

Author: clombart
Date: Thu Oct 19 11:58:26 2006
New Revision: 465724

URL: http://svn.apache.org/viewvc?view=rev&rev=465724
Log:
add unit tests for GRTF-110 provided by Felix Meschberger

Added:
    incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualNodesCollectionConverterImplTest.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualPropertiesCollectionConverterImplTest.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/testmodel/Residual.java
Modified:
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ResidualPropertiesCollectionConverterImpl.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/test-config/jcrmapping.xml
    incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/AllTests.java

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ResidualPropertiesCollectionConverterImpl.java
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ResidualPropertiesCollectionConverterImpl.java?view=diff&rev=465724&r1=465723&r2=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ResidualPropertiesCollectionConverterImpl.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/collectionconverter/impl/ResidualPropertiesCollectionConverterImpl.java Thu Oct 19 11:58:26 2006
@@ -1,204 +1,204 @@
-/*
- * Copyright 2000-2005 The Apache Software Foundation.
- * 
- * Licensed 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.portals.graffito.jcr.persistence.collectionconverter.impl;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.ValueFactory;
-import javax.jcr.ValueFormatException;
-
-import org.apache.portals.graffito.jcr.exception.PersistenceException;
-import org.apache.portals.graffito.jcr.mapper.Mapper;
-import org.apache.portals.graffito.jcr.mapper.model.CollectionDescriptor;
-import org.apache.portals.graffito.jcr.mapper.model.FieldDescriptor;
-import org.apache.portals.graffito.jcr.persistence.atomictypeconverter.AtomicTypeConverter;
-import org.apache.portals.graffito.jcr.persistence.collectionconverter.ManageableCollection;
-import org.apache.portals.graffito.jcr.persistence.collectionconverter.ManageableCollectionUtil;
-import org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.AbstractCollectionConverterImpl;
-import org.apache.portals.graffito.jcr.persistence.objectconverter.ObjectConverter;
-import org.apache.portals.graffito.jcr.reflection.ReflectionUtils;
-
-/**
- * The <code>ResidualPropertiesCollectionConverterImpl</code> is a collection
- * converter for multiple properties accessed through
- * Node.getProperties(String pattern).
- *
- * @author <a href="mailto:fmeschbe[at]apache[dot]com">Felix Meschberger</a>
- */
-public class ResidualPropertiesCollectionConverterImpl extends
-        AbstractCollectionConverterImpl {
-    
-    /**
-     * Constructor
-     *
-     * @param atomicTypeConverters
-     * @param objectConverter
-     * @param mapper
-     */
-    public ResidualPropertiesCollectionConverterImpl(Map atomicTypeConverters,
-        ObjectConverter objectConverter, Mapper mapper) {
-        super(atomicTypeConverters, objectConverter, mapper);
-    }
-
-    /**
-     *
-     * @see AbstractCollectionConverterImpl#doInsertCollection(Session, Node, CollectionDescriptor, ManageableCollection)
-     */
-    protected void doInsertCollection(Session session, Node parentNode,
-        CollectionDescriptor collectionDescriptor,
-        ManageableCollection collection) throws RepositoryException {
-        internalSetProperties(session, parentNode, collectionDescriptor,
-            collection, false);
-    }
-
-    /**
-     *
-     * @see AbstractCollectionConverterImpl#doUpdateCollection(Session, Node, CollectionDescriptor, ManageableCollection)
-     */
-    protected void doUpdateCollection(Session session, Node parentNode,
-        CollectionDescriptor collectionDescriptor,
-        ManageableCollection collection) throws RepositoryException {
-        internalSetProperties(session, parentNode, collectionDescriptor,
-            collection, true);
-    }
-
-    /**
-     * @see AbstractCollectionConverterImpl#doGetCollection(Session, Node, CollectionDescriptor, Class)
-     */
-    protected ManageableCollection doGetCollection(Session session,
-        Node parentNode, CollectionDescriptor collectionDescriptor,
-        Class collectionFieldClass) throws RepositoryException {
-        try {
-            String jcrName = getCollectionJcrName(collectionDescriptor);
-            PropertyIterator pi = parentNode.getProperties(jcrName);
-            if (!pi.hasNext()) {
-                return null;
-            }
-
-            ManageableCollection collection = ManageableCollectionUtil.getManageableCollection(collectionFieldClass);
-            String elementClassName = collectionDescriptor.getElementClassName();
-            Class elementClass = ReflectionUtils.forName(elementClassName);
-            AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(elementClass);
-
-            while (pi.hasNext()) {
-                Property prop = pi.nextProperty();
-
-                // ignore protected properties here
-                if (prop.getDefinition().isProtected()) {
-                    continue;
-                }
-
-                // handle multvalues as a list
-                Object value;
-                if (prop.getDefinition().isMultiple()) {
-                    List valueList = new ArrayList();
-                    Value[] values = prop.getValues();
-                    for (int i = 0; i < values.length; i++) {
-                        valueList.add(atomicTypeConverter.getObject(values[i]));
-                    }
-                    value = valueList;
-                } else {
-                    value = atomicTypeConverter.getObject(prop.getValue());
-                }
-
-                if (collection instanceof Map) {
-                    String name = prop.getName();
-                    ((Map) collection).put(name, value);
-                } else {
-                    collection.addObject(value);
-                }
-            }
-
-            return collection;
-        } catch (ValueFormatException vfe) {
-            throw new PersistenceException("Cannot get the collection field : "
-                + collectionDescriptor.getFieldName() + "for class "
-                + collectionDescriptor.getClassDescriptor().getClassName(), vfe);
-        }
-    }
-
-    /**
-     * @see AbstractCollectionConverterImpl#doIsNull(Session, Node, CollectionDescriptor, Class)
-     */
-    protected boolean doIsNull(Session session, Node parentNode,
-            CollectionDescriptor collectionDescriptor, Class collectionFieldClass)
-            throws RepositoryException {
-        String jcrName = getCollectionJcrName(collectionDescriptor);
-        return (parentNode == null || !parentNode.getProperties(jcrName).hasNext());
-    }
-
-    private void internalSetProperties(Session session, Node parentNode,
-        CollectionDescriptor collectionDescriptor,
-        ManageableCollection collection, boolean removeExisting)
-        throws RepositoryException {
-
-        String jcrName = getCollectionJcrName(collectionDescriptor);
-
-        // Delete existing values - before checking for collection !
-        if (removeExisting) {
-            for (PropertyIterator pi = parentNode.getProperties(jcrName); pi.hasNext();) {
-                pi.nextProperty().remove();
-            }
-        }
-
-        // can only persist maps, not general collections
-        if (!(collection instanceof Map)) {
-            return;
-        }
-
-        try {
-            Map map = (Map) collection;
-            ValueFactory valueFactory = session.getValueFactory();
-            for (Iterator ei = map.entrySet().iterator(); ei.hasNext();) {
-                Map.Entry entry = (Map.Entry) ei.next();
-                String name = String.valueOf(entry.getKey());
-                Object value = entry.getValue();
-                if (value instanceof List) {
-                    // multi value
-                    List valueList = (List) value;
-                    Value[] jcrValues = new Value[valueList.size()];
-                    int i = 0;
-                    for (Iterator vi = valueList.iterator(); vi.hasNext();) {
-                        value = vi.next();
-                        AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(value);
-                        jcrValues[i++] = atomicTypeConverter.getValue(
-                            valueFactory, value);
-                    }
-                    parentNode.setProperty(name, jcrValues);
-                } else {
-                    // single value
-                    AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(value);
-                    Value jcrValue = atomicTypeConverter.getValue(valueFactory,
-                        value);
-                    parentNode.setProperty(name, jcrValue);
-                }
-            }
-        } catch (ValueFormatException vfe) {
-            throw new PersistenceException("Cannot insert collection field : "
-                + collectionDescriptor.getFieldName() + " of class "
-                + collectionDescriptor.getClassDescriptor().getClassName(), vfe);
-        }
-    }
+/*
+ * Copyright 2000-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.portals.graffito.jcr.persistence.collectionconverter.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+
+import org.apache.portals.graffito.jcr.exception.PersistenceException;
+import org.apache.portals.graffito.jcr.mapper.Mapper;
+import org.apache.portals.graffito.jcr.mapper.model.CollectionDescriptor;
+import org.apache.portals.graffito.jcr.mapper.model.FieldDescriptor;
+import org.apache.portals.graffito.jcr.persistence.atomictypeconverter.AtomicTypeConverter;
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.ManageableCollection;
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.ManageableCollectionUtil;
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.AbstractCollectionConverterImpl;
+import org.apache.portals.graffito.jcr.persistence.objectconverter.ObjectConverter;
+import org.apache.portals.graffito.jcr.reflection.ReflectionUtils;
+
+/**
+ * The <code>ResidualPropertiesCollectionConverterImpl</code> is a collection
+ * converter for multiple properties accessed through
+ * Node.getProperties(String pattern).
+ *
+ * @author <a href="mailto:fmeschbe[at]apache[dot]com">Felix Meschberger</a>
+ */
+public class ResidualPropertiesCollectionConverterImpl extends
+        AbstractCollectionConverterImpl {
+    
+    /**
+     * Constructor
+     *
+     * @param atomicTypeConverters
+     * @param objectConverter
+     * @param mapper
+     */
+    public ResidualPropertiesCollectionConverterImpl(Map atomicTypeConverters,
+        ObjectConverter objectConverter, Mapper mapper) {
+        super(atomicTypeConverters, objectConverter, mapper);
+    }
+
+    /**
+     *
+     * @see AbstractCollectionConverterImpl#doInsertCollection(Session, Node, CollectionDescriptor, ManageableCollection)
+     */
+    protected void doInsertCollection(Session session, Node parentNode,
+        CollectionDescriptor collectionDescriptor,
+        ManageableCollection collection) throws RepositoryException {
+        internalSetProperties(session, parentNode, collectionDescriptor,
+            collection, false);
+    }
+
+    /**
+     *
+     * @see AbstractCollectionConverterImpl#doUpdateCollection(Session, Node, CollectionDescriptor, ManageableCollection)
+     */
+    protected void doUpdateCollection(Session session, Node parentNode,
+        CollectionDescriptor collectionDescriptor,
+        ManageableCollection collection) throws RepositoryException {
+        internalSetProperties(session, parentNode, collectionDescriptor,
+            collection, true);
+    }
+
+    /**
+     * @see AbstractCollectionConverterImpl#doGetCollection(Session, Node, CollectionDescriptor, Class)
+     */
+    protected ManageableCollection doGetCollection(Session session,
+        Node parentNode, CollectionDescriptor collectionDescriptor,
+        Class collectionFieldClass) throws RepositoryException {
+        try {
+            String jcrName = getCollectionJcrName(collectionDescriptor);
+            PropertyIterator pi = parentNode.getProperties(jcrName);
+            if (!pi.hasNext()) {
+                return null;
+            }
+
+            ManageableCollection collection = ManageableCollectionUtil.getManageableCollection(collectionFieldClass);
+            String elementClassName = collectionDescriptor.getElementClassName();
+            Class elementClass = ReflectionUtils.forName(elementClassName);
+            AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(elementClass);
+
+            while (pi.hasNext()) {
+                Property prop = pi.nextProperty();
+
+                // ignore protected properties here
+                if (prop.getDefinition().isProtected()) {
+                    continue;
+                }
+
+                // handle multvalues as a list
+                Object value;
+                if (prop.getDefinition().isMultiple()) {
+                    List valueList = new ArrayList();
+                    Value[] values = prop.getValues();
+                    for (int i = 0; i < values.length; i++) {
+                        valueList.add(atomicTypeConverter.getObject(values[i]));
+                    }
+                    value = valueList;
+                } else {
+                    value = atomicTypeConverter.getObject(prop.getValue());
+                }
+
+                if (collection instanceof Map) {
+                    String name = prop.getName();
+                    ((Map) collection).put(name, value);
+                } else {
+                    collection.addObject(value);
+                }
+            }
+
+            return collection;
+        } catch (ValueFormatException vfe) {
+            throw new PersistenceException("Cannot get the collection field : "
+                + collectionDescriptor.getFieldName() + "for class "
+                + collectionDescriptor.getClassDescriptor().getClassName(), vfe);
+        }
+    }
+
+    /**
+     * @see AbstractCollectionConverterImpl#doIsNull(Session, Node, CollectionDescriptor, Class)
+     */
+    protected boolean doIsNull(Session session, Node parentNode,
+            CollectionDescriptor collectionDescriptor, Class collectionFieldClass)
+            throws RepositoryException {
+        String jcrName = getCollectionJcrName(collectionDescriptor);
+        return (parentNode == null || !parentNode.getProperties(jcrName).hasNext());
+    }
+
+    private void internalSetProperties(Session session, Node parentNode,
+        CollectionDescriptor collectionDescriptor,
+        ManageableCollection collection, boolean removeExisting)
+        throws RepositoryException {
+
+        String jcrName = getCollectionJcrName(collectionDescriptor);
+
+        // can only persist maps, not general collections
+        if (!(collection instanceof Map)) {
+            return;
+        }
+
+        // Delete existing values - before checking for collection !
+        if (removeExisting) {
+            for (PropertyIterator pi = parentNode.getProperties(jcrName); pi.hasNext();) {
+                pi.nextProperty().remove();
+            }
+        }
+
+        try {
+            Map map = (Map) collection;
+            ValueFactory valueFactory = session.getValueFactory();
+            for (Iterator ei = map.entrySet().iterator(); ei.hasNext();) {
+                Map.Entry entry = (Map.Entry) ei.next();
+                String name = String.valueOf(entry.getKey());
+                Object value = entry.getValue();
+                if (value instanceof List) {
+                    // multi value
+                    List valueList = (List) value;
+                    Value[] jcrValues = new Value[valueList.size()];
+                    int i = 0;
+                    for (Iterator vi = valueList.iterator(); vi.hasNext();) {
+                        value = vi.next();
+                        AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(value.getClass());
+                        jcrValues[i++] = atomicTypeConverter.getValue(
+                            valueFactory, value);
+                    }
+                    parentNode.setProperty(name, jcrValues);
+                } else {
+                    // single value
+                    AtomicTypeConverter atomicTypeConverter = (AtomicTypeConverter) atomicTypeConverters.get(value.getClass());
+                    Value jcrValue = atomicTypeConverter.getValue(valueFactory,
+                        value);
+                    parentNode.setProperty(name, jcrValue);
+                }
+            }
+        } catch (ValueFormatException vfe) {
+            throw new PersistenceException("Cannot insert collection field : "
+                + collectionDescriptor.getFieldName() + " of class "
+                + collectionDescriptor.getClassDescriptor().getClassName(), vfe);
+        }
+    }
 }

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/test-config/jcrmapping.xml
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/test-config/jcrmapping.xml?view=diff&rev=465724&r1=465723&r2=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/test-config/jcrmapping.xml (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/test-config/jcrmapping.xml Thu Oct 19 11:58:26 2006
@@ -1,92 +1,92 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!DOCTYPE graffito-jcr PUBLIC "-//The Apache Software Foundation//DTD Repository//EN" "./src/dtd/graffito-jcr-mapping.dtd">
-<graffito-jcr>
-    
-  
-
-	<!--
-		The following classes are used to test object associations
-		A has an assocition (1..1) with B (field b) => B is mapped as subnode in A
-		A has a collection of C (field "collection" ) => there are n subnodes used to map the "C" collection 
-		
-	-->
-	<class-descriptor
-		className="org.apache.portals.graffito.jcr.testmodel.A"
-		jcrNodeType="nt:unstructured">
-		<!-- Field-descriptor is used to map simple attributes to jcr property -->
-		<field-descriptor fieldName="path" path="true" />
-		<field-descriptor fieldName="a1" jcrName="a1" />
-		<field-descriptor fieldName="a2" jcrName="a2" />
-
-		<!-- bean-descriptor is used to map a bean into subnode
-			* The definition of the associated class has to be defined in this mapping file 
-			* proxy="true" => use lazy laoding for this attribute b when retrieving A
-		-->
-		<bean-descriptor fieldName="b" jcrName="b" proxy="false" jcrNodeType="nt:unstructured"
-        jcrAutoCreated="false" jcrMandatory="false" jcrOnParentVersion="IGNORE"
-        jcrProtected="false" jcrSameNameSiblings="false" />
-
-		<!-- 
-			Use the default collection mapping stategy and the default collection type (can be a Vector, an ArrayList, a Collection or a List) 
-			The default collection mapping strategy map a collection under an extra JCR node (specify by the jcrName).
-			
-		-->
-		<collection-descriptor fieldName="collection" jcrName="collection" proxy="false"
-        elementClassName="org.apache.portals.graffito.jcr.testmodel.C" jcrNodeType="graffito:C"
-        jcrAutoCreated="false" jcrMandatory="false" jcrOnParentVersion="IGNORE"
-        jcrProtected="false" jcrSameNameSiblings="false"/>
-        
-		<collection-descriptor fieldName="emptyCollection" jcrName="emptyCollection" proxy="false"
-        elementClassName="org.apache.portals.graffito.jcr.testmodel.C" />
-		
-	</class-descriptor>
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.B"  jcrNodeType="nt:unstructured" jcrSuperTypes="nt:base">
-		<!-- Field-descriptor is used to map simple attributes to jcr property -->
-
-		<field-descriptor fieldName="b1" jcrName="b1" jcrType="String" jcrAutoCreated="false" jcrMandatory="false"
-        jcrOnParentVersion="IGNORE" jcrProtected="false" jcrMultiple="false" />
-		
-        <field-descriptor fieldName="b2" jcrName="b2" jcrType="String" jcrAutoCreated="false" jcrMandatory="false"
-        jcrOnParentVersion="IGNORE" jcrProtected="false" jcrMultiple="false" />
-
-	</class-descriptor>
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.C" jcrNodeType="graffito:C" discriminator="false" >
-		<!-- Field-descriptor is used to map simple attributes to jcr property -->
-		<field-descriptor fieldName="id" jcrName="graffito:id" 	id="true" />
-		<field-descriptor fieldName="name" jcrName="graffito:name" />
-	</class-descriptor>
-
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Page" jcrNodeType="graffito:page" discriminator="false" >
-		<field-descriptor fieldName="path" path="true" />
-		<field-descriptor fieldName="title" jcrName="graffito:title" />
-		<collection-descriptor fieldName="paragraphs" proxy="false" 
-		                       elementClassName="org.apache.portals.graffito.jcr.testmodel.Paragraph" 
-		                       collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.NTCollectionConverterImpl" />
-	</class-descriptor>
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Paragraph" jcrNodeType="graffito:paragraph" discriminator="false" >
-		<field-descriptor fieldName="path" path="true" />
-		<field-descriptor fieldName="text" jcrName="graffito:text"/>
-	</class-descriptor>
-
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.hashmap.Main" jcrNodeType="nt:unstructured"  >
-		<field-descriptor fieldName="path" path="true" />
-		<field-descriptor fieldName="text" jcrName="text" />
-		<collection-descriptor fieldName="elements"  proxy="false" 
-		                       elementClassName="org.apache.portals.graffito.jcr.testmodel.hashmap.Element" 
-		                       collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.NTCollectionConverterImpl" 
-		                       collectionClassName="org.apache.portals.graffito.jcr.testmodel.hashmap.HashMapElement" />
-		                       
-	</class-descriptor>
-
-	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.hashmap.Element" jcrNodeType="graffito:element" discriminator="false" >
-		<field-descriptor fieldName="id" jcrName="graffito:id"  />
-		<field-descriptor fieldName="text" jcrName="graffito:text" />
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE graffito-jcr PUBLIC "-//The Apache Software Foundation//DTD Repository//EN" "./src/dtd/graffito-jcr-mapping.dtd">
+<graffito-jcr>
+    
+  
+
+	<!--
+		The following classes are used to test object associations
+		A has an assocition (1..1) with B (field b) => B is mapped as subnode in A
+		A has a collection of C (field "collection" ) => there are n subnodes used to map the "C" collection 
+		
+	-->
+	<class-descriptor
+		className="org.apache.portals.graffito.jcr.testmodel.A"
+		jcrNodeType="nt:unstructured">
+		<!-- Field-descriptor is used to map simple attributes to jcr property -->
+		<field-descriptor fieldName="path" path="true" />
+		<field-descriptor fieldName="a1" jcrName="a1" />
+		<field-descriptor fieldName="a2" jcrName="a2" />
+
+		<!-- bean-descriptor is used to map a bean into subnode
+			* The definition of the associated class has to be defined in this mapping file 
+			* proxy="true" => use lazy laoding for this attribute b when retrieving A
+		-->
+		<bean-descriptor fieldName="b" jcrName="b" proxy="false" jcrNodeType="nt:unstructured"
+        jcrAutoCreated="false" jcrMandatory="false" jcrOnParentVersion="IGNORE"
+        jcrProtected="false" jcrSameNameSiblings="false" />
+
+		<!-- 
+			Use the default collection mapping stategy and the default collection type (can be a Vector, an ArrayList, a Collection or a List) 
+			The default collection mapping strategy map a collection under an extra JCR node (specify by the jcrName).
+			
+		-->
+		<collection-descriptor fieldName="collection" jcrName="collection" proxy="false"
+        elementClassName="org.apache.portals.graffito.jcr.testmodel.C" jcrNodeType="graffito:C"
+        jcrAutoCreated="false" jcrMandatory="false" jcrOnParentVersion="IGNORE"
+        jcrProtected="false" jcrSameNameSiblings="false"/>
+        
+		<collection-descriptor fieldName="emptyCollection" jcrName="emptyCollection" proxy="false"
+        elementClassName="org.apache.portals.graffito.jcr.testmodel.C" />
+		
+	</class-descriptor>
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.B"  jcrNodeType="nt:unstructured" jcrSuperTypes="nt:base">
+		<!-- Field-descriptor is used to map simple attributes to jcr property -->
+
+		<field-descriptor fieldName="b1" jcrName="b1" jcrType="String" jcrAutoCreated="false" jcrMandatory="false"
+        jcrOnParentVersion="IGNORE" jcrProtected="false" jcrMultiple="false" />
+		
+        <field-descriptor fieldName="b2" jcrName="b2" jcrType="String" jcrAutoCreated="false" jcrMandatory="false"
+        jcrOnParentVersion="IGNORE" jcrProtected="false" jcrMultiple="false" />
+
+	</class-descriptor>
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.C" jcrNodeType="graffito:C" discriminator="false" >
+		<!-- Field-descriptor is used to map simple attributes to jcr property -->
+		<field-descriptor fieldName="id" jcrName="graffito:id" 	id="true" />
+		<field-descriptor fieldName="name" jcrName="graffito:name" />
+	</class-descriptor>
+
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Page" jcrNodeType="graffito:page" discriminator="false" >
+		<field-descriptor fieldName="path" path="true" />
+		<field-descriptor fieldName="title" jcrName="graffito:title" />
+		<collection-descriptor fieldName="paragraphs" proxy="false" 
+		                       elementClassName="org.apache.portals.graffito.jcr.testmodel.Paragraph" 
+		                       collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.NTCollectionConverterImpl" />
+	</class-descriptor>
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Paragraph" jcrNodeType="graffito:paragraph" discriminator="false" >
+		<field-descriptor fieldName="path" path="true" />
+		<field-descriptor fieldName="text" jcrName="graffito:text"/>
+	</class-descriptor>
+
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.hashmap.Main" jcrNodeType="nt:unstructured"  >
+		<field-descriptor fieldName="path" path="true" />
+		<field-descriptor fieldName="text" jcrName="text" />
+		<collection-descriptor fieldName="elements"  proxy="false" 
+		                       elementClassName="org.apache.portals.graffito.jcr.testmodel.hashmap.Element" 
+		                       collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.NTCollectionConverterImpl" 
+		                       collectionClassName="org.apache.portals.graffito.jcr.testmodel.hashmap.HashMapElement" />
+		                       
+	</class-descriptor>
+
+	<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.hashmap.Element" jcrNodeType="graffito:element" discriminator="false" >
+		<field-descriptor fieldName="id" jcrName="graffito:id"  />
+		<field-descriptor fieldName="text" jcrName="graffito:text" />
 	</class-descriptor>
 	
 	
@@ -94,5 +94,26 @@
 		<field-descriptor fieldName="path" path="true" />
 		<field-descriptor fieldName="content" jcrName="graffito:content" />
 	</class-descriptor>		
-</graffito-jcr>
+
+
+    <class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Residual$ResidualProperties" jcrNodeType="nt:unstructured">
+        <field-descriptor fieldName="path" path="true" />
+        <collection-descriptor fieldName="elements" proxy="false" 
+                               jcrName="value*"
+                               elementClassName="java.lang.String"
+                               collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ResidualPropertiesCollectionConverterImpl" 
+                               collectionClassName="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ManagedHashMap" />
+                               
+    </class-descriptor>
+
+    <class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Residual$ResidualNodes" jcrNodeType="nt:unstructured">
+        <field-descriptor fieldName="path" path="true" />
+        <collection-descriptor fieldName="elements" proxy="false" 
+                               jcrName="value*"
+                               elementClassName="java.lang.Object"
+                               collectionConverter="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ResidualNodesCollectionConverterImpl" 
+                               collectionClassName="org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ManagedHashMap" />
+                               
+    </class-descriptor>
+</graffito-jcr>
  

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/AllTests.java
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/AllTests.java?view=diff&rev=465724&r1=465723&r2=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/AllTests.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/AllTests.java Thu Oct 19 11:58:26 2006
@@ -40,6 +40,8 @@
         suite.addTestSuite(HashMapTest.class);
         suite.addTestSuite(MultiValueCollectionConverterImplTest.class);
         suite.addTestSuite(NTCollectionConverterImplTest.class);
+        suite.addTestSuite(ResidualPropertiesCollectionConverterImplTest.class);
+        suite.addTestSuite(ResidualNodesCollectionConverterImplTest.class);
         //$JUnit-END$
 
         return suite;

Added: incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualNodesCollectionConverterImplTest.java
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualNodesCollectionConverterImplTest.java?view=auto&rev=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualNodesCollectionConverterImplTest.java (added)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualNodesCollectionConverterImplTest.java Thu Oct 19 11:58:26 2006
@@ -0,0 +1,137 @@
+/* ========================================================================
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.portals.graffito.jcr.persistence.collectionconverter;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.portals.graffito.jcr.RepositoryLifecycleTestSetup;
+import org.apache.portals.graffito.jcr.TestBase;
+import org.apache.portals.graffito.jcr.persistence.PersistenceManager;
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ManagedHashMap;
+import org.apache.portals.graffito.jcr.testmodel.Paragraph;
+import org.apache.portals.graffito.jcr.testmodel.Residual;
+
+/**
+ * Test ResidualNodesCollectionConverterImpl
+ *
+ * @author <a href="mailto:fmeschbe[at]apache[dot]com">Felix Meschberger</a>
+ * 
+ */
+public class ResidualNodesCollectionConverterImplTest extends TestBase
+{
+    private final static Log log = LogFactory.getLog(ResidualNodesCollectionConverterImplTest.class);
+
+    /**
+     * <p>Defines the test case name for junit.</p>
+     * @param testName The test case name.
+     */
+    public ResidualNodesCollectionConverterImplTest(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(ResidualNodesCollectionConverterImplTest.class));
+    }
+
+    
+    /**
+     * @see junit.framework.TestCase#tearDown()
+     */
+    public void tearDown() throws Exception
+    {
+        if (getPersistenceManager().objectExists("/test"))
+        {
+            getPersistenceManager().remove("/test");
+            getPersistenceManager().save();
+        }        
+    	
+        super.tearDown();
+    }    
+
+    public void testResidualNodes()
+    {
+        try
+        {
+        	PersistenceManager persistenceManager = getPersistenceManager();
+
+            // --------------------------------------------------------------------------------
+            // Create and store an object graph in the repository
+            // --------------------------------------------------------------------------------
+
+            Residual residual = new Residual.ResidualNodes();
+            residual.setPath("/test");
+            
+            ManagedHashMap map = new ManagedHashMap();
+            map.put("value1", new Paragraph("Value1"));
+            map.put("value2", new Paragraph("Value2"));
+            map.put("value3", new Paragraph("Value3"));
+            map.put("value4", new Paragraph("Value4"));
+            residual.setElements(map);
+            
+            persistenceManager.insert(residual);
+            persistenceManager.save();
+            
+            // --------------------------------------------------------------------------------
+            // Get the object
+            // --------------------------------------------------------------------------------           
+            residual = (Residual) persistenceManager.getObject( "/test");
+            assertNotNull("Object is null", residual);
+            assertTrue("Incorrect number of values", residual.getElements().size() == 4);            
+            assertTrue("Incorrect collection element type", (residual.getElements().get("value2") instanceof Paragraph));
+            assertEquals("Incorrect collection element text", ((Paragraph) residual.getElements().get("value2")).getText(), "Value2");
+            
+            // --------------------------------------------------------------------------------
+            // Update the object
+            // --------------------------------------------------------------------------------
+            map = new ManagedHashMap();
+            map.put("value11", new Paragraph("Value11"));
+            map.put("value12", new Paragraph("Value12"));
+            map.put("value13", new Paragraph("Value13"));
+            map.put("value14", new Paragraph("Value14"));
+            map.put("value15", new Paragraph("Value15"));
+            residual.setElements(map);
+            
+            persistenceManager.update(residual);
+            persistenceManager.save();
+
+            // --------------------------------------------------------------------------------
+            // Get the object
+            // --------------------------------------------------------------------------------           
+
+            residual = (Residual) persistenceManager.getObject( "/test");
+            assertNotNull("Object is null", residual);
+            assertTrue("Incorrect number of values", residual.getElements().size() == 5);
+            assertNull("Unexpected collection element", residual.getElements().get("value2"));
+            assertTrue("Incorrect collection element type", (residual.getElements().get("value15") instanceof Paragraph));
+            assertEquals("Incorrect collection element text", ((Paragraph) residual.getElements().get("value15")).getText(), "Value15");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            fail("Exception occurs during the unit test : " + e);
+        }
+        
+    }
+
+   
+}

Added: incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualPropertiesCollectionConverterImplTest.java
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualPropertiesCollectionConverterImplTest.java?view=auto&rev=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualPropertiesCollectionConverterImplTest.java (added)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/persistence/collectionconverter/ResidualPropertiesCollectionConverterImplTest.java Thu Oct 19 11:58:26 2006
@@ -0,0 +1,148 @@
+/* ========================================================================
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.portals.graffito.jcr.persistence.collectionconverter;
+
+import java.util.Arrays;
+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.portals.graffito.jcr.RepositoryLifecycleTestSetup;
+import org.apache.portals.graffito.jcr.TestBase;
+import org.apache.portals.graffito.jcr.persistence.PersistenceManager;
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ManagedHashMap;
+import org.apache.portals.graffito.jcr.testmodel.Residual;
+
+/**
+ * Test ResidualPropertiesCollectionConverterImpl
+ *
+ * @author <a href="mailto:fmeschbe[at]apache[dot]com">Felix Meschberger</a>
+ * 
+ */
+public class ResidualPropertiesCollectionConverterImplTest extends TestBase
+{
+    private final static Log log = LogFactory.getLog(ResidualPropertiesCollectionConverterImplTest.class);
+
+    /**
+     * <p>Defines the test case name for junit.</p>
+     * @param testName The test case name.
+     */
+    public ResidualPropertiesCollectionConverterImplTest(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(ResidualPropertiesCollectionConverterImplTest.class));
+    }
+
+    
+    /**
+     * @see junit.framework.TestCase#tearDown()
+     */
+    public void tearDown() throws Exception
+    {
+        if (getPersistenceManager().objectExists("/test"))
+        {
+            getPersistenceManager().remove("/test");
+            getPersistenceManager().save();
+        }        
+    	
+        super.tearDown();
+    }    
+
+    public void testResidualProperties()
+    {
+        try
+        {
+        	PersistenceManager persistenceManager = getPersistenceManager();
+
+            // --------------------------------------------------------------------------------
+            // Create and store an object graph in the repository
+            // --------------------------------------------------------------------------------
+
+            Residual residual = new Residual.ResidualProperties();
+            residual.setPath("/test");
+            
+            ManagedHashMap map = new ManagedHashMap();
+            map.put("value1", "Value1");
+            map.put("value2", "Value2");
+            map.put("value3", "Value3");
+            map.put("value4", "Value4");
+            map.put("value5", Arrays.asList(new String[]{ "Value5-1", "Value5-2" }));
+            residual.setElements(map);
+            
+            persistenceManager.insert(residual);
+            persistenceManager.save();
+            
+            // --------------------------------------------------------------------------------
+            // Get the object
+            // --------------------------------------------------------------------------------           
+            residual = (Residual) persistenceManager.getObject( "/test");
+            assertNotNull("Object is null", residual);
+            assertTrue("Incorrect number of values", residual.getElements().size() == 5);            
+            assertTrue("Incorrect collection element", residual.getElements().get("value2").equals("Value2"));
+            assertNotNull("Missing collection element", residual.getElements().get("value5"));
+            assertTrue("Incorrect collection element type", (residual.getElements().get("value5") instanceof List));
+            assertEquals("Incorrect collection element list size", ((List) residual.getElements().get("value5")).size(), 2);
+            assertEquals("Incorrect collection element list value", ((List) residual.getElements().get("value5")).get(0), "Value5-1");
+            
+            // --------------------------------------------------------------------------------
+            // Update the object
+            // --------------------------------------------------------------------------------
+            map = new ManagedHashMap();
+            map.put("value11", "Value11");
+            map.put("value12", "Value12");
+            map.put("value13", "Value13");
+            map.put("value14", "Value14");
+            map.put("value15", "Value15");
+            map.put("value16", Arrays.asList(new String[]{ "Value16-1", "Value16-2" }));
+            residual.setElements(map);
+            
+            persistenceManager.update(residual);
+            persistenceManager.save();
+
+            // --------------------------------------------------------------------------------
+            // Get the object
+            // --------------------------------------------------------------------------------           
+
+            residual = (Residual) persistenceManager.getObject( "/test");
+            assertNotNull("Object is null", residual);
+            assertTrue("Incorrect number of values", residual.getElements().size() == 6);
+            assertNull("Unexpected collection element", residual.getElements().get("value2"));
+            assertNull("Unexpected collection element", residual.getElements().get("value5"));
+            assertTrue("Incorrect collection element", residual.getElements().get("value15").equals("Value15"));
+            assertNotNull("Missing collection element", residual.getElements().get("value16"));
+            assertTrue("Incorrect collection element type", (residual.getElements().get("value16") instanceof List));
+            assertEquals("Incorrect collection element list size", ((List) residual.getElements().get("value16")).size(), 2);
+            assertEquals("Incorrect collection element list value", ((List) residual.getElements().get("value16")).get(0), "Value16-1");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            fail("Exception occurs during the unit test : " + e);
+        }
+        
+    }
+
+   
+}

Added: incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/testmodel/Residual.java
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/testmodel/Residual.java?view=auto&rev=465724
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/testmodel/Residual.java (added)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/test/org/apache/portals/graffito/jcr/testmodel/Residual.java Thu Oct 19 11:58:26 2006
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.portals.graffito.jcr.testmodel;
+
+import org.apache.portals.graffito.jcr.persistence.collectionconverter.impl.ManagedHashMap;
+
+/**
+ *
+ * @author <a href="mailto:fmeschbe[at]apache[dot]com">Felix Meschberger</a>
+ * 
+ */
+public class Residual
+{
+	private String path;
+    private ManagedHashMap elements;
+    
+    public static class ResidualProperties extends Residual {}
+    public static class ResidualNodes extends Residual {}
+    
+    protected Residual() {}
+    
+    
+    public String getPath() {
+		return path;
+	}
+	public void setPath(String path) {
+		this.path = path;
+	}
+	/**
+     * @return Returns the elements.
+     */
+    public ManagedHashMap getElements()
+    {
+        return elements;
+    }
+    /**
+     * @param elements The elements to set.
+     */
+    public void setElements(ManagedHashMap elements)
+    {
+        this.elements = elements;
+    }
+}