pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / analyzers / common / src / java / org / apache / lucene / analysis / fr / FrenchLightStemmer.java
1 package org.apache.lucene.analysis.fr;
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 French.
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 FrenchLightStemmer {
65  
66   public int stem(char s[], int len) {
67     if (len > 5 && s[len-1] == 'x') {
68       if (s[len-3] == 'a' && s[len-2] == 'u' && s[len-4] != 'e')
69         s[len-2] = 'l';
70       len--;
71     }
72     
73     if (len > 3 && s[len-1] == 'x')
74       len--;
75     
76     if (len > 3 && s[len-1] == 's')
77       len--;
78     
79     if (len > 9 && endsWith(s, len, "issement")) {
80       len -= 6;
81       s[len-1] = 'r';
82       return norm(s, len);
83     }
84     
85     if (len > 8 && endsWith(s, len, "issant")) {
86       len -= 4;
87       s[len-1] = 'r';
88       return norm(s, len);
89     }
90     
91     if (len > 6 && endsWith(s, len, "ement")) {
92       len -= 4;
93       if (len > 3 && endsWith(s, len, "ive")) {
94         len--;
95         s[len-1] = 'f';
96       }
97       return norm(s, len);
98     }
99     
100     if (len > 11 && endsWith(s, len, "ficatrice")) {
101       len -= 5;
102       s[len-2] = 'e';
103       s[len-1] = 'r';
104       return norm(s, len);
105     }
106     
107     if (len > 10 && endsWith(s, len, "ficateur")) {
108       len -= 4;
109       s[len-2] = 'e';
110       s[len-1] = 'r';
111       return norm(s, len);
112     }
113     
114     if (len > 9 && endsWith(s, len, "catrice")) {
115       len -= 3;
116       s[len-4] = 'q';
117       s[len-3] = 'u';
118       s[len-2] = 'e';
119       //s[len-1] = 'r' <-- unnecessary, already 'r'.
120       return norm(s, len);
121     }
122     
123     if (len > 8 && endsWith(s, len, "cateur")) {
124       len -= 2;
125       s[len-4] = 'q';
126       s[len-3] = 'u';
127       s[len-2] = 'e';
128       s[len-1] = 'r';
129       return norm(s, len);
130     }
131     
132     if (len > 8 && endsWith(s, len, "atrice")) {
133       len -= 4;
134       s[len-2] = 'e';
135       s[len-1] = 'r';
136       return norm(s, len);
137     }
138     
139     if (len > 7 && endsWith(s, len, "ateur")) {
140       len -= 3;
141       s[len-2] = 'e';
142       s[len-1] = 'r';
143       return norm(s, len);
144     }
145     
146     if (len > 6 && endsWith(s, len, "trice")) {
147       len--;
148       s[len-3] = 'e';
149       s[len-2] = 'u';
150       s[len-1] = 'r';
151     }
152     
153     if (len > 5 && endsWith(s, len, "ième"))
154       return norm(s, len-4);
155     
156     if (len > 7 && endsWith(s, len, "teuse")) {
157       len -= 2;
158       s[len-1] = 'r';
159       return norm(s, len);
160     }
161     
162     if (len > 6 && endsWith(s, len, "teur")) {
163       len--;
164       s[len-1] = 'r';
165       return norm(s, len);
166     }
167     
168     if (len > 5 && endsWith(s, len, "euse"))
169       return norm(s, len-2);
170     
171     if (len > 8 && endsWith(s, len, "ère")) {
172       len--;
173       s[len-2] = 'e';
174       return norm(s, len);
175     }
176     
177     if (len > 7 && endsWith(s, len, "ive")) {
178       len--;
179       s[len-1] = 'f';
180       return norm(s, len);
181     }
182     
183     if (len > 4 && 
184         (endsWith(s, len, "folle") ||
185          endsWith(s, len, "molle"))) {
186       len -= 2;
187       s[len-1] = 'u';
188       return norm(s, len);
189     }
190     
191     if (len > 9 && endsWith(s, len, "nnelle"))
192       return norm(s, len-5);
193     
194     if (len > 9 && endsWith(s, len, "nnel"))
195       return norm(s, len-3);
196     
197     if (len > 4 && endsWith(s, len, "ète")) {
198       len--;
199       s[len-2] = 'e';
200     }
201     
202     if (len > 8 && endsWith(s, len, "ique"))
203       len -= 4;
204     
205     if (len > 8 && endsWith(s, len, "esse"))
206       return norm(s, len-3);
207     
208     if (len > 7 && endsWith(s, len, "inage"))
209       return norm(s, len-3);
210     
211     if (len > 9 && endsWith(s, len, "isation")) {
212       len -= 7;
213       if (len > 5 && endsWith(s, len, "ual"))
214         s[len-2] = 'e';
215       return norm(s, len);
216     }
217     
218     if (len > 9 && endsWith(s, len, "isateur"))
219       return norm(s, len-7);
220     
221     if (len > 8 && endsWith(s, len, "ation"))
222       return norm(s, len-5);
223
224     if (len > 8 && endsWith(s, len, "ition"))
225       return norm(s, len-5);
226     
227     return norm(s, len);
228   }
229
230   private int norm(char s[], int len) {
231     if (len > 4) {
232       for (int i = 0; i < len; i++)
233         switch(s[i]) {
234           case 'à': 
235           case 'á':
236           case 'â': s[i] = 'a'; break;
237           case 'ô': s[i] = 'o'; break;
238           case 'è':
239           case 'é':
240           case 'ê': s[i] = 'e'; break;
241           case 'ù':
242           case 'û': s[i] = 'u'; break;
243           case 'î': s[i] = 'i'; break;
244           case 'ç': s[i] = 'c'; break;
245         }
246       
247       char ch = s[0];
248       for (int i = 1; i < len; i++) {
249         if (s[i] == ch)
250           len = delete(s, i--, len);
251         else
252           ch = s[i];
253       }
254     }
255     
256     if (len > 4 && endsWith(s, len, "ie"))
257       len -= 2;
258     
259     if (len > 4) {
260         if (s[len-1] == 'r') len--;
261         if (s[len-1] == 'e') len--;
262         if (s[len-1] == 'e') len--;
263         if (s[len-1] == s[len-2]) len--;
264     }
265     return len;
266   }
267 }