~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/contrib/analyzers/common/src/java/org/apache/lucene/analysis/tr/TurkishLowerCaseFilter.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.apache.lucene.analysis.tr;
2
 
 
3
 
/**
4
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
5
 
 * contributor license agreements.  See the NOTICE file distributed with
6
 
 * this work for additional information regarding copyright ownership.
7
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
8
 
 * (the "License"); you may not use this file except in compliance with
9
 
 * the License.  You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
import java.io.IOException;
21
 
 
22
 
import org.apache.lucene.analysis.TokenFilter;
23
 
import org.apache.lucene.analysis.TokenStream;
24
 
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
25
 
 
26
 
/**
27
 
 * Normalizes Turkish token text to lower case.
28
 
 * <p>
29
 
 * Turkish and Azeri have unique casing behavior for some characters. This
30
 
 * filter applies Turkish lowercase rules. For more information, see <a
31
 
 * href="http://en.wikipedia.org/wiki/Turkish_dotted_and_dotless_I"
32
 
 * >http://en.wikipedia.org/wiki/Turkish_dotted_and_dotless_I</a>
33
 
 * </p>
34
 
 */
35
 
public final class TurkishLowerCaseFilter extends TokenFilter {
36
 
  private static final int LATIN_CAPITAL_LETTER_I = '\u0049';
37
 
  private static final int LATIN_SMALL_LETTER_I = '\u0069';
38
 
  private static final int LATIN_SMALL_LETTER_DOTLESS_I = '\u0131';
39
 
  private static final int COMBINING_DOT_ABOVE = '\u0307';
40
 
  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
41
 
  
42
 
  /**
43
 
   * Create a new TurkishLowerCaseFilter, that normalizes Turkish token text 
44
 
   * to lower case.
45
 
   * 
46
 
   * @param in TokenStream to filter
47
 
   */
48
 
  public TurkishLowerCaseFilter(TokenStream in) {
49
 
    super(in);
50
 
  }
51
 
  
52
 
  @Override
53
 
  public final boolean incrementToken() throws IOException {
54
 
    boolean iOrAfter = false;
55
 
    
56
 
    if (input.incrementToken()) {
57
 
      final char[] buffer = termAtt.buffer();
58
 
      int length = termAtt.length();
59
 
      for (int i = 0; i < length;) {
60
 
        final int ch = Character.codePointAt(buffer, i);
61
 
    
62
 
        iOrAfter = (ch == LATIN_CAPITAL_LETTER_I || 
63
 
            (iOrAfter && Character.getType(ch) == Character.NON_SPACING_MARK));
64
 
        
65
 
        if (iOrAfter) { // all the special I turkish handling happens here.
66
 
          switch(ch) {
67
 
            // remove COMBINING_DOT_ABOVE to mimic composed lowercase
68
 
            case COMBINING_DOT_ABOVE:
69
 
              length = delete(buffer, i, length);
70
 
              continue;
71
 
            // i itself, it depends if it is followed by COMBINING_DOT_ABOVE
72
 
            // if it is, we will make it small i and later remove the dot
73
 
            case LATIN_CAPITAL_LETTER_I:
74
 
              if (isBeforeDot(buffer, i + 1, length)) {
75
 
                buffer[i] = LATIN_SMALL_LETTER_I;
76
 
              } else {
77
 
                buffer[i] = LATIN_SMALL_LETTER_DOTLESS_I;
78
 
                // below is an optimization. no COMBINING_DOT_ABOVE follows,
79
 
                // so don't waste time calculating Character.getType(), etc
80
 
                iOrAfter = false;
81
 
              }
82
 
              i++;
83
 
              continue;
84
 
          }
85
 
        }
86
 
        
87
 
        i += Character.toChars(Character.toLowerCase(ch), buffer, i);
88
 
      }
89
 
      
90
 
      termAtt.setLength(length);
91
 
      return true;
92
 
    } else
93
 
      return false;
94
 
  }
95
 
  
96
 
  
97
 
  /**
98
 
   * lookahead for a combining dot above.
99
 
   * other NSMs may be in between.
100
 
   */
101
 
  private boolean isBeforeDot(char s[], int pos, int len) {
102
 
    for (int i = pos; i < len;) {
103
 
      final int ch = Character.codePointAt(s, i);
104
 
      if (Character.getType(ch) != Character.NON_SPACING_MARK)
105
 
        return false;
106
 
      if (ch == COMBINING_DOT_ABOVE)
107
 
        return true;
108
 
      i += Character.charCount(ch);
109
 
    }
110
 
    
111
 
    return false;
112
 
  }
113
 
  
114
 
  /**
115
 
   * delete a character in-place.
116
 
   * rarely happens, only if COMBINING_DOT_ABOVE is found after an i
117
 
   */
118
 
  private int delete(char s[], int pos, int len) {
119
 
    if (pos < len) 
120
 
      System.arraycopy(s, pos + 1, s, pos, len - pos - 1);
121
 
    
122
 
    return len - 1;
123
 
  }
124
 
}