com.entopix.maui.stemmers.PorterStemmer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maui Show documentation
Show all versions of maui Show documentation
Maui automatically identifies main topics in text documents. Depending on the task,
topics are tags, keywords, keyphrases, vocabulary terms, descriptors, index terms or
titles of Wikipedia articles.
The newest version!
package com.entopix.maui.stemmers;
/**
*
* PorterStemmer.java
* Programmer: John Keyes ([email protected])
* Last Modified: January 3, 1998
* This class implements the PORTER stemming algorithm, which
* is fully described in "An algorithm for suffix stripping",
* M.F. Porter (1980), _Program_, Vol. 14, No. 3, pp. 130-137
*
*/
public class PorterStemmer extends Stemmer {
/**
*
*/
private static final long serialVersionUID = 1L;
public String stem(String str) {
// check for zero length
if (str.length() > 3) {
// all characters must be letters
char[] c = str.toCharArray();
for (int i = 0; i < c.length; i++) {
if (!Character.isLetter(c[i])) {
return str;
}
}
} else {
return str;
}
str = step1a(str);
str = step1b(str);
str = step1c(str);
str = step2(str);
str = step3(str);
str = step4(str);
str = step5a(str);
str = step5b(str);
return str;
} // end stem
protected String step1a (String str) {
// SSES -> SS
if (str.endsWith("sses")) {
return str.substring(0, str.length() - 2);
// IES -> I
} else if (str.endsWith("ies")) {
return str.substring(0, str.length() - 2);
// SS -> S
} else if (str.endsWith("ss")) {
return str;
// S ->
} else if (str.endsWith("s")) {
return str.substring(0, str.length() - 1);
} else {
return str;
}
} // end step1a
protected String step1b (String str) {
// (m > 0) EED -> EE
if (str.endsWith("eed")) {
if (stringMeasure(str.substring(0, str.length() - 3)) > 0)
return str.substring(0, str.length() - 1);
else
return str;
// (*v*) ED ->
} else if ((str.endsWith("ed")) &&
(containsVowel(str.substring(0, str.length() - 2)))) {
return step1b2(str.substring(0, str.length() - 2));
// (*v*) ING ->
} else if ((str.endsWith("ing")) &&
(containsVowel(str.substring(0, str.length() - 3)))) {
return step1b2(str.substring(0, str.length() - 3));
} // end if
return str;
} // end step1b
protected String step1b2 (String str) {
// AT -> ATE
if (str.endsWith("at") ||
str.endsWith("bl") ||
str.endsWith("iz")) {
return str + "e";
} else if ((str.length() > 1) && (endsWithDoubleConsonent(str)) &&
(!(str.endsWith("l") || str.endsWith("s") || str.endsWith("z")))) {
return str.substring(0, str.length() - 1);
} else if ((stringMeasure(str) == 1) &&
(endsWithCVC(str))) {
return str + "e";
} else {
return str;
}
} // end step1b2
protected String step1c(String str) {
// (*v*) Y -> I
if (str.endsWith("y")) {
if (containsVowel(str.substring(0, str.length() - 1)))
return str.substring(0, str.length() - 1) + "i";
} // end if
return str;
} // end step1c
protected String step2 (String str) {
// (m > 0) ATIONAL -> ATE
if ((str.endsWith("ational")) &&
(stringMeasure(str.substring(0, str.length() - 5)) > 0)) {
return str.substring(0, str.length() - 5) + "e";
// (m > 0) TIONAL -> TION
} else if ((str.endsWith("tional")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) ENCI -> ENCE
} else if ((str.endsWith("enci")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) ANCI -> ANCE
} else if ((str.endsWith("anci")) &&
(stringMeasure(str.substring(0, str.length() - 1)) > 0)) {
return str.substring(0, str.length() - 1) + "e";
// (m > 0) IZER -> IZE
} else if ((str.endsWith("izer")) &&
(stringMeasure(str.substring(0, str.length() - 1)) > 0)) {
return str.substring(0, str.length() - 1);
// (m > 0) ABLI -> ABLE
} else if ((str.endsWith("abli")) &&
(stringMeasure(str.substring(0, str.length() - 1)) > 0)) {
return str.substring(0, str.length() - 1) + "e";
// (m > 0) ENTLI -> ENT
} else if ((str.endsWith("alli")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) ELI -> E
} else if ((str.endsWith("entli")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) OUSLI -> OUS
} else if ((str.endsWith("eli")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) IZATION -> IZE
} else if ((str.endsWith("ousli")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) IZATION -> IZE
} else if ((str.endsWith("ization")) &&
(stringMeasure(str.substring(0, str.length() - 5)) > 0)) {
return str.substring(0, str.length() - 5) + "e";
// (m > 0) ATION -> ATE
} else if ((str.endsWith("ation")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3) + "e";
// (m > 0) ATOR -> ATE
} else if ((str.endsWith("ator")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2) + "e";
// (m > 0) ALISM -> AL
} else if ((str.endsWith("alism")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) IVENESS -> IVE
} else if ((str.endsWith("iveness")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 0)) {
return str.substring(0, str.length() - 4);
// (m > 0) FULNESS -> FUL
} else if ((str.endsWith("fulness")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 0)) {
return str.substring(0, str.length() - 4);
// (m > 0) OUSNESS -> OUS
} else if ((str.endsWith("ousness")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 0)) {
return str.substring(0, str.length() - 4);
// (m > 0) ALITII -> AL
} else if ((str.endsWith("aliti")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) IVITI -> IVE
} else if ((str.endsWith("iviti")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3) + "e";
// (m > 0) BILITI -> BLE
} else if ((str.endsWith("biliti")) &&
(stringMeasure(str.substring(0, str.length() - 5)) > 0)) {
return str.substring(0, str.length() - 5) + "le";
} // end if
return str;
} // end step2
protected String step3 (String str) {
// (m > 0) ICATE -> IC
if ((str.endsWith("icate")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) ATIVE ->
} else if ((str.endsWith("ative")) &&
(stringMeasure(str.substring(0, str.length() - 5)) > 0)) {
return str.substring(0, str.length() - 5);
// (m > 0) ALIZE -> AL
} else if ((str.endsWith("alize")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) ICITI -> IC
} else if ((str.endsWith("iciti")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) ICAL -> IC
} else if ((str.endsWith("ical")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 0)) {
return str.substring(0, str.length() - 2);
// (m > 0) FUL ->
} else if ((str.endsWith("ful")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 0)) {
return str.substring(0, str.length() - 3);
// (m > 0) NESS ->
} else if ((str.endsWith("ness")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 0)) {
return str.substring(0, str.length() - 4);
} // end if
return str;
} // end step3
protected String step4 (String str) {
if ((str.endsWith("al")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 1)) {
return str.substring(0, str.length() - 2);
// (m > 1) ANCE ->
} else if ((str.endsWith("ance")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 1)) {
return str.substring(0, str.length() - 4);
// (m > 1) ENCE ->
} else if ((str.endsWith("ence")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 1)) {
return str.substring(0, str.length() - 4);
// (m > 1) ER ->
} else if ((str.endsWith("er")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 1)) {
return str.substring(0, str.length() - 2);
// (m > 1) IC ->
} else if ((str.endsWith("ic")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 1)) {
return str.substring(0, str.length() - 2);
// (m > 1) ABLE ->
} else if ((str.endsWith("able")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 1)) {
return str.substring(0, str.length() - 4);
// (m > 1) IBLE ->
} else if ((str.endsWith("ible")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 1)) {
return str.substring(0, str.length() - 4);
// (m > 1) ANT ->
} else if ((str.endsWith("ant")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) EMENT ->
} else if ((str.endsWith("ement")) &&
(stringMeasure(str.substring(0, str.length() - 5)) > 1)) {
return str.substring(0, str.length() - 5);
// (m > 1) MENT ->
} else if ((str.endsWith("ment")) &&
(stringMeasure(str.substring(0, str.length() - 4)) > 1)) {
return str.substring(0, str.length() - 4);
// (m > 1) ENT ->
} else if ((str.endsWith("ent")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) and (*S or *T) ION ->
} else if ((str.endsWith("sion") || str.endsWith("tion")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) OU ->
} else if ((str.endsWith("ou")) &&
(stringMeasure(str.substring(0, str.length() - 2)) > 1)) {
return str.substring(0, str.length() - 2);
// (m > 1) ISM ->
} else if ((str.endsWith("ism")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) ATE ->
} else if ((str.endsWith("ate")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) ITI ->
} else if ((str.endsWith("iti")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) OUS ->
} else if ((str.endsWith("ous")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) IVE ->
} else if ((str.endsWith("ive")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
// (m > 1) IZE ->
} else if ((str.endsWith("ize")) &&
(stringMeasure(str.substring(0, str.length() - 3)) > 1)) {
return str.substring(0, str.length() - 3);
} // end if
return str;
} // end step4
protected String step5a (String str) {
// (m > 1) E ->
if ((stringMeasure(str.substring(0, str.length() - 1)) > 1) &&
str.endsWith("e"))
return str.substring(0, str.length() -1);
// (m = 1 and not *0) E ->
else if ((stringMeasure(str.substring(0, str.length() - 1)) == 1) &&
(!endsWithCVC(str.substring(0, str.length() - 1))) &&
(str.endsWith("e")))
return str.substring(0, str.length() - 1);
else
return str;
} // end step5a
protected String step5b (String str) {
// (m > 1 and *d and *L) ->
if (str.endsWith("l") &&
endsWithDoubleConsonent(str) &&
(stringMeasure(str.substring(0, str.length() - 1)) > 1)) {
return str.substring(0, str.length() - 1);
} else {
return str;
}
} // end step5b
/*
-------------------------------------------------------
The following are functions to help compute steps 1 - 5
-------------------------------------------------------
*/
// does string end with 's'?
protected boolean endsWithS(String str) {
return str.endsWith("s");
} // end function
// does string contain a vowel?
protected boolean containsVowel(String str) {
char[] strchars = str.toCharArray();
for (int i = 0; i < strchars.length; i++) {
if (isVowel(strchars[i]))
return true;
}
// no aeiou but there is y
if (str.indexOf('y') > -1)
return true;
else
return false;
} // end function
// is char a vowel?
public boolean isVowel(char c) {
if ((c == 'a') ||
(c == 'e') ||
(c == 'i') ||
(c == 'o') ||
(c == 'u'))
return true;
else
return false;
} // end function
// does string end with a double consonent?
protected boolean endsWithDoubleConsonent(String str) {
char c = str.charAt(str.length() - 1);
if (c == str.charAt(str.length() - 2))
if (!containsVowel(str.substring(str.length() - 2))) {
return true;
}
return false;
} // end function
// returns a CVC measure for the string
protected int stringMeasure(String str) {
int count = 0;
boolean vowelSeen = false;
char[] strchars = str.toCharArray();
for (int i = 0; i < strchars.length; i++) {
if (isVowel(strchars[i])) {
vowelSeen = true;
} else if (vowelSeen) {
count++;
vowelSeen = false;
}
} // end for
return count;
} // end function
// does stem end with CVC?
protected boolean endsWithCVC (String str) {
char c, v, c2 = ' ';
if (str.length() >= 3) {
c = str.charAt(str.length() - 1);
v = str.charAt(str.length() - 2);
c2 = str.charAt(str.length() - 3);
} else {
return false;
}
if ((c == 'w') || (c == 'x') || (c == 'y')) {
return false;
} else if (isVowel(c)) {
return false;
} else if (!isVowel(v)) {
return false;
} else if (isVowel(c2)) {
return false;
} else {
return true;
}
} // end function
} // end class