/*
 * 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.uima.cas.impl;

import java.util.ArrayList;
import java.util.Arrays;

import org.apache.uima.cas.FeatureStructure;

public abstract class FsIterator_subtypes_list <T extends FeatureStructure>  extends FsIterator_subtypes<T> {

  // An array of iterators, one for each subtype.
  //   This array has the indexes for all the subtypes that were non-empty at the time of iterator creation
  protected FsIterator_singletype<T>[] iterators;

  protected int lastValidIndex = 0;
   
  public FsIterator_subtypes_list(FsIndex_iicp<T> iicp) {
    super(iicp);
    this.iterators = initIterators();
//    can't do moveToFirst, subtypes haven't yet set up enough things (like comparator)
    // subtypes must do this call after setup complete
//    moveToFirst();  // needed in order to set up lastvalid index, etc.
  }
  
  // skip including iterators for empty indexes
  //   The concurrent modification exception notification doesn't occur when subsequent "adds" are done, but
  //   that is the same as current: 
  //   where the move to first would mark the iterator "invalid" (because it was initially empty) and it would be
  //     subsequently ignored - same effect
  private FsIterator_singletype<T>[] initIterators() {
    iicp.createIndexIteratorCache();
    final ArrayList<FsIndex_singletype<FeatureStructure>> cachedSubIndexes = iicp.cachedSubFsLeafIndexes;
        
    FsIterator_singletype<T>[] r = cachedSubIndexes.stream()
        .filter(leafIndex -> leafIndex.size() > 0)  // filter out empty ones     
        .map( index -> index.iterator())  // map fsIndex_singletype to an iterator over that
        .toArray(FsIterator_singletype[]::new);

    // if all are empty, put the first one in (to avoid handling 0 as a special case)
    return (r.length != 0) ? r : new FsIterator_singletype[] {(FsIterator_singletype) cachedSubIndexes.get(0).iterator()};
  }

  /* (non-Javadoc)
   * @see org.apache.uima.cas.impl.LowLevelIterator#ll_indexSize()
   */
  @Override
  public int ll_indexSize() {
    return Arrays.stream(iterators).mapToInt(it -> it.ll_getIndex().size()).sum();
  }
  
}

@@ -2142,18 +2142,8 @@
 nal 
-ArrayList%3C
 FsIn
@@ -2174,17 +2174,18 @@
 ructure%3E
-%3E
+%5B%5D
  cachedS
@@ -2232,24 +2232,26 @@
 %0D%0A        %0D%0A
+//
     FsIterat
@@ -2300,16 +2300,18 @@
 ream()%0D%0A
+//
         
@@ -2385,16 +2385,18 @@
 s     %0D%0A
+//
         
@@ -2481,16 +2481,18 @@
 r that%0D%0A
+//
         
@@ -2534,16 +2534,310 @@
 ew);%0D%0A%0D%0A
+    ArrayList%3CFsIterator_singletype%3CT%3E%3E r = new ArrayList%3C%3E();%0D%0A    for (FsIndex_singletype%3CFeatureStructure%3E leafIndex : iicp.cachedSubFsLeafIndexes) %7B%0D%0A      if (leafIndex.size() == 0) %7B%0D%0A        continue;%0D%0A      %7D%0D%0A      r.add((FsIterator_singletype%3CT%3E) leafIndex.iterator());%0D%0A    %7D%0D%0A    %0D%0A
     // i
@@ -2933,24 +2933,99 @@
  (r.
-length
+size()
  != 0) 
-? r
+%0D%0A             ? r.toArray(new FsIterator_singletype%5Br.size()%5D) %0D%0A            
  : n
@@ -3074,16 +3074,19 @@
 ngletype
+%3CT%3E
 ) cached
@@ -3099,15 +3099,11 @@
 exes
-.get(0)
+%5B0%5D
 .ite
@@ -3267,85 +3267,138 @@
     
-return Arrays.stream(iterators).mapToInt(it -%3E it.ll_getIndex().size()).sum()
+int sz = 0;%0D%0A    for (FsIterator_singletype%3CT%3E it : iterators) %7B%0D%0A      sz += it.ll_getIndex().size();      %0D%0A    %7D%0D%0A    return sz
 ;%0D%0A 

convert cache from arraylist to array.