You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2015/08/06 16:29:07 UTC

svn commit: r1694511 - in /lucene/dev/branches/lucene5012/lucene: analysis/common/src/java/org/apache/lucene/analysis/stages/ analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ analysis/common/src/test/org/apache/lucene/analysis/sta...

Author: mikemccand
Date: Thu Aug  6 14:29:07 2015
New Revision: 1694511

URL: http://svn.apache.org/r1694511
Log:
LUCENE-5012: don't separate interface from impl for attributes

Added:
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ArcAttribute.java   (with props)
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/DeletedAttribute.java   (with props)
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/OffsetAttribute.java   (with props)
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/TermAttribute.java   (with props)
Removed:
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/ArcAttribute.java
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/ArcAttributeImpl.java
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/DeletedAttribute.java
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/DeletedAttributeImpl.java
Modified:
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/AutomatonStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/CharTokenizerStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/InsertDeletedPunctuationStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/LowerCaseFilterStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SplitOnDashFilterStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/Stage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StageToTokenStream.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StopFilterStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SynonymFilterStage.java
    lucene/dev/branches/lucene5012/lucene/analysis/common/src/test/org/apache/lucene/analysis/stages/AssertingStage.java
    lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectDocValuesProducer.java
    lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/MemoryDocValuesProducer.java
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene42/Lucene42DocValuesProducer.java
    lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/AutomatonStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/AutomatonStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/AutomatonStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/AutomatonStage.java Thu Aug  6 14:29:07 2015
@@ -17,18 +17,18 @@ package org.apache.lucene.analysis.stage
 * limitations under the License.
 */
 
-import java.io.IOException;
-import java.io.Reader;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.automaton.Automaton;
 import org.apache.lucene.util.automaton.State;
 import org.apache.lucene.util.automaton.Transition;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+
 /** Pass-through stage that builds an Automaton from the
  *  input tokens it sees. */
 
@@ -44,12 +44,12 @@ public class AutomatonStage extends Stag
   private Map<Integer,State> toStates;
   private Map<Integer,State> fromStates;
   private final ArcAttribute arcAtt;
-  private final TermToBytesRefAttribute termAtt;
+  private final TermAttribute termAtt;
 
   public AutomatonStage(Stage prevStage) {
     super(prevStage);
     arcAtt = prevStage.get(ArcAttribute.class);
-    termAtt = prevStage.get(TermToBytesRefAttribute.class);
+    termAtt = prevStage.get(TermAttribute.class);
   }
 
   @Override
@@ -96,20 +96,19 @@ public class AutomatonStage extends Stag
   @Override
   public boolean next() throws IOException {
     if (prevStage.next()) {
-      BytesRef term = termAtt.getBytesRef();
-      termAtt.fillBytesRef();
-      if (term.length == 0) {
+      String term = termAtt.get();
+      if (term.length() == 0) {
         throw new IllegalStateException("cannot handle empty-string term");
       }
       State lastState = getFromState(arcAtt.from());
-      for(int i=0;i<term.length;i++) {
+      for(int i=0;i<term.length();i++) {
         State toState;
-        if (i == term.length-1) {
+        if (i == term.length()-1) {
           toState = getToState(arcAtt.to());
         } else {
           toState = new State();
         }
-        lastState.addTransition(new Transition(term.bytes[term.offset + i], toState));
+        lastState.addTransition(new Transition(term.charAt(i), toState));
         lastState = toState;
       }    
       return true;

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/CharTokenizerStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/CharTokenizerStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/CharTokenizerStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/CharTokenizerStage.java Thu Aug  6 14:29:07 2015
@@ -17,24 +17,25 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Arrays;
-
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.analysis.util.CharacterUtils.CharacterBuffer;
 import org.apache.lucene.analysis.util.CharacterUtils;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Attribute;
 import org.apache.lucene.util.Version;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Arrays;
+
 public abstract class CharTokenizerStage extends Stage {
   private static final int MAX_WORD_LEN = 255;
   private static final int IO_BUFFER_SIZE = 4096;
 
   private Reader input;
-  private final CharTermAttribute termAtt;
+  private final TermAttribute termAtt;
   private final OffsetAttribute offsetAtt;
   private final ArcAttribute arcAtt;
 
@@ -52,9 +53,11 @@ public abstract class CharTokenizerStage
 
   private int lastNode;
 
+  private char[] buffer = new char[10];
+
   public CharTokenizerStage() {
     super(null);
-    termAtt = create(CharTermAttribute.class);
+    termAtt = create(TermAttribute.class);
     offsetAtt = create(OffsetAttribute.class);
     arcAtt = create(ArcAttribute.class);
   }
@@ -75,7 +78,6 @@ public abstract class CharTokenizerStage
     int length = 0;
     int start = -1; // this variable is always initialized
     int end = -1;
-    char[] buffer = termAtt.buffer();
     while (true) {
       if (bufferIndex >= dataLen) {
         offset += dataLen;
@@ -105,7 +107,7 @@ public abstract class CharTokenizerStage
           start = offset + bufferIndex - charCount;
           end = start;
         } else if (length >= buffer.length-1) { // check if a supplementary could run out of bounds
-          buffer = termAtt.resizeBuffer(2+length); // make sure a supplementary fits in the buffer
+          buffer = ArrayUtil.grow(buffer, 2+length); // make sure a supplementary fits in the buffer
         }
         end += charCount;
         length += Character.toChars(normalize(c), buffer, length); // buffer it, normalized
@@ -117,7 +119,7 @@ public abstract class CharTokenizerStage
       }
     }
 
-    termAtt.setLength(length);
+    termAtt.set(new String(buffer, 0, length));
 
     offsetAtt.setOffset(correctOffset(start), correctOffset(start+length));
 

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/InsertDeletedPunctuationStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/InsertDeletedPunctuationStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/InsertDeletedPunctuationStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/InsertDeletedPunctuationStage.java Thu Aug  6 14:29:07 2015
@@ -17,18 +17,18 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.io.Reader;
-
 import org.apache.lucene.analysis.CharFilter;
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.DeletedAttribute;
-import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.DeletedAttribute;
+import org.apache.lucene.analysis.stages.attributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.FixedBitSet;
 
-/** Uses a CharFilter to detect when punction occurs in the
+import java.io.IOException;
+import java.io.Reader;
+
+/** Uses a CharFilter to detect when punctuation occurs in the
  *  input in between two tokens, and then as a Stage it will
  *  re-insert [deleted] tokens when it notices the tokenizer
  *  had deleted the punctuation.  E.g. this can be used to
@@ -38,12 +38,12 @@ public class InsertDeletedPunctuationSta
 
   private final DeletedAttribute delAttIn;
   private final ArcAttribute arcAttIn;
-  private final CharTermAttribute termAttIn;
+  private final TermAttribute termAttIn;
   private final OffsetAttribute offsetAttIn;
 
   private final ArcAttribute arcAttOut;
   private final DeletedAttribute delAttOut;
-  private final CharTermAttribute termAttOut;
+  private final TermAttribute termAttOut;
   private final OffsetAttribute offsetAttOut;
 
   private final String punctToken;
@@ -55,12 +55,12 @@ public class InsertDeletedPunctuationSta
     delAttIn = prevStage.get(DeletedAttribute.class);
     offsetAttIn = prevStage.get(OffsetAttribute.class);
     arcAttIn = prevStage.get(ArcAttribute.class);
-    termAttIn = prevStage.get(CharTermAttribute.class);
+    termAttIn = prevStage.get(TermAttribute.class);
 
     delAttOut = create(DeletedAttribute.class);
     offsetAttOut = create(OffsetAttribute.class);
     arcAttOut = create(ArcAttribute.class);
-    termAttOut = create(CharTermAttribute.class);
+    termAttOut = create(TermAttribute.class);
   }
 
   private static class FindPunctuationCharFilter extends CharFilter {
@@ -146,8 +146,7 @@ public class InsertDeletedPunctuationSta
         delAttOut.set(true);
         offsetAttOut.setOffset(lastEndOffset, startOffset);
         // nocommit: should we copy over the actual punct chars...?
-        termAttOut.setEmpty();
-        termAttOut.append(punctToken);
+        termAttOut.set(punctToken);
         nodeOffset++;
       } else {
         copyToken();
@@ -165,8 +164,7 @@ public class InsertDeletedPunctuationSta
     } else {
       delAttOut.set(false);
     }
-    termAttOut.setEmpty();
-    termAttOut.append(termAttIn);
+    termAttOut.set(termAttIn.get());
     offsetAttOut.setOffset(offsetAttIn.startOffset(), offsetAttIn.endOffset());
     arcAttOut.set(arcAttIn.from()+nodeOffset, arcAttIn.to() + nodeOffset);
   }

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/LowerCaseFilterStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/LowerCaseFilterStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/LowerCaseFilterStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/LowerCaseFilterStage.java Thu Aug  6 14:29:07 2015
@@ -19,37 +19,36 @@ package org.apache.lucene.analysis.stage
 
 import java.io.IOException;
 
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.analysis.util.CharacterUtils;
 import org.apache.lucene.util.Attribute;
 import org.apache.lucene.util.Version;
 
 public class LowerCaseFilterStage extends Stage {
   private final CharacterUtils charUtils;
-  private final CharTermAttribute termAttOut;
-  private final CharTermAttribute termAttIn;
+  private final TermAttribute termAttOut;
+  private final TermAttribute termAttIn;
 
   public LowerCaseFilterStage(Version version, Stage prevStage) {
     super(prevStage);
     charUtils = CharacterUtils.getInstance(version);
-    termAttIn = prevStage.get(CharTermAttribute.class);
-    termAttOut = create(CharTermAttribute.class);
+    termAttIn = prevStage.get(TermAttribute.class);
+    termAttOut = create(TermAttribute.class);
   }
   
   @Override
   public final boolean next() throws IOException {
     if (prevStage.next()) {
-      final char[] buffer = termAttIn.buffer();
-      final int length = termAttIn.length();
-      final char[] bufferOut = termAttOut.resizeBuffer(length);
+      final String term = termAttIn.get();
+      int length = term.length();
+      final char[] bufferOut = new char[length];
       for (int i = 0; i < length;) {
         // nocommit correct?
         i += Character.toChars(
                 Character.toLowerCase(
-                   charUtils.codePointAt(buffer, i, length)), bufferOut, i);
+                   charUtils.codePointAt(term, i)), bufferOut, i);
       }
-      termAttOut.setLength(length);
+      termAttOut.set(new String(bufferOut));
       return true;
     } else {
       return false;

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SplitOnDashFilterStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SplitOnDashFilterStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SplitOnDashFilterStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SplitOnDashFilterStage.java Thu Aug  6 14:29:07 2015
@@ -17,23 +17,21 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.io.Reader;
-
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.ArcAttributeImpl;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl;
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.analysis.util.CharacterUtils;
 import org.apache.lucene.util.Attribute;
 
+import java.io.IOException;
+import java.io.Reader;
+
 /** Simple example of decompounder-as-filter, just dividing
  *  a word at its dashes and keeping the original. */
 public class SplitOnDashFilterStage extends Stage {
 
   // We change the term:
-  private final CharTermAttribute termAttIn;
-  private final CharTermAttribute termAttOut;
+  private final TermAttribute termAttIn;
+  private final TermAttribute termAttOut;
 
   // We change the to/from:
   private final ArcAttribute arcAttIn;
@@ -44,8 +42,8 @@ public class SplitOnDashFilterStage exte
 
   public SplitOnDashFilterStage(Stage prevStage) {
     super(prevStage);
-    termAttIn = prevStage.get(CharTermAttribute.class);
-    termAttOut = create(CharTermAttribute.class);
+    termAttIn = prevStage.get(TermAttribute.class);
+    termAttOut = create(TermAttribute.class);
     arcAttIn = prevStage.get(ArcAttribute.class);
     arcAttOut = create(ArcAttribute.class);
   }
@@ -60,8 +58,7 @@ public class SplitOnDashFilterStage exte
   public boolean next() throws IOException {
     if (parts != null) {
 
-      termAttOut.setEmpty();
-      termAttOut.append(parts[nextPart]);
+      termAttOut.set(parts[nextPart]);
       int from;
       if (nextPart == 0) {
         from = arcAttIn.from();
@@ -90,8 +87,7 @@ public class SplitOnDashFilterStage exte
     if (prevStage.next()) {
 
       // nocommit copyTo?
-      termAttOut.setEmpty();
-      termAttOut.append(termAttIn);
+      termAttOut.set(termAttIn.get());
       arcAttOut.set(arcAttIn.from(), arcAttIn.to());
       
       parts = termAttIn.toString().split("-");

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/Stage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/Stage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/Stage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/Stage.java Thu Aug  6 14:29:07 2015
@@ -37,17 +37,8 @@ public abstract class Stage {
   // stages:
   protected final NodeTracker nodes;
 
-  // nocommit is all this hair really worth the separation
-  // of interface from impl?  can we just have concrete
-  // attrs?
-
-  private static final WeakIdentityMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>> attClassImplMap =
-    WeakIdentityMap.newConcurrentHashMap(false);
-
-
   /** Which Attributes this stage defines */
-  private final Map<Class<? extends AttributeImpl>, AttributeImpl> attImpls = new LinkedHashMap<Class<? extends AttributeImpl>, AttributeImpl>();
-  private final Map<Class<? extends Attribute>, AttributeImpl> atts = new LinkedHashMap<Class<? extends Attribute>, AttributeImpl>();
+  private final Map<Class<? extends Attribute>, Attribute> atts = new LinkedHashMap<Class<? extends Attribute>, Attribute>();
 
   protected Stage(Stage prevStage) {
     this.prevStage = prevStage;
@@ -58,112 +49,30 @@ public abstract class Stage {
     }
   }
 
-  /** a cache that stores all interfaces for known implementation classes for performance (slow reflection) */
-  private static final WeakIdentityMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>> knownImplClasses =
-    WeakIdentityMap.newConcurrentHashMap(false);
-  
-  static LinkedList<WeakReference<Class<? extends Attribute>>> getAttributeInterfaces(final Class<? extends AttributeImpl> clazz) {
-    LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces = knownImplClasses.get(clazz);
-    if (foundInterfaces == null) {
-      // we have the slight chance that another thread may do the same, but who cares?
-      foundInterfaces = new LinkedList<WeakReference<Class<? extends Attribute>>>();
-      // find all interfaces that this attribute instance implements
-      // and that extend the Attribute interface
-      Class<?> actClazz = clazz;
-      do {
-        for (Class<?> curInterface : actClazz.getInterfaces()) {
-          if (curInterface != Attribute.class && Attribute.class.isAssignableFrom(curInterface)) {
-            foundInterfaces.add(new WeakReference<Class<? extends Attribute>>(curInterface.asSubclass(Attribute.class)));
-          }
-        }
-        actClazz = actClazz.getSuperclass();
-      } while (actClazz != null);
-      knownImplClasses.put(clazz, foundInterfaces);
-    }
-    return foundInterfaces;
-  }
-
-  /** <b>Expert:</b> Adds a custom AttributeImpl instance with one or more Attribute interfaces.
-   * <p><font color="red"><b>Please note:</b> It is not guaranteed, that <code>att</code> is added to
-   * the <code>AttributeSource</code>, because the provided attributes may already exist.
-   * You should always retrieve the wanted attributes using {@link #getAttribute} after adding
-   * with this method and cast to your class.
-   * The recommended way to use custom implementations is using an {@link AttributeFactory}.
-   * </font></p>
-   */
-  public final void addAttributeImpl(final AttributeImpl att) {
-    final Class<? extends AttributeImpl> clazz = att.getClass();
-    if (attImpls.containsKey(clazz)) return;
-    
-    // add all interfaces of this AttributeImpl to the maps
-    for (WeakReference<Class<? extends Attribute>> curInterfaceRef : getAttributeInterfaces(clazz)) {
-      final Class<? extends Attribute> curInterface = curInterfaceRef.get();
-      assert (curInterface != null) :
-        "We have a strong reference on the class holding the interfaces, so they should never get evicted";
-      // Attribute is a superclass of this interface
-      if (!atts.containsKey(curInterface)) {
-        atts.put(curInterface, att);
-        attImpls.put(clazz, att);
-      }
-    }
-  }
-  
-  private static Class<? extends AttributeImpl> getClassForInterface(Class<? extends Attribute> attClass) {
-    final WeakReference<Class<? extends AttributeImpl>> ref = attClassImplMap.get(attClass);
-    Class<? extends AttributeImpl> clazz = (ref == null) ? null : ref.get();
-    if (clazz == null) {
-      // we have the slight chance that another thread may do the same, but who cares?
-      try {
-        attClassImplMap.put(attClass,
-                            new WeakReference<Class<? extends AttributeImpl>>(
-                                clazz = Class.forName(attClass.getName() + "Impl", true, attClass.getClassLoader())
-                                .asSubclass(AttributeImpl.class))
-                            );
-      } catch (ClassNotFoundException e) {
-        throw new IllegalArgumentException("Could not find implementing class for " + attClass.getName());
-      }
-    }
-    return clazz;
-  }
-
-  /**
-   * The caller must pass in a Class&lt;? extends Attribute&gt; value.
-   * This method first checks if an instance of that class is 
-   * already in this AttributeSource and returns it. Otherwise a
-   * new instance is created, added to this AttributeSource and returned. 
-   */
   protected final <A extends Attribute> A create(Class<A> attClass) {
-    AttributeImpl attImpl = atts.get(attClass);
-    if (attImpl == null) {
-      if (!(attClass.isInterface() && Attribute.class.isAssignableFrom(attClass))) {
-        throw new IllegalArgumentException(
-          "addAttribute() only accepts an interface that extends Attribute, but " +
-          attClass.getName() + " does not fulfil this contract."
-        );
-      }
-
+    Attribute att = atts.get(attClass);
+    if (att == null) {
       try {
-        attImpl = getClassForInterface(attClass).newInstance();
+        att = attClass.newInstance();
       } catch (InstantiationException e) {
         throw new IllegalArgumentException("Could not instantiate implementing class for " + attClass.getName());
       } catch (IllegalAccessException e) {
         throw new IllegalArgumentException("Could not instantiate implementing class for " + attClass.getName());
       }
 
-      addAttributeImpl(attImpl);
-      return attClass.cast(attImpl);
+      atts.put(attClass, att);
+      return attClass.cast(att);
     } else {
       throw new IllegalArgumentException(attClass + " was already added");
     }
   }
 
   public final <A extends Attribute> A get(Class<A> attClass) {
-    AttributeImpl attImpl = atts.get(attClass);
+    Attribute attImpl = atts.get(attClass);
     if (attImpl == null) {
       if (prevStage != null) {
         return prevStage.get(attClass);
       } else {
-        //throw new IllegalArgumentException("This AttributeSource does not have the attribute '" + attClass.getName() + "'.");
         return null;
       }
     }

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StageToTokenStream.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StageToTokenStream.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StageToTokenStream.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StageToTokenStream.java Thu Aug  6 14:29:07 2015
@@ -17,20 +17,20 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.DeletedAttribute;
+import org.apache.lucene.analysis.stages.attributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.util.ArrayUtil;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.DeletedAttribute;
-import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
-import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
-import org.apache.lucene.util.ArrayUtil;
-
 // TODO
 //   - is there an adversary here?  that can cause
 //     indefinite buffering?
@@ -41,21 +41,27 @@ import org.apache.lucene.util.ArrayUtil;
 // current indexer ... eg use captureState/restoreState to
 // pass through any custom atts too
 
-/** Takes a Stage as input and produces a TokenStream as
- *  output that can be consumed for indexing.  This is not
- *  general purpose: it currently only sets the attributes
- *  that the (core, no custom indexing chain) indexer
+/** This is a compatibility class, to map the new {@link Stage} API to
+ *  the legacy {@link TokenStream} API currently used/required by
+ *  consumers like {@link IndexWriter} and query parsers.  It takes
+ *  a {@link Stage} as input and produces a {@link TokenStream} as
+ *  output.  This is not general purpose: it currently only sets
+ *  the attributes that the (core, no custom indexing chain) indexer 
  *  requires. */
+
 public class StageToTokenStream extends TokenStream {
 
-  private final Stage prevStage;
+  // nocommit: cutover to the approach from SausageGraphFilter
+
+  private final Stage stage;
   private final DeletedAttribute delAtt;
-  private final CharTermAttribute termAttIn;
-  private final CharTermAttribute termAttOut;
+  private final TermAttribute termAttIn;
   private final ArcAttribute arcAttIn;
-  private final PositionIncrementAttribute posIncAttOut;
   private final OffsetAttribute offsetAttIn;
-  private final OffsetAttribute offsetAttOut;
+
+  private final org.apache.lucene.analysis.tokenattributes.CharTermAttribute termAttOut;
+  private final org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute posIncAttOut;
+  private final org.apache.lucene.analysis.tokenattributes.OffsetAttribute offsetAttOut;
 
   protected boolean resetCalled;
   protected boolean closeCalled = true;
@@ -99,15 +105,15 @@ public class StageToTokenStream extends
     }
   }
 
-  public StageToTokenStream(Stage prevStage) {
-    this.prevStage = prevStage;
-    termAttIn = prevStage.get(CharTermAttribute.class);
-    termAttOut = addAttribute(CharTermAttribute.class);
-    posIncAttOut = addAttribute(PositionIncrementAttribute.class);
-    offsetAttIn = prevStage.get(OffsetAttribute.class);
-    offsetAttOut = addAttribute(OffsetAttribute.class);
-    arcAttIn = prevStage.get(ArcAttribute.class);
-    delAtt = prevStage.get(DeletedAttribute.class);
+  public StageToTokenStream(Stage stage) {
+    this.stage = stage;
+    termAttIn = stage.get(TermAttribute.class);
+    termAttOut = addAttribute(org.apache.lucene.analysis.tokenattributes.CharTermAttribute.class);
+    posIncAttOut = addAttribute(org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute.class);
+    offsetAttIn = stage.get(OffsetAttribute.class);
+    offsetAttOut = addAttribute(org.apache.lucene.analysis.tokenattributes.OffsetAttribute.class);
+    arcAttIn = stage.get(ArcAttribute.class);
+    delAtt = stage.get(DeletedAttribute.class);
   }
 
   private Node getNode(Map<Integer,Node> nodes, int node) {
@@ -205,8 +211,8 @@ public class StageToTokenStream extends
       // buffered token(s) were deleted (holes)
     }
 
-    if (prevStage.next()) {
-      if (prevStage.nodes.anyNodesCanChange()) {
+    if (stage.next()) {
+      if (stage.nodes.anyNodesCanChange()) {
         System.out.println("  now buffer: " + termAttIn);
         Map<Integer,Node> nodes = new HashMap<Integer,Node>();
         nodes.put(arcAttIn.from(), new Node());
@@ -216,14 +222,14 @@ public class StageToTokenStream extends
         // until it un-clumps itself:
         saveToken(nodes);
         while (true) {
-          boolean result = prevStage.next();
+          boolean result = stage.next();
           // So long as there are still nodes that can
           // change, there must be more tokens (hmm is this
           // really true...):
           assert result: "Stage.next ended without freezing all nodes";
           saveToken(nodes);
-          System.out.println("  buffer again: " + termAttIn + "; " + prevStage.anyNodesCanChange() + " " + frontierNodeCount);
-          if (!prevStage.anyNodesCanChange() && frontierNodeCount == 1) {
+          System.out.println("  buffer again: " + termAttIn + "; " + stage.anyNodesCanChange() + " " + frontierNodeCount);
+          if (!stage.anyNodesCanChange() && frontierNodeCount == 1) {
             System.out.println("  clump done");
             break;
           }
@@ -247,7 +253,7 @@ public class StageToTokenStream extends
         System.out.println("  pass through");
         // Fast path (pass through): no buffering necessary:
         termAttOut.setEmpty();
-        termAttOut.append(termAttIn);
+        termAttOut.append(termAttIn.get());
         offsetAttOut.setOffset(offsetAttIn.startOffset(),
                                offsetAttIn.endOffset());
         posIncAttOut.setPositionIncrement(1 + pendingPosInc);

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StopFilterStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StopFilterStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StopFilterStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/StopFilterStage.java Thu Aug  6 14:29:07 2015
@@ -19,22 +19,22 @@ package org.apache.lucene.analysis.stage
 
 import java.io.IOException;
 
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.DeletedAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
+import org.apache.lucene.analysis.stages.attributes.DeletedAttribute;
 import org.apache.lucene.analysis.util.CharArraySet;
 
 /** Marks stop words as deleted */
 public class StopFilterStage extends Stage {
 
   private final CharArraySet stopWords;
-  private final CharTermAttribute termAtt;
+  private final TermAttribute termAtt;
   private final DeletedAttribute delAttIn;
   private final DeletedAttribute delAttOut;
 
   public StopFilterStage(Stage prevStage, CharArraySet stopWords) {
     super(prevStage);
     this.stopWords = stopWords;
-    termAtt = prevStage.get(CharTermAttribute.class);
+    termAtt = prevStage.get(TermAttribute.class);
     delAttIn = prevStage.get(DeletedAttribute.class);
     delAttOut = create(DeletedAttribute.class);
   }
@@ -42,7 +42,7 @@ public class StopFilterStage extends Sta
   @Override
   public boolean next() throws IOException {
     if (prevStage.next()) {
-      if ((delAttIn != null && delAttIn.deleted()) || stopWords.contains(termAtt.buffer(), 0, termAtt.length())) {
+      if ((delAttIn != null && delAttIn.deleted()) || stopWords.contains(termAtt.get())) {
         delAttOut.set(true);
       } else {
         delAttOut.set(false);

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SynonymFilterStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SynonymFilterStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SynonymFilterStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/SynonymFilterStage.java Thu Aug  6 14:29:07 2015
@@ -17,16 +17,10 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.OffsetAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
 import org.apache.lucene.analysis.synonym.SynonymMap;
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.store.ByteArrayDataInput;
 import org.apache.lucene.util.Attribute;
 import org.apache.lucene.util.BytesRef;
@@ -34,6 +28,12 @@ import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.UnicodeUtil;
 import org.apache.lucene.util.fst.FST;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
 // nocommit does not do keepOrig
 
 // nocommit should we ... allow recursing on ourselves?  ie
@@ -47,8 +47,8 @@ import org.apache.lucene.util.fst.FST;
 public class SynonymFilterStage extends Stage {
 
   // We change the term:
-  private final CharTermAttribute termAttIn;
-  private final CharTermAttribute termAttOut;
+  private final TermAttribute termAttIn;
+  private final TermAttribute termAttOut;
 
   // We change the to/from:
   private final ArcAttribute arcAttIn;
@@ -113,8 +113,8 @@ public class SynonymFilterStage extends
 
   public SynonymFilterStage(Stage prevStage, SynonymMap synonyms, boolean ignoreCase) {
     super(prevStage);
-    termAttIn = prevStage.get(CharTermAttribute.class);
-    termAttOut = create(CharTermAttribute.class);
+    termAttIn = prevStage.get(TermAttribute.class);
+    termAttOut = create(TermAttribute.class);
     arcAttIn = prevStage.get(ArcAttribute.class);
     arcAttOut = create(ArcAttribute.class);
     offsetAttIn = prevStage.get(OffsetAttribute.class);
@@ -151,11 +151,10 @@ public class SynonymFilterStage extends
       output = fst.outputs.getNoOutput();
     }
 
-    char[] buffer = termAttIn.buffer();
-    int bufferLen = termAttIn.length();
+    int bufferLen = termAttIn.get().length();
     int bufUpto = 0;
     while(bufUpto < bufferLen) {
-      final int codePoint = Character.codePointAt(buffer, bufUpto, bufferLen);
+      final int codePoint = Character.codePointAt(termAttIn.get(), bufUpto);
       if (fst.findTargetArc(ignoreCase ? Character.toLowerCase(codePoint) : codePoint, scratchArc, scratchArc, fstReader) == null) {
         return;
       }
@@ -297,8 +296,7 @@ public class SynonymFilterStage extends
     if (token != null) {
       //System.out.println("  insert output token! text=" + token.text + " offset=" + token.startOffset + "/" + token.endOffset);
       // We still have outputs pending from previous match:
-      termAttOut.setEmpty();
-      termAttOut.append(token.text);
+      termAttOut.set(token.text);
       offsetAttOut.setOffset(token.startOffset, token.endOffset);
       arcAttOut.set(token.fromNode, token.toNode);
       return true;
@@ -319,8 +317,7 @@ public class SynonymFilterStage extends
       match();
       
       // nocommit copy?
-      termAttOut.setEmpty();
-      termAttOut.append(termAttIn);
+      termAttOut.set(termAttIn.get());
 
       offsetAttOut.setOffset(offsetAttIn.startOffset(),
                              offsetAttIn.endOffset());

Added: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ArcAttribute.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ArcAttribute.java?rev=1694511&view=auto
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ArcAttribute.java (added)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/ArcAttribute.java Thu Aug  6 14:29:07 2015
@@ -0,0 +1,72 @@
+package org.apache.lucene.analysis.stages.attributes;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.util.Attribute;
+
+public class ArcAttribute implements Attribute, Cloneable {
+  private int from;
+  private int to;
+  
+  public ArcAttribute() {
+  }
+
+  public int from() {
+    return from;
+  }
+
+  public int to() {
+    return to;
+  }
+
+  public void set(int from, int to) {
+    this.from = from;
+    this.to = to;
+  }
+
+  public void clear() {
+    from = 0;
+    to = 0;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    
+    if (other instanceof ArcAttribute) {
+      ArcAttribute o = (ArcAttribute) other;
+      return o.from == from && o.to == to;
+    }
+    
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    int code = from;
+    code = code * 31 + to;
+    return code;
+  } 
+  
+  public void copyTo(Attribute target) {
+    ArcAttribute t = (ArcAttribute) target;
+    t.set(from, to);
+  }  
+}

Added: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/DeletedAttribute.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/DeletedAttribute.java?rev=1694511&view=auto
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/DeletedAttribute.java (added)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/DeletedAttribute.java Thu Aug  6 14:29:07 2015
@@ -0,0 +1,63 @@
+package org.apache.lucene.analysis.stages.attributes;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.util.Attribute;
+
+public class DeletedAttribute implements Attribute, Cloneable {
+  private boolean deleted;
+  
+  public DeletedAttribute() {
+  }
+
+  public boolean deleted() {
+    return deleted;
+  }
+
+  public void set(boolean deleted) {
+    this.deleted = deleted;
+  }
+
+  public void clear() {
+    deleted = false;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    
+    if (other instanceof DeletedAttribute) {
+      DeletedAttribute o = (DeletedAttribute) other;
+      return o.deleted == deleted;
+    }
+    
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return deleted ? 31 : 57;
+  } 
+  
+  public void copyTo(Attribute target) {
+    DeletedAttribute t = (DeletedAttribute) target;
+    t.set(deleted);
+  }  
+}

Added: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/OffsetAttribute.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/OffsetAttribute.java?rev=1694511&view=auto
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/OffsetAttribute.java (added)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/OffsetAttribute.java Thu Aug  6 14:29:07 2015
@@ -0,0 +1,87 @@
+package org.apache.lucene.analysis.stages.attributes;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.util.Attribute;
+
+public class OffsetAttribute implements Attribute, Cloneable {
+  private int startOffset;
+  private int endOffset;
+  
+  /** Initialize this attribute with startOffset and endOffset of 0. */
+  public OffsetAttribute() {
+  }
+
+  public int startOffset() {
+    return startOffset;
+  }
+
+  public void setOffset(int startOffset, int endOffset) {
+
+    // TODO: we could assert that this is set-once, ie,
+    // current values are -1?  Very few token filters should
+    // change offsets once set by the tokenizer... and
+    // tokenizer should call clearAtts before re-using
+    // OffsetAtt
+
+    if (startOffset < 0 || endOffset < startOffset) {
+      throw new IllegalArgumentException("startOffset must be non-negative, and endOffset must be >= startOffset, "
+          + "startOffset=" + startOffset + ",endOffset=" + endOffset);
+    }
+
+    this.startOffset = startOffset;
+    this.endOffset = endOffset;
+  }
+  
+  public int endOffset() {
+    return endOffset;
+  }
+
+  public void clear() {
+    // TODO: we could use -1 as default here?  Then we can
+    // assert in setOffset...
+    startOffset = 0;
+    endOffset = 0;
+  }
+  
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    
+    if (other instanceof OffsetAttribute) {
+      OffsetAttribute o = (OffsetAttribute) other;
+      return o.startOffset == startOffset && o.endOffset == endOffset;
+    }
+    
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    int code = startOffset;
+    code = code * 31 + endOffset;
+    return code;
+  } 
+  
+  public void copyTo(Attribute target) {
+    OffsetAttribute t = (OffsetAttribute) target;
+    t.setOffset(startOffset, endOffset);
+  }  
+}

Added: lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/TermAttribute.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/TermAttribute.java?rev=1694511&view=auto
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/TermAttribute.java (added)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/java/org/apache/lucene/analysis/stages/attributes/TermAttribute.java Thu Aug  6 14:29:07 2015
@@ -0,0 +1,38 @@
+package org.apache.lucene.analysis.stages.attributes;
+
+/*
+ * 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.
+ */
+
+import org.apache.lucene.util.Attribute;
+
+// TODO: CharSequence again?
+public class TermAttribute implements Attribute {
+  private String term;
+
+  public void set(String term) {
+    this.term = term;
+  }
+
+  public String get() {
+    return term;
+  }
+
+  @Override
+  public String toString() {
+    return term;
+  }
+}

Modified: lucene/dev/branches/lucene5012/lucene/analysis/common/src/test/org/apache/lucene/analysis/stages/AssertingStage.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/analysis/common/src/test/org/apache/lucene/analysis/stages/AssertingStage.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/analysis/common/src/test/org/apache/lucene/analysis/stages/AssertingStage.java (original)
+++ lucene/dev/branches/lucene5012/lucene/analysis/common/src/test/org/apache/lucene/analysis/stages/AssertingStage.java Thu Aug  6 14:29:07 2015
@@ -17,17 +17,17 @@ package org.apache.lucene.analysis.stage
  * limitations under the License.
  */
 
+import org.apache.lucene.analysis.stages.attributes.ArcAttribute;
+import org.apache.lucene.analysis.stages.attributes.TermAttribute;
+
 import java.io.IOException;
 import java.io.Reader;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.lucene.analysis.tokenattributes.ArcAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-
 class AssertingStage extends Stage {
   final ArcAttribute arcAtt;
-  final CharTermAttribute termAtt;
+  final TermAttribute termAtt;
   private int lastFrom;
   private int lastTo;
 
@@ -37,7 +37,7 @@ class AssertingStage extends Stage {
   public AssertingStage(Stage prevStage) {
     super(prevStage);
     arcAtt = prevStage.get(ArcAttribute.class);
-    termAtt = prevStage.get(CharTermAttribute.class);
+    termAtt = prevStage.get(TermAttribute.class);
   }
 
   @Override

Modified: lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectDocValuesProducer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectDocValuesProducer.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectDocValuesProducer.java (original)
+++ lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectDocValuesProducer.java Thu Aug  6 14:29:07 2015
@@ -106,9 +106,9 @@ class DirectDocValuesProducer extends Do
     }
 
     success = false;
+    String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
+    data = state.directory.openInput(dataName, state.context);
     try {
-      String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
-      data = state.directory.openInput(dataName, state.context);
       final int version2 = CodecUtil.checkHeader(data, dataCodec, 
                                                  VERSION_START,
                                                  VERSION_CURRENT);

Modified: lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/MemoryDocValuesProducer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/MemoryDocValuesProducer.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/MemoryDocValuesProducer.java (original)
+++ lucene/dev/branches/lucene5012/lucene/codecs/src/java/org/apache/lucene/codecs/memory/MemoryDocValuesProducer.java Thu Aug  6 14:29:07 2015
@@ -127,9 +127,9 @@ class MemoryDocValuesProducer extends Do
     }
 
     success = false;
+    String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
+    data = state.directory.openInput(dataName, state.context);
     try {
-      String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
-      data = state.directory.openInput(dataName, state.context);
       final int version2 = CodecUtil.checkHeader(data, dataCodec, 
                                                  VERSION_START,
                                                  VERSION_CURRENT);

Modified: lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene42/Lucene42DocValuesProducer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene42/Lucene42DocValuesProducer.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene42/Lucene42DocValuesProducer.java (original)
+++ lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene42/Lucene42DocValuesProducer.java Thu Aug  6 14:29:07 2015
@@ -127,9 +127,9 @@ class Lucene42DocValuesProducer extends
     }
 
     success = false;
+    String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
+    data = state.directory.openInput(dataName, state.context);
     try {
-      String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
-      data = state.directory.openInput(dataName, state.context);
       final int version2 = CodecUtil.checkHeader(data, dataCodec, 
                                                  VERSION_START,
                                                  VERSION_CURRENT);

Modified: lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java?rev=1694511&r1=1694510&r2=1694511&view=diff
==============================================================================
--- lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java (original)
+++ lucene/dev/branches/lucene5012/lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java Thu Aug  6 14:29:07 2015
@@ -128,9 +128,9 @@ public class Lucene45DocValuesProducer e
     }
 
     success = false;
+    String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
+    data = state.directory.openInput(dataName, state.context);
     try {
-      String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension);
-      data = state.directory.openInput(dataName, state.context);
       final int version2 = CodecUtil.checkHeader(data, dataCodec, 
                                                  Lucene45DocValuesFormat.VERSION_START,
                                                  Lucene45DocValuesFormat.VERSION_CURRENT);