package org.apache.uima.cas.impl;

import java.util.Comparator;
import java.util.ConcurrentModificationException;

import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;

public abstract class FsIterator_singletype<T extends FeatureStructure>
                    implements LowLevelIterator<T>, 
                               Comparable<FsIterator_singletype<T>> {

  private int modificationSnapshot; // to catch illegal modifications

  /**
   * This is a ref to the shared value in the FSIndexRepositoryImpl
   * OR it may be null which means skip the checking (done for some internal routines
   * which know they are not updating the index, and assume no other thread is)
   */
  final protected int[] detectIllegalIndexUpdates; // shared copy with Index Repository

  protected final int typeCode;  // needed for the detect concurrent modification
  
  /**
   * The generic type is FeatureStructure to allow comparing between
   * an instance of T and some other template type which can be a supertype of T, as long as
   * the keys are defined in both.
   */
  final protected Comparator<FeatureStructure> comparator;

  public FsIterator_singletype(int[] detectConcurrentMods, int typeCode, Comparator<FeatureStructure> comparator){
    this.comparator = comparator;
    this.detectIllegalIndexUpdates = detectConcurrentMods;
    this.typeCode = typeCode;
    resetConcurrentModification();
    // subtypes do moveToFirst after they finish initialization
  }
    
  final protected <I extends FSIterator<T>> I checkConcurrentModification() {
    if ((null != detectIllegalIndexUpdates) && (modificationSnapshot != detectIllegalIndexUpdates[typeCode])) {
      throw new ConcurrentModificationException();
    }
    return (I) this;
  }
  
  protected void resetConcurrentModification() {  
    this.modificationSnapshot = (null == this.detectIllegalIndexUpdates) ? 0 : this.detectIllegalIndexUpdates[typeCode];
  }

  @Override
  public int compareTo(FsIterator_singletype<T> o) {
    if (comparator != null) {
      return comparator.compare(this.get(), o.get());
    } 
    return Integer.compare(this.get().id(), o.get().id());
  }
   
  @Override
  public abstract FsIterator_singletype<T> copy();
  
  @Override
  public String toString() {
    Type type = this.ll_getIndex().getType();
    StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()).append(":").append(System.identityHashCode(this));
    sb.append(" over Type: ").append(type.getName()).append(":").append(typeCode);
    sb.append(", size: ").append(this.ll_indexSize());
    return sb.toString();
  }
  
}

@@ -508,23 +508,27 @@
 ions%0D%0A%0D%0A
+//
   /**%0D%0A
+//
    * Thi
@@ -588,16 +588,18 @@
 ryImpl%0D%0A
+//
    * OR 
@@ -677,16 +677,18 @@
 utines%0D%0A
+//
    * whi
@@ -760,23 +760,27 @@
 ad is)%0D%0A
+//
    */%0D%0A
+//
   final 
@@ -884,71 +884,22 @@
 nal 
-int typeCode;  // needed for the detect concurrent modification
+TypeImpl ti;  
 %0D%0A  
@@ -1211,48 +1211,19 @@
 ype(
-int%5B%5D detectConcurrentMods, int typeCode
+TypeImpl ti
 , Co
@@ -1298,16 +1298,18 @@
 rator;%0D%0A
+//
     this
@@ -1374,29 +1374,19 @@
 is.t
-ypeCode = typeCode
+i = ti
 ;%0D%0A
+//
     
@@ -1411,24 +1411,94 @@
 ification();
+  // can't do here, each subtype must finish it's initialization first
 %0D%0A    // sub
@@ -1557,18 +1557,77 @@
 n%0D%0A  %7D%0D%0A
-  
+%0D%0A  protected abstract int getModificationCountFromIndex();%0D%0A
   %0D%0A  fi
@@ -1697,24 +1697,94 @@
 cation() %7B%0D%0A
+    if (modificationSnapshot != getModificationCountFromIndex()) %7B%0D%0A//
     if ((nul
@@ -2057,16 +2057,19 @@
 apshot =
+ //
  (null =
@@ -2151,16 +2151,80 @@
 Code%5D;%0D%0A
+                              getModificationCountFromIndex();%0D%0A
   %7D%0D%0A%0D%0A 
@@ -2586,35 +2586,9 @@
  = t
-his.ll_getIndex().getType()
+i
 ;%0D%0A 
@@ -2785,23 +2785,27 @@
 append(t
-ype
+i.get
 Code
+()
 );%0D%0A    

change to concurrent mod detection