You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ra...@apache.org on 2006/08/04 21:14:20 UTC

svn commit: r428846 - /xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java

Author: radup
Date: Fri Aug  4 12:14:19 2006
New Revision: 428846

URL: http://svn.apache.org/viewvc?rev=428846&view=rev
Log:
Fixed the array setter (again).

Modified:
    xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java

Modified: xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java?rev=428846&r1=428845&r2=428846&view=diff
==============================================================================
--- xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java (original)
+++ xmlbeans/trunk/src/typeimpl/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java Fri Aug  4 12:14:19 2006
@@ -1052,23 +1052,110 @@
 
     protected void arraySetterHelper ( XmlObject[] sources, QName elemName )
     {
-        int n = sources == null ? 0 : sources.length;
-        
         TypeStore store = get_store();
 
-        int m = store.count_elements( elemName );
+        if (sources == null || sources.length == 0)
+        {
+            int m = store.count_elements( elemName );
+            for ( ; m > 0 ; m-- )
+                store.remove_element( elemName, 0 );
+            return;
+        }
+
+        // Verify if the sources contain children of this node
+        int i;
+        int m = store.count_elements( elemName ); // how many elements in the original array
+        int startSrc = 0, startDest = 0;
+        for (i = 0; i < sources.length; i++)
+        {
+            XmlCursor c = sources[i].newCursor();
+            if (c.toParent() && c.getObject() == this)
+            {
+                c.dispose();
+                break;
+            }
+            c.dispose();
+        }
+        if (i < sources.length)
+        {
+            TypeStoreUser current = store.find_element_user( elemName, 0 );
+            if (current == sources[i])
+            {
+                // The new object matches what already exists in the array
+                // Heuristic: we optimize for the case where the new elements
+                // in the array are the same as the existing elements with
+                // potentially new elements inserted
+
+                // First insert the new element in the array at position 0
+                int j = 0;
+                for ( j = 0; j < i; j++ )
+                {
+                    TypeStoreUser user = store.insert_element_user( elemName, j );
+                    ((XmlObjectBase) user).set( sources[j] );
+                }
+                for ( i++, j++; i < sources.length; i++, j++)
+                {
+                    XmlCursor c = sources[i].newCursor();
+                    if (c.toParent() && c.getObject() == this)
+                    {
+                        c.dispose();
+                        current = store.find_element_user( elemName, j );
+                        if (current == sources[i])
+                            ; // advance
+                        else
+                        {
+                            // Fall back to the general case
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        c.dispose();
+                        // Insert before the current element
+                        TypeStoreUser user = store.insert_element_user( elemName, j );
+                        ((XmlObjectBase) user).set( sources[i] );
+                    }
+                }
+                startDest = j;
+                startSrc = i;
+                m = store.count_elements( elemName );
+            }
+            // Fall through
+        }
+        else
+        {
+            // All of the elements in the existing array are to
+            // be deleted and replaced with elements from the
+            // sources array
+        }
 
-        for ( ; m > n ; m-- )
+        // The general case: we assume that some of the elements
+        // in the new array already exist, but at different indexes
+
+        // Starting with position i in the sources array, copy the remaining elements
+        // to the end of the original array...
+        for (int j = i; j < sources.length; j++)
+        {
+            TypeStoreUser user = store.add_element_user( elemName );
+            ((XmlObjectBase) user).set( sources[ j ] );
+        }
+
+        // ... then come back and insert the elements starting with startSource
+        // up to i from the sources array into the current array, starting with
+        // startDest
+        int n = i;
+        for ( ; m > n - startSrc + startDest; m-- )
             store.remove_element( elemName, m - 1 );
 
-        for ( int i = 0 ; i < n ; i++ )
+        int j;
+        for ( i = startSrc, j = startDest ; i < n ; i++, j++ )
         {
             TypeStoreUser user;
-            
-            if (i >= m)
+
+            if (j >= m)
                 user = store.add_element_user( elemName );
             else
-                user = store.find_element_user( elemName, i );
+                user = store.find_element_user( elemName, j );
 
             ((XmlObjectBase) user).set( sources[ i ] );
         }
@@ -1076,28 +1163,115 @@
         // We can't just delegate to array_setter because we need
         // synchronization on the sources (potentially each element
         // in the array on a different lock)
-        // get_store().array_setter( sources, elemName );
+//         get_store().array_setter( sources, elemName );
     }
 
     protected void arraySetterHelper ( XmlObject[] sources, QName elemName, QNameSet set )
     {
-        int n = sources == null ? 0 : sources.length;
-        
         TypeStore store = get_store();
 
-        int m = store.count_elements( set );
+        if (sources == null || sources.length == 0)
+        {
+            int m = store.count_elements( set );
+            for ( ; m > 0 ; m-- )
+                store.remove_element( set, 0 );
+            return;
+        }
+
+        // Verify if the sources contain children of this node
+        int i;
+        int m = store.count_elements( set ); // how many elements in the original array
+        int startSrc = 0, startDest = 0;
+        for (i = 0; i < sources.length; i++)
+        {
+            XmlCursor c = sources[i].newCursor();
+            if (c.toParent() && c.getObject() == this)
+            {
+                c.dispose();
+                break;
+            }
+            c.dispose();
+        }
+        if (i < sources.length)
+        {
+            TypeStoreUser current = store.find_element_user( set, 0 );
+            if (current == sources[i])
+            {
+                // The new object matches what already exists in the array
+                // Heuristic: we optimize for the case where the new elements
+                // in the array are the same as the existing elements with
+                // potentially new elements inserted
+
+                // First insert the new element in the array at position 0
+                int j = 0;
+                for ( j = 0; j < i; j++ )
+                {
+                    TypeStoreUser user = store.insert_element_user( set, elemName, j );
+                    ((XmlObjectBase) user).set( sources[j] );
+                }
+                for ( i++, j++; i < sources.length; i++, j++)
+                {
+                    XmlCursor c = sources[i].newCursor();
+                    if (c.toParent() && c.getObject() == this)
+                    {
+                        c.dispose();
+                        current = store.find_element_user( set, j );
+                        if (current == sources[i])
+                            ; // advance
+                        else
+                        {
+                            // Fall back to the general case
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        c.dispose();
+                        // Insert before the current element
+                        TypeStoreUser user = store.insert_element_user( set, elemName, j );
+                        ((XmlObjectBase) user).set( sources[i] );
+                    }
+                }
+                startDest = j;
+                startSrc = i;
+                m = store.count_elements( elemName );
+            }
+            // Fall through
+        }
+        else
+        {
+            // All of the elements in the existing array are to
+            // be deleted and replaced with elements from the
+            // sources array
+        }
 
-        for ( ; m > n ; m-- )
+        // The general case: we assume that some of the elements
+        // in the new array already exist, but at different indexes
+
+        // Starting with position i in the sources array, copy the remaining elements
+        // to the end of the original array...
+        for (int j = i; j < sources.length; j++)
+        {
+            TypeStoreUser user = store.add_element_user( elemName );
+            ((XmlObjectBase) user).set( sources[ j ] );
+        }
+
+        // ... then come back and insert the elements starting with startSource
+        // up to i from the sources array into the current array, starting with
+        // startDest
+        int n = i;
+        for ( ; m > n - startSrc + startDest; m-- )
             store.remove_element( set, m - 1 );
 
-        for ( int i = 0 ; i < n ; i++ )
+        int j;
+        for ( i = startSrc, j = startDest ; i < n ; i++, j++ )
         {
             TypeStoreUser user;
-            
-            if (i >= m)
+
+            if (j >= m)
                 user = store.add_element_user( elemName );
             else
-                user = store.find_element_user( set, i );
+                user = store.find_element_user( set, j );
 
             ((XmlObjectBase) user).set( sources[ i ] );
         }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: commits-help@xmlbeans.apache.org