You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2015/11/01 14:11:17 UTC

svn commit: r1711750 [2/2] - /uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java

Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java?rev=1711750&r1=1711749&r2=1711750&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java Sun Nov  1 13:11:17 2015
@@ -24,12 +24,11 @@ import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.ConcurrentModificationException;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
+import java.util.Map;
 import java.util.Vector;
 
 import org.apache.uima.UIMARuntimeException;
@@ -39,23 +38,18 @@ import org.apache.uima.cas.CASRuntimeExc
 import org.apache.uima.cas.FSIndex;
 import org.apache.uima.cas.FSIterator;
 import org.apache.uima.cas.FeatureStructure;
-import org.apache.uima.cas.SofaFS;
 import org.apache.uima.cas.Type;
-import org.apache.uima.cas.TypeSystem;
 import org.apache.uima.cas.admin.CASAdminException;
 import org.apache.uima.cas.admin.FSIndexComparator;
 import org.apache.uima.cas.admin.FSIndexRepositoryMgr;
 import org.apache.uima.cas.admin.LinearTypeOrder;
 import org.apache.uima.cas.admin.LinearTypeOrderBuilder;
-import org.apache.uima.cas.impl.FSIndexFlat.FSIteratorFlat;
 import org.apache.uima.cas.text.AnnotationFS;
-import org.apache.uima.internal.util.ComparableIntPointerIterator;
-import org.apache.uima.internal.util.Int2IntArrayMapFixedSize;
-import org.apache.uima.internal.util.IntComparator;
-import org.apache.uima.internal.util.IntPointerIterator;
 import org.apache.uima.internal.util.IntVector;
-import org.apache.uima.internal.util.PositiveIntSet;
-import org.apache.uima.internal.util.PositiveIntSet_impl;
+import org.apache.uima.internal.util.ObjHashSet;
+import org.apache.uima.jcas.cas.AnnotationBase;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.jcas.tcas.Annotation;
 import org.apache.uima.util.Misc;
 
 /**
@@ -64,20 +58,16 @@ import org.apache.uima.util.Misc;
  * Some parts of the data here are shared between all views of a CAS.
  * 
  * Many things refer to specific types, and their associated Java Cover classes.
- *    There are 2 kinds of cover classes:
- *        If JCas is not being used, or if there is no JCas cover class defined for a type, then
- *        the Java class FeatureStructureImplC is used as the cover class.
+ *    Java impl classes are always used for each type; 
+ *        If there is no JCas cover class defined for a type, then
+ *        the most specific superclass which has a JCas defined class is used;
+ *        this is the class TOP or one of its subclasses.
  *        
- *        If the JCas is being used, then the JCas cover type (a subtype of TOP) is used as the cover class.
- *        
- *        Both of these classes inherit from FeatureStructureImpl (an abstract class)
- *        
- *    Both of these classes implement the common interface FeatureStructure.
  *
  * Generic typing: 
  *   User facing APIs can make use of the (JCas) Java cover types, for indexes and iterators over them
  *   The general generic type used is typically written here as T extends FeatureStructure, where
- *   FeatureStructure is the super interface of all cover types (JCas and non-JCas).  
+ *   FeatureStructure is the super interface of all JCas types.  
  *
  *   APIs having no reference to Java cover types (i.e., low level iterators) are not generic, unless they
  *   are needed to be to pass along the associated type to other APIs. 
@@ -85,1685 +75,82 @@ import org.apache.uima.util.Misc;
 public class FSIndexRepositoryImpl implements FSIndexRepositoryMgr, LowLevelIndexRepository {
 
   private final static boolean DEBUG = false;
+  
+  public final static boolean ITEM_ADDED_TO_INDEX = true;
+  public final static boolean ITEM_REMOVED_FROM_INDEX = false;
   /**
    * The default size of an index.
    */
   public static final int DEFAULT_INDEX_SIZE = 16;
 
-
+  /**
+   * flag used when removing FSs due to corruption avoidance
+   */
+  public static final boolean SKIP_BAG_INDEXES = true;
+  public static final boolean INCLUDE_BAG_INDEXES = false;
+  
   /**
    * Define this JVM property to allow adding the same identical FS to Set and Sorted indexes more than once.  
    */
-
   public static final String ALLOW_DUP_ADD_TO_INDEXES = "uima.allow_duplicate_add_to_indexes";
-  
-  // accessed by FSIntArrayIndex and tests
-  public static final boolean IS_ALLOW_DUP_ADD_2_INDEXES  =  Misc.getNoValueSystemProperty(ALLOW_DUP_ADD_TO_INDEXES);
+  static { 
+    if (Misc.getNoValueSystemProperty(ALLOW_DUP_ADD_TO_INDEXES)) {
+      throw new CASAdminException(CASAdminException.INDEX_DUPLICATES_NOT_SUPPORTED);
+    }
+  }
   
   public static final String DISABLE_ENHANCED_WRONG_INDEX = "uima.disable_enhanced_check_wrong_add_to_index";
  
   private static final boolean IS_DISABLE_ENHANCED_WRONG_INDEX_CHECK = Misc.getNoValueSystemProperty(DISABLE_ENHANCED_WRONG_INDEX);
-
-  /**
-   * Kinds of extra functions for iterators
-   */
-  public enum IteratorExtraFunction {
-    SNAPSHOT,  // snapshot iterators
-    UNORDERED, // unordered iterators - means unordered among subtypes, but each subtype may have an order
-  }
-    
-  private static final FSIterator emptyFSIterator = new FSIteratorImplBase<FeatureStructure>() {
-
-    @Override
-    public boolean isValid() {return false;}
-
-    @Override
-    public FeatureStructure get() throws NoSuchElementException { throw new NoSuchElementException(); }
-
-    @Override
-    public void moveToNext() {}
-
-    @Override
-    public void moveToPrevious() {}
-
-    @Override
-    public void moveToFirst() {}
-
-    @Override
-    public void moveToLast() {}
-
-    @Override
-    public void moveTo(FeatureStructure fs) {}
-
-    @Override
-    public FSIterator<FeatureStructure> copy() {
-      return this;
-    }
-    @Override
-    <TT extends AnnotationFS> void moveTo(int begin, int end) {}
-  };
-
-  private static final LowLevelIterator emptyLlIterator = new FSIntIteratorImplBase<FeatureStructure>(null, null) {
-
-    @Override
-    public boolean isValid() { return false; }
-
-    @Override
-    public int get() { throw new NoSuchElementException(); }
-
-    @Override
-    public void moveTo(int i) {}
-
-    @Override
-    public void moveToFirst() {}
-
-    @Override
-    public void moveToLast() {}
-
-    @Override
-    public Object copy() { return this; }
-
-    @Override
-    public void moveToNext() {}
-
-    @Override
-    public void moveToPrevious() {}
-
-    @Override
-    public int ll_indexSize() { return 0; }
-
-  };
+      
   // Implementation note: the use of equals() here is pretty hairy and
   // should probably be fixed. We rely on the fact that when two
   // FSIndexComparators are compared, the type of the comparators is
   // ignored! A fix for this would be to split the FSIndexComparator
   // class into two classes, one for the key-comparator pairs, and one
   // for the combination of the two. Note also that we compare two
-  // IndexIteratorCachePairs by comparing their
+  // FsIndex_iicps by comparing their
   // index.getComparator()s.
 
-  /**
-   * IndexIteratorCachePair (iicp)
-   * 
-   * A pair of an leaf index and an iterator cache. An iterator cache is the set of all leaf-indexes necessary
-   * to create an iterator for the type of the index.
-   * 
-   *  The cache includes the index for the type of this index, as well as all subtypes.
-   *  
-   * compareTo() is based on types and the comparator of the index.
-   * 
-   * T is the Java cover class of the top type (root) in the index set
-   * 
-   * Also includes a lazily initialized reference to a corresponding FSIndexFlat instance.
-   * 
-   * This class is package private to share with FSIndexFlat
-   * For Internal Use
-   */
-  class IndexIteratorCachePair<T extends FeatureStructure> 
-               implements Comparable<IndexIteratorCachePair<? extends FeatureStructure>> {
-
-    /**
-     *  The "root" index, i.e., index of the type of the iterator.
-     *  default visibility to make it accessable by FSIndexFlat
-     */
-    final private FSLeafIndexImpl<T> fsLeafIndex;
-    
-    FSLeafIndexImpl<T> getFsLeafIndex() {
-      return fsLeafIndex;
-    }
-
-    /**
-     * A list of indexes (the sub-indexes that we need for an iterator). 
-     * I.e., one index for each type that's subsumed by the iterator's type; 
-     * includes the iterator's type leaf index too.
-     */
-    private ArrayList<FSLeafIndexImpl<? extends T>> cachedSubFsLeafIndexes = null;
-    
-    // VOLATILE to permit double-checked locking technique
-    private volatile boolean isIteratorCacheSetup = false;
-    
-    /**
-     * Link to associated flattened information, set up lazily, only if this level has an iterator
-     */
-    private FSIndexFlat<T> flatIndex = null;
-    
-    /**
-     * The type codes corresponding to the cachedSubFsLeafIndexes, set up lazily
-     */
-    int[] sortedTypeCodes;
-    
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("IndexIteratorCachePair, index=");
-      sb.append(fsLeafIndex).append('\n');
-      if (!isIteratorCacheSetup) {
-        sb.append(" cache not set up yet");
-      } else {  
-        int len = Math.min(3,  cachedSubFsLeafIndexes.size());
-        for (int i = 0; i < len; i++) {
-          FSLeafIndexImpl<? extends T> lii = cachedSubFsLeafIndexes.get(i); 
-          sb.append("  cache ").append(i++);
-          sb.append("  ").append(lii).append('\n');
-        }
-        if (cachedSubFsLeafIndexes.size() > 3) {
-          sb.append(" ... and " + (cachedSubFsLeafIndexes.size() - 3) + " more\n");
-        }
-      }
-      return sb.toString();
-    }
-
-    private IndexIteratorCachePair(FSLeafIndexImpl<T> fsLeafIndex) {
-      this.fsLeafIndex = fsLeafIndex;
-//      setAndTestMask = FSIndexRepositoryImpl.this.cas.getTypeSystemImpl().getSetAndTestMasks(fsLeafIndex.getTypeCode());
-    }
-
-    // Two IICPs are equal iff their index comparators are equal AND their
-    // indexing strategy is the same.
-    // Equal is used when creating the index iterator cache to select
-    //   from the set of all IndexIteratorCachePairs for a particular type,
-    //   the one that goes with the same index definition
-    @Override
-    public boolean equals(Object o) {
-      if (!(o instanceof IndexIteratorCachePair)) {
-        return false;
-      }
-      @SuppressWarnings("rawtypes")
-      final IndexIteratorCachePair iicp = (IndexIteratorCachePair) o;
-      return this.fsLeafIndex.getComparator().equals(iicp.fsLeafIndex.getComparator())
-          && (this.fsLeafIndex.getIndexingStrategy() == iicp.fsLeafIndex.getIndexingStrategy());
-    }
-
-// if this throws, then the Eclipse debugger fails to show the object saying 
-// com.sun.jdi.InvocationException occurred invoking method. 
-    @Override
-    public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + this.fsLeafIndex.getComparator().hashCode();
-      result = prime * result + this.fsLeafIndex.getIndexingStrategy();
-      return result;
-    }
-
-    // Populate the cache.
-    // For read-only CASes, this may be called on multiple threads, so do some synchronization
-        
-    @SuppressWarnings("unchecked")
-    private void createIndexIteratorCache() {
-      // using double-checked sync - see http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
-      if (isIteratorCacheSetup) {
-        return;
-      }
-      synchronized (this) {
-        if (isIteratorCacheSetup) {
-          return;
-        }
-        final Type rootType = this.fsLeafIndex.getComparator().getType();
-        final int indexKind = this.fsLeafIndex.getIndexingStrategy();
-        ArrayList<Type> allTypes = null;
-        if (indexKind == FSIndex.DEFAULT_BAG_INDEX) {
-          allTypes = new ArrayList<Type>();
-          allTypes.add(rootType);
-        } else {
-          // includes the original type as element 0
-          allTypes = getAllSubsumedTypes(rootType, FSIndexRepositoryImpl.this.sii.tsi);
-        }
-        
-        final ArrayList<FSLeafIndexImpl<? extends T>> tempSubIndexCache = new ArrayList<FSLeafIndexImpl<? extends T>>();
-        final int len = allTypes.size();
-        if (indexKind == FSIndex.SORTED_INDEX) {
-          sortedTypeCodes = new int[len];
-        }
-        
-        for (int i = 0; i < len; i++) {
-          final int typeCode = ((TypeImpl) allTypes.get(i)).getCode();
-          final ArrayList<IndexIteratorCachePair<?>> indexList = FSIndexRepositoryImpl.this.indexArray[typeCode];
-          final int indexPos = indexList.indexOf(this);
-          FSLeafIndexImpl<? extends T> leafIndex = (FSLeafIndexImpl<? extends T>) indexList.get(indexPos).fsLeafIndex;
-          if (indexPos >= 0) {  // is always true???
-            tempSubIndexCache.add(leafIndex);            
-          } else {
-            throw new RuntimeException("never happen");
-          }
-          if (indexKind == FSIndex.SORTED_INDEX) {
-            sortedTypeCodes[i] = leafIndex.getTypeCode();
-          }
-        }
-        this.cachedSubFsLeafIndexes = tempSubIndexCache; 
-        if (this.fsLeafIndex.getIndexingStrategy() == FSIndex.SORTED_INDEX) {
-          Arrays.sort(sortedTypeCodes);
-          this.flatIndex = FSIndexFlat.enabled ? new FSIndexFlat<>(this) : null; // must follow cachedSubFsLeafIndexes setup
-        }
-        // assign to "volatile" at end, after all initialization is complete
-        this.isIteratorCacheSetup = true;
-      }  // end of synchronized block
-    }
-
-    
-    /**
-     * Maybe not used 3/2015
-     * 
-     * Compares first using the type code of the main types
-     *   If those are equal,
-     *   Compares using the comparator objects
-     * @see java.lang.Comparable#compareTo(Object)
-     * 
-     */
-    public int compareTo(IndexIteratorCachePair<? extends FeatureStructure> cp) {
-      final int typeCode1 = ((TypeImpl) this.fsLeafIndex.getType()).getCode();
-      final int typeCode2 = ((TypeImpl) cp.fsLeafIndex.getType()).getCode();
-      if (typeCode1 < typeCode2) {
-        return -1;
-      } else if (typeCode1 > typeCode2) {
-        return 1;
-      } else { // types are equal
-        return this.fsLeafIndex.getComparator().compareTo(cp.fsLeafIndex.getComparator());
-      }
-    }
-
-    /**
-     * 
-     * @return the sum of the sizes of the indexes of the type + all subtypes
-     */
-    int size() {
-      int size = 0;
-      createIndexIteratorCache();  // does nothing if already created
-      final ArrayList<FSLeafIndexImpl<? extends T>> localIc = this.cachedSubFsLeafIndexes;
-      final int len = localIc.size();
-      for (int i = 0; i < len; i++) {
-        size += localIc.get(i).size();
-      }
-      return size;
-    }
-    
-    boolean has1OrMoreEntries() {
-      createIndexIteratorCache();  // does nothing if already created
-      final ArrayList<FSLeafIndexImpl<? extends T>> localIc = this.cachedSubFsLeafIndexes;
-      final int len = localIc.size();
-      for (int i = 0; i < len; i++) {
-        if (localIc.get(i).size() > 0) {
-          return true;
-        };
-      }
-      return false;
-    }
-    
-    /**
-     * A faster version of size() when there are lots of subtypes
-     * The cache must be already set up
-     * 
-     * Guess by adding the sizes of up to the first 3 type/subtypes, 
-     * then add 1 more for each subtype in addition.
-     * 
-     * @return a guess at the size, done quickly
-     */
-    int guessedSize() {
-      final ArrayList<FSLeafIndexImpl<? extends T>> localIc = this.cachedSubFsLeafIndexes;
-      final int len = localIc.size();
-      final int lim = Math.min(3, len);
-      int size = 0;
-      for (int i = 0; i < lim; i++) {
-        size += localIc.get(i).size();
-      }
-      size += len - lim;
-      return size;
-    }
-       
-    /**
-     * Flat array filled, ordered
-     * @param flatArray the array to fill
-     */
-    public void fillFlatArray(FeatureStructure[] flatArray) {
-      LowLevelIterator it = (LowLevelIterator) createPointerIterator(this);
-      int i = 0;
-      while (it.isValid()) {
-        if (i >= flatArray.length) {
-          throw new ConcurrentModificationException();
-        }
-        flatArray[i++] = cas.createFS(it.ll_get());
-        if (DEBUG) {
-          int tc1 = fsLeafIndex.getTypeCode();
-          int tc2 = ((TypeImpl)(flatArray[i-1].getType())).getCode();
-          if (!subsumes(tc1, tc2)) {
-            throw new RuntimeException(String.format("FillFlatArray for element %,d produced a non-subtype, tc1 = %d, tc2 = %d%n"
-                + "iicp = %s%nfs = %s%n",
-                tc1,  tc2,
-                i-1,
-                this,
-                flatArray[i-1]));
-          }
-        }
-        it.moveToNext();
-      }
-      if (i != flatArray.length) {
-//        System.out.println("Debug - got iterator invalid before all items filled, i = " + i + ", size = " + flatArray.length);
-        throw new ConcurrentModificationException();
-      }
-    }
-    
-    Int2IntArrayMapFixedSize createIndexUpdateCountsAtReset() {
-      Int2IntArrayMapFixedSize m = new Int2IntArrayMapFixedSize(sortedTypeCodes.length);
-      captureIndexUpdateCounts(m);
-      return m;
-    }
-    
-    void captureIndexUpdateCounts() {
-      captureIndexUpdateCounts(this.flatIndex.indexUpdateCountsResetValues);
-    }
-    
-    private void captureIndexUpdateCounts(Int2IntArrayMapFixedSize m) {
-      final int[] localSortedTypeCodes = sortedTypeCodes;
-      for (int i = 0; i < localSortedTypeCodes.length; i++) {
-        m.putAtIndex(i, detectIllegalIndexUpdates[localSortedTypeCodes[i]]);
-      } 
-    }
-    
-    boolean isUpdateFreeSinceLastCounterReset() {
-      final Int2IntArrayMapFixedSize typeCode2updateCount = this.flatIndex.indexUpdateCountsResetValues;
-      final int[] localSortedTypeCodes = sortedTypeCodes;
-      for (int i = 0; i < localSortedTypeCodes.length; i++) {
-        if (typeCode2updateCount.getAtIndex(i) != detectIllegalIndexUpdates[localSortedTypeCodes[i]]) {
-          return false;
-        }
-      }
-      return true;
-    }
-        
-    boolean isUpdateFreeSinceLastCounterReset(final int typeCode) {
-      return this.flatIndex.indexUpdateCountsResetValues.get(typeCode, sortedTypeCodes) == 
-          detectIllegalIndexUpdates[typeCode];
-    }
-      
-    boolean subsumes(int superType, int subType) {
-      return cas.getTypeSystemImpl().subsumes(superType,  subType);
-    }
-    
-    // debug
-    CASImpl getCASImpl() {
-      return cas;
-    }
-    
-    void addToIteratedSortedIndexes() {
-      iteratedSortedIndexes.add(this);
-    }
-    
-    // flatIndex is null except for sorted indexes
-    private boolean hasFlatIndex() {
-      if (! FSIndexFlat.enabled) {
-        return false;
-      } else {
-        return isIteratorCacheSetup && (flatIndex != null) && flatIndex.hasFlatIndex();
-      }
-    }
-    
-  }  // end of class definition for IndexIteratorCachePair
-
-  
-  /* ============================================================================================================*/
-  /*           Pointer Iterators                                                                                
-  /* ============================================================================================================*/
-  /**
-   * Create an "ordered" (e.g. one that maintains iicp sort order for sorted index) pointer iterator over an iicp
-   * @param iicp - the index plus its subtype list of indexes
-   * @return an int iterator
-   */
-  IntPointerIterator createPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp) {
-    return createPointerIterator(iicp, false);
-  }
-
-
-  /**
-   * Create an ordered or iicp-unordered pointer iterator over an iicp
-   * 
-   *  Note that flattened index iterators are not int style; and they're created higher up...
-   *  
-   * @param iicp - the index plus its subtype list of indexes
-   * @param is_unordered true if ordering among subtypes not needed
-   * @return an int iterator
-   */
-  <T extends FeatureStructure> IntPointerIterator createPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp, boolean is_unordered) {
-    iicp.createIndexIteratorCache();
-    if (iicp.cachedSubFsLeafIndexes.size() > 1) {
-      final int strat = iicp.fsLeafIndex.getIndexingStrategy();
-      if (strat == FSIndex.BAG_INDEX ||           
-          strat == FSIndex.SET_INDEX ||  // because set indexes do not enforce ordering
-          is_unordered) {
-        return new PointerIteratorUnordered(iicp);
-      } else {
-        return new PointerIterator(iicp);
-      }
-    }
-    return createLeafPointerIterator(iicp);
-  }
-
-  <T extends FeatureStructure> IntPointerIterator createPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp, int fs) {
-    return createPointerIterator(iicp, false, fs);
-  }
-  
-  <T extends FeatureStructure> IntPointerIterator createPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp, boolean is_unordered, int fs) {
-    IntPointerIterator it = createPointerIterator(iicp, is_unordered);
-    it.moveTo(fs);
-    return it;
-  }
-  
-  private <T extends FeatureStructure> IntPointerIterator createLeafPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp) {
-    FSLeafIndexImpl<T> leafIndex = (FSLeafIndexImpl<T>) iicp.fsLeafIndex;
-    return leafIndex.pointerIterator(leafIndex, this.detectIllegalIndexUpdates, leafIndex.getTypeCode());
-  }
-
-  /**
-   * The next 3 classes (PointerIterator, PointerIteratorUnordered and LeafPointerIterator) 
-   * implement iterators for particular indexes.
-   * 
-   * PointerIteratorUnordered is used for bag and things like all indexed fs where order is not important.
-   * It uses the same impl as PointerIterator, except it works by sequentially iterating over each of the 
-   * iterator pieces.
-   * 
-   * This class handles the concepts involved with iterating over a type and
-   * all of its subtypes, keeping the ordering among the subtypes. 
-   * 
-   * The LeafPointerIterator handles just iterating over a particular type or subtype
-   * (the one that this class picks).
-   * 
-   * The iterator implementation for indexes. Tricky because the iterator needs to be able to move
-   * backwards as well as forwards.
-   */
-  private class PointerIterator implements IntPointerIterator, LowLevelIterator {
-
-    /**
-     * The number of elements to keep in order before the binary heap starts. This section helps the
-     * performance in cases where a couple of types dominate the index.
-     */
-    static final int SORTED_SECTION = 3;
-
-    // The IICP
-    final private IndexIteratorCachePair<? extends FeatureStructure> iicp;
-
-    protected IndexIteratorCachePair<? extends FeatureStructure> getIicp() {
-      return iicp;
-    }
-
-    // An array of ComparableIntPointerIterators, one for each subtype.
-    //   Each instance of these has a Class.this kind of ref to a particular variety of FSLeafIndex (bag, set, sorted) corresponding to 1 type
-    //   This array has the indexes for all the subtypes that were non-empty at the time of iterator creation
-    protected ComparableIntPointerIterator[] iterators;
-
-    int lastValidIndex;
-
-    // snapshot to detectIllegalIndexUpdates
-    // need to move this to ComparableIntPointerIterator so it can be tested
-
-    // currentIndex is always 0
-
-    // The iterator works in two modes:
-    // Forward and backward processing. This flag tells which mode we're in.
-    // The iterator heap needs to be reconstructed when we switch direction.
-    protected boolean wentForward;
-
-    // Comparator that is used to compare FS addresses for the purposes of
-    // iteration.
-    final private IntComparator iteratorComparator;
-
-    // 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 ComparableIntPointerIterator[] initPointerIterator() {
-      // Note to maintainers: Make sure the iterator cache exists on all paths calling this
-      final ArrayList<?> cachedSubIndexes = iicp.cachedSubFsLeafIndexes;
-      final int length = cachedSubIndexes.size();
-      
-      final ArrayList<ComparableIntPointerIterator> pia = new ArrayList<ComparableIntPointerIterator>(cachedSubIndexes.size());
-
-      // put all non-empty leaf iterators into the iteration, and if all are empty, put the last one in
-      //   (to avoid handling 0 as a special case)
-      for (int i = 0; i < length; i++) {
-        final FSLeafIndexImpl<?> leafIndex = (FSLeafIndexImpl<?>) cachedSubIndexes.get(i);
-        if ((leafIndex.size() > 0) || 
-            ((i == length -1) &&        // this logic puts in the last one if all are empty
-             (0 == pia.size()))) {
-          pia.add(leafIndex.pointerIterator(
-              this.iteratorComparator,
-              FSIndexRepositoryImpl.this.detectIllegalIndexUpdates,
-              ((TypeImpl) leafIndex.getType()).getCode()));
-        }
-      }
-      
-      ComparableIntPointerIterator[] piaa = new ComparableIntPointerIterator[pia.size()];
-      return pia.toArray(piaa);
-    }
-
-    private PointerIterator(final IndexIteratorCachePair<? extends FeatureStructure> iicp) {
-      // next 3 are final so aren't done in the common init
-      this.iicp = iicp;
-      this.iteratorComparator = iicp.cachedSubFsLeafIndexes.get(0);
-      this.iterators = initPointerIterator();
-      moveToFirst();
-    }
-
-    private PointerIterator(final IndexIteratorCachePair<? extends FeatureStructure> iicp, int fs) {
-      // next 3 are final so aren't done in the common init
-      this.iicp = iicp;
-      this.iteratorComparator = iicp.cachedSubFsLeafIndexes.get(0);
-      this.iterators = initPointerIterator();
-      moveTo(fs);
-    }
-
-    public boolean isValid() {
-      // We're valid as long as at least one index is.
-      return (this.lastValidIndex >= 0 );
-    }
-
-    protected ComparableIntPointerIterator<?> checkConcurrentModification(int i) {
-      final FSIntIteratorImplBase<?> cipi = (FSIntIteratorImplBase<?>) this.iterators[i];
-      cipi.checkConcurrentModification();  // throws if concurrentModification
-      return cipi;
-    }
-
-    /**
-     * Test the order with which the two iterators should be used. Introduces arbitrary ordering for
-     * equivalent FSs. Only called with valid iterators.
-     * 
-     * @param l
-     * @param r
-     * @param dir
-     *          Direction of movement, 1 for forward, -1 for backward
-     * @return true if the left iterator needs to be used before the right one.
-     */
-    private boolean is_before(ComparableIntPointerIterator l, ComparableIntPointerIterator r,
-        int dir) {
-      final int il = l.get();
-      final int ir = r.get();
-      int d = this.iteratorComparator.compare(il, ir);
-
-      // If two FSs are identical wrt the comparator of the index,
-      // we still need to be able to distinguish them to be able to have a
-      // well-defined sequence. In that case, we arbitrarily order FSs by
-      // their
-      // addresses. We need to do this in order to be able to ensure that a
-      // reverse iterator produces the reverse order of the forward iterator.
-      if (d == 0) {
-        d = il - ir;
-      }
-
-      return d * dir < 0;
-    }
-
-    /**
-     * Move the idx'th element up in the heap until it finds its proper position.
-     * 
-     * @param it
-     *          indexes[idx]
-     * @param idx
-     *          Element to move
-     * @param dir
-     *          Direction of iterator movement, 1 for forward, -1 for backward
-     */
-    private void heapify_up(ComparableIntPointerIterator it, int idx, int dir) {
-      FSIndexFlat<? extends FeatureStructure> flatIndexInfo = iicp.flatIndex;
-      if (null != flatIndexInfo) {
-        flatIndexInfo.incrementReorderingCount();
-      }
-      int nidx;
-
-      while (idx > SORTED_SECTION) {
-        nidx = (idx + SORTED_SECTION - 1) >> 1;
-        if (!is_before(it, this.iterators[nidx], dir)) {
-          this.iterators[idx] = it;
-          return;
-        }
-        this.iterators[idx] = this.iterators[nidx];
-        idx = nidx;
-      }
-
-      while (idx > 0) {
-        nidx = idx - 1;
-        if (!is_before(it, this.iterators[nidx], dir)) {
-          this.iterators[idx] = it;
-          return;
-        }
-        this.iterators[idx] = this.iterators[nidx];
-        idx = nidx;
-      }
-
-      this.iterators[idx] = it;
-    }
-
-    /**
-     * Move the top element down in the heap until it finds its proper position.
-     * 
-     * @param it
-     *          indexes[0]
-     * @param dir
-     *          Direction of iterator movement, 1 for forward, -1 for backward
-     */
-    private void heapify_down(ComparableIntPointerIterator it, int dir) {
-      FSIndexFlat<? extends FeatureStructure> flatIndexInfo = iicp.flatIndex;
-      if (null != flatIndexInfo) {
-        flatIndexInfo.incrementReorderingCount();
-      }
-
-      if (!it.isValid()) {
-        final ComparableIntPointerIterator itl = checkConcurrentModification(this.lastValidIndex);
-        this.iterators[this.lastValidIndex] = it;
-        this.iterators[0] = itl;
-        --this.lastValidIndex;
-        it = itl;
-      }
-
-      final int num = this.lastValidIndex;
-      if ((num < 1) || !is_before(checkConcurrentModification(1), it, dir)) {
-        return;
-      }
-
-      int idx = 1;
-      this.iterators[0] = this.iterators[1];
-      final int end = Math.min(num, SORTED_SECTION);
-      int nidx = idx + 1;
-
-      // make sure we don't leave the iterator in a completely invalid state
-      // (i.e. one it can't recover from using moveTo/moveToFirst/moveToLast)
-      // in case of a concurrent modification
-      try {
-        while (nidx <= end) {
-          if (!is_before(checkConcurrentModification(nidx), it, dir)) {
-            return; // passes through finally
-          }
-
-          this.iterators[idx] = this.iterators[nidx];
-          idx = nidx;
-          nidx = idx + 1;
-        }
-
-        nidx = SORTED_SECTION + 1;
-        while (nidx <= num) {
-          if ((nidx < num)
-              && is_before(checkConcurrentModification(nidx + 1),
-                  checkConcurrentModification(nidx), dir)) {
-            ++nidx;
-          }
-
-          if (!is_before(this.iterators[nidx], it, dir)) {
-            return;
-          }
-
-          this.iterators[idx] = this.iterators[nidx];
-          idx = nidx;
-          nidx = (nidx << 1) - (SORTED_SECTION - 1);
-        }
-      } finally {
-        this.iterators[idx] = it;
-      }
-    }
-
-    public void moveToFirst() {
-      int lvi = this.iterators.length - 1;
-      // Need to consider all iterators.
-      // Set all iterators to insertion point.
-      int i = 0;
-      while (i <= lvi) {
-        final FSIntIteratorImplBase<?> it = (FSIntIteratorImplBase<?>) this.iterators[i];
-        it.resetConcurrentModification();
-        it.moveToFirst();
-        if (it.isValid()) {
-          heapify_up(it, i, 1);
-          ++i;
-        } else {
-          // swap this iterator with the last possibly valid one
-          // lvi might be equal to i, this will not be a problem
-          this.iterators[i] = this.iterators[lvi];
-          this.iterators[lvi] = it;
-          --lvi;
-        }
-      }
-      // configured to continue with forward iterations
-      this.wentForward = true;
-      this.lastValidIndex = lvi;
-    }
-
-    public void moveToLast() {
-      int lvi = this.iterators.length - 1;
-      // Need to consider all iterators.
-      // Set all iterators to insertion point.
-      int i = 0;
-      while (i <= lvi) {
-        final FSIntIteratorImplBase<?> it = (FSIntIteratorImplBase<?>) this.iterators[i];
-        it.resetConcurrentModification();
-        it.moveToLast();
-        if (it.isValid()) {
-          heapify_up(it, i, -1);
-          ++i;
-        } else {
-          // swap this iterator with the last possibly valid one
-          // lvi might be equal to i, this will not be a problem
-          this.iterators[i] = this.iterators[lvi];
-          this.iterators[lvi] = it;
-          --lvi;
-        }
-      }
-      // configured to continue with backward iterations
-      this.wentForward = false;
-      this.lastValidIndex = lvi;
-    }
-
-    public void moveToNext() {
-      if (!isValid()) {
-        return;
-      }
-
-      final ComparableIntPointerIterator it0 = checkConcurrentModification(0);
-
-      if (this.wentForward) {
-        it0.inc();
-        heapify_down(it0, 1);
-      } else {
-        // We need to increment everything.
-        int lvi = this.iterators.length - 1;
-        int i = 1;
-        while (i <= lvi) {
-          // Any iterator other than the current one needs to be
-          // incremented until it's pointing at something that's
-          // greater than the current element.
-          final ComparableIntPointerIterator it = checkConcurrentModification(i);
-          // If the iterator we're considering is not valid, we
-          // set it to the first element. This should be it for this iterator...
-          if (!it.isValid()) {
-            it.moveToFirst();
-          }
-          // Increment the iterator while it is valid and pointing
-          // at something smaller than the current element.
-          while (it.isValid() && is_before(it, it0, 1)) {
-            it.inc();
-          }
-
-          // find placement
-          if (it.isValid()) {
-            heapify_up(it, i, 1);
-            ++i;
-          } else {
-            // swap this iterator with the last possibly valid one
-            // lvi might be equal to i, this will not be a problem
-            this.iterators[i] = this.iterators[lvi];
-            this.iterators[lvi] = it;
-            --lvi;
-          }
-        }
-
-        this.lastValidIndex = lvi;
-        this.wentForward = true;
-
-        it0.inc();
-        heapify_down(it0, 1);
-      }
-    }
-
-    public void moveToPrevious() {
-      if (!isValid()) {
-        return;
-      }
-
-      final ComparableIntPointerIterator it0 = checkConcurrentModification(0);
-      if (!this.wentForward) {
-        it0.dec();
-        // this also takes care of invalid iterators
-        heapify_down(it0, -1);
-      } else {
-        // We need to decrement everything.
-        int lvi = this.iterators.length - 1;
-        int i = 1;
-        while (i <= lvi) {
-          // Any iterator other than the current one needs to be
-          // decremented until it's pointing at something that's
-          // smaller than the current element.
-          final ComparableIntPointerIterator it = checkConcurrentModification(i);
-          // If the iterator we're considering is not valid, we
-          // set it to the last element. This should be it for this iterator...
-          if (!it.isValid()) {
-            it.moveToLast();
-          }
-          // Decrement the iterator while it is valid and pointing
-          // at something greater than the current element.
-          while (it.isValid() && is_before(it, it0, -1)) {
-            it.dec();
-          }
-
-          // find placement
-          if (it.isValid()) {
-            heapify_up(it, i, -1);
-            ++i;
-          } else {
-            // swap this iterator with the last possibly valid one
-            // lvi might be equal to i, this will not be a problem
-            this.iterators[i] = this.iterators[lvi];
-            this.iterators[lvi] = it;
-            --lvi;
-          }
-        }
-
-        this.lastValidIndex = lvi;
-        this.wentForward = false;
-
-        it0.dec();
-        heapify_down(it0, -1);
-      }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIterator#ll_get()
-     */
-    public int get() throws NoSuchElementException {
-      return ll_get();
-    }
-
-    public int ll_get() {
-      if (!isValid()) {
-        throw new NoSuchElementException();
-      }
-      return checkConcurrentModification(0).get();
-    }
-
-    public Object copy() {
-      // If this.isValid(), return a copy pointing to the same element.
-      if (this.isValid()) {
-        PointerIterator it = new PointerIterator(this.iicp);
-        moveTo(this.get());
-        return it;
-      }
-      // Else, create a copy that is also not valid.
-      final PointerIterator pi = new PointerIterator(this.iicp);
-      pi.moveToFirst();
-      pi.moveToPrevious();
-      return pi;
-    }
-  
-    /**
-     * @see org.apache.uima.internal.util.IntPointerIterator#moveTo(int)
-     */
-    public void moveTo(int fs) {
-      moveTo(fs, false);
-    }
-    /**
-     * @param fs the FS to move to
-     * @param isExact if true, move to this exact one (must be present),
-     *                if false, move to the left-most element that is equal to fs
-     *                using the comparator for the index or if none is equal,
-     *                move to the next element that is greater than this fs
-     *                or invalid position of all are less than this fs
-     */
-   void moveTo(int fs, boolean isExact) {
-      int lvi = this.iterators.length - 1;
-      // Need to consider all iterators.
-      // Set all iterators to insertion point.
-      int i = 0;
-      while (i <= lvi) {
-        final FSIntIteratorImplBase<?> it = (FSIntIteratorImplBase<?>) this.iterators[i];
-        it.moveTo(fs, isExact);
-        if (it.isValid()) {
-          heapify_up(it, i, 1);
-          ++i;
-        } else {
-          // swap this iterator with the last possibly valid one
-          // lvi might be equal to i, this will not be a problem
-          this.iterators[i] = this.iterators[lvi];
-          this.iterators[lvi] = it;
-          --lvi;
-        }
-      }
-      // configured to continue with forward iterations
-      this.wentForward = true;
-      this.lastValidIndex = lvi;
-     
-      // moved to leaf iterator
-//      if (!isValid()) {
-//        // this means the moveTo found the insert point at the end of the index
-//        // so just return invalid, since there's no way to return an insert point for a position
-//        // that satisfies the FS at that position is greater than fs  
-//        return;
-//      }
-//      // Go back until we find a FS that is really smaller
-//      while (true) {
-//        moveToPrevious();
-//        if (isValid()) {
-//          int prev = get();
-//          if (this.iicp.index.compare(prev, fs) != 0) {
-//            moveToNext();
-//            break;
-//          }
-//        } else {
-//          moveToFirst();
-//          break;
-//        }
-//      }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToNext()
-     */
-    public void inc() {
-      moveToNext();
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToPrevious()
-     */
-    public void dec() {
-      moveToPrevious();
-    }
-
-    public int ll_indexSize() {
-      return this.iicp.size();
-    }
-
-    public LowLevelIndex ll_getIndex() {
-      return (LowLevelIndex) this.iicp.fsLeafIndex;
-    }
-    
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder(this.getClass().getSimpleName() + " [iicp=" + iicp + ", indexes=\n");
-      int i = 0;
-      for (ComparableIntPointerIterator item : iterators) {
-        sb.append("  ").append(i++).append("  ").append(item).append('\n');
-        if (i > 4) {
-          break;
-        }
-      }
-      if (i < iterators.length) {
-        sb.append("  and ").append(iterators.length - i).append(" more.\n");
-      }
-      sb.append("  lastValidIndex="
-          + lastValidIndex + ", wentForward=" + wentForward + ", iteratorComparator=" + iteratorComparator + "]");
-      return sb.toString();
-    }
-
-  }  // end of class PointerIterator
-  
-  /**
-   * Version of pointer iterator for unordered uses (bags and getAllIndexedFSs
-   * Since bags have no order, simplify the iteration by just going thru sequentially
-   * all the subtypes
-   *
-   */
-  private class PointerIteratorUnordered extends PointerIterator {
-    
-    private PointerIteratorUnordered(final IndexIteratorCachePair<? extends FeatureStructure> iicp) {
-      super(iicp);
-    }
-    
-    private PointerIteratorUnordered(final IndexIteratorCachePair<? extends FeatureStructure> iicp, int fs) {
-      super(iicp); 
-      moveTo(fs);
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#isValid()
-     */
-    @Override
-    public boolean isValid() {
-      return (lastValidIndex >= 0) && (lastValidIndex < iterators.length);
-    }
-    
-    
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#ll_get()
-     */
-    @Override
-    public int ll_get() {
-      if (!isValid()) {
-        throw new NoSuchElementException();
-      }
-      return checkConcurrentModification(lastValidIndex).get();
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#moveToFirst()
-     */
-    @Override
-    public void moveToFirst() {
-      for (int i = 0; i < iterators.length; i++) {
-        FSIntIteratorImplBase<?> it = (FSIntIteratorImplBase<?>) iterators[i];
-        it.moveToFirst();
-        it.resetConcurrentModification();
-        if (it.isValid()) {
-          lastValidIndex = i;
-          return;
-        }
-      }
-      lastValidIndex = -1; // no valid index
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#moveToLast()
-     */
-    @Override
-    public void moveToLast() {
-      for (int i = iterators.length -1; i >= 0; i--) {
-        FSIntIteratorImplBase<?> it = (FSIntIteratorImplBase<?>) iterators[i];
-        it.moveToLast();
-        it.resetConcurrentModification();
-        if (it.isValid()) {
-          lastValidIndex = i;
-          return;
-        }
-      }
-      lastValidIndex = -1;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#moveToNext()
-     */
-    @Override
-    public void moveToNext() {
-      if (!isValid()) {
-        return;
-      }
-      
-      ComparableIntPointerIterator it = checkConcurrentModification(lastValidIndex);
-
-      it.inc();
-      
-      while (!it.isValid()) {
-        // loop until find valid index, or end
-        lastValidIndex ++;
-        if (lastValidIndex == iterators.length) {
-          return; // all subsequent indices are invalid
-        }
-        it = iterators[lastValidIndex];
-        it.moveToFirst();
-      }
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#moveToPrevious()
-     */
-    @Override
-    public void moveToPrevious() {
-      if (!isValid()) {
-        return;
-      }
-      
-      ComparableIntPointerIterator it = checkConcurrentModification(lastValidIndex);
-
-      it.dec();
-      
-      while (!it.isValid()) {
-        // loop until find valid index or end
-        lastValidIndex --;
-        if (lastValidIndex < 0) {
-          return; 
-        }
-        it = iterators[lastValidIndex];
-        it.moveToLast();
-      }
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#copy()
-     */
-    @Override
-    public Object copy() {
-      // If this.isValid(), return a copy pointing to the same element.
-      if (this.isValid()) {
-        return new PointerIteratorUnordered(getIicp(), get());
-      }
-      // Else, create a copy that is also not valid.
-      final PointerIteratorUnordered pi = new PointerIteratorUnordered(getIicp());
-      pi.moveToFirst();
-      pi.moveToPrevious();
-      return pi;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.uima.cas.impl.FSIndexRepositoryImpl.PointerIterator#moveTo(int)
-     * 
-     * moveTo is used internally in the contains and find methods of FSIndexes
-     *   The unordered version is only called on for bags and sets having subtypes
-     *   There, the logic needs to iterate over all the iterators, looking for an equal (for set) or eq one (for bags)
-     *   If not found, its more useful to make the iterator not-valid
-     *   
-     * Should not be called if sorted, but do something reasonable:
-     *   stop on first one found equal.  This will be the left-most
-     *   equal one in cas there are multiples of this particular type
-     *   if none found equal on one subType, go to next subType
-     *   if none found equal on any subType, mark iterator invalid 
-     *     (NOTE: not really the contract for moveTo, but 
-     *      as stated in the beginning, probably not called for unordered)
-     */
-    @Override
-    public void moveTo(int fs) {
-      moveTo(fs, false);
-    }
-    
-    void moveTo(int fs, boolean isExact) {
-      IndexIteratorCachePair<? extends FeatureStructure> iicp = getIicp();
-      int kind = iicp.fsLeafIndex.getIndexingStrategy();
-      for (int i = 0; i < iterators.length; i++) {
-        if (kind == FSIndex.SORTED_INDEX) {
-          // case: sorted index being used in unordered mode, eg. for getAllIndexedFSs
-          FSIntArrayIndex<? extends FeatureStructure> sortedIndex = 
-              (FSIntArrayIndex<? extends FeatureStructure>) ((FSIntIteratorImplBase) iterators[i]).getFSLeafIndexImpl(); 
-          if ((isExact ? sortedIndex.findEq(fs) :sortedIndex.findLeftmost(fs)) < 0) {
-            continue;  // fs not found in the index of this subtype  
-          }
-        }
-        // if sorted index, fs is in this leaf index
-        // if it is not sorted, we're in some type/subtype of the index
-        FSIntIteratorImplBase<?> li = (FSIntIteratorImplBase<?>) iterators[i];
-        li.moveTo(fs); 
-        if (li.isValid() && (0 == iicp.fsLeafIndex.compare(fs, li.get()))) {
-          lastValidIndex = i;
-          li.resetConcurrentModification();
-          return;
-        }
-        // if get here, iterate to the next subtype
-      }
-      // if get here, nothing found that was equal or eq for bag
-      // make iterator invalid
-      moveToFirst();
-      moveToPrevious();
-    }
-  }
 
   /**
-   * This class and the previous ones (PointerIterator, PointerIteratorUnordered, and LeafPointerIterator) 
-   * implement iterators for particular indexes.
+   * The index repository holds instances of defined and built-in indexes.
    * 
-   * PointerIterator and PointerIteratorUnordered handles the concepts involved with iterating over a type and
-   * all of its subtypes
+   * Indexes implement Java's NavigableSet ( *** do this later ??? may be a bit of work to make work over subtypes )
    * 
-   * This class handles just iterating over a particular type or subtype
-   * (the one that the previous class picks).
-
-   * The iterator implementation for indexes. Tricky because the iterator needs to be able to move
-   * backwards as well as forwards.
-   */
-  
-  // removed 4/2015 - was an extra wrapper, needed maintenance, and the wrapper provided no purpose.
-//  private class LeafPointerIterator implements IntPointerIterator, LowLevelIterator {
-//
-//    // The IICP
-//    final private IndexIteratorCachePair<? extends FeatureStructure> iicp;
-//
-//    // The underlying iterator
-//    final private ComparableIntPointerIterator iter;
-//
-//    
-//    @Override
-//    public String toString() {
-//      return "LeafPointerIterator [iicp=" + iicp + ", index=" + iter + "]";
-//    }
-//
-//    private LeafPointerIterator(final IndexIteratorCachePair<? extends FeatureStructure> iicp) {
-//      this.iicp = iicp;
-//      // Make sure the iterator cache exists.
-//      final ArrayList<?> iteratorCache = iicp.cachedSubFsLeafIndexes;
-//      final FSLeafIndexImpl<?> leafIndex = (FSLeafIndexImpl<?>) iteratorCache.get(0);
-//      this.iter = leafIndex.pointerIterator(leafIndex,
-//          FSIndexRepositoryImpl.this.detectIllegalIndexUpdates,
-//          ((TypeImpl) leafIndex.getType()).getCode());
-//    }
-//
-//    private LeafPointerIterator(IndexIteratorCachePair<? extends FeatureStructure> iicp, int fs) {
-//      this(iicp);
-//      moveTo(fs);
-//    }
-//
-//    private ComparableIntPointerIterator checkConcurrentModification() {
-//      if (this.iter.isConcurrentModification()) {
-//        throw new ConcurrentModificationException();
-//      }
-//      return this.iter;
-//    }
-//
-//    public boolean isValid() {
-//      return this.iter.isValid();
-//    }
-//
-//    public void moveToLast() {
-//      this.iter.resetConcurrentModification();
-//      this.iter.moveToLast();
-//    }
-//
-//    public void moveToFirst() {
-//      this.iter.resetConcurrentModification();
-//      this.iter.moveToFirst();
-//    }
-//
-//    public void moveToNext() {
-//      checkConcurrentModification().inc();
-//    }
-//
-//    public void moveToPrevious() {
-//      checkConcurrentModification().dec();
-//    }
-//
-//    public int get() throws NoSuchElementException {
-//      return ll_get();
-//    }
-//
-//    public int ll_get() {
-//      if (!isValid()) {
-//        throw new NoSuchElementException();
-//      }
-//      return checkConcurrentModification().get();
-//    }
-//
-//    public Object copy() {
-//      // If this.isValid(), return a copy pointing to the same element.
-//      if (this.isValid()) {
-//        return new LeafPointerIterator(this.iicp, this.get());
-//      }
-//      // Else, create a copy that is also not valid.
-//      final LeafPointerIterator pi = new LeafPointerIterator(this.iicp);
-//      pi.moveToFirst();
-//      pi.moveToPrevious();
-//      return pi;
-//    }
-//
-//    /**
-//     * @see org.apache.uima.internal.util.IntPointerIterator#moveTo(int)
-//     */
-//    public void moveTo(int fs) {
-//      this.iter.resetConcurrentModification();
-//      this.iter.moveTo(fs);
-//    }
-//
-//    /*
-//     * (non-Javadoc)
-//     * 
-//     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToNext()
-//     */
-//    public void inc() {
-//      checkConcurrentModification().inc();
-//    }
-//
-//    /*
-//     * (non-Javadoc)
-//     * 
-//     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToPrevious()
-//     */
-//    public void dec() {
-//      checkConcurrentModification().dec();
-//    }
-//
-//    public int ll_indexSize() {
-//      return this.iicp.size();
-//    }
-//
-//    public LowLevelIndex ll_getIndex() {
-//      return (LowLevelIndex) this.iicp.fsLeafIndex;
-//    }
-//
-//  }  // end of LeafPointerIterator
-
-  /**
-   * This implementation creates a pseudo index that is
-   * flattened and 
-   * copied (so it is a snapshot), and
-   * returns an iterator over that 
-   * 
-   */
-  private class SnapshotPointerIterator<T extends FeatureStructure> implements IntPointerIterator, LowLevelIterator {
-
-    final private FSIntArrayIndex<T> sortedLeafIndex;
-    final private int[] snapshot;
-    final private int size;   // can't get from snapshot.length - that might have extra space  https://issues.apache.org/jira/browse/UIMA-4248
-    private int pos = 0;
-      
-    @Override
-    public String toString() {
-      return "SnapshotPointerIterator[size: " + snapshot.length + ", position: " + pos + "]";
-    }
-    
-    private SnapshotPointerIterator(IndexIteratorCachePair<T> iicp0) {
-      this(iicp0, false);
-    }
-    
-    private SnapshotPointerIterator(IndexIteratorCachePair<T> iicp0, boolean isRootOnly) {
-      FSLeafIndexImpl<T> leafIndex = iicp0.fsLeafIndex;
-      FSIndexComparator comp = leafIndex.getComparator();
-      
-      final int size = iicp0.size();  // adds up all the sizes of the indexes
-      sortedLeafIndex = (FSIntArrayIndex<T>) FSIndexRepositoryImpl.this.<T>addNewIndexCore(comp, size, FSIndex.SORTED_INDEX);
-      snapshot = sortedLeafIndex.getVector().getArray();
-      this.size = size;
-      flattenCopy(iicp0, isRootOnly);
-      sortedLeafIndex.getVector().setSize(size);
-      moveToFirst();      
-    }
-
-    private SnapshotPointerIterator(IndexIteratorCachePair<T> iicp0, int fs) {
-      this(iicp0);
-      moveTo(fs);
-    }
-    
-    private void flattenCopy(IndexIteratorCachePair<T> iicp0, boolean isRootOnly) {
-    
-      
-//      if (iicp0.iteratorCache.size() > 1) {
-//        if (indexKind == FSIndex.BAG_INDEX) {
-//          // have a set of bag indexes, just copy them into the snapshot in bulk
-//        } else { 
-//          // for sorted or set, extract the elements 
-//          
-//        }
-      LowLevelIterator it = (LowLevelIterator) 
-          (isRootOnly ?
-              createLeafPointerIterator(iicp0) :
-              createPointerIterator(iicp0));
-      int i = 0;
-      while (it.isValid()) {
-        snapshot[i++] = it.ll_get();
-        it.moveToNext();
-      }
-    }
-       
-    public boolean isValid() {
-      return (0 <= pos) && (pos < size);
-    }
-    
-    public void moveToLast() {
-      pos = size - 1;
-    }
-
-    public void moveToFirst() {
-      pos = 0;
-    }
-
-    public void moveToNext() {
-      pos ++;
-    }
-
-    public void moveToPrevious() {
-      pos --;
-    }
-
-    public int get() throws NoSuchElementException {
-      return ll_get();
-    }
-
-    public int ll_get() {
-      if (!isValid()) {
-        throw new NoSuchElementException();
-      }
-      return snapshot[pos];  // no concurrent mod test
-    }
-
-    /**
-     * @see org.apache.uima.internal.util.IntPointerIterator#moveTo(int)
-     */
-    public void moveTo(int fs) {
-      moveTo(fs, false);
-    }
-    
-    void moveTo(int fs, boolean isExact) {
-      if (sortedLeafIndex.getComparator().getNumberOfKeys() == 0) {
-        // use identity, search from beginning to get "left-most"
-        int i = 0;
-        for (; i < size; i++) {
-          if (fs == snapshot[i]) {
-            break;
-          }
-        }
-        pos = i;
-      } else {
-        int position = isExact ? sortedLeafIndex.findEq(fs) : sortedLeafIndex.findLeftmost(fs);
-        if (position >= 0) {
-          pos = position;
-        } else {
-          if (isExact) {
-            throw new UIMARuntimeException(); // Internal error
-          }
-          pos = -(position + 1);
-        }
-      }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToNext()
-     */
-    public void inc() {
-      pos ++;  // no concurrent mod check
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIterator#moveToPrevious()
-     */
-    public void dec() {
-      pos --;  // no concurrent mod check
-    }
-    
-    public int ll_indexSize() {
-      return size;
-    }
-    
-    public Object copy() {
-      // If this.isValid(), return a copy pointing to the same element.
-      IndexIteratorCachePair<T> iicp = new IndexIteratorCachePair<T>(sortedLeafIndex);
-      if (this.isValid()) {
-        SnapshotPointerIterator<T> it = new SnapshotPointerIterator<T>(iicp);
-        it.moveTo(this.get(), true); // move to exact match
-        return it;
-      }
-      // Else, create a copy that is also not valid.
-      SnapshotPointerIterator<T> pi = new SnapshotPointerIterator<T>(iicp);
-      pi.pos = -1;
-      return pi;
-    }
-
-    public LowLevelIndex ll_getIndex() {
-      return (LowLevelIndex) sortedLeafIndex;
-    }
-
-  }  // end of SnapshotPointerIterator
-
-  /**
-   * Implementation of a particular index for a particular Type (and its subtypes)
-   *
-   * @param <T> - the particular type (and it subtypes) this particular index is associated with
+   * There are various kinds of iterators that can be obtained:
+   *   Iterator - plain Java iterator - goes forward only
+   *   FSIterator - an extension that can go in either direction, and can locate a position via an FS
+   * 
+   *   Low-level iterators return internal "ints" representing FS ids; these are only for backwards compatibility   
+   *   IntPointerIterator - for backwards compatibility - a wrapper around FSIterator, plus inc() dec()
+   *     - may be dropped if only internally used
+   *   LowLevelIterator - for backwards compatibility - a wrapper around FSIterator, plus ll_get, ll_indexSize, ll_getIndex
+   * 
+   * To obtain normal iterators, use the FSIndex methods 
+   *   iterator
+   *   iterator(FeatureStructure) - to initially position to the FS)
+   *   index.withSnapshotIterators() - to get snapshot versions of the indexes to iterate over   
+   *    
+   * To get the low level iterators, 
+   *   get a low-level indexrepository (CAS -> getLowLevelCAS -> get low-level index repository), and from there
+   *     get a low-level index
+   *       get a low-level iterator
    */
-  // needs default visibility
-  class IndexImpl<T extends FeatureStructure> implements FSIndex<T>, FSIndexImpl {
-
-    private final IndexIteratorCachePair<T> iicp;
-    
-    private final boolean is_with_snapshot_iterators;
-
-    private final boolean is_unordered; //Set for getAllIndexedFSs
-
-    private IndexImpl(IndexIteratorCachePair<T> iicp) {
-      this.iicp = iicp;
-      is_with_snapshot_iterators = false;
-      is_unordered = false;
-    }
-    
-    private IndexImpl(IndexIteratorCachePair<T> iicp, IteratorExtraFunction extraFn) {
-      this.iicp = iicp;
-      is_with_snapshot_iterators = (extraFn == IteratorExtraFunction.SNAPSHOT);
-      is_unordered = (extraFn == IteratorExtraFunction.UNORDERED);
-    }    
-
-    public int ll_compare(int ref1, int ref2) {
-      return this.iicp.fsLeafIndex.ll_compare(ref1, ref2);
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#getIndexingStrategy()
-     */
-    @Override
-    public int getIndexingStrategy() {
-      return this.iicp.fsLeafIndex.getIndexingStrategy();
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndexImpl#getComparator()
-     */
-    @Override
-    public FSIndexComparator getComparator() {
-      return this.iicp.fsLeafIndex.getComparator();
-    }
-    
-    // never used 3/2015
-//    protected IntComparator getIntComparator() {
-//      return this.iicp.fsLeafIndex.getIntComparator();
-//    }
-
-    // probably never called 3/15/2015
-    public void flush() {
-      this.iicp.fsLeafIndex.flush();
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#compare(FeatureStructure, FeatureStructure)
-     */
-    @Override
-    public int compare(FeatureStructure fs1, FeatureStructure fs2) {
-      return this.iicp.fsLeafIndex.compare(fs1, fs2);
-    }
-        
-    /**
-     * @see org.apache.uima.cas.FSIndex#contains(FeatureStructure)
-     */
-    @Override
-    public boolean contains(FeatureStructure fs) {
-      FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
-      IntPointerIterator it = createPointerIterator(this.iicp); 
-      it.moveTo(fsi.getAddress());
-      return it.isValid() && (0 == this.iicp.fsLeafIndex.ll_compare(fsi.getAddress(), it.get()));
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#find(FeatureStructure)
-     */
-    @Override
-    public FeatureStructure find(FeatureStructure fs) {
-      FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
-      IntPointerIterator it = createPointerIterator(this.iicp); 
-      it.moveTo(fsi.getAddress());
-      if (it.isValid()) {
-        int v = it.get();
-        return (0 == this.iicp.fsLeafIndex.ll_compare(fsi.getAddress(), v)) ? 
-            this.iicp.getCASImpl().createFS(v) :
-            null;
-      }
-      return null;
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#getType()
-     */
-    @Override
-    public Type getType() {
-      return this.iicp.fsLeafIndex.getType();
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#iterator()
-     */
-    @Override
-    public FSIterator<T> iterator() {
-      return iterator(null);
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#iterator(FeatureStructure)
-     */
-   @Override
-   public FSIterator<T> iterator(FeatureStructure fs) {
-      if (this.iicp.flatIndex != null) {
-        FSIteratorFlat<T> flatIterator = this.iicp.flatIndex.iterator(fs);
-        if (flatIterator != null) {
-          if (DEBUG) {
-            // this stuff - the flat iterator will have been created by other means, and could be ordered, 
-            // so don't force unordering
-            return new FSIteratorWrapperDoubleCheck<T>(nonFlatIterator(fs, false), flatIterator);
-          }
-          return flatIterator;
-        }
-      }
-      return nonFlatIterator(fs, true);
-    }
- 
-    private FSIterator<T> nonFlatIterator(FeatureStructure fs, boolean respectUnordered) {
-      if (null != fs) {
-        final int fsAddr = ((FeatureStructureImpl) fs).getAddress();
-        return new FSIteratorWrapper<T>(
-            is_with_snapshot_iterators ?
-                new SnapshotPointerIterator<T>(iicp, fsAddr) :
-                createPointerIterator(this.iicp, fsAddr),
-            FSIndexRepositoryImpl.this.cas);
-      } else {
-        return new FSIteratorWrapper<T>(
-            is_with_snapshot_iterators ?
-                new SnapshotPointerIterator<T>(iicp) :
-                createPointerIterator(this.iicp, respectUnordered && is_unordered),
-            FSIndexRepositoryImpl.this.cas);
-      }
-    }
-        
-    // probably never called 3/15/2015
-    public IntPointerIterator getIntIterator() {
-      return createPointerIterator(this.iicp, is_unordered);
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#size()
-     */
-    @Override
-    public int size() {
-      return this.iicp.size();
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.uima.cas.impl.LowLevelIndex#ll_iterator()
-     */
-    public LowLevelIterator ll_iterator() {
-      return (LowLevelIterator) 
-          (is_with_snapshot_iterators ?
-              new SnapshotPointerIterator<T>(iicp) :
-              createPointerIterator(this.iicp, is_unordered));
-    }
-
-    public LowLevelIterator ll_rootIterator() {
-      this.iicp.createIndexIteratorCache();
-      return (LowLevelIterator) (is_with_snapshot_iterators ?
-          new SnapshotPointerIterator<T>(iicp, true) : 
-          createLeafPointerIterator(this.iicp));
-    }
-
-    public LowLevelIterator ll_iterator(boolean ambiguous) {
-      if (ambiguous) {
-        return this.ll_iterator();
-      }
-      return new LLUnambiguousIteratorImpl(this.ll_iterator(), this.iicp.fsLeafIndex.lowLevelCAS);
-    }
-
-    /**
-     * @see org.apache.uima.cas.FSIndex#withSnapshotIterators()
-     */
-    @Override
-    public FSIndex<T> withSnapshotIterators() {
-      return new IndexImpl<T>(this.iicp, IteratorExtraFunction.SNAPSHOT);
-    }
-
-    FSIndexRepositoryImpl getFsRepositoryImpl() {
-      return iicp.getCASImpl().indexRepository;
-    }
-  }  // end of class IndexImpl
   
+  /**
+   * General FSIterator creation
+   * 
+   *   There are some alternatives
+   *     If the index has subtypes, then 
+   *       - the iterator may be ordered/unordered.  
+   *         - Ordered ones select among the subtypes as needed.
+   *         - Unordered ones return all elements from each subtype and then switch to the next subtype.
+   *           This is for efficiency.
+   *       - (currently disabled) flattened indexes may be created and used    
+   *     If the index says to use snapshots, then each call makes a snapshot of the index, and iterates over that.
+   *       - these don't throw ConcurrentModificationExceptions.
+   */  
    
   /*************************************************************
    * Information about indexes that is shared across all views *
@@ -1783,11 +170,6 @@ public class FSIndexRepositoryImpl imple
     private Comparator<AnnotationFS> annotationFsComparator = null;
     
     /**
-     * lazily created comparator using the built-in annotation index, but for ints
-     */
-    private IntComparator annotationComparator = null;
-    
-    /**
      * optimization only - bypasses some shared (among views) initialization if already done
      */
     private boolean isSetUpFromBaseCAS = false;
@@ -1797,14 +179,62 @@ public class FSIndexRepositoryImpl imple
     }
   }
   
+  /**
+   * For processing index updates in batch mode when deserializing from a remote service;
+   * lists of FSs that were added, removed, or reindexed
+   * 
+   *  only used when processing updates in batch mode
+   */
   private static class ProcessedIndexInfo {
-    final private PositiveIntSet fsAddedToIndex = new PositiveIntSet_impl(); // only used when processing updates in batch mode
-
-    final private PositiveIntSet fsDeletedFromIndex = new PositiveIntSet_impl(); // only used when processing updates in batch mode
-
-    final private PositiveIntSet fsReindexed = new PositiveIntSet_impl(); // only used when processing updates in batch mode
+    final private ObjHashSet<FeatureStructureImplC> fsAddedToIndex     = new ObjHashSet<>(FeatureStructureImplC.class);
+    final private ObjHashSet<FeatureStructureImplC> fsDeletedFromIndex = new ObjHashSet<>(FeatureStructureImplC.class); 
+    final private ObjHashSet<FeatureStructureImplC> fsReindexed        = new ObjHashSet<>(FeatureStructureImplC.class);
   }
   
+  /**
+   * Information about all the indexes for a single type.  This is kept in an 
+   * List, with the key being the type code.
+   */
+  static class IndexesForType {
+    /**
+     * true if one or more of the indexes is a set index
+     */
+    boolean hasSetIndex; 
+    /**
+     * index of any sorted index or -1 if no sorted index
+     */
+    int aSortedIndex = -1;   // -1 or the position of an arbitrary sorted index
+    int aBagIndex = -1;      // -1 or the position of an arbitrary bag index
+    ArrayList<FsIndex_iicp<FeatureStructure>> indexesForType = new ArrayList<>(1); 
+    
+    FsIndex_iicp<FeatureStructure> getNonSetIndex() {
+      if (aSortedIndex < 0 && aBagIndex < 0) { // index is empty!
+        return null;
+      }
+      return indexesForType.get((aBagIndex >= 0) ? aBagIndex : aSortedIndex);
+    }
+    
+    void add(FsIndex_iicp<FeatureStructure> iicp) {
+      final int kind = iicp.fsIndex_singletype.getIndexingStrategy();
+      int i = indexesForType.size();
+      switch (kind) {
+      case FSIndex.BAG_INDEX:
+        aBagIndex = i;
+        break;
+      case FSIndex.DEFAULT_BAG_INDEX:
+        if (aBagIndex == -1) {  // real bag indexes have priority
+          aBagIndex = i;
+        }
+        break;
+      case FSIndex.SORTED_INDEX:
+        aSortedIndex = i;
+        break;
+      }
+      indexesForType.add(iicp);
+    }
+    
+    
+  }
   /*****  I N S T A N C E   V A R I A B L E S  *****/
   /*****           Replicated per view         *****/                 
 
@@ -1815,15 +245,17 @@ public class FSIndexRepositoryImpl imple
   private boolean locked = false;
 
   /** 
-   * An array of ArrayLists, one for each type in the type hierarchy. 
-   * The ArrayLists are unordered lists of IndexIteratorCachePairs for 
-   * that type, corresponding to the different index definitions over that type.
-   * This list includes iicps for subtypes of defined and default indexes over some type
+   * An array of information about defined indexes, one for each type in the type hierarchy. 
+   *   - includes for each type, an unordered list of FsIndex_iicps for 
+   *     that type, corresponding to the different index definitions over that type.
+   * 
+   * The key is the typecode of the type.
    */
-  final private ArrayList<IndexIteratorCachePair<? extends FeatureStructure>>[] indexArray;
   
-  <T extends FeatureStructure> ArrayList<IndexIteratorCachePair<T>> getIndexesForType(int typeCode) {
-    return (ArrayList<IndexIteratorCachePair<T>>) (Object) indexArray[typeCode];
+  final IndexesForType[] indexArray;
+  
+  IndexesForType getIndexesForType(int typeCode) {
+    return  indexArray[typeCode];
   }
 
   /** 
@@ -1835,15 +267,21 @@ public class FSIndexRepositoryImpl imple
   final int[] detectIllegalIndexUpdates;
   
   /**
-   * A map from names to IndexIteratorCachePairs, which represent the index at the
+   * A map from names to FsIndex_iicps, which represent the index at the
    * top-most type declared in the index specification.    
    * Different names may map to the same iicp.
    * The keys are the same across all views, but the values are different, per view
    */
-  final private HashMap<String, IndexIteratorCachePair<? extends FeatureStructure>> name2indexMap;
-  
+  final HashMap<String, FsIndex_iicp<FeatureStructure>> name2indexMap;
+ 
+  /**
+   * speedup for annotation index accessing by type, lazily initialized
+   */
+  final private Map<TypeImpl, FsIndex_annotation<Annotation>> annotationIndexes = 
+      new IdentityHashMap<TypeImpl, FsIndex_annotation<Annotation>>();
+
   // the next are for journaling updates to indexes
-  final private IntVector indexUpdates;
+  final private List<FeatureStructure> indexUpdates;
 
   final private BitSet indexUpdateOperation;
 
@@ -1858,8 +296,8 @@ public class FSIndexRepositoryImpl imple
   final private boolean[] isUsed;
   
   // Monitor which indexes are iterated over, to allow resetting flatIndexes
-  final private List<IndexIteratorCachePair<? extends FeatureStructure>> iteratedSortedIndexes = 
-      Collections.synchronizedList(new ArrayList<IndexIteratorCachePair<? extends FeatureStructure>>());
+  final private List<FsIndex_iicp<? extends FeatureStructure>> iteratedSortedIndexes = 
+      Collections.synchronizedList(new ArrayList<FsIndex_iicp<? extends FeatureStructure>>());
   
   private final SharedIndexInfo sii;
 
@@ -1931,18 +369,18 @@ public class FSIndexRepositoryImpl imple
     final int numTypes = ts.getNumberOfTypes() + 1;
     this.detectIllegalIndexUpdates = new int[numTypes];
 //    this.flattenedIndexValid = new ConcurrentBits(numTypes);
-    this.name2indexMap = new HashMap<String, IndexIteratorCachePair<? extends FeatureStructure>>();
-    this.indexUpdates = new IntVector();
+    this.name2indexMap = new HashMap<String, FsIndex_iicp<FeatureStructure>>();
+    this.indexUpdates = new ArrayList<>();
     this.indexUpdateOperation = new BitSet();
     this.logProcessed = false;
-    this.indexArray = new ArrayList[this.sii.tsi.getNumberOfTypes() + 1];
+    this.indexArray = new IndexesForType[this.sii.tsi.getNumberOfTypes() + 1];
     this.usedIndexes = new IntVector();
     this.isUsed = new boolean[numTypes];
     init();
   }
 
   /**
-   * Constructor for views.
+   * Constructor for additional views.
    * 
    * @param cas
    * @param baseIndexRepository
@@ -1959,50 +397,119 @@ public class FSIndexRepositoryImpl imple
     this.detectIllegalIndexUpdates = new int[numTypes];
 //    this.flattenedIndexValid = new ConcurrentBits(numTypes);
     
-    this.name2indexMap = new HashMap<String, IndexIteratorCachePair<? extends FeatureStructure>>();
-    this.indexUpdates = new IntVector();
+    this.name2indexMap = new HashMap<String, FsIndex_iicp<FeatureStructure>>();
+    this.indexUpdates = new ArrayList<>();
     this.indexUpdateOperation = new BitSet();
     this.logProcessed = false;
-    this.indexArray = new ArrayList[numTypes];
+    this.indexArray = new IndexesForType[numTypes];
     this.usedIndexes = new IntVector();
     this.isUsed = new boolean[numTypes];
 
     init();
-    final Set<String> keys = baseIndexRepo.name2indexMap.keySet();
-    if (!keys.isEmpty()) {
-      final Iterator<String> keysIter = keys.iterator();
-      while (keysIter.hasNext()) {
-        final String key = keysIter.next();
-        final IndexIteratorCachePair<? extends FeatureStructure> iicp = baseIndexRepo.name2indexMap.get(key);
-        createIndexNoQuestionsAsked(iicp.fsLeafIndex.getComparator(), key,
-            
-            iicp.fsLeafIndex.getIndexingStrategy());
-      }
-    }
+    // cant do this here because need to have the CAS's ref to this instance set before this is done.
+//    baseIndexRepo.name2indexMap.keySet().stream().forEach(key -> createIndex(baseIndexRepo, key));
   }
 
   /**
-   * Initialize data. Called from the constructor.
+   * Initialize data. Common initialization called from the constructors.
    */
   private void init() {
     final TypeSystemImpl ts = this.sii.tsi;
-    // Type counting starts at 1.
-    final int numTypes = ts.getNumberOfTypes() + 1;
-    // Can't instantiate arrays of generic types.
+    
+    /* **********************************************
+     * for each type in the TypeSystem, 
+     *   create a list of iicp's 
+     *     each one corresponding to a defined index
+     * **********************************************/
+    final int numTypes = ts.getNumberOfTypes() + 1; // Type counting starts at 1.
+    // Can't instantiate arrays of generic types, but this is ok for ArrayList.
     for (int i = 1; i < numTypes; i++) {
-      this.indexArray[i] = new ArrayList<IndexIteratorCachePair<? extends FeatureStructure>>();
+      this.indexArray[i] = new IndexesForType();
     }
-    resetDetectIllegalIndexUpdates();
+    
+    Arrays.fill(detectIllegalIndexUpdates, Integer.MIN_VALUE);
     mPii = new ProcessedIndexInfo();
-//    this.fsAddedToIndex = new PositiveIntSet_impl();
-//    this.fsDeletedFromIndex = new PositiveIntSet_impl();
-//    this.fsReindexed = new PositiveIntSet_impl();
   }
-  
-  private void resetDetectIllegalIndexUpdates() {
-    for (int i = 0; i < detectIllegalIndexUpdates.length; i++) {
-      detectIllegalIndexUpdates[i] = Integer.MIN_VALUE;
+
+  /* ***************
+   * Create indexes 
+   * ***************/
+   
+  <T extends FeatureStructure> 
+      void createIndex(FSIndexRepositoryImpl baseIndexRepo, String key) {
+    final FsIndex_singletype<FeatureStructure> fsIndex = baseIndexRepo.name2indexMap.get(key).fsIndex_singletype;
+    createIndexNoQuestionsAsked(fsIndex.getComparatorForIndexSpecs(), key, fsIndex.getIndexingStrategy());
+  }
+
+  /**
+   * @see org.apache.uima.cas.admin.FSIndexRepositoryMgr#createIndex(FSIndexComparator, String)
+   */
+  @Override
+  public boolean createIndex(FSIndexComparator comp, String label, int indexType) throws CASAdminException {
+    if (this.locked) {
+      throw new CASAdminException(CASAdminException.REPOSITORY_LOCKED);
+    }
+    return createIndexNoQuestionsAsked(comp, label, indexType);
+  }
+
+  /**
+   * This is public only until the xml specifier format supports specifying index kinds (set, bag
+   * etc.).
+   * 
+   * @param comp -
+   * @param label -
+   * @param indexType -
+   * @return -
+   */
+  public <T extends FeatureStructure> 
+      boolean createIndexNoQuestionsAsked(final FSIndexComparator comp, String label, int indexType) {
+    
+    FsIndex_iicp<FeatureStructure> cp = this.name2indexMap.get(label);
+   
+
+    if (cp == null) {
+      // Create new index
+      cp = this.addNewIndexRecursive(comp, indexType);
+      
+      // create a set of feature codes that are in one or more index definitions,
+      // only once for all cas views
+      if (!sii.isSetUpFromBaseCAS) {        
+        for (int i = 0, nKeys = comp.getNumberOfKeys(); i < nKeys; i++) {
+          if (comp.getKeyType(i) == FSIndexComparator.FEATURE_KEY) {
+            cas.featureCodesInIndexKeysAdd(comp.getKeyFeature(i).getCode());
+          }
+        }
+      }
+      
+      this.name2indexMap.put(label, cp);
+      return true;
     }
+    
+    // For now, just return false if the label already exists.
+    return false;
+    // // An index has previously been registered for this name. We need to
+    // // compare the types to see if the new addition is compatible with the
+    // // pre-existing one. There are three cases: the new type can be a sub-type
+    // // of the old one, in which case we don't need to do anything; or, the
+    // // new type is a super-type of the old one, in which case we add the new
+    // // index while keeping the old one; or, there is no subsumption relation,
+    // // in which case we can't add the index.
+    // Type oldType = cp.index.getType(); // Get old type from the index.
+    // Type newType = comp.getType(); // Get new type from comparator.
+    // if (this.sii.typeSystem.subsumes(oldType, newType)) {
+    // // We don't need to do anything.
+    // return true;
+    // } else if (this.sii.typeSystem.subsumes(newType, oldType)) {
+    // // Add the index, subsuming the old one.
+    // cp = this.addIndexRecursive(comp);
+    // // Replace the old index with the new one in the map.
+    // this.name2indexMap.put(label, cp);
+    // return true;
+    // } else {
+    // // Can't add index under that name.
+    // return false;
+    // }
+    // }
   }
 
   /**
@@ -2020,16 +527,13 @@ public class FSIndexRepositoryImpl imple
     if (this.usedIndexes.size() == 0) {
       return;
     }
-
-    for (int i = 0; i < this.usedIndexes.size(); i++) {
-      this.isUsed[this.usedIndexes.get(i)] = false;
-      ArrayList<IndexIteratorCachePair<? extends FeatureStructure>> v = 
-          this.indexArray[this.usedIndexes.get(i)];
-      int max = v.size();
-      for (int j = 0; j < max; j++) {
-        IndexIteratorCachePair<? extends FeatureStructure> iicp = v.get(j);
-        iicp.fsLeafIndex.flush();
-      }
+    
+    annotationIndexes.clear();
+    
+    for (int i = 0; i < usedIndexes.size(); i++) {
+      int used = this.usedIndexes.get(i);
+      isUsed[used] = false;
+      indexArray[used].indexesForType.stream().forEach(iicp -> iicp.fsIndex_singletype.flush());
     }
 
     clearIteratedSortedIndexes();
@@ -2037,7 +541,7 @@ public class FSIndexRepositoryImpl imple
     // reset the index update trackers
 //    resetDetectIllegalIndexUpdates();
     
-    this.indexUpdates.removeAllElements();
+    this.indexUpdates.clear();
     this.indexUpdateOperation.clear();
     mPii = new ProcessedIndexInfo();
 //    this.fsAddedToIndex = new IntSet();
@@ -2047,212 +551,195 @@ public class FSIndexRepositoryImpl imple
     this.usedIndexes.removeAllElements();
   }
   
+  // for now, with flattened index optimization disabled, this should be a no-op
   private void clearIteratedSortedIndexes() {
     int sz = iteratedSortedIndexes.size();
     if (DEBUG) {
       System.out.println("Index Flush flatIndex, size = " + sz);
     }
+    
+//    iteratedSortedIndexes.stream().forEach(iicp -> iicp.flatIndex.flush());
 
-    for (IndexIteratorCachePair<? extends FeatureStructure> iicp : iteratedSortedIndexes) {
-      iicp.flatIndex.flush();
-    }
-    if (iteratedSortedIndexes.size() != sz) {
-      throw new RuntimeException(
-          "Index Flush flatIndex, size not the same, before = " + 
-          sz + ", after = " + iteratedSortedIndexes.size());
+    if (DEBUG) {
+      if (iteratedSortedIndexes.size() != sz) {
+        throw new RuntimeException(
+            "Index Flush flatIndex, size not the same, before = " + 
+            sz + ", after = " + iteratedSortedIndexes.size());
+      }
     }
     iteratedSortedIndexes.clear();
   }
 
-  public void addFS(int fsRef) {
-    ll_addFS(fsRef);
-  }
-
-  private IndexIteratorCachePair<? extends FeatureStructure> addNewIndex(FSIndexComparator comparator, int indexType) {
+  /* *****************************************
+   * Adding indexes to the index repository
+   *******************************************/
+  
+  private FsIndex_iicp<FeatureStructure> addNewIndex(FSIndexComparator comparator, int indexType) {
     return addNewIndex(comparator, DEFAULT_INDEX_SIZE, indexType);
   }
 
   /**
    * This is where the actual index gets created.
    */
-  private <T extends FeatureStructure> IndexIteratorCachePair<T> addNewIndex(final FSIndexComparator comparator, int initialSize,
-      int indexType) {
-    
-    FSLeafIndexImpl<T> fsLeafIndex = addNewIndexCore(comparator, initialSize, indexType);
-    IndexIteratorCachePair<T> iicp = new IndexIteratorCachePair<T>(fsLeafIndex); 
-//    iicp.fsLeafIndex =  addNewIndexCore(comparator, initialSize, indexType);
-    final Type type = comparator.getType();
-    final int typeCode = ((TypeImpl) type).getCode();
-    // add indexes so that sorted ones are first, to benefit getAllIndexedFSs
-    if (indexType == FSIndex.SORTED_INDEX) {
-      this.indexArray[typeCode].add(0, iicp);
+  private <T extends FeatureStructure> FsIndex_iicp<T> addNewIndex(final FSIndexComparator comparator, int initialSize, int indexType) {
+    FsIndex_iicp<T> iicp = null;
+    if (isAnnotationIndex(comparator, indexType)) {
+      FsIndex_singletype<Annotation> index = addNewIndexCore(comparator, initialSize, indexType);
+      iicp = (FsIndex_iicp<T>) new FsIndex_annotation<Annotation>(index); 
     } else {
-      this.indexArray[typeCode].add(iicp);
+      FsIndex_singletype<FeatureStructure> index = addNewIndexCore(comparator, initialSize, indexType);
+      iicp = (FsIndex_iicp<T>) new FsIndex_iicp<FeatureStructure>(index); 
     }
+    final Type type = comparator.getType();
+    final int typeCode = ((TypeImpl) type).getCode();
+
+//    add indexes so that sorted ones are first, to benefit getAllIndexedFSs
+//    if (indexType == FSIndex.SORTED_INDEX) {
+//      this.indexArray[typeCode].add(0, iicp);  // shifts rest down
+//    } else 
+    this.indexArray[typeCode].add((FsIndex_iicp<FeatureStructure>) iicp);
+//    }
     return iicp;
   }
   
-  private <T extends FeatureStructure> FSLeafIndexImpl<T> addNewIndexCore(
-      final FSIndexComparator comparator, 
+  private boolean isAnnotationIndex(FSIndexComparator c, int indexKind) {
+    TypeSystemImpl tsi = getTypeSystemImpl();
+    return indexKind == FSIndex.SORTED_INDEX &&
+           getTypeSystemImpl().annotType.subsumes((TypeImpl) c.getType()) &&
+           c.getNumberOfKeys() == 3 &&
+           
+           c.getKeyType(0) == FSIndexComparator.FEATURE_KEY &&
+           c.getKeyComparator(0) == FSIndexComparator.STANDARD_COMPARE &&
+           c.getKeyFeature(0) == tsi.startFeat &&
+           
+           c.getKeyType(1) == FSIndexComparator.FEATURE_KEY &&
+           c.getKeyComparator(1) == FSIndexComparator.REVERSE_STANDARD_COMPARE &&
+           c.getKeyFeature(1) == tsi.endFeat &&
+           
+           c.getKeyType(2) == FSIndexComparator.TYPE_ORDER_KEY;           
+  }
+  
+  /**
+   * @param comparatorForIndexSpecs -
+   * @param initialSize -
+   * @param indexType -
+   * @return -
+   */
+  <T extends FeatureStructure> FsIndex_singletype<T> addNewIndexCore(
+      final FSIndexComparator comparatorForIndexSpecs, 
       int initialSize,
       int indexType) {
-    final Type type = comparator.getType();
+    final Type type = comparatorForIndexSpecs.getType();
     // final int vecLen = indexVector.size();
-    FSLeafIndexImpl<T> ind;
+    FsIndex_singletype<T> ind;
     switch (indexType) {
-    case FSIndex.SET_INDEX: {
-      ind = new FSRBTSetIndex<T>(this.cas, type, indexType);
+    
+    case FSIndex.SET_INDEX: 
+      ind = new FsIndex_set_sorted<T>(this.cas, type, indexType, false); // false = is set
       break;
-    }
+    
+//    case FSIndex.FLAT_INDEX: 
+//      // this index is only created from another existing index
+//      throw new UIMARuntimeException(UIMARuntimeException.INTERNAL_ERROR);
+    
     case FSIndex.BAG_INDEX:
-    case FSIndex.DEFAULT_BAG_INDEX: {
-      ind = new FSBagIndex<T>(this.cas, type, initialSize, indexType);
+    case FSIndex.DEFAULT_BAG_INDEX: 
+      ind = new FsIndex_bag<T>(this.cas, type, initialSize, indexType);
       break;
-    }
-    default: {
-      // SORTED_INDEX is the default. We don't throw any errors, if the
-      // code is unknown, we just create a sorted index (with duplicates).
-      // ind = new FSRBTIndex(this.cas, type, FSIndex.SORTED_INDEX);
-       
-      ind = new FSIntArrayIndex<T>(this.cas, type, initialSize, FSIndex.SORTED_INDEX, isAnnotationIndex(type, comparator));
+    
+    default: 
+      // SORTED_INDEX is the default. We don't throw any errors, if the code is unknown, we just create a sorted index.
+      ind = new FsIndex_set_sorted<T>(this.cas, type, FSIndex.SORTED_INDEX, true); // true = is sorted
       break;
+ 
     }
-    }
-    // ind = new FSRBTIndex(this.cas, type);
-    // ind = new FSVectorIndex(this.cas, initialSize);
-    ind.init(comparator);
+    ind.init(comparatorForIndexSpecs);
     return ind;
   }
   
-  private boolean isAnnotationIndex(Type type, FSIndexComparator comp) {
-    TypeSystemImpl tsi = cas.getTypeSystemImpl();
+  private boolean isAnnotationIndex(Type type, FSIndexComparator compForIndexSpecs) {
+    TypeSystemImpl tsi = this.sii.tsi;
     return 
         (type == tsi.annotType) &&
-        (comp.getNumberOfKeys() == 3) &&
-        (comp.getKeyType(0) == FSIndexComparator.FEATURE_KEY) &&
-        (comp.getKeyType(1) == FSIndexComparator.FEATURE_KEY) &&
-        (comp.getKeyType(2) == FSIndexComparator.TYPE_ORDER_KEY) &&
-        (comp.getKeyComparator(0) == FSIndexComparator.STANDARD_COMPARE) &&
-        (comp.getKeyComparator(1) == FSIndexComparator.REVERSE_STANDARD_COMPARE) &&       
-        (comp.getKeyComparator(2) == FSIndexComparator.STANDARD_COMPARE) &&
-        (comp.getKeyFeature(0) == tsi.startFeat) &&
-        (comp.getKeyFeature(1) == tsi.endFeat); 
+        (compForIndexSpecs.getNumberOfKeys() == 3) &&
+        (compForIndexSpecs.getKeyType(0) == FSIndexComparator.FEATURE_KEY) &&
+        (compForIndexSpecs.getKeyType(1) == FSIndexComparator.FEATURE_KEY) &&
+        (compForIndexSpecs.getKeyType(2) == FSIndexComparator.TYPE_ORDER_KEY) &&
+        (compForIndexSpecs.getKeyComparator(0) == FSIndexComparator.STANDARD_COMPARE) &&
+        (compForIndexSpecs.getKeyComparator(1) == FSIndexComparator.REVERSE_STANDARD_COMPARE) &&       
+        (compForIndexSpecs.getKeyComparator(2) == FSIndexComparator.STANDARD_COMPARE) &&
+        (compForIndexSpecs.getKeyFeature(0) == tsi.startFeat) &&
+        (compForIndexSpecs.getKeyFeature(1) == tsi.endFeat); 
   }
-
-  /*
-   * private IndexIteratorCachePair addIndex( FSIndexComparator comparator, int initialSize) { final
-   * Type type = comparator.getType(); final int typeCode = ((TypeImpl) type).getCode(); final
-   * Vector indexVector = this.indexArray[typeCode]; final int vecLen = indexVector.size();
-   * FSLeafIndexImpl ind;
-   * 
-   * for (int i = 0; i < vecLen; i++) { ind = ((IndexIteratorCachePair) indexVector.get(i)).index;
-   * if (comparator.equals(ind.getComparator())) { return null; } }
-   * 
-   * ind = new FSRBTIndex(this.cas, type); // ind = new FSVectorIndex(this.cas, initialSize);
-   * ind.init(comparator); IndexIteratorCachePair iicp = new IndexIteratorCachePair(); iicp.index =
-   * ind; indexVector.add(iicp); return iicp; }
-   */
-  // private IndexIteratorCachePair addIndexRecursive(FSIndexComparator
-  // comparator) {
-  // final FSIndexComparatorImpl compCopy =
-  // ((FSIndexComparatorImpl) comparator).copy();
-  // return addIndexRec(compCopy);
-  // }
-  
+ 
   /**
    * Top level call to add the indexes for a particular index definition
-   * @param comparator
+   * @param compForIndexSpecs
    * @param indexType
    * @return the iicp for the top new index
    */
-  private IndexIteratorCachePair<? extends FeatureStructure> addNewIndexRecursive(FSIndexComparator comparator, int indexType) {
-    final FSIndexComparatorImpl compCopy = ((FSIndexComparatorImpl) comparator).copy();
+  private FsIndex_iicp<FeatureStructure> addNewIndexRecursive(FSIndexComparator compForIndexSpecs, int indexType) {
+    final FSIndexComparatorImpl compCopy = ((FSIndexComparatorImpl)compForIndexSpecs).copy();
     return addNewIndexRec(compCopy, indexType);
   }
 
-  /**
-   * Finds an index among iicp's for all defined indexes of a type, such that
-   *   the type of the index (SET, BAG, SORTED) is the same and 
-   *   the comparator (the keys) are the same
-   * @param indexes
-   * @param comp
-   * @param indexType
-   * @return the index in the set of iicps for this type for the matching index
-   */
-  private static final <T extends FeatureStructure> int findIndex(ArrayList<IndexIteratorCachePair<T>> indexes,
-      FSIndexComparator comp,
-      int indexType) {
-    FSIndexComparator indexComp;
-    final int max = indexes.size();
-    for (int i = 0; i < max; i++) {
-      FSLeafIndexImpl<? extends FeatureStructure> index = indexes.get(i).fsLeafIndex;
-      if (index.getIndexingStrategy() != indexType) {
-        continue;
-      }
-      indexComp = index.getComparator();
-      if (comp.equals(indexComp)) {
-        return i;
-      }
-    }
-    return -1;
-  }
 
-  /*

[... 1465 lines stripped ...]