~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/hu/HungarianLightStemmer.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.hu;
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
 
/* 
21
 
 * This algorithm is updated based on code located at:
22
 
 * http://members.unine.ch/jacques.savoy/clef/
23
 
 * 
24
 
 * Full copyright for that code follows:
25
 
 */
26
 
 
27
 
/*
28
 
 * Copyright (c) 2005, Jacques Savoy
29
 
 * All rights reserved.
30
 
 *
31
 
 * Redistribution and use in source and binary forms, with or without 
32
 
 * modification, are permitted provided that the following conditions are met:
33
 
 *
34
 
 * Redistributions of source code must retain the above copyright notice, this 
35
 
 * list of conditions and the following disclaimer. Redistributions in binary 
36
 
 * form must reproduce the above copyright notice, this list of conditions and
37
 
 * the following disclaimer in the documentation and/or other materials 
38
 
 * provided with the distribution. Neither the name of the author nor the names 
39
 
 * of its contributors may be used to endorse or promote products derived from 
40
 
 * this software without specific prior written permission.
41
 
 * 
42
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
43
 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
44
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
45
 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
46
 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
47
 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
48
 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
49
 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
50
 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
51
 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52
 
 * POSSIBILITY OF SUCH DAMAGE.
53
 
 */
54
 
 
55
 
import static org.apache.lucene.analysis.util.StemmerUtil.*;
56
 
 
57
 
/**
58
 
 * Light Stemmer for Hungarian.
59
 
 * <p>
60
 
 * This stemmer implements the "UniNE" algorithm in:
61
 
 * <i>Light Stemming Approaches for the French, Portuguese, German and Hungarian Languages</i>
62
 
 * Jacques Savoy
63
 
 */
64
 
public class HungarianLightStemmer {
65
 
  public int stem(char s[], int len) {
66
 
    for (int i = 0; i < len; i++)
67
 
      switch(s[i]) {
68
 
        case 'á': s[i] = 'a'; break;
69
 
        case 'ë':
70
 
        case 'é': s[i] = 'e'; break;
71
 
        case 'í': s[i] = 'i'; break;
72
 
        case 'ó':
73
 
        case 'ő':
74
 
        case 'õ':
75
 
        case 'ö': s[i] = 'o'; break;
76
 
        case 'ú':
77
 
        case 'ű':
78
 
        case 'ũ':
79
 
        case 'û':
80
 
        case 'ü': s[i] = 'u'; break;
81
 
      }
82
 
    
83
 
    len = removeCase(s, len);
84
 
    len = removePossessive(s, len);
85
 
    len = removePlural(s, len);
86
 
    return normalize(s, len);
87
 
  }
88
 
  
89
 
  private int removeCase(char s[], int len) {
90
 
    if (len > 6 && endsWith(s, len, "kent"))
91
 
      return len - 4;
92
 
    
93
 
    if (len > 5) {
94
 
      if (endsWith(s, len, "nak") ||
95
 
          endsWith(s, len, "nek") ||
96
 
          endsWith(s, len, "val") ||
97
 
          endsWith(s, len, "vel") ||
98
 
          endsWith(s, len, "ert") ||
99
 
          endsWith(s, len, "rol") ||
100
 
          endsWith(s, len, "ban") ||
101
 
          endsWith(s, len, "ben") ||
102
 
          endsWith(s, len, "bol") ||
103
 
          endsWith(s, len, "nal") ||
104
 
          endsWith(s, len, "nel") ||
105
 
          endsWith(s, len, "hoz") ||
106
 
          endsWith(s, len, "hez") ||
107
 
          endsWith(s, len, "tol"))
108
 
        return len - 3;
109
 
      
110
 
      if (endsWith(s, len, "al") || endsWith(s, len, "el")) {
111
 
        if (!isVowel(s[len-3]) && s[len-3] == s[len-4])
112
 
          return len - 3;
113
 
      }
114
 
    }
115
 
    
116
 
    if (len > 4) {
117
 
      if (endsWith(s, len, "at") ||
118
 
          endsWith(s, len, "et") ||
119
 
          endsWith(s, len, "ot") ||
120
 
          endsWith(s, len, "va") ||
121
 
          endsWith(s, len, "ve") ||
122
 
          endsWith(s, len, "ra") ||
123
 
          endsWith(s, len, "re") ||
124
 
          endsWith(s, len, "ba") ||
125
 
          endsWith(s, len, "be") ||
126
 
          endsWith(s, len, "ul") ||
127
 
          endsWith(s, len, "ig"))
128
 
        return len - 2;
129
 
      
130
 
      if ((endsWith(s, len, "on") || endsWith(s, len, "en")) && !isVowel(s[len-3]))
131
 
          return len - 2;
132
 
      
133
 
      switch(s[len-1]) {
134
 
        case 't':
135
 
        case 'n': return len - 1;
136
 
        case 'a':
137
 
        case 'e': if (s[len-2] == s[len-3] && !isVowel(s[len-2])) return len - 2;
138
 
      }
139
 
    }
140
 
    
141
 
    return len;
142
 
  }
143
 
 
144
 
  private int removePossessive(char s[], int len) {
145
 
    if (len > 6) {
146
 
      if (!isVowel(s[len-5]) && 
147
 
         (endsWith(s, len, "atok") || 
148
 
          endsWith(s, len, "otok") || 
149
 
          endsWith(s, len, "etek")))
150
 
        return len - 4;
151
 
      
152
 
      if (endsWith(s, len, "itek") || endsWith(s, len, "itok"))
153
 
        return len - 4;
154
 
    }
155
 
    
156
 
    if (len > 5) {
157
 
      if (!isVowel(s[len-4]) &&
158
 
        (endsWith(s, len, "unk") ||
159
 
         endsWith(s, len, "tok") ||
160
 
         endsWith(s, len, "tek")))
161
 
        return len - 3;
162
 
      
163
 
      if (isVowel(s[len-4]) && endsWith(s, len, "juk"))
164
 
        return len - 3;
165
 
      
166
 
      if (endsWith(s, len, "ink"))
167
 
        return len - 3;
168
 
    }
169
 
    
170
 
    if (len > 4) {
171
 
      if (!isVowel(s[len-3]) &&
172
 
         (endsWith(s, len, "am") ||
173
 
          endsWith(s, len, "em") ||
174
 
          endsWith(s, len, "om") ||
175
 
          endsWith(s, len, "ad") ||
176
 
          endsWith(s, len, "ed") ||
177
 
          endsWith(s, len, "od") ||
178
 
          endsWith(s, len, "uk")))
179
 
        return len - 2;
180
 
      
181
 
      if (isVowel(s[len-3]) &&
182
 
         (endsWith(s, len, "nk") ||
183
 
          endsWith(s, len, "ja") ||
184
 
          endsWith(s, len, "je")))
185
 
        return len - 2;
186
 
      
187
 
      if (endsWith(s, len, "im") ||
188
 
          endsWith(s, len, "id") ||
189
 
          endsWith(s, len, "ik"))
190
 
        return len - 2;
191
 
    }
192
 
    
193
 
    if (len > 3)
194
 
      switch(s[len-1]) {
195
 
        case 'a':
196
 
        case 'e': if (!isVowel(s[len-2])) return len - 1; break;
197
 
        case 'm':
198
 
        case 'd': if (isVowel(s[len-2])) return len - 1; break;
199
 
        case 'i': return len - 1;
200
 
      }
201
 
    
202
 
    return len;
203
 
  }
204
 
 
205
 
  @SuppressWarnings("fallthrough")
206
 
  private int removePlural(char s[], int len) {
207
 
    if (len > 3 && s[len-1] == 'k')
208
 
      switch(s[len-2]) {
209
 
        case 'a':
210
 
        case 'o':
211
 
        case 'e': if (len > 4) return len - 2; /* intentional fallthru */
212
 
        default: return len - 1;
213
 
      }
214
 
    return len;
215
 
  }
216
 
 
217
 
  private int normalize(char s[], int len) {
218
 
    if (len > 3)
219
 
      switch(s[len-1]) {
220
 
        case 'a':
221
 
        case 'e':
222
 
        case 'i':
223
 
        case 'o': return len - 1;
224
 
      }
225
 
    return len;
226
 
  }
227
 
 
228
 
  private boolean isVowel(char ch) {
229
 
    switch(ch) {
230
 
      case 'a':
231
 
      case 'e':
232
 
      case 'i':
233
 
      case 'o':
234
 
      case 'u':
235
 
      case 'y': return true;
236
 
      default: return false;
237
 
    }
238
 
  }
239
 
}