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 15:56:18 UTC

svn commit: r1711793 - /uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/

Author: schor
Date: Sun Nov  1 14:56:18 2015
New Revision: 1711793

URL: http://svn.apache.org/viewvc?rev=1711793&view=rev
Log:
[UIMA-4664]Rename and update and reorganize index classes

Added:
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_annotation.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java
      - copied, changed from r1693269, uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_flat.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_iicp.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_singletype.java
      - copied, changed from r1693269, uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSLeafIndexImpl.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_snapshot.java
Removed:
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexFlat.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexImpl.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIntArrayIndex.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSLeafIndexImpl.java
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSRBTSetIndex.java

Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_annotation.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_annotation.java?rev=1711793&view=auto
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_annotation.java (added)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_annotation.java Sun Nov  1 14:56:18 2015
@@ -0,0 +1,157 @@
+/*
+ * 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 org.apache.uima.cas.FSIndex;
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.cas.text.AnnotationIndex;
+import org.apache.uima.cas.text.AnnotationTree;
+
+/**
+ * Implementation of annotation indexes.
+ * Implements AnnotationIndex
+ * replaces AnnotationIndexImpl in v2
+ */
+public class FsIndex_annotation <T extends AnnotationFS> 
+                 extends FsIndex_iicp<T> 
+                 implements AnnotationIndex<T> {
+  
+  public FsIndex_annotation(FsIndex_singletype<T> fsIndex_singletype) {
+    super(fsIndex_singletype);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.cas.text.AnnotationIndex#iterator(boolean)
+   */
+  @Override
+  public FSIterator<T> iterator(boolean ambiguous) {
+    if (ambiguous) {
+      return iterator();
+    }
+    // return non-constrained, non-strict, unambiguous iterator
+    boolean strict = true;
+    boolean isBounded = false;
+    return (FSIterator<T>) new Subiterator<T>(iterator(), 
+                              null, 
+                              0, 
+                              0, 
+                              ambiguous, 
+                              strict, 
+                              isBounded, 
+                              this.getFsRepositoryImpl());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.cas.text.AnnotationIndex#subiterator(org.apache.uima.cas.text.AnnotationFS)
+   */
+  @Override
+  public FSIterator<T> subiterator(AnnotationFS annot) {
+    return subiterator(annot, true, true);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.cas.text.AnnotationIndex#subiterator(org.apache.uima.cas.text.AnnotationFS,
+   *      boolean, boolean)
+   */
+  @Override
+  public FSIterator<T> subiterator(AnnotationFS annot, boolean ambiguous, boolean strict) {
+    boolean isBounded = true;
+    return (FSIterator<T>) new Subiterator<T>(iterator(), 
+        annot,
+        0, 
+        0, 
+        ambiguous, 
+        strict, 
+        isBounded, 
+        this.getFsRepositoryImpl());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.cas.text.AnnotationIndex#tree(org.apache.uima.cas.text.AnnotationFS)
+   */
+  @Override
+  public AnnotationTree<T> tree(T annot) {
+    AnnotationTreeImpl<T> tree = new AnnotationTreeImpl<T>();
+    AnnotationTreeNodeImpl<T> root = new AnnotationTreeNodeImpl<T>();
+    tree.setRoot(root);
+    root.set(annot);
+    addChildren(root, subiterator(annot, false, true));
+    return tree;
+  }
+
+  private void addChildren(AnnotationTreeNodeImpl<T> node, FSIterator<T> it) {
+    AnnotationTreeNodeImpl<T> dtr;
+    T annot;
+    while (it.isValid()) {
+      annot = it.get();
+      it.moveToNext();
+      dtr = new AnnotationTreeNodeImpl<T>();
+      dtr.set(annot);
+      node.addChild(dtr);
+      addChildren(dtr, subiterator(annot, false, true));
+    }
+  }
+
+//  /* ***********************************
+//   *  Support for withSnapshotIterators
+//   *  using proxy
+//   * ***********************************/
+//  private final static Class<?>[] proxyInterface = new Class<?>[] {FsIndex_annotation.class};
+//  
+//  private class ProxySnapshotHandler implements InvocationHandler {
+//    @Override
+//    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+//      if ("iterator".equals(method.getName())) {
+//        if (args == null || args.length == 0) {
+//          if (fsIndex_singletype.getIndexingStrategy() == FSIndex.SORTED_INDEX) {
+//            return iterator(IteratorExtraFunction.SNAPSHOT);
+//          }
+//          return iterator(IteratorExtraFunction.UNORDERED_SNAPSHOT);
+//        }
+//        // iterator call with an arg boolean ambiguous
+//        // TODO ambiguous/unambig with snapshot
+//      }
+//      
+//      // pass thru all other methods
+//      return method.invoke(args);
+//    }    
+//  }
+
+  @Override
+  public FSIndex<T> withSnapshotIterators() {
+    return new FsIndex_snapshot(this);
+  }
+//  public FSIndex<T> withSnapshotIterators() {
+//    return (FSIndex<T>) Proxy.newProxyInstance(
+//        FSIndex.class.getClassLoader(),  // class loader 
+//        proxyInterface,  
+//        new ProxySnapshotHandler());
+//  }
+  
+}

Copied: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java (from r1693269, uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java)
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java?p2=uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java&p1=uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java&r1=1693269&r2=1711793&rev=1711793&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSBagIndex.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java Sun Nov  1 14:56:18 2015
@@ -19,49 +19,44 @@
 
 package org.apache.uima.cas.impl;
 
+import java.util.List;
+
+import org.apache.uima.cas.FSIterator;
 import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.admin.FSIndexComparator;
-import org.apache.uima.internal.util.ComparableIntPointerIterator;
-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;
 
 /**
  * Used for UIMA FS Bag Indexes
- * Uses IntVector or PositiveIntSet to hold values of FSs
+ * Uses ObjHashSet to hold instances of FeatureStructures
  * @param <T> the Java cover class type for this index, passed along to (wrapped) iterators producing Java cover classes
+ * NOTE: V3 doesn't support ALLOW_DUP_ADD_TO_INDEXES
  */
-public class FSBagIndex<T extends FeatureStructure> extends FSLeafIndexImpl<T> {
+public class FsIndex_bag<T extends FeatureStructure> extends FsIndex_singletype<T> {
   
-  // package private
-  final static boolean USE_POSITIVE_INT_SET = !FSIndexRepositoryImpl.IS_ALLOW_DUP_ADD_2_INDEXES;
+//  // package private
+//  final static boolean USE_POSITIVE_INT_SET = !FSIndexRepositoryImpl.IS_ALLOW_DUP_ADD_2_INDEXES;
 
-  // The index, a vector of FS references.
-  final private IntVector index;
+  // The index
+  final private ObjHashSet<FeatureStructureImplC> index;
   
-  final private PositiveIntSet indexP = USE_POSITIVE_INT_SET ? new PositiveIntSet_impl() : null;
-
-  private int initialSize;
-
-  FSBagIndex(CASImpl cas, Type type, int initialSize, int indexType) {
+  FsIndex_bag(CASImpl cas, Type type, int initialSize, int indexType) {
     super(cas, type, indexType);
-    this.initialSize = initialSize;
-    this.index = USE_POSITIVE_INT_SET ? null : new IntVector(initialSize);
+    this.index = new ObjHashSet<FeatureStructureImplC>(initialSize, FeatureStructureImplC.class);
   }
 
   /**
+   * Substitutes an empty comparator if one is specified - may not be needed
    * @see org.apache.uima.cas.impl.FSLeafIndexImpl#init(org.apache.uima.cas.admin.FSIndexComparator)
    */
   boolean init(FSIndexComparator comp) {
     // The comparator for a bag index must be empty, except for the type. If
-    // it
-    // isn't, we create an empty one.
+    // it isn't, we create an empty one.
     FSIndexComparator newComp;
     if (comp.getNumberOfKeys() > 0) {
-      newComp = new FSIndexComparatorImpl(this.lowLevelCAS);
+      newComp = new FSIndexComparatorImpl(casImpl);
       newComp.setType(comp.getType());
     } else {
       newComp = comp;
@@ -70,68 +65,25 @@ public class FSBagIndex<T extends Featur
   }
 
   public void flush() {
-    // done this way to reset to initial size if it grows
-    if (USE_POSITIVE_INT_SET) {
-      indexP.clear();      
-    } else {
-      if (this.index.size() > this.initialSize) {
-        this.index.resetSize(this.initialSize);
-//        this.index = new IntVector(this.initialSize);
-      } else {
-        this.index.removeAllElements();
-      }
-    }
+    index.clear();
   }
 
-  public final boolean insert(int fs) {
-    if (USE_POSITIVE_INT_SET) {
-      return indexP.add(fs);
-    } else {
-      index.add(fs);
-      return true;  // supposed to return true if added, but can't tell, return value ignored anyways
-    }
-  }
-
-  /**
-   * 
-   * @param ele the element to find
-   * @return the position of the element, or if not found, -1
-   */
-  private int find(int ele) {
-    if (USE_POSITIVE_INT_SET) {
-      return indexP.find(ele);
-    } else {
-      return this.index.indexOfOptimizeAscending(ele);
-    }
+  @Override
+  public final boolean insert(T fs) {
+    return index.add((FeatureStructureImplC) fs);
   }
 
-  /**
-   * Left most in case there are multiple instances of the same item
-   * This only works if not use Positive Int Set
-   * because that's the only time there are multiple instances of the same
-   * (meaning having the same heap address) item
-   * @param ele the featuresturcture to match
-   * @return -1 if the item is not found, or a position value that can be used with iterators to start at that item.
-   */
-  int findLeftmost(int ele) {
-    if (USE_POSITIVE_INT_SET) {
-      return indexP.find(ele);
-    } else {
-      return this.index.indexOf(ele);
-    }
+  @SuppressWarnings("unchecked")
+  public final boolean insert(int fs) {
+    return insert((T) casImpl.getFsFromId(fs)); 
   }
-  
+    
   /**
+   * Override the super impl which uses comparators.
    * For bag indexes, compare equal only if identical addresses
    */
-  public int compare(int fs1, int fs2) {
-    if (fs1 < fs2) {
-      return -1;
-    } else if (fs1 > fs2) {
-      return 1;
-    } else {
-      return 0;
-    }
+  public int compare(FeatureStructure fs1, FeatureStructure fs2) {
+    return (fs1 == fs2) ? 0 : (fs1.get_id() < fs2.get_id()) ? -1 : 1;
   }
 
   /*
@@ -163,35 +115,9 @@ public class FSBagIndex<T extends Featur
    * }
    */
 
-  public ComparableIntPointerIterator<T> pointerIterator(IntComparator comp,
-          int[] detectIllegalIndexUpdates, int typeCode) {
-    return new IntIterator4bag<T>(this, detectIllegalIndexUpdates);
-  }
-
-  /**
-   * @see org.apache.uima.cas.impl.FSLeafIndexImpl#refIterator()
-   */
-  protected IntPointerIterator refIterator() {
-    return new IntIterator4bag<T>(this, null);  // no concurrent mod checking, internal use
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.cas.impl.LowLevelIndex#ll_iterator()
-   */
-  public LowLevelIterator ll_iterator() {
-    return new IntIterator4bag<T>(this, null); // no concurrent mod checking
-  }
-
-  /**
-   * @see org.apache.uima.cas.impl.FSLeafIndexImpl#refIterator(int)
-   */
-  protected IntPointerIterator refIterator(int fsCode) {
-    IntIterator4bag<T> it = new IntIterator4bag<T>(this, null); // no concurrent mod checking, internal use
-    it.moveTo(fsCode);
-    return it;
-  }
+//  public FsIterator_bag<T>SIteratorSingleType_ImplBase<T> createFSIterator(int[] detectIllegalIndexUpdates, int typeCode) {
+//    return new FsIterator_bag<T>(this, detectIllegalIndexUpdates, typeCode);
+//  }
 
   /**
    * @see org.apache.uima.cas.FSIndex#contains(FeatureStructure)
@@ -200,28 +126,27 @@ public class FSBagIndex<T extends Featur
    * @return <code>true</code> if the index contains such an element.
    */
   public boolean contains(FeatureStructure fs) {
-    return ll_contains(((FeatureStructureImpl) fs).getAddress());
+    return this.index.contains(fs);
+  }
+  
+  public boolean containsEq(FeatureStructureImplC fs) {
+    return index.contains(fs);
   }
   
   boolean ll_contains(int fsAddr) {
-    return USE_POSITIVE_INT_SET ?
-        indexP.contains(fsAddr) :
-        (find(fsAddr) >= 0);
+    return contains(casImpl.getFsFromId(fsAddr));
   }
 
-  public FeatureStructure find(FeatureStructure fs) {
-    if (USE_POSITIVE_INT_SET) {
-      final FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
-      final int addr = fsi.getAddress();
-      return (indexP.contains(addr)) ? fsi.getCASImpl().createFS(addr) : null;
-    }
-    // Cast to implementation.
-    FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
-    // Use internal find method.
-    final int resultAddr = find(fsi.getAddress());
-    // If found, create new FS to return.
-    if (resultAddr > 0) {
-      return fsi.getCASImpl().createFS(this.index.get(resultAddr));
+  /**
+   * This is a silly method for bag indexes in V3, since dupl add to indexes is not allowed.
+   * @param fs
+   * @return null or the original fs if the fs is in the index
+   */
+  @Override
+  public T find(FeatureStructure fs) {
+    final int resultAddr =  this.index.find((FeatureStructureImplC) fs);
+    if (resultAddr >= 0) {
+      return (T) fs;
     }
     // Not found.
     return null;
@@ -231,29 +156,20 @@ public class FSBagIndex<T extends Featur
    * @see org.apache.uima.cas.FSIndex#size()
    */
   public int size() {
-    return USE_POSITIVE_INT_SET ? indexP.size() : index.size();
+    return this.index.size();
   }
 
   /**
-   * @see org.apache.uima.cas.impl.FSLeafIndexImpl#deleteFS(org.apache.uima.cas.FeatureStructure)
+   * only for backwards compatibility
+   * 
    */
-  public void deleteFS(FeatureStructure fs) {
-    remove( ((FeatureStructureImpl) fs).getAddress());  
+  public boolean deleteFS(FeatureStructure fs) {
+    return this.index.remove(fs);
   }
   
   @Override
-  public boolean remove(int fsRef) {
-    if (USE_POSITIVE_INT_SET) {
-      return indexP.remove(fsRef);
-    } else {
-      final int pos = this.index.indexOfOptimizeAscending(fsRef);
-      if (pos >= 0) {
-        this.index.remove(pos);
-        return true;
-      } else {
-        return false;
-      }
-    }
+  public boolean remove(int fsRef) {    
+    return deleteFS(casImpl.getFsFromId(fsRef));
   }
 
   public int hashCode() {
@@ -261,60 +177,54 @@ public class FSBagIndex<T extends Featur
   }
 
   @Override
-  boolean insert(int fs, int count) {
-    // only need this multi-insert to support Set and Sorted indexes for
-    // protectIndexes kinds of things
-    throw new UnsupportedOperationException();
+  protected void bulkAddTo(List<FeatureStructure> fss) {
+    fss.addAll(this.index);
   }
 
   @Override
-  protected void bulkAddTo(IntVector v) {
-    if (USE_POSITIVE_INT_SET) {
-      indexP.bulkAddTo(v);
-    } else {
-      v.addBulk(index);
-    }    
+  protected void bulkAddTo(IntVector fss) {
+    this.index.stream().mapToInt(FeatureStructureImplC::get_id).forEach(fss::add);
   }
   
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#iterator()
+   */
+  @Override
+  public FSIterator<T> iterator() {
+    return new FsIterator_bag<T>(this, getDetectIllegalIndexUpdates(), getTypeCode());
+  }
+
   /*
    * Iterator support 
    */
   boolean isValid(int itPos) {
-    if (USE_POSITIVE_INT_SET) {
-      return indexP.isValid(itPos);
-    } else {
-      return (itPos >=0) && (itPos < index.size());
-    }
+    return index.isValid(itPos);
   }
   
   int moveToFirst() {
-    return USE_POSITIVE_INT_SET ? 
-          indexP.moveToFirst() : 
-          ((index.size() == 0) ? -1 : 0);
+    return index.moveToFirst();
   }
 
   int moveToLast() {
-    return FSBagIndex.USE_POSITIVE_INT_SET ? 
-        indexP.moveToLast() :
-        index.size() - 1;
+    return index.moveToLast();
   }
   
   int moveToNext(int itPos) {
-    return USE_POSITIVE_INT_SET ? 
-      indexP.moveToNext(itPos) :
-      (itPos < 0) ? -1 : itPos + 1;
+     return index.moveToNext(itPos);
   }
   
   int moveToPrevious(int itPos) {
-    return USE_POSITIVE_INT_SET ? 
-      indexP.moveToPrevious(itPos) :
-      (itPos >= index.size())? -1 : (itPos - 1);
+    return index.moveToPrevious(itPos);
   }
   
-  int get(int itPos) {
-    return FSBagIndex.USE_POSITIVE_INT_SET ?
-        indexP.get(itPos) :
-        index.get(itPos);
+  T get(int itPos) {
+    return (T) index.get(itPos);
   }
+  
+  ObjHashSet<FeatureStructureImplC> getObjHashSet() {
+    return index;
+  }
+  
+  
 
 }

Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_flat.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_flat.java?rev=1711793&view=auto
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_flat.java (added)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_flat.java Sun Nov  1 14:56:18 2015
@@ -0,0 +1,183 @@
+/*
+ * 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.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.ConcurrentModificationException;
+import java.util.List;
+
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.FeatureStructure;
+import org.apache.uima.internal.util.IntVector;
+
+/**
+ * Common part of flattened indexes, used for both snapshot iterators and 
+ * flattened sorted indexes
+ *  
+ * @param <T> the Java class type for this index
+ */
+public class FsIndex_flat<T extends FeatureStructure> extends FsIndex_singletype<T> {
+
+  // The index, an array.
+  final private FeatureStructureImplC[] indexedFSs;
+  
+  final private FsIndex_iicp<T> iicp;
+  
+  final private Comparator<FeatureStructure> comparator;
+    
+  FsIndex_flat(FsIndex_iicp<T> iicp) {
+    super(iicp.getCASImpl(), iicp.fsIndex_singletype.getType(), iicp.fsIndex_singletype.getIndexingStrategy());
+    this.iicp = iicp;
+    indexedFSs = fillFlatArray();
+    comparator = iicp.fsIndex_singletype;
+  }  
+  
+  /**
+   * Flat array filled, ordered
+   * @param flatArray the array to fill
+   */
+  private FeatureStructureImplC[] fillFlatArray() {
+    
+    FeatureStructureImplC[] a =  (FeatureStructureImplC[]) Array.newInstance(FeatureStructureImplC.class, iicp.size());
+    
+    FSIterator<T> it = iicp.iterator();
+    int i = 0;
+    while (it.hasNext()) {
+      a[i++] = (FeatureStructureImplC) it.next();
+    }
+    
+    if (i != a.length) {
+//      System.out.println("Debug - got iterator invalid before all items filled, i = " + i + ", size = " + flatArray.length);
+      throw new ConcurrentModificationException();
+    }
+    return a;
+  }
+  
+  FeatureStructureImplC[] getFlatArray() {
+    return indexedFSs;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#iterator()
+   */
+  @Override
+  public FSIterator<T> iterator() {
+    return new FsIterator_subtypes_snapshot<T>(this);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.impl.FsIndex_singletype#insert(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  boolean insert(T fs) {
+    throw new UnsupportedOperationException();  
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.impl.FsIndex_singletype#contains(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  public boolean contains(FeatureStructure fs) {
+    return find(fs) != null;
+  }
+  
+  @Override
+  public boolean containsEq(FeatureStructureImplC fs) {
+    return findEq((T) fs) != null;
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#find(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  public T find(FeatureStructure fs) {
+    if (isSorted()) {
+      for (FeatureStructureImplC item : indexedFSs) {
+        if (comparator.compare(item,  fs) == 0) {
+          return (T) item;
+        }
+      }
+      return null;
+    }
+
+    // ordered case
+    // r is index if found, otherwise, (-(insertion point) - 1). 
+    int r = Arrays.binarySearch(indexedFSs,  fs, comparator);
+    return (r >= 0) ? (T) indexedFSs[r] : null;
+  }
+
+  public T findEq(T fs) {
+    
+    if (isSorted()) {
+      Arrays.binarySearch((T[]) indexedFSs, 0, indexedFSs.length, fs, (T fs1, T fs2) -> fs1 == fs2 ? 0 : -1);
+    } else {
+      for (FeatureStructureImplC item : indexedFSs) {
+        if (fs == item) {
+          return (T) item;
+        }
+      }
+      return null;
+    }
+
+    // ordered case
+    // r is index if found, otherwise, (-(insertion point) - 1). 
+    int r = Arrays.binarySearch(indexedFSs, (FeatureStructureImplC) fs, (FeatureStructureImplC f1, FeatureStructureImplC f2) -> Integer.compare(f1.get_id(), f2.get_id()));
+    return (r == 0) ? fs : null;    
+  }
+
+  /**
+   * @see org.apache.uima.cas.FSIndex#size()
+   */
+  public int size() {
+    return this.indexedFSs.length;
+  }
+
+  /**
+   * @see org.apache.uima.cas.impl.FsIndex_singletype#deleteFS(T)
+   */
+  public boolean deleteFS(T fs) {
+    throw new UnsupportedOperationException();
+  }  
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.impl.FsIndex_singletype#bulkAddTo(java.util.List)
+   */
+  @Override
+  protected void bulkAddTo(List<FeatureStructure> v) {
+    v.addAll(Arrays.asList(indexedFSs));
+  }
+  
+  @Override
+  protected void bulkAddTo(IntVector v) {
+    Arrays.stream(indexedFSs).mapToInt(FeatureStructureImplC::get_id).forEach(v::add);
+  }
+  
+  /**
+   * @see org.apache.uima.cas.FSIndex#compare(T, T)
+   */    
+  @Override
+  public int compare(FeatureStructure fs1, FeatureStructure fs2) {
+    return comparator.compare(fs1,  fs2);
+  }
+
+
+}

Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_iicp.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_iicp.java?rev=1711793&view=auto
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_iicp.java (added)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_iicp.java Sun Nov  1 14:56:18 2015
@@ -0,0 +1,444 @@
+package org.apache.uima.cas.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.uima.cas.FSIndex;
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.FeatureStructure;
+import org.apache.uima.cas.Type;
+import org.apache.uima.cas.admin.FSIndexComparator;
+
+/**
+ * FsIndex_iicp (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 FsIndex_iicp<T extends FeatureStructure> 
+          implements Comparable<FsIndex_iicp<? extends FeatureStructure>>,
+                     Comparator<T>,
+                     LowLevelIndex<T>
+                      {
+
+//  private final static boolean DEBUG = false;
+
+  final FSIndexRepositoryImpl fsIndexRepositoryImpl;
+  /**
+   *  The "root" index, i.e., index of the type of the iterator.
+   *  default visibility to make it accessible by FSIndexFlat
+   */
+  final FsIndex_singletype<T> fsIndex_singletype;
+  
+  /**
+   * 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.
+   * 
+   * This is set up lazily on first need, to avoid extra work when won't be accessed
+   */
+  ArrayList<FsIndex_singletype<FeatureStructure>> cachedSubFsLeafIndexes = null;
+  
+  // VOLATILE to permit double-checked locking technique
+  private volatile boolean isIteratorCacheSetup = false;
+    
+  /**
+   * The type codes corresponding to the cachedSubFsLeafIndexes, set up lazily
+   */
+  int[] sortedTypeCodes;
+
+  FsIndex_iicp(FsIndex_singletype<T> fsIndex_singletype) {
+    this.fsIndex_singletype = fsIndex_singletype;
+    fsIndexRepositoryImpl = fsIndex_singletype.casImpl.indexRepository;
+//      setAndTestMask = fsIndexRepositoryImpl.cas.getTypeSystemImpl().getSetAndTestMasks(fsIndex_singletype.getTypeCode());
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()).append(", index=");
+    sb.append(fsIndex_singletype).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++) {
+        FsIndex_singletype<FeatureStructure> 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();
+  }
+  
+//    FSIterator<T> createFSIterator(boolean is_unordered) {
+//      return fsIndexRepositoryImpl.createFSIterator(this, is_unordered);
+//    }
+
+  // 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 FsIndex_iicps for a particular type,
+  //   the one that goes with the same index definition
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof FsIndex_iicp)) {
+      return false;
+    }
+    @SuppressWarnings("rawtypes")
+    final FsIndex_iicp iicp = (FsIndex_iicp) o;
+    return this.fsIndex_singletype.getComparatorForIndexSpecs().equals(iicp.fsIndex_singletype.getComparatorForIndexSpecs())
+        && (this.getIndexingStrategy() == iicp.getIndexingStrategy());
+  }
+
+// Implement a hashCode; 
+// previously tried just throwing an exception, but if the hashCode method 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.fsIndex_singletype.getComparatorForIndexSpecs().hashCode();
+    result = prime * result + this.getIndexingStrategy();
+    return result;
+  }
+
+  
+  // Populate the cache.
+  // For read-only CASes, this may be called on multiple threads, so do some synchronization
+      
+  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 TypeImpl rootType = (TypeImpl) this.fsIndex_singletype.getComparatorForIndexSpecs().getType();
+      final int indexKind = this.getIndexingStrategy();
+      int size = (indexKind == FSIndex.DEFAULT_BAG_INDEX) ? 1 : 1 + (int) rootType.getAllSubtypes().count();
+
+      final ArrayList<FsIndex_singletype<FeatureStructure>> tempSubIndexCache = new ArrayList<FsIndex_singletype<FeatureStructure>>();
+      sortedTypeCodes = (indexKind == FSIndex.SORTED_INDEX) ? new int[size] : null;
+
+      initOneType(rootType, tempSubIndexCache, indexKind);
+      
+      
+//      Stream<TypeImpl> typePlusSubtypes = (indexKind == FSIndex.DEFAULT_BAG_INDEX) 
+//          ? Stream.of(rootType)
+//          : Stream.concat(Stream.of(rootType), rootType.getAllSubtypes()); 
+//      
+//      
+//      typePlusSubtypes  // for the type + all its subtypes, being set up for this one index:
+//      
+//          // map to the IndexesForType structure, which is a list of all FsIndex_iicp's defined for each type
+//         .map(typeImpl -> fsIndexRepositoryImpl.getIndexesForType(typeImpl.getCode()).indexesForType)
+//      
+//         // map to the "equal" element in the list. and then its fsIndex_singletype
+//         .map(ift -> ift.get(ift.indexOf(this)).fsIndex_singletype)
+//         
+//         // collect (ordered) into ArrayList and if SORTED_INDEX, collect into int array the typecodes, ordered
+//         .forEachOrdered(singleIndex -> {if (indexKind == FSIndex.SORTED_INDEX) {
+//                                           sortedTypeCodes[tempSubIndexCache.size()] = singleIndex.getTypeCode();
+//                                         }
+//                                         tempSubIndexCache.add(singleIndex);});
+ 
+      this.cachedSubFsLeafIndexes = tempSubIndexCache; 
+      if (this.getIndexingStrategy() == FSIndex.SORTED_INDEX) {
+        Arrays.sort(sortedTypeCodes);
+      }
+      // assign to "volatile" at end, after all initialization is complete
+      this.isIteratorCacheSetup = true;
+    }  // end of synchronized block
+  }
+  
+  private void initOneType(TypeImpl ti, ArrayList<FsIndex_singletype<FeatureStructure>> cache, int indexKind) {
+    ArrayList<FsIndex_iicp<FeatureStructure>> ift = 
+        fsIndexRepositoryImpl.getIndexesForType(ti.getCode()).indexesForType;
+    
+    FsIndex_singletype<FeatureStructure> singleIndex = ift.get(ift.indexOf(this)).fsIndex_singletype;
+    
+    if (indexKind == FSIndex.SORTED_INDEX) {
+      sortedTypeCodes[cache.size()] = singleIndex.getTypeCode();
+    }
+    
+    cache.add(singleIndex);
+    if (indexKind != FSIndex.DEFAULT_BAG_INDEX) {
+      for (TypeImpl subti : ti.getDirectSubtypes()) {
+        initOneType(subti, cache, indexKind);        
+      }
+    }
+  }
+
+  
+  /**
+   * Maybe not used 3/2015
+   * 
+   * Compares first using the type code of the main types
+   *   If those are equal,
+   *   Compares using the comparatorForIndexSpecs objects
+   * @see java.lang.Comparable#compareTo(Object)
+   * 
+   */
+  public int compareTo(FsIndex_iicp<? extends FeatureStructure> cp) {
+    final int typeCode1 = ((TypeImpl) this.fsIndex_singletype.getType()).getCode();
+    final int typeCode2 = ((TypeImpl) cp.fsIndex_singletype.getType()).getCode();
+    if (typeCode1 < typeCode2) {
+      return -1;
+    } else if (typeCode1 > typeCode2) {
+      return 1;
+    } else { // types are equal
+      return this.fsIndex_singletype.getComparatorForIndexSpecs()
+          .compareTo(cp.fsIndex_singletype.getComparatorForIndexSpecs());
+    }
+  }
+
+  /**
+   * 
+   * @return the sum of the sizes of the indexes of the type + all subtypes
+   */
+  public int size() {
+    createIndexIteratorCache();  // does nothing if already created
+    return cachedSubFsLeafIndexes.stream().mapToInt(iicp -> iicp.size()).sum();
+  }
+  
+  boolean has1OrMoreEntries() {
+    createIndexIteratorCache();  // does nothing if already created
+    final ArrayList<FsIndex_singletype<FeatureStructure>> 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<FsIndex_singletype<FeatureStructure>> 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;
+  }
+     
+  
+//    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 getCASImpl().getTypeSystemImpl().subsumes(superType,  subType);
+  }
+  
+  // debug
+  CASImpl getCASImpl() {
+    return fsIndex_singletype.casImpl;
+  }
+
+  // for flat index support
+//    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();
+//      }
+//    }
+  
+  FsIndex_singletype<FeatureStructure> getNoSubtypeIndexForType(Type type) {
+    createIndexIteratorCache();
+    for (FsIndex_singletype<FeatureStructure> noSubtypeIndex : cachedSubFsLeafIndexes) {
+      if (noSubtypeIndex.getType() == type) {
+        return noSubtypeIndex;
+      }
+    }
+    return null;
+  }
+  
+  FSIndexRepositoryImpl getFSIndexRepositoryImpl() {
+    return fsIndexRepositoryImpl;
+  }
+
+  FsIndex_singletype<T> getFsIndex_singleType() {
+    return fsIndex_singletype;
+  }
+  
+  boolean isDefaultBagIndex () {
+    return getIndexingStrategy() == FSIndex.DEFAULT_BAG_INDEX;
+  }
+
+  boolean isSetIndex () {
+    return getIndexingStrategy() == FSIndex.SET_INDEX;
+  }
+
+  @Override
+  public int ll_compare(int ref1, int ref2) {
+    return fsIndex_singletype.ll_compare(ref1,  ref2);
+  }
+
+  @Override
+  public int getIndexingStrategy() {
+    return fsIndex_singletype.getIndexingStrategy();
+  }
+
+  @Override
+  public FSIndexComparator getComparatorForIndexSpecs() {
+    return fsIndex_singletype.getComparatorForIndexSpecs();
+  }
+
+  @Override
+  public int compare(FeatureStructure fs1, FeatureStructure fs2) {
+    return fsIndex_singletype.compare(fs1,  fs2);
+  }
+
+  @Override
+  public boolean contains(FeatureStructure fs) {
+    return find(fs) != null;
+  }
+
+  @Override
+  public T find(FeatureStructure fs) {
+    createIndexIteratorCache();  // does nothing if already created
+    
+    for (FsIndex_singletype<FeatureStructure> idx : cachedSubFsLeafIndexes) {
+     FeatureStructure result = idx.find(fs);
+      if (result != null) {
+        return (T) result;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public Type getType() {
+    return fsIndex_singletype.getType();
+  }
+
+  @Override
+  public CASImpl getCasImpl() {
+    return fsIndex_singletype.casImpl;
+  }
+  
+  public FSIterator<T> iterator() {
+    createIndexIteratorCache();  // may not be needed here   
+   
+    return (cachedSubFsLeafIndexes.size() == 1)
+           ? fsIndex_singletype.iterator()
+           : fsIndex_singletype.isSorted()
+             ? new FsIterator_subtypes_ordered<T>(this)
+             : new FsIterator_aggregation_common<T>(new FsIterator_subtypes_unordered<T>(this).iterators, fsIndex_singletype);
+  } 
+
+  /**
+   * Iterator over arbitrary Feature Structures, but also filters out non-AnnotationFS FeatureStructures
+   * @param ambiguous true for normal iteration, false to do unambiguous iteration
+   * @return the iterator
+   */
+  /* 
+   * Implementation note: this is different from the Subiterator in that it can be over an iterator that that
+   * includes non- annotationFS for the unambiguous case, in which case these are filtered out.
+   */
+  @Override
+  public LowLevelIterator<T> ll_iterator(boolean ambiguous) {
+    if (!ambiguous) {
+      return new LLUnambiguousIteratorImpl<T>((LowLevelIterator<FeatureStructure>) iterator());
+     } else {
+       return (LowLevelIterator<T>) iterator();
+     }
+  }
+  
+//  /* ***********************************
+//   *  Support for withSnapshotIterators
+//   *  using proxy
+//   * ***********************************/
+//  private final static Class<?>[] proxyInterface = new Class<?>[] {FSIndex.class};
+//  
+//  private class ProxySnapshotHandler implements InvocationHandler {
+//    @Override
+//    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+//      if ("iterator".equals(method.getName())) {
+//        if (getIndexingStrategy() == FSIndex.SORTED_INDEX) {
+//          return iterator(IteratorExtraFunction.SNAPSHOT);
+//        }
+//        return iterator(IteratorExtraFunction.UNORDERED_SNAPSHOT);
+//      }
+//      // pass thru all other methods
+//      return method.invoke(args);
+//    }    
+//  }
+    
+  @Override
+  public FSIndex<T> withSnapshotIterators() {
+    return new FsIndex_snapshot<>(this);
+  }
+
+  public FSIndexRepositoryImpl getFsRepositoryImpl() {
+    return getCasImpl().indexRepository;
+  }
+
+}

Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java?rev=1711793&view=auto
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java (added)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java Sun Nov  1 14:56:18 2015
@@ -0,0 +1,202 @@
+/*
+ * 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.Iterator;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.TreeSet;
+
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.FeatureStructure;
+import org.apache.uima.cas.Type;
+import org.apache.uima.internal.util.IntVector;
+
+/**
+ * Common index impl for set and sorted indexes.
+ * 
+ * Differences:
+ *   - Number of "equal" (but not identical) FSs: Set: 1, Sorted, N
+ *   - Iterators: Set: unordered, Sorted: ordered 
+ * 
+ * The FSs are kept in a TreeSet in an ordering, to permit faster searching.
+ *   
+ * This is an index over just one type (excluding subtypes)
+ * 
+ * Uses a NavigableSet as the index (of FSs).  
+ *   For sorted, because this is a set, to allow multiple (different) FSs having
+ *     the same key values to be in the index, the key used for the index is augmented by a least-significant
+ *     key which is the _id field of the FS itself.
+ * 
+ * @param <T> the Java class type for this index
+ */
+public class FsIndex_set_sorted<T extends FeatureStructure> extends FsIndex_singletype<T> {
+
+  // The index, a NavigableSet. 
+  // Should be over T, but has to be over FeatureStructure in order to have the comparator take FeatureStructures
+  final private NavigableSet<FeatureStructure> indexedFSs;
+   
+  FsIndex_set_sorted(CASImpl cas, Type type, int indexType, boolean useSorted) {
+    super(cas, type, indexType);
+    this.indexedFSs = useSorted 
+                        ?  new TreeSet<FeatureStructure>(
+                            (FeatureStructure o1, FeatureStructure o2) -> {
+                              final int c = compare(o1,  o2); 
+                              // augment normal comparator with one that compares IDs if everything else equal
+                              return (c == 0) ? (Integer.compare(o1.get_id(), o2.get_id())) : c;})
+                        : new TreeSet<FeatureStructure>( (FeatureStructure o1, FeatureStructure o2) -> compare(o1,  o2));     
+  }
+
+  @Override
+  public void flush() {
+    this.indexedFSs.clear();
+  }
+
+  /**
+   * @see org.apache.uima.cas.FSIndex#contains(FeatureStructure)
+   * @param fs the feature structure
+   * @return true if the fs is contained
+   */
+  @Override
+  public boolean contains(FeatureStructure templateKey) {
+    T r = find(templateKey);
+    return r != null;
+  }
+  
+  /**
+   * @param fs the FeatureStructure to see if it is in the set
+   * @return true if this exact fs is in the set
+   */
+  @Override
+  public boolean containsEq(FeatureStructureImplC fs) {
+    return CASImpl.isSameCAS(casImpl, fs.getCAS()) && indexedFSs.contains(fs);
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.impl.FsIndex_singletype#insert(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  boolean insert(T fs) {
+    return this.indexedFSs.add(fs);
+  }
+
+  /**
+   * find any arbitrary matching FS
+   *   two comparators:  cp, and cpx (has extra id comparing)
+   * 
+   * First find an FS in the index that's the smallest that's GE to key using cpx
+   *   - if none found, then all of the entries in the index are LessThan the key (using cpx); 
+   *                    but one might be equal using cp
+   *     -- if one or more would be equal using cp, it would be because 
+   *           the only reason for the inequality using cpx was due to the _id miscompare.
+   *           Therefore we only need to check the last of the previous ones to see if it is cp equal
+   *  - if we find one that is GE using cpx, 
+   *     -- if it is equal then return it (any equal one is ok)
+   *     -- if it is GT, then the ones preceding it are LessThan (using cpx) the key.
+   *           Do the same check as above to see if the last of the preceding ones is equal using cp.
+   *   
+   * @param fs the matching fs template
+   * @return an arbitrary fs that matches 
+   */
+  @Override
+  public T find(FeatureStructure templateKey) {
+    if (null == templateKey || this.indexedFSs.size() == 0) {
+      return null;
+    }
+    T found;
+    FeatureStructure fs1GEfs = this.indexedFSs.ceiling(templateKey);
+    
+    if (fs1GEfs == null) {  // then all elements are less-that the templateKey
+      found = (T) indexedFSs.lower(templateKey);  //highest of elements less-than the template key
+      return (found == null) ? null : (compare(found, templateKey) == 0) ? found : null;
+    }
+    
+    // fs1GEfs is the least element that is greater-than-or-equal to the template key, using the fine-grained comparator
+    if (0 == compare(fs1GEfs, templateKey)) {
+      return (T) fs1GEfs; 
+    }
+    
+    // fs1GEfs not null, GreaterThan the templateKey using compare
+    // Therefore, the ones preceding it are LessThan using the index comparator, but 
+    //   may be equal using the compare.
+    found = (T) indexedFSs.lower(templateKey);  // the greatest element in this set strictly less than the templateKey
+    return (found == null) ? null : (compare(found, templateKey) == 0) ? found : null;
+  }
+
+  public T findLeftmost(FeatureStructure templateKey) {
+    // descending iterator over elements LessThan templateKey
+    Iterator<T> it = (Iterator<T>) indexedFSs.headSet(templateKey, false).descendingIterator();
+  
+    T elementBefore = null;
+    T lastEqual = null;
+    // move to left until run out or have element not equal using compare to templateKey
+    while (it.hasNext() && (0 == compare(elementBefore = it.next(), templateKey))) {
+      lastEqual = elementBefore;
+    }
+  
+    if (!it.hasNext()) { // moved past beginning
+      return elementBefore;  // might return null to indicate not found
+    }
+    return lastEqual;
+  }
+
+  /**
+   * @see org.apache.uima.cas.FSIndex#size()
+   */
+  @Override
+  public int size() {
+    return this.indexedFSs.size();
+  }
+
+  /**
+   * This code is written to remove (if it exists)
+   * the exact FS, not just one which matches in the sort comparator.
+   *
+   * @see org.apache.uima.cas.impl.FSLeafIndexImpl#deleteFS(org.apache.uima.cas.FeatureStructure)
+   * @param fs the feature structure to remove
+   * @return true if it was in the index previously
+   */
+  /**
+   * 
+   */
+  @Override
+  public boolean deleteFS(T fs) {
+    return this.indexedFSs.remove(fs);
+  }
+  
+  @Override
+  protected void bulkAddTo(List<FeatureStructure> v) {
+    v.addAll(indexedFSs);
+  }
+  
+  @Override
+  protected void bulkAddTo(IntVector v) {
+    this.indexedFSs.stream().mapToInt(fs -> ((FeatureStructureImplC)fs).get_id()).forEach(v::add);
+  }
+  
+  NavigableSet<FeatureStructure> getNavigableSet() { //used by FsIterator_sorted to compute various derivitive nav sets
+    return indexedFSs;
+  }
+   
+  @Override
+  public FSIterator<T> iterator() {
+    return new FsIterator_set_sorted<T>(this, getDetectIllegalIndexUpdates(), getTypeCode(), this);
+  }
+}

Copied: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_singletype.java (from r1693269, uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSLeafIndexImpl.java)
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_singletype.java?p2=uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_singletype.java&p1=uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSLeafIndexImpl.java&r1=1693269&r2=1711793&rev=1711793&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSLeafIndexImpl.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_singletype.java Sun Nov  1 14:56:18 2015
@@ -20,415 +20,261 @@
 package org.apache.uima.cas.impl;
 
 import java.util.Comparator;
+import java.util.List;
 
-import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.FSIndex;
 import org.apache.uima.cas.FSIterator;
-import org.apache.uima.cas.Feature;
 import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.admin.FSIndexComparator;
 import org.apache.uima.cas.admin.LinearTypeOrder;
-import org.apache.uima.internal.util.ComparableIntPointerIterator;
-import org.apache.uima.internal.util.IntComparator;
-import org.apache.uima.internal.util.IntPointerIterator;
 import org.apache.uima.internal.util.IntVector;
 
 /**
- * The common (among all index kinds - set, sorted, bag) info for an index
+ * The common (among all index kinds - set, sorted, bag) info for an index over 1 type (excluding subtypes)
+ *   The name "Leaf" is a misnomer - it's just over one type excluding any subtypes if they exist
  * Subtypes define the actual index repository (integers indexing the CAS) for each kind.
  * 
  * @param <T> the Java cover class type for this index, passed along to (wrapped) iterators producing Java cover classes
  */
-public abstract class FSLeafIndexImpl<T extends FeatureStructure> implements Comparator<T>, IntComparator, FSIndexImpl {
+public abstract class FsIndex_singletype<T extends FeatureStructure> implements Comparator<FeatureStructure>, LowLevelIndex<T> {
+
+  private final static String[] indexTypes = new String[] {"Sorted", "Set", "Bag", "DefaultBag"}; 
 
   private final int indexType;  // Sorted, Set, Bag, Default-bag, etc.
 
   // A reference to the low-level CAS.
-  final protected CASImpl lowLevelCAS;
-
-  private static final int STRING_CODE = 0;
-
-  private static final int FLOAT_CODE = 1;
-
-  private static final int INT_CODE = 2;
-
-  private static final int TYPE_ORDER_CODE = 3;
-
-  private static final int BOOLEAN_CODE = 4;
-
-  private static final int BYTE_CODE = 5;
-
-  private static final int SHORT_CODE = 6;
-
-  private static final int LONG_CODE = 7;
-
-  private static final int DOUBLE_CODE = 8;
-
-  private FSIndexComparatorImpl comparator;
+  final protected CASImpl casImpl;
+  
+  private FSIndexComparatorImpl comparatorForIndexSpecs;
 
   private boolean isInitialized = false;
 
+  /***********  Info about Index Comparator (not used for bag ***********
+   * Index into these arrays is the key number (indexes can have multiple keys)
+   */
   // For each key, the int code of the type of that key.
-  private int[] keyType;
-
-  // For each feature key, the feature offset.
-  private int[] keyOffset;
-
-  // An array of the type orders used. This array is dense, most values will
-  // be null.
-  private LinearTypeOrder[] typeOrder;
+  private Object[] keys;   // either a FeatImpl or a LinearTypeOrder;
 
+  private int[] keyTypeCodes;
   // For each key, the comparison to use.
-  private int[] keyComp;
+  private boolean[] isReverse;    // true = reverse, false = standard
 
-  // The number of keys.
-  private int numKeys;
-
-  final private Type type; // The type of this
+  final private TypeImpl type; // The type of this
   
   final private int typeCode;
-
   
   
   @Override
   public String toString() {
-    String kind;
-    switch (indexType) {
-    case 0:
-      kind = "Sorted";
-      break;
-    case 1:
-      kind = "Set";
-      break;
-    case 2:
-      kind = "Bag";
-      break;
-    case 3:
-      kind = "Default Bag";
-      break;
-    default:
-      kind = "Invalid";
-    }
-    return "FSLeafIndexImpl ["  
-//        + "indexType=" + indexType + ", comparator=" + comparator + ", keyType="
-//        + Arrays.toString(keyType) + ", keyOffset=" + Arrays.toString(keyOffset) + ", typeOrder="
-//        + Arrays.toString(typeOrder) + ", keyComp=" + Arrays.toString(keyComp) + ", numKeys=" + numKeys 
-        + "type=" + type + ", kind=" + kind + "]";
+    String kind = (indexType >= 0 && indexType < 4) ? indexTypes[indexType] : "Invalid";     
+    return this.getClass().getSimpleName() + " [type=" + type.getName() + ", kind=" + kind + "(" + indexType + ")]";
   }
 
   // never called
   // declared private to block external calls
   @SuppressWarnings("unused")
-  private FSLeafIndexImpl() {
+  private FsIndex_singletype() {
     this.indexType = 0; // must do because it's final
-    this.lowLevelCAS = null;
+    this.casImpl = null;
     this.type = null;
     this.typeCode = 0;
   }
 
   /**
-   * Constructor for FSLeafIndexImpl.
+   * Constructor for FsIndex_singletype.
    * @param cas -
    * @param type -
    * @param indexType -
    */
-  protected FSLeafIndexImpl(CASImpl cas, Type type, int indexType) {
+  protected FsIndex_singletype(CASImpl cas, Type type, int indexType) {
     super();
     this.indexType = indexType;
-    this.lowLevelCAS = cas;
-    this.type = type;
+    this.casImpl = cas;
+    this.type = (TypeImpl) type;
     this.typeCode = ((TypeImpl)type).getCode();
   }
-
-  abstract boolean insert(int fs);
   
-  abstract boolean insert(int fs, int count);  // for bulk addback
+  /**
+   * Adding FS to an index.
+   *   not in upper interfaces because it's internal use only - called via addToIndexes etc.
+   * @param fs the fs to be added
+   * @return true if the fs was added, (an identical one wasn't already there)
+   */
+  abstract boolean insert(T fs);  // not in upper interfaces because it's internal use only
 
   /**
    * @param fs - the Feature Structure to be removed.
-   * Only this exact Feature Structure is removed (this is a stronger test than, for example,
-   * what moveTo(fs) does, where the fs in that case is used as a template).  
-   * It is not an error if this exact Feature Structure is not in an index.
+   *             Only this exact Feature Structure is removed (this is a stronger test than, for example,
+   *             what moveTo(fs) does, where the fs in that case is used as a template).  
+   *             It is not an error if this exact Feature Structure is not in an index.
    * @return true if something was removed, false if not found
    */
-  abstract boolean remove(int fs);
-
-  // public abstract IntListIterator iterator();
-
-  // public abstract ComparableIntIterator iterator(IntComparator comp);
-
-  public abstract ComparableIntPointerIterator<T> pointerIterator(IntComparator comp,
-          int[] detectIllegalIndexUpdates, int typeCode);
-
-  public FSIndexComparator getComparator() {
-    return this.comparator;
+  boolean remove(int fs) {
+    return deleteFS(getCasImpl().getFsFromId(fs));
   }
-
-  IntComparator getIntComparator() {
-    return this;
+   
+  /**
+   * @param fs - the Feature Structure to be removed.
+   *             Only this exact Feature Structure is removed (this is a stronger test than, for example,
+   *             what moveTo(fs) does, where the fs in that case is used as a template).  
+   *             It is not an error if this exact Feature Structure is not in an index.
+   * @return true if something was removed, false if not found
+   */
+  abstract boolean deleteFS(T fs);
+  
+  @Override
+  public FSIterator<T> iterator(FeatureStructure initialPositionFs) {
+    FSIterator<T> fsIt = iterator();
+    fsIt.moveTo(initialPositionFs);
+    return fsIt;
+  }
+  
+  @Override
+  public FSIndexComparator getComparatorForIndexSpecs() {
+    return this.comparatorForIndexSpecs;
   }
 
+  @Override
   public int getIndexingStrategy() {
     return this.indexType;
   }
 
+  public int[] getDetectIllegalIndexUpdates() {
+    return this.casImpl.indexRepository.detectIllegalIndexUpdates;
+  }
+  /**
+   * Comparators - 
+   *   These are converted to use fs instances
+   * @param comp
+   * @return
+   */
   boolean init(FSIndexComparator comp) {
     if (this.isInitialized) {
       return false;
     }
-    FSIndexComparatorImpl comp1 = (FSIndexComparatorImpl) comp;
-    this.comparator = comp1.copy();
-    if (!this.comparator.isValid()) {
+    FSIndexComparatorImpl compForIndexSpecs = (FSIndexComparatorImpl) comp;
+    this.comparatorForIndexSpecs = compForIndexSpecs.copy();
+    if (!this.comparatorForIndexSpecs.isValid()) {
       return false;
     }
-    final int nKeys = this.comparator.getNumberOfKeys();
+    
     // Initialize the comparator info.
-    this.keyType = new int[nKeys];
-    this.keyOffset = new int[nKeys];
-    this.keyComp = new int[nKeys];
-    this.typeOrder = new LinearTypeOrder[nKeys];
-    Feature keyFeature;
+    final int nKeys = this.comparatorForIndexSpecs.getNumberOfKeys();
+    this.keys = new Object[nKeys];
+    this.keyTypeCodes = new int[nKeys];
+    this.isReverse = new boolean[nKeys];
+
     for (int i = 0; i < nKeys; i++) {
-      switch (comp.getKeyType(i)) {
-        case FSIndexComparator.FEATURE_KEY: {
-          keyFeature = this.comparator.getKeyFeature(i);
-          this.keyType[i] = getKeyCode(keyFeature);
-          this.keyOffset[i] = getFeatureOffset(keyFeature);
-          this.keyComp[i] = this.comparator.getKeyComparator(i);
-          break;
-        }
-        case FSIndexComparator.TYPE_ORDER_KEY: {
-          this.keyType[i] = TYPE_ORDER_CODE;
-          this.keyComp[i] = this.comparator.getKeyComparator(i);
-          this.typeOrder[i] = this.comparator.getKeyTypeOrder(i);
-          this.keyOffset[i] = 0;
-          break;
-        }
-        default: {
-          // This is an internal error.
-          throw new RuntimeException("Assertion failed.");
-        }
+      
+      final Object k =  (comp.getKeyType(i) == FSIndexComparator.FEATURE_KEY)
+                     ? (FeatureImpl) this.comparatorForIndexSpecs.getKeyFeature(i)
+                     : this.comparatorForIndexSpecs.getKeyTypeOrder(i);
+      keys[i] = k; 
+      if (k instanceof FeatureImpl) {
+        keyTypeCodes[i] = ((TypeImpl)((FeatureImpl)k).getRange()).getCode();
       }
+      isReverse[i] = this.comparatorForIndexSpecs.getKeyComparator(i) == FSIndexComparator.REVERSE_STANDARD_COMPARE;
     }
-    this.numKeys = nKeys;
     this.isInitialized = true;
     return true;
   }
 
-  private static final int getKeyCode(Feature feat) {
-    String typeName = feat.getRange().getName();
-    if (typeName.equals(CAS.TYPE_NAME_STRING)) {
-      return STRING_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_FLOAT)) {
-      return FLOAT_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_BOOLEAN)) {
-      return BOOLEAN_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_BYTE)) {
-      return BYTE_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_SHORT)) {
-      return SHORT_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_LONG)) {
-      return LONG_CODE;
-    }
-    if (typeName.equals(CAS.TYPE_NAME_DOUBLE)) {
-      return DOUBLE_CODE;
-    }
-    // This is defaulty and not nice. We rely on the checking in
-    // FSIndexComparatorImpl to make sure that only correct types get
-    // through.
-    return INT_CODE;
-  }
-
-  private final int getFeatureOffset(Feature feat) {
-    return this.comparator.getLowLevelCAS().getFeatureOffset(((FeatureImpl) feat).getCode());
-  }
-
   /**
-   * Note: may return other than -1 , 0, and 1  (e.g., might return -6)
    * @param fs1 -
    * @param fs2 -
    * @return 0 if equal, &lt; 0 if fs1 &lt; fs2, &gt; 0 if fs1 &gt; fs2
    */
+  @Override
   public int ll_compare(int fs1, int fs2) {
     return this.compare(fs1, fs2);
   }
 
   /**
-   * Note: may return other than -1 , 0, and 1  (e.g., might return -6)
    * @param fs1 -
    * @param fs2 -
    * @return 0 if equal, &lt; 0 if fs1 &lt; fs2, &gt; 0 if fs1 &gt; fs2
    */
   public int compare(int fs1, int fs2) {
-    final int[] heap = this.lowLevelCAS.getHeap().heap;
-    final int[] localKeyType = this.keyType;
-    final int[] localKeyOffset = this.keyOffset;
-    final int[] localKeyComp = this.keyComp;
-    final int localNumKeys = this.numKeys;
-    for (int i = 0; i < localNumKeys; i++) {
-      final int val1 = heap[fs1 + localKeyOffset[i]];
-      final int val2 = heap[fs2 + localKeyOffset[i]];
-      switch (localKeyType[i]) {
-        case STRING_CODE: {
-          // System.out.println("Comparing string codes " + val1 + " and "
-          // + val2);
-          // System.out.println(
-          // "Strings: "
-          // + lowLevelCAS.getStringForCode(val1)
-          // + ", "
-          // + lowLevelCAS.getStringForCode(val2));
-          // if (lowLevelCAS.getStringForCode(val1) == null) {
-          // System.out.println("Value for " + val1 + " is <null>.");
-          // }
-          // if (lowLevelCAS.getStringForCode(val2) == null) {
-          // System.out.println("Value for " + val2 + " is <null>.");
-          // }
-          final String string1 = this.lowLevelCAS.getStringForCode(val1);
-          final String string2 = this.lowLevelCAS.getStringForCode(val2);
-          int compVal;
-          if (string1 == null) {
-            if (string2 == null) {
-              compVal = 0;
-            } else {
-              compVal = -1;
-            }
-          } else {
-            if (string2 == null) {
-              compVal = 1;
-            } else {
-              compVal = string1.compareTo(string2);
-            }
-          }
-
-          if (compVal != 0) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return compVal;
-            }
-            return -compVal;
-          }
+    return compare(casImpl.getFsFromId(fs1), casImpl.getFsFromId(fs2));
+  }
+  
+  /**
+   * @see org.apache.uima.cas.FSIndex#compare(T, T)
+   */    
+  @Override
+  public int compare(FeatureStructure fs1, FeatureStructure fs2) {
+  
+    if (fs1 == fs2) {
+      return 0;
+    }
+    final FeatureStructureImplC fsc1 = (FeatureStructureImplC) fs1;
+    final FeatureStructureImplC fsc2 = (FeatureStructureImplC) fs2;
+        
+    /**
+     * for each key:
+     *   if Feature:
+     *     Switch by type:  float, 
+     *       get the value:  fsc1.getXXX, compare
+     */
+    int i = -1;
+    for (Object key : keys) {
+      int result = 0;
+      i++;
+      if (key instanceof FeatureImpl) {
+        FeatureImpl fi = (FeatureImpl) key;
+        switch (keyTypeCodes[i]) {
+        case TypeSystemImpl.booleanTypeCode:
+          result = Integer.compare(fsc1.getBooleanValue(fi) ? 1 : 0,
+                                   fsc2.getBooleanValue(fi) ? 1 : 0);
           break;
-        }
-        case FLOAT_CODE: {
-          final float float1 = CASImpl.int2float(val1);
-          final float float2 = CASImpl.int2float(val2);
-          if (float1 < float2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return -1;
-            }
-            return 1;
-          } else if (float1 > float2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return 1;
-            }
-            return -1;
-          }
+        case TypeSystemImpl.byteTypeCode:
+          result = Integer.compare(fsc1.getByteValue(fi), fsc2.getByteValue(fi));
           break;
-        }
-        case TYPE_ORDER_CODE: {
-          if (val1 == val2) {
-            break;
-          }
-          if (this.typeOrder[i].lessThan(val1, val2)) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return -1;
-            }
-            return 1;
-          }
-          if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-            return 1;
-          }
-          return -1;
-        }
-        case LONG_CODE: {
-          final long long1 = this.lowLevelCAS.getLongHeap().getHeapValue(val1);
-          final long long2 = this.lowLevelCAS.getLongHeap().getHeapValue(val2);
-          if (long1 < long2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return -1;
-            }
-            return 1;
-          } else if (long1 > long2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return 1;
-            }
-            return -1;
-          }
+        case TypeSystemImpl.shortTypeCode:
+          result = Integer.compare(fsc1.getShortValue(fi), fsc2.getShortValue(fi));
           break;
-        }
-        case DOUBLE_CODE: {
-          final double double1 = Double.longBitsToDouble(this.lowLevelCAS.getLongHeap().getHeapValue(val1));
-          final double double2 = Double.longBitsToDouble(this.lowLevelCAS.getLongHeap().getHeapValue(val2));
-          if (double1 < double2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return -1;
-            }
-            return 1;
-          } else if (double1 > double2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return 1;
-            }
-            return -1;
-          }
+        case TypeSystemImpl.intTypeCode:
+          result = Integer.compare(fsc1.getIntValue(fi), fsc2.getIntValue(fi));
           break;
-        }
-
-        default: { // Compare the int values directly.
-          // boolean compare done here as well.
-          // byte compare done here as well.
-          // short compare done here as well.
-          if (val1 < val2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return -1;
-            }
-            return 1;
-          } else if (val1 > val2) {
-            if (localKeyComp[i] == FSIndexComparator.STANDARD_COMPARE) {
-              return 1;
-            }
-            return -1;
-
-          }
+        case TypeSystemImpl.longTypeCode:
+          result = Long.compare(fsc1.getLongValue(fi), fsc2.getLongValue(fi));
           break;
+        case TypeSystemImpl.floatTypeCode:
+          result = Float.compare(fsc1.getFloatValue(fi), fsc2.getFloatValue(fi));
+          break;
+        case TypeSystemImpl.doubleTypeCode:
+          result = Double.compare(fsc1.getDoubleValue(fi), fsc2.getDoubleValue(fi));
+          break;
+        case TypeSystemImpl.stringTypeCode:
+          String s1 = fsc1.getStringValue(fi);
+          String s2 = fsc1.getStringValue(fi);
+          result = (s1 == null)
+                   ? ((s2 == null) ? 0 : -1)   // s1 null is lessthan a non-null s2
+                   : ( (s2 == null)            
+                       ? 1                     // s1 not null is greaterthan a null s2
+                       : s1.compareTo(s2) );   // if both not null, do compare
+          break;         
         }
+      } else {  // is type order compare    
+        result = ((LinearTypeOrder) key).compare(fsc1, fsc2);
       }
-    }
-    // FSs are identical as far as this comparator goes.
-    return 0;
+        
+      if (result == 0) {
+        continue;  
+      }
+      
+      return (isReverse[i]) ? ( (result < 0) ? 1 : -1) 
+                            : ( (result > 0) ? 1 : -1);
+    } // of for loop iterating over all compare keys    
+    return 0;  // all keys compare equal      
   }
 
-  // Eclipse says this method is never called by uimaj-core methods 9-2009
-//  public final boolean equals(Object o) {
-//    if (this == o) {
-//      return true;
-//    }
-//    return this.comparator.equals(o);
-//    // if (o instanceof FSIndexComparator) {
-//    // return this.comparator.equals(o);
-//    // } else if (o instanceof FSVectorIndex) {
-//    // return this.comparator.equals(((FSLeafIndexImpl)o).comparator);
-//    // } else {
-//    // return false;
-//    // }
-//  }
-  
-  
-
-//  public int hashCode() {
-//    // if this throws exception, then Eclipse debugger fails to show data in inspector
-//    // throw new UnsupportedOperationException(); 
-//    return 0;
-//  }
-
   @Override
   public int hashCode() {
     final int prime = 31;
     int result = 1;
-    result = prime * result + ((comparator == null) ? 0 : comparator.hashCode());
+    result = prime * result + ((comparatorForIndexSpecs == null) ? 0 : comparatorForIndexSpecs.hashCode());
     return result;
   }
 
@@ -440,102 +286,74 @@ public abstract class FSLeafIndexImpl<T
       return false;
     if (getClass() != obj.getClass())
       return false;
-    FSLeafIndexImpl<?> other = (FSLeafIndexImpl<?>) obj;
-    if (comparator == null) {
-      if (other.comparator != null)
+    FsIndex_singletype<?> other = (FsIndex_singletype<?>) obj;
+    if (comparatorForIndexSpecs == null) {
+      if (other.comparatorForIndexSpecs != null)
         return false;
-    } else if (!comparator.equals(other.comparator))
+    } else if (!comparatorForIndexSpecs.equals(other.comparatorForIndexSpecs))
       return false;
     return true;
   }
 
   /**
-   * @see org.apache.uima.cas.FSIndex#compare(FeatureStructure, FeatureStructure)
-   */
-  public int compare(FeatureStructure fs1, FeatureStructure fs2) {
-    return compare(((FeatureStructureImpl) fs1).getAddress(), ((FeatureStructureImpl) fs2)
-            .getAddress());
-  }
-
-  /**
    * @see org.apache.uima.cas.FSIndex#getType()
    * @return The type of feature structures in this index.
    */
+  @Override
   public Type getType() {
     return this.type;
   }
   
+  public TypeImpl getTypeImpl() {
+    return this.type;
+  }
+  
   int getTypeCode() {
     return this.typeCode;
   }
 
-  protected abstract IntPointerIterator refIterator();
-
-  public IntPointerIterator getIntIterator() {
-    return refIterator();
-  }
-
   /**
-   * For serialization: get all the items in this index and bulk add to an IntVector
+   * For serialization: get all the items in this index and bulk add to an List<T>
    * @param v the set of items to add
    */
+  protected abstract void bulkAddTo(List<FeatureStructure> v);
+  
   protected abstract void bulkAddTo(IntVector v);
   
-  protected abstract IntPointerIterator refIterator(int fsCode);
-
-  // these next two are never called (maybe)
-  // because the object this method is called on is
-  // never this object, but instead the FSIndexRepositoryImpl.IndexImpl object
-  //
-  // It would be good to refactor this so that this confusion is eliminated,
-  // perhaps by not having this class implement FSIndex
-
-//  /**
-//   * @see org.apache.uima.cas.FSIndex#iterator()
-//   */
-//  public FSIterator<T> iterator() {
-//    return new FSIteratorWrapper<T>(refIterator(), this.lowLevelCAS);
-//  }
-
-  /**
-   * @see org.apache.uima.cas.FSIndex#iterator(FeatureStructure)
-   * 
-   * This has no callers, and is probably not used.
-   * The iterator it produces is only over one leaf index and
-   * doesn't include Concurrent Modification Exception testing
-   * @param fs -
-   * @return -
-   */
-  public FSIterator<T> iterator(FeatureStructure fs) {
-    return new FSIteratorWrapper<T>(refIterator(((FeatureStructureImpl) fs).getAddress()),
-            this.lowLevelCAS);
-  }
-
-  /**
-   * Method deleteFS.
-   * 
-   * @param fs -
-   */
-  public abstract void deleteFS(FeatureStructure fs);
-
-  public LowLevelIterator ll_iterator(boolean ambiguous) {
+  @Override
+  public LowLevelIterator<T> ll_iterator(boolean ambiguous) {
     if (ambiguous) {
       return this.ll_iterator();
     }
 
     return null;
   }
-
-  public LowLevelIterator ll_rootIterator() {
-      return this.ll_iterator();
+  
+  @Override
+  public CASImpl getCasImpl() {
+    return this.casImpl;
   }
+  
+  @Override
+  public FSIndex<T> withSnapshotIterators() {
+    // Is a no-op because this is a single type index.
+    // should never be called
+    // this is an artifact of the fact that FsIndex_singletype implements FSIndex interface
+    return this;
+  }
+  
+  /**
+   * used to see if a particular fs is in the index  
+   * @param fs
+   * @return
+   */
+  public abstract boolean containsEq(FeatureStructureImplC fs);
 
-//  @Override
-//  public FSIndex<T> withSnapshotIterators() {
-//    // should never be called
-//    // this is an artifact of the fact that FSLeafIndexImpl implements FSIndex interface
-//    //   which seems incorrect?
-//    throw new UnsupportedOperationException();
-//  }
-
+  boolean isSetOrSorted() {
+    return indexType == FSIndex.SET_INDEX || indexType == FSIndex.SORTED_INDEX;
+  }
+  
+  boolean isSorted() {
+    return indexType == FSIndex.SORTED_INDEX;
+  }
 }

Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_snapshot.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_snapshot.java?rev=1711793&view=auto
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_snapshot.java (added)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_snapshot.java Sun Nov  1 14:56:18 2015
@@ -0,0 +1,98 @@
+/*
+ * 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 org.apache.uima.cas.FSIndex;
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.FeatureStructure;
+import org.apache.uima.cas.Type;
+
+/**
+ * Implementation of light-weight wrapper of normal indexes, which support special kinds of iterators
+ *   base on the setting of IteratorExtraFunction
+ */
+public class FsIndex_snapshot <T extends FeatureStructure> implements FSIndex<T> {
+  
+  static final boolean ORDERED = false;
+  static final boolean UNORDERED = true;
+  
+  /**
+   * wrapped index 
+   */
+  private final FsIndex_iicp<T> wrapped;
+  
+  public FsIndex_snapshot(FsIndex_iicp<T> wrapped) {
+    this.wrapped = wrapped;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#getType()
+   */
+  @Override
+  public Type getType() { return wrapped.getType(); }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#contains(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  public boolean contains(FeatureStructure fs) { return wrapped.contains(fs); }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#find(org.apache.uima.cas.FeatureStructure)
+   */
+  @Override
+  public T find(FeatureStructure fs) { return wrapped.find(fs); }
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#iterator()
+   */
+  @Override
+  public FSIterator<T> iterator() {
+    return new FsIterator_subtypes_snapshot<T>(new FsIndex_flat<T>(wrapped));
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#getIndexingStrategy()
+   */
+  @Override
+  public int getIndexingStrategy() { return wrapped.getIndexingStrategy(); }
+  
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.FSIndex#withSnapshotIterators()
+   */
+  @Override
+  public FSIndex<T> withSnapshotIterators() {
+    return new FsIndex_snapshot<T>(wrapped);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.cas.impl.LowLevelIndex#size()
+   */
+  @Override
+  public int size() { return wrapped.size(); }
+
+  
+  /* (non-Javadoc)
+   * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+   */
+  @Override
+  public int compare(FeatureStructure o1, FeatureStructure o2) { return wrapped.compare(o1,  o2); }
+
+}