add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / analyzers / common / src / java / org / apache / lucene / analysis / id / IndonesianStemmer.java
1 package org.apache.lucene.analysis.id;
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 static org.apache.lucene.analysis.util.StemmerUtil.*;
21
22 /**
23  * Stemmer for Indonesian.
24  * <p>
25  * Stems Indonesian words with the algorithm presented in:
26  * <i>A Study of Stemming Effects on Information Retrieval in 
27  * Bahasa Indonesia</i>, Fadillah Z Tala.
28  * http://www.illc.uva.nl/Publications/ResearchReports/MoL-2003-02.text.pdf
29  */
30 public class IndonesianStemmer {
31   private int numSyllables;
32   private int flags;
33   private static final int REMOVED_KE = 1;
34   private static final int REMOVED_PENG = 2;
35   private static final int REMOVED_DI = 4;
36   private static final int REMOVED_MENG = 8;
37   private static final int REMOVED_TER = 16;
38   private static final int REMOVED_BER = 32;
39   private static final int REMOVED_PE = 64;
40   
41   /**
42    * Stem a term (returning its new length).
43    * <p>
44    * Use <code>stemDerivational</code> to control whether full stemming
45    * or only light inflectional stemming is done.
46    */
47   public int stem(char text[], int length, boolean stemDerivational) {
48     flags = 0;
49     numSyllables = 0;
50     for (int i = 0; i < length; i++)
51       if (isVowel(text[i]))
52           numSyllables++;
53     
54     if (numSyllables > 2) length = removeParticle(text, length);
55     if (numSyllables > 2) length = removePossessivePronoun(text, length);
56     
57     if (stemDerivational)
58       length = stemDerivational(text, length);
59     return length;
60   }
61   
62   private int stemDerivational(char text[], int length) {
63     int oldLength = length;
64     if (numSyllables > 2) length = removeFirstOrderPrefix(text, length);
65     if (oldLength != length) { // a rule is fired
66       oldLength = length;
67       if (numSyllables > 2) length = removeSuffix(text, length);
68       if (oldLength != length) // a rule is fired
69         if (numSyllables > 2) length = removeSecondOrderPrefix(text, length);
70     } else { // fail
71       if (numSyllables > 2) length = removeSecondOrderPrefix(text, length);
72       if (numSyllables > 2) length = removeSuffix(text, length);
73     }
74     return length;
75   }
76   
77   private boolean isVowel(char ch) {
78     switch(ch) {
79       case 'a':
80       case 'e':
81       case 'i':
82       case 'o':
83       case 'u':
84         return true;
85       default:
86         return false;
87     }
88   }
89   
90   private int removeParticle(char text[], int length) {
91     if (endsWith(text, length, "kah") || 
92         endsWith(text, length, "lah") || 
93         endsWith(text, length, "pun")) {
94         numSyllables--;
95         return length - 3;
96     }
97     
98     return length;
99   }
100   
101   private int removePossessivePronoun(char text[], int length) {
102     if (endsWith(text, length, "ku") || endsWith(text, length, "mu")) {
103       numSyllables--;
104       return length - 2;
105     }
106     
107     if (endsWith(text, length, "nya")) {
108       numSyllables--;
109       return length - 3;
110     }
111     
112     return length;
113   }
114   
115   private int removeFirstOrderPrefix(char text[], int length) {
116     if (startsWith(text, length, "meng")) {
117       flags |= REMOVED_MENG;
118       numSyllables--;
119       return deleteN(text, 0, length, 4);
120     }
121     
122     if (startsWith(text, length, "meny") && length > 4 && isVowel(text[4])) {
123       flags |= REMOVED_MENG;
124       text[3] = 's';
125       numSyllables--;
126       return deleteN(text, 0, length, 3);
127     }
128     
129     if (startsWith(text, length, "men")) {
130       flags |= REMOVED_MENG;
131       numSyllables--;
132       return deleteN(text, 0, length, 3);
133     }
134  
135     if (startsWith(text, length, "mem")) {
136       flags |= REMOVED_MENG;
137       numSyllables--;
138       return deleteN(text, 0, length, 3);
139     }
140     
141     if (startsWith(text, length, "me")) {
142       flags |= REMOVED_MENG;
143       numSyllables--;
144       return deleteN(text, 0, length, 2);
145     }
146     
147     if (startsWith(text, length, "peng")) {
148       flags |= REMOVED_PENG;
149       numSyllables--;
150       return deleteN(text, 0, length, 4);
151     }
152     
153     if (startsWith(text, length, "peny") && length > 4 && isVowel(text[4])) {
154       flags |= REMOVED_PENG;
155       text[3] = 's';
156       numSyllables--;
157       return deleteN(text, 0, length, 3);
158     }
159     
160     if (startsWith(text, length, "peny")) {
161       flags |= REMOVED_PENG;
162       numSyllables--;
163       return deleteN(text, 0, length, 4);
164     }
165     
166     if (startsWith(text, length, "pen") && length > 3 && isVowel(text[3])) {
167       flags |= REMOVED_PENG;
168       text[2] = 't';
169       numSyllables--;
170       return deleteN(text, 0, length, 2);
171     }
172
173     if (startsWith(text, length, "pen")) {
174       flags |= REMOVED_PENG;
175       numSyllables--;
176       return deleteN(text, 0, length, 3);
177     }
178     
179     if (startsWith(text, length, "pem")) {
180       flags |= REMOVED_PENG;
181       numSyllables--;
182       return deleteN(text, 0, length, 3);
183     }
184     
185     if (startsWith(text, length, "di")) {
186       flags |= REMOVED_DI;
187       numSyllables--;
188       return deleteN(text, 0, length, 2);
189     }
190     
191     if (startsWith(text, length, "ter")) {
192       flags |= REMOVED_TER;
193       numSyllables--;
194       return deleteN(text, 0, length, 3);
195     }
196     
197     if (startsWith(text, length, "ke")) {
198       flags |= REMOVED_KE;
199       numSyllables--;
200       return deleteN(text, 0, length, 2);
201     }
202     
203     return length;
204   }
205   
206   private int removeSecondOrderPrefix(char text[], int length) {
207     if (startsWith(text, length, "ber")) {
208       flags |= REMOVED_BER;
209       numSyllables--;
210       return deleteN(text, 0, length, 3);
211     }
212     
213     if (length == 7 && startsWith(text, length, "belajar")) {
214       flags |= REMOVED_BER;
215       numSyllables--;
216       return deleteN(text, 0, length, 3);
217     }
218     
219     if (startsWith(text, length, "be") && length > 4 
220         && !isVowel(text[2]) && text[3] == 'e' && text[4] == 'r') {
221       flags |= REMOVED_BER;
222       numSyllables--;
223       return deleteN(text, 0, length, 2);
224     }
225     
226     if (startsWith(text, length, "per")) {
227       numSyllables--;
228       return deleteN(text, 0, length, 3);
229     }
230     
231     if (length == 7 && startsWith(text, length, "pelajar")) {
232       numSyllables--;
233       return deleteN(text, 0, length, 3);
234     }
235     
236     if (startsWith(text, length, "pe")) {
237       flags |= REMOVED_PE;
238       numSyllables--;
239       return deleteN(text, 0, length, 2);
240     }
241
242     return length;
243   }
244   
245   private int removeSuffix(char text[], int length) {
246     if (endsWith(text, length, "kan") 
247         && (flags & REMOVED_KE) == 0 
248         && (flags & REMOVED_PENG) == 0 
249         && (flags & REMOVED_PE) == 0) {
250       numSyllables--;
251       return length - 3;
252     }
253     
254     if (endsWith(text, length, "an") 
255         && (flags & REMOVED_DI) == 0 
256         && (flags & REMOVED_MENG) == 0 
257         && (flags & REMOVED_TER) == 0) {
258       numSyllables--;
259       return length - 2;
260     }
261     
262     if (endsWith(text, length, "i") 
263         && !endsWith(text, length, "si") 
264         && (flags & REMOVED_BER) == 0 
265         && (flags & REMOVED_KE) == 0 
266         && (flags & REMOVED_PENG) == 0) {
267       numSyllables--;
268       return length - 1;
269     }
270     return length;
271   }  
272 }