2222import javax .xml .namespace .QName ;
2323import java .math .BigDecimal ;
2424import java .math .BigInteger ;
25+ import java .util .ArrayList ;
2526import java .util .Calendar ;
2627import java .util .Date ;
2728import java .util .List ;
@@ -342,7 +343,14 @@ protected void arraySetterHelper(XmlObject[] sources, QName elemName, QNameSet s
342343 }
343344 }
344345 if (i < sources .length ) {
345- TypeStoreUser current = (set == null ) ? store .find_element_user (elemName , 0 ) : store .find_element_user (set , 0 );
346+ // Get all existing elements upfront to avoid O(n^2) from repeated find_element_user calls
347+ List <XmlObject > existingList = new ArrayList <>(m );
348+ if (set == null ) {
349+ store .find_all_element_users (elemName , existingList );
350+ } else {
351+ store .find_all_element_users (set , existingList );
352+ }
353+ TypeStoreUser current = existingList .isEmpty () ? null : (TypeStoreUser ) existingList .get (0 );
346354 if (current == sources [i ]) {
347355 // The new object matches what already exists in the array
348356 // Heuristic: we optimize for the case where the new elements
@@ -351,16 +359,26 @@ protected void arraySetterHelper(XmlObject[] sources, QName elemName, QNameSet s
351359
352360 // First insert the new element in the array at position 0
353361 int j ;
362+ int originalI = i ; // capture for index arithmetic in the inner loop
354363 for (j = 0 ; j < i ; j ++) {
355364 TypeStoreUser user = (set == null ) ? store .insert_element_user (elemName , j ) : store .insert_element_user (set , elemName , j );
356365 ((XmlObjectBase ) user ).set (sources [j ]);
357366 }
367+ // Track inserts made inside this loop so we can compute the correct
368+ // index into existingList without calling find_element_user each time.
369+ int insertCount = 0 ;
358370 for (i ++, j ++; i < sources .length ; i ++, j ++) {
359371 // Cursor is implicitly closed
360372 XmlCursor c = sources [i ].isImmutable () ? null : sources [i ].newCursor ();
361373 if (c != null && c .toParent () && c .getObject () == this ) {
362374 c .close ();
363- current = (set == null ) ? store .find_element_user (elemName , j ) : store .find_element_user (set , j );
375+ // Each of the originalI pre-inserts shifted existing elements right by
376+ // originalI positions; each subsequent insert in this loop shifts them
377+ // one more. So j (the current store position) maps to
378+ // existingList[j - originalI - insertCount], where originalI accounts
379+ // for pre-loop inserts and insertCount for in-loop inserts so far.
380+ int existingIdx = j - originalI - insertCount ;
381+ current = (existingIdx < existingList .size ()) ? (TypeStoreUser ) existingList .get (existingIdx ) : null ;
364382 if (current != sources [i ]) {
365383 // Fall back to the general case
366384 break ;
@@ -372,11 +390,12 @@ protected void arraySetterHelper(XmlObject[] sources, QName elemName, QNameSet s
372390 // Insert before the current element
373391 TypeStoreUser user = (set == null ) ? store .insert_element_user (elemName , j ) : store .insert_element_user (set , elemName , j );
374392 ((XmlObjectBase ) user ).set (sources [i ]);
393+ insertCount ++;
375394 }
376395 }
377396 startDest = j ;
378397 startSrc = i ;
379- m = store .count_elements (elemName );
398+ m = ( set == null ) ? store .count_elements (elemName ) : store . count_elements ( set );
380399 }
381400 // Fall through
382401 } else {
@@ -407,19 +426,28 @@ protected void arraySetterHelper(XmlObject[] sources, QName elemName, QNameSet s
407426 }
408427 }
409428
429+ // Get existing elements upfront to avoid O(n^2) from repeated find_element_user calls.
430+ // The list is built lazily since it may not be needed when all remaining elements are new.
431+ List <XmlObject > finalList = null ;
410432 int j ;
411433 for (i = startSrc , j = startDest ; i < n ; i ++, j ++) {
412- TypeStoreUser user ;
434+ XmlObjectBase user ;
413435
414436 if (j >= m ) {
415- user = store .add_element_user (elemName );
416- } else if (set == null ) {
417- user = store .find_element_user (elemName , j );
437+ user = (XmlObjectBase ) store .add_element_user (elemName );
418438 } else {
419- user = store .find_element_user (set , j );
439+ if (finalList == null ) {
440+ finalList = new ArrayList <>(m );
441+ if (set == null ) {
442+ store .find_all_element_users (elemName , finalList );
443+ } else {
444+ store .find_all_element_users (set , finalList );
445+ }
446+ }
447+ user = (XmlObjectBase ) finalList .get (j );
420448 }
421449
422- (( XmlObjectBase ) user ) .set (sources [i ]);
450+ user .set (sources [i ]);
423451 }
424452
425453 // We can't just delegate to array_setter because we need
@@ -446,17 +474,26 @@ private void commonSetterHelper(QName elemName, QNameSet set, int n, BiConsumer<
446474 }
447475 }
448476
477+ // Get existing elements upfront to avoid O(n^2) from repeated find_element_user calls
478+ List <XmlObject > existing = new ArrayList <>(m );
479+ if (m > 0 ) {
480+ if (set == null ) {
481+ store .find_all_element_users (elemName , existing );
482+ } else {
483+ store .find_all_element_users (set , existing );
484+ }
485+ }
486+
449487 for (int i = 0 ; i < n ; i ++) {
450- TypeStoreUser user ;
488+ XmlObjectBase user ;
451489
452490 if (i >= m ) {
453- user = store .add_element_user (elemName );
454- } else if (set == null ) {
455- user = store .find_element_user (elemName , i );
491+ user = (XmlObjectBase ) store .add_element_user (elemName );
456492 } else {
457- user = store . find_element_user ( set , i );
493+ user = ( XmlObjectBase ) existing . get ( i );
458494 }
459- fun .accept ((XmlObjectBase ) user , i );
495+
496+ fun .accept (user , i );
460497 }
461498 }
462499
@@ -475,17 +512,26 @@ private <T> void commonSetterHelper2(QName elemName, QNameSet set, T[] sources,
475512 }
476513 }
477514
515+ // Get existing elements upfront to avoid O(n^2) from repeated find_element_user calls
516+ List <XmlObject > existing = new ArrayList <>(m );
517+ if (m > 0 ) {
518+ if (set == null ) {
519+ store .find_all_element_users (elemName , existing );
520+ } else {
521+ store .find_all_element_users (set , existing );
522+ }
523+ }
524+
478525 for (int i = 0 ; i < n ; i ++) {
479- TypeStoreUser user ;
526+ XmlObjectBase user ;
480527
481528 if (i >= m ) {
482- user = store .add_element_user (elemName );
483- } else if (set == null ) {
484- user = store .find_element_user (elemName , i );
529+ user = (XmlObjectBase ) store .add_element_user (elemName );
485530 } else {
486- user = store . find_element_user ( set , i );
531+ user = ( XmlObjectBase ) existing . get ( i );
487532 }
488- c .accept ((XmlObjectBase ) user , sources [i ]);
533+
534+ c .accept (user , sources [i ]);
489535 }
490536 }
491537}
0 commit comments