diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java b/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java index 7e42ebf50..300236d20 100644 --- a/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java @@ -2303,6 +2303,39 @@ public void remove_elements_after(QName name, int i) { } } + @Override + public void remove_elements_between(final QName name, final int m, final int n) { + if (m < 0 || n < 0) { + throw new IndexOutOfBoundsException(); + } + + if (!isContainer()) { + throw new IllegalStateException(); + } + + if (m >= n) { + return; + } + + ArrayList toRemove = new ArrayList<>(); + Xobj x; + int i = m; + int count = 0; + for (x = _firstChild; x != null; x = x._nextSibling) { + if (x.isElem() && x._name.equals(name) && --i < 0) { + toRemove.add(x); + count++; + if (count >= n - m) { + break; // no need to continue if we've removed enough + } + } + } + final int size = toRemove.size(); + for (int j = size - 1; j >= 0; j--) { + removeElement(toRemove.get(j)); + } + } + @Override public void remove_element(QNameSet names, int i) { if (i < 0) { @@ -2343,6 +2376,39 @@ public void remove_elements_after(QNameSet names, int i) { } } + @Override + public void remove_elements_between(final QNameSet names, final int m, final int n) { + if (m < 0 || n < 0) { + throw new IndexOutOfBoundsException(); + } + + if (!isContainer()) { + throw new IllegalStateException(); + } + + if (m >= n) { + return; + } + + ArrayList toRemove = new ArrayList<>(); + Xobj x; + int i = m; + int count = 0; + for (x = _firstChild; x != null; x = x._nextSibling) { + if (x.isElem() && names.contains(x._name) && --i < 0) { + toRemove.add(x); + count++; + if (count >= n - m) { + break; // no need to continue if we've removed enough + } + } + } + final int size = toRemove.size(); + for (int j = size - 1; j >= 0; j--) { + removeElement(toRemove.get(j)); + } + } + public TypeStoreUser find_attribute_user(QName name) { Xobj a = getAttr(name); diff --git a/src/main/java/org/apache/xmlbeans/impl/values/TypeStore.java b/src/main/java/org/apache/xmlbeans/impl/values/TypeStore.java index 5e404bf14..51935201a 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/TypeStore.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/TypeStore.java @@ -276,16 +276,30 @@ void find_multiple_element_users(QNameSet names, List f void remove_element(QNameSet names, int i); /** - * Removes all elements after the i-th element with the given name. + * Removes all elements from the i-th element with the given name. * @since 5.4.0 */ void remove_elements_after(QName name, int i); /** - * Removes all elements after the i-th element with the given name. + * Removes all elements from the i-th element with the given names. * @since 5.4.0 */ - void remove_elements_after(QNameSet name, int i); + void remove_elements_after(QNameSet names, int i); + + /** + * Removes all elements from the m-th element with the given name up to the n-th + * element with the given name but not including the n-th element. + * @since 5.4.0 + */ + void remove_elements_between(QName name, int m, int n); + + /** + * Removes all elements from the m-th element with the given name up to the n-th + * element with the given name but not including the n-th element. + * @since 5.4.0 + */ + void remove_elements_between(QNameSet names, int m, int n); /** * Returns the TypeStoreUser underneath the attribute with the given diff --git a/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java b/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java index b4ad6a119..7a09a1e74 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java @@ -396,13 +396,15 @@ protected void arraySetterHelper(XmlObject[] sources, QName elemName, QNameSet s // ... 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--) { + final int n = i; + final int startPos = n - startSrc + startDest; + if (m > startPos) { if (set == null) { - store.remove_element(elemName, m - 1); + store.remove_elements_between(elemName, startPos, m); } else { - store.remove_element(set, m - 1); + store.remove_elements_between(set, startPos, m); } + m = startPos; } int j; @@ -531,13 +533,12 @@ protected void arraySetterHelper2(XmlObject[] sources, QName elemName, QNameSet // up to i from the sources array into the current array, starting with // startDest final int n = i; - if (set == null) { - store.remove_elements_after(elemName, n - startSrc + startDest); + store.remove_elements_between(elemName, n - startSrc + startDest, m); } else { - store.remove_elements_after(set, n - startSrc + startDest); + store.remove_elements_between(set, n - startSrc + startDest, m); } - + m = n - startSrc + startDest; final int size = Math.min(m - startDest, sources.length - startSrc); ArrayList users = new ArrayList<>(size);