Index: src/java/org/apache/lucene/analysis/position/PositionFilter.java
===================================================================
--- src/java/org/apache/lucene/analysis/position/PositionFilter.java	(revision 0)
+++ src/java/org/apache/lucene/analysis/position/PositionFilter.java	(revision 0)
@@ -0,0 +1,71 @@
+package org.apache.lucene.analysis.position;
+
+/**
+ * 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 java.io.IOException;
+
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Token;
+
+/** Set the positionIncrement of all tokens to the "positionIncrement",
+ * except the first return token which retains its original positionIncrement value.
+ * The default positionIncrement value is zero.
+ */
+public class PositionFilter extends TokenFilter {
+
+    /**
+     * @see #setPositionIncrement(int)
+     */
+    private int positionIncrement = 0;
+    /** the first token must still have positionIncrement=1 **/
+    private boolean firstTokenPositioned = false;
+
+    public PositionFilter(final TokenStream input) {
+        super(input);
+    }
+
+    public PositionFilter(final TokenStream input, final int positionIncrement){
+        this(input);
+        this.positionIncrement = positionIncrement;
+    }
+
+    /** What positionIncrement should all but the first token be updated with.
+     * @param positionIncrement all but the first token be updated with.
+     */
+    public void setPositionIncrement(final int positionIncrement) {
+        this.positionIncrement = positionIncrement;
+    }
+
+    public Token next(Token reusableToken) throws IOException {
+
+        assert reusableToken != null;
+        reusableToken = input.next(reusableToken);
+        if(null != reusableToken){
+            if(firstTokenPositioned){
+                reusableToken.setPositionIncrement(positionIncrement);
+            }else{
+                firstTokenPositioned = true;
+            }
+        }else{
+            // end of stream so reset firstTokePositioned
+            firstTokenPositioned = false;
+        }
+        return reusableToken;
+    }
+}

Property changes on: src/java/org/apache/lucene/analysis/position/PositionFilter.java
___________________________________________________________________
Added: svn:keywords
   + Id

Index: src/test/org/apache/lucene/analysis/position/PositionFilterTest.java
===================================================================
--- src/test/org/apache/lucene/analysis/position/PositionFilterTest.java	(revision 0)
+++ src/test/org/apache/lucene/analysis/position/PositionFilterTest.java	(revision 0)
@@ -0,0 +1,147 @@
+package org.apache.lucene.analysis.position;
+
+/**
+ * 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 java.io.IOException;
+
+import junit.framework.TestCase;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.shingle.ShingleFilter;
+
+public class PositionFilterTest extends TestCase {
+
+  public class TestTokenStream extends TokenStream {
+
+    protected int index = 0;
+    protected Token[] testToken;
+
+    public TestTokenStream(Token[] testToken) {
+      super();
+      this.testToken = testToken;
+    }
+
+    public Token next(final Token reusableToken) throws IOException {
+      assert reusableToken != null;
+      if (index < testToken.length) {
+        return testToken[index++];
+      } else {
+        return null;
+      }
+    }
+  }
+
+  public static void main(String[] args) {
+    junit.textui.TestRunner.run(PositionFilterTest.class);
+  }
+  
+  public static final Token[] TEST_TOKEN = new Token[] {
+      createToken("please", 0, 6),
+      createToken("divide", 7, 13),
+      createToken("this", 14, 18),
+      createToken("sentence", 19, 27),
+      createToken("into", 28, 32),
+      createToken("shingles", 33, 39),
+  };
+  
+  public static final Token[] SIX_GRAM_NO_POSITIONS_TOKENS = new Token[] {
+    createToken("please", 0, 6),
+    createToken("please divide", 0, 13),
+    createToken("please divide this", 0, 18),
+    createToken("please divide this sentence", 0, 27),
+    createToken("please divide this sentence into", 0, 32),
+    createToken("please divide this sentence into shingles", 0, 39),
+    createToken("divide", 7, 13),
+    createToken("divide this", 7, 18),
+    createToken("divide this sentence", 7, 27),
+    createToken("divide this sentence into", 7, 32),
+    createToken("divide this sentence into shingles", 7, 39),
+    createToken("this", 14, 18),
+    createToken("this sentence", 14, 27),
+    createToken("this sentence into", 14, 32),
+    createToken("this sentence into shingles", 14, 39),
+    createToken("sentence", 19, 27),
+    createToken("sentence into", 19, 32),
+    createToken("sentence into shingles", 19, 39),
+    createToken("into", 28, 32),
+    createToken("into shingles", 28, 39),
+    createToken("shingles", 33, 39),
+  };
+
+  public static final int[] SIX_GRAM_NO_POSITIONS_INCREMENTS = new int[] {
+    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+  };
+
+  public static final String[] SIX_GRAM_NO_POSITIONS_TYPES = new String[] {
+    "word", "shingle",  "shingle",  "shingle",  "shingle",  "shingle", 
+    "word", "shingle",  "shingle",  "shingle",  "shingle", 
+    "word", "shingle",  "shingle",  "shingle", 
+    "word", "shingle",  "shingle", 
+    "word", "shingle", 
+    "word"
+  };
+ 
+  /** Tests ShingleFilter up to six shingles against six terms.
+   *  Tests PositionFilter setting all but the first positionIncrement to zero.
+   * @throws java.io.IOException @see Token#next(Token)
+   */
+  public void test6GramFilterNoPositions() throws IOException {
+      
+    ShingleFilter filter = new ShingleFilter(new TestTokenStream(TEST_TOKEN), 6);
+    this.filterTest(new PositionFilter(filter),
+                           SIX_GRAM_NO_POSITIONS_TOKENS,
+                           SIX_GRAM_NO_POSITIONS_INCREMENTS,
+                           SIX_GRAM_NO_POSITIONS_TYPES);
+  }  
+
+  protected void filterTest(int maxSize, Token[] tokensToShingle, Token[] tokensToCompare,
+                                   int[] positionIncrements, String[] types)
+    throws IOException {
+
+    filterTest(new ShingleFilter(new TestTokenStream(tokensToShingle), maxSize),
+            tokensToCompare, positionIncrements, types);
+  }
+  
+  protected void filterTest(TokenStream filter, Token[] tokensToCompare,
+                                   int[] positionIncrements, String[] types)
+    throws IOException {    
+      
+    int i = 0;
+    final Token reusableToken = new Token();
+    for (Token nextToken = filter.next(reusableToken); nextToken != null; nextToken = filter.next(reusableToken)) {
+      String termText = nextToken.term();
+      String goldText = tokensToCompare[i].term();
+      assertEquals("Wrong termText", goldText, termText);
+      assertEquals("Wrong startOffset for token \"" + termText + "\"",
+          tokensToCompare[i].startOffset(), nextToken.startOffset());
+      assertEquals("Wrong endOffset for token \"" + termText + "\"",
+          tokensToCompare[i].endOffset(), nextToken.endOffset());
+      assertEquals("Wrong positionIncrement for token \"" + termText + "\"",
+          positionIncrements[i], nextToken.getPositionIncrement());
+      assertEquals("Wrong type for token \"" + termText + "\"", types[i], nextToken.type());
+      i++;
+    }
+  }
+
+  private static Token createToken(String term, int start, int offset)
+  {
+    Token token = new Token(start, offset);
+    token.setTermBuffer(term);
+    return token;
+  }
+}

Property changes on: src/test/org/apache/lucene/analysis/position/PositionFilterTest.java
___________________________________________________________________
Added: svn:keywords
   + Id

