package controller.similaritycheck; import java.util.*; import java.util.regex.*; /** * Transforms words from singular to plural * Some special cases like man -> men will be consided in SpellCheck * So we don't need to handle them here * Other special cases like mice or "~oes" are not consider right now * * @author Dong Guo */ public class PluralInflector { //Can't think of a better name, but this is needed to avoid the price of initializing the pattern on each call. private static final Pattern UNDERSCORE_PATTERN_1 = Pattern.compile("([A-Z]+)([A-Z][a-z])"); private static final Pattern UNDERSCORE_PATTERN_2 = Pattern.compile("([a-z\\d])([A-Z])"); private static List<RuleAndReplacement> plurals = new ArrayList<RuleAndReplacement>(); private static PluralInflector instance; // (Pseudo-)Singleton instance. //constructor private PluralInflector() { initialize(); } //regex patterns private void initialize() { plural("$", "s"); plural("(s|z|x|ch|ss|sh)$", "$1es"); plural("([^aeiouy]|qu)y$", "$1ies"); plural("(?:([^f])fe|([lr])f)$", "$1$2ves"); plural("(ox)$", "$1en"); plural("(child)$", "$1ren"); } //Factory function public static PluralInflector getInstance() { if (instance == null) { instance = new PluralInflector(); } return instance; } //public API, the one that will be invoked public String pluralize(String word) { return replaceWithFirstRule(word, plurals); } //process function private String replaceWithFirstRule(String word, List<RuleAndReplacement> ruleAndReplacements) { for (RuleAndReplacement rar : ruleAndReplacements) { String rule = rar.getRule(); String replacement = rar.getReplacement(); // Return if we find a match. Matcher matcher = Pattern.compile(rule, Pattern.CASE_INSENSITIVE).matcher(word); if (matcher.find()) { return matcher.replaceAll(replacement); } } return word; } public static void plural(String rule, String replacement) { plurals.add(0, new RuleAndReplacement(rule, replacement)); } public static Pattern getUnderscorePattern1() { return UNDERSCORE_PATTERN_1; } public static Pattern getUnderscorePattern2() { return UNDERSCORE_PATTERN_2; } } //content class class RuleAndReplacement { private String rule; private String replacement; //constructor public RuleAndReplacement(String rule, String replacement) { this.rule = rule; this.replacement = replacement; } /** * Get the part that will replace the original * * @return replacement String */ public String getReplacement() { return replacement; } /** * Set the part that will replace the original * * @param replacement */ public void setReplacement(String replacement) { this.replacement = replacement; } /** * Get the String that will be changed * * @return rule String */ public String getRule() { return rule; } /** * Set the String that will be changed * * @param rule */ public void setRule(String rule) { this.rule = rule; } }