pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / analyzers / common / src / java / org / apache / lucene / analysis / reverse / ReverseStringFilter.java
diff --git a/lucene-java-3.5.0/lucene/contrib/analyzers/common/src/java/org/apache/lucene/analysis/reverse/ReverseStringFilter.java b/lucene-java-3.5.0/lucene/contrib/analyzers/common/src/java/org/apache/lucene/analysis/reverse/ReverseStringFilter.java
new file mode 100644 (file)
index 0000000..7f67d0a
--- /dev/null
@@ -0,0 +1,327 @@
+/**
+ * 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.lucene.analysis.reverse;
+
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.util.Version;
+
+import java.io.IOException;
+
+/**
+ * Reverse token string, for example "country" => "yrtnuoc".
+ * <p>
+ * If <code>marker</code> is supplied, then tokens will be also prepended by
+ * that character. For example, with a marker of &#x5C;u0001, "country" =>
+ * "&#x5C;u0001yrtnuoc". This is useful when implementing efficient leading
+ * wildcards search.
+ * </p>
+ * <a name="version"/>
+ * <p>You must specify the required {@link Version}
+ * compatibility when creating ReverseStringFilter, or when using any of
+ * its static methods:
+ * <ul>
+ *   <li> As of 3.1, supplementary characters are handled correctly
+ * </ul>
+ */
+public final class ReverseStringFilter extends TokenFilter {
+
+  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
+  private final char marker;
+  private final Version matchVersion;
+  private static final char NOMARKER = '\uFFFF';
+  
+  /**
+   * Example marker character: U+0001 (START OF HEADING) 
+   */
+  public static final char START_OF_HEADING_MARKER = '\u0001';
+  
+  /**
+   * Example marker character: U+001F (INFORMATION SEPARATOR ONE)
+   */
+  public static final char INFORMATION_SEPARATOR_MARKER = '\u001F';
+  
+  /**
+   * Example marker character: U+EC00 (PRIVATE USE AREA: EC00) 
+   */
+  public static final char PUA_EC00_MARKER = '\uEC00';
+  
+  /**
+   * Example marker character: U+200F (RIGHT-TO-LEFT MARK)
+   */
+  public static final char RTL_DIRECTION_MARKER = '\u200F';
+  
+  /**
+   * Create a new ReverseStringFilter that reverses all tokens in the 
+   * supplied {@link TokenStream}.
+   * <p>
+   * The reversed tokens will not be marked. 
+   * </p>
+   * 
+   * @param in {@link TokenStream} to filter
+   * @deprecated use {@link #ReverseStringFilter(Version, TokenStream)} 
+   *    instead. This constructor will be removed in Lucene 4.0
+   */
+  @Deprecated
+  public ReverseStringFilter(TokenStream in) {
+    this(in, NOMARKER);
+  }
+  
+  /**
+   * Create a new ReverseStringFilter that reverses and marks all tokens in the
+   * supplied {@link TokenStream}.
+   * <p>
+   * The reversed tokens will be prepended (marked) by the <code>marker</code>
+   * character.
+   * </p>
+   * 
+   * @param in {@link TokenStream} to filter
+   * @param marker A character used to mark reversed tokens
+   * @deprecated use {@link #ReverseStringFilter(Version, TokenStream, char)} 
+   *    instead. This constructor will be removed in Lucene 4.0 
+   */
+  @Deprecated
+  public ReverseStringFilter(TokenStream in, char marker) {
+    this(Version.LUCENE_30, in, marker);
+  }
+  
+  /**
+   * Create a new ReverseStringFilter that reverses all tokens in the 
+   * supplied {@link TokenStream}.
+   * <p>
+   * The reversed tokens will not be marked. 
+   * </p>
+   * 
+   * @param matchVersion See <a href="#version">above</a>
+   * @param in {@link TokenStream} to filter
+   */
+  public ReverseStringFilter(Version matchVersion, TokenStream in) {
+    this(matchVersion, in, NOMARKER);
+  }
+
+  /**
+   * Create a new ReverseStringFilter that reverses and marks all tokens in the
+   * supplied {@link TokenStream}.
+   * <p>
+   * The reversed tokens will be prepended (marked) by the <code>marker</code>
+   * character.
+   * </p>
+   * 
+   * @param matchVersion See <a href="#version">above</a>
+   * @param in {@link TokenStream} to filter
+   * @param marker A character used to mark reversed tokens
+   */
+  public ReverseStringFilter(Version matchVersion, TokenStream in, char marker) {
+    super(in);
+    this.matchVersion = matchVersion;
+    this.marker = marker;
+  }
+
+  @Override
+  public boolean incrementToken() throws IOException {
+    if (input.incrementToken()) {
+      int len = termAtt.length();
+      if (marker != NOMARKER) {
+        len++;
+        termAtt.resizeBuffer(len);
+        termAtt.buffer()[len - 1] = marker;
+      }
+      reverse( matchVersion, termAtt.buffer(), 0, len );
+      termAtt.setLength(len);
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Reverses the given input string
+   * 
+   * @param input the string to reverse
+   * @return the given input string in reversed order
+   * @deprecated use {@link #reverse(Version, String)} instead. This method 
+   *    will be removed in Lucene 4.0
+   */
+  @Deprecated
+  public static String reverse( final String input ){
+    return reverse(Version.LUCENE_30, input);
+  }
+  
+  /**
+   * Reverses the given input string
+   * 
+   * @param matchVersion See <a href="#version">above</a>
+   * @param input the string to reverse
+   * @return the given input string in reversed order
+   */
+  public static String reverse( Version matchVersion, final String input ){
+    final char[] charInput = input.toCharArray();
+    reverse( matchVersion, charInput, 0, charInput.length );
+    return new String( charInput );
+  }
+  
+  /**
+   * Reverses the given input buffer in-place
+   * @param buffer the input char array to reverse
+   * @deprecated use {@link #reverse(Version, char[])} instead. This 
+   *    method will be removed in Lucene 4.0
+   */
+  @Deprecated
+  public static void reverse( final char[] buffer ){
+    reverse( buffer, 0, buffer.length );
+  }
+  
+  /**
+   * Reverses the given input buffer in-place
+   * @param matchVersion See <a href="#version">above</a>
+   * @param buffer the input char array to reverse
+   */
+  public static void reverse(Version matchVersion, final char[] buffer) {
+    reverse(matchVersion, buffer, 0, buffer.length);
+  }
+  
+  /**
+   * Partially reverses the given input buffer in-place from offset 0
+   * up to the given length.
+   * @param buffer the input char array to reverse
+   * @param len the length in the buffer up to where the
+   *        buffer should be reversed
+   * @deprecated use {@link #reverse(Version, char[], int)} instead. This 
+   *    method will be removed in Lucene 4.0
+   */
+  @Deprecated
+  public static void reverse( final char[] buffer, final int len ){
+    reverse( buffer, 0, len );
+  }
+  
+  /**
+   * Partially reverses the given input buffer in-place from offset 0
+   * up to the given length.
+   * @param matchVersion See <a href="#version">above</a>
+   * @param buffer the input char array to reverse
+   * @param len the length in the buffer up to where the
+   *        buffer should be reversed
+   */
+  public static void reverse(Version matchVersion, final char[] buffer,
+      final int len) {
+    reverse( matchVersion, buffer, 0, len );
+  }
+  
+  /**
+   * Partially reverses the given input buffer in-place from the given offset
+   * up to the given length.
+   * @param buffer the input char array to reverse
+   * @param start the offset from where to reverse the buffer
+   * @param len the length in the buffer up to where the
+   *        buffer should be reversed
+   * @deprecated use {@link #reverse(Version, char[], int, int)} instead. This 
+   *    method will be removed in Lucene 4.0
+   */
+  @Deprecated
+  public static void reverse(char[] buffer, int start, int len ) {
+    reverseUnicode3(buffer, start, len);
+  }
+  
+  /**
+   * @deprecated Remove this when support for 3.0 indexes is no longer needed.
+   */
+  @Deprecated
+  private static void reverseUnicode3( char[] buffer, int start, int len ){
+    if( len <= 1 ) return;
+    int num = len>>1;
+    for( int i = start; i < ( start + num ); i++ ){
+      char c = buffer[i];
+      buffer[i] = buffer[start * 2 + len - i - 1];
+      buffer[start * 2 + len - i - 1] = c;
+    }
+  }
+  
+  /**
+   * Partially reverses the given input buffer in-place from the given offset
+   * up to the given length.
+   * @param matchVersion See <a href="#version">above</a>
+   * @param buffer the input char array to reverse
+   * @param start the offset from where to reverse the buffer
+   * @param len the length in the buffer up to where the
+   *        buffer should be reversed
+   */
+  public static void reverse(Version matchVersion, final char[] buffer,
+      final int start, final int len) {
+    if (!matchVersion.onOrAfter(Version.LUCENE_31)) {
+      reverseUnicode3(buffer, start, len);
+      return;
+    }
+    /* modified version of Apache Harmony AbstractStringBuilder reverse0() */
+    if (len < 2)
+      return;
+    int end = (start + len) - 1;
+    char frontHigh = buffer[start];
+    char endLow = buffer[end];
+    boolean allowFrontSur = true, allowEndSur = true;
+    final int mid = start + (len >> 1);
+    for (int i = start; i < mid; ++i, --end) {
+      final char frontLow = buffer[i + 1];
+      final char endHigh = buffer[end - 1];
+      final boolean surAtFront = allowFrontSur
+          && Character.isSurrogatePair(frontHigh, frontLow);
+      if (surAtFront && (len < 3)) {
+        // nothing to do since surAtFront is allowed and 1 char left
+        return;
+      }
+      final boolean surAtEnd = allowEndSur
+          && Character.isSurrogatePair(endHigh, endLow);
+      allowFrontSur = allowEndSur = true;
+      if (surAtFront == surAtEnd) {
+        if (surAtFront) {
+          // both surrogates
+          buffer[end] = frontLow;
+          buffer[--end] = frontHigh;
+          buffer[i] = endHigh;
+          buffer[++i] = endLow;
+          frontHigh = buffer[i + 1];
+          endLow = buffer[end - 1];
+        } else {
+          // neither surrogates
+          buffer[end] = frontHigh;
+          buffer[i] = endLow;
+          frontHigh = frontLow;
+          endLow = endHigh;
+        }
+      } else {
+        if (surAtFront) {
+          // surrogate only at the front
+          buffer[end] = frontLow;
+          buffer[i] = endLow;
+          endLow = endHigh;
+          allowFrontSur = false;
+        } else {
+          // surrogate only at the end
+          buffer[end] = frontHigh;
+          buffer[i] = endHigh;
+          frontHigh = frontLow;
+          allowEndSur = false;
+        }
+      }
+    }
+    if ((len & 0x01) == 1 && !(allowFrontSur && allowEndSur)) {
+      // only if odd length
+      buffer[end] = allowFrontSur ? endLow : frontHigh;
+    }
+  }
+}