FrenchInflector.java
package org.andromda.utils.inflector;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Language utility for transforming French words
*
* @author Cédric Vidal
*/
public class FrenchInflector
{
private static final List<Inflection> plurals = new ArrayList<Inflection>();
private static final List<Pattern> uncountables = new ArrayList<Pattern>();
/**
*
*/
static class Inflection
{
private final Pattern pattern;
private final String replace;
/**
* @param pattern
* @param replace
*/
public Inflection(Pattern pattern, String replace)
{
super();
this.pattern = pattern;
this.replace = replace;
}
/**
* @param regexp
* @param replace
*/
public Inflection(String regexp, String replace)
{
super();
this.pattern = Pattern.compile(regexp);
this.replace = replace;
}
/**
* @return pattern
*/
public Pattern getPattern()
{
return pattern;
}
/**
* @return replace
*/
public String getReplace()
{
return replace;
}
}
static
{
/*
* NON COMPOSED WORDS
*/
uncountable(endsWith("(s|x|z)"));
/*
* -al words such as cheval -> chevaux (horse)
*/
takeAnS(new String[]{"bal", "carnaval", "c?r?monial", "chacal",
"choral", "festival", "nopal", "pal", "r?cital", "r?gal",
"santal"});
plural(endsWith("(al)"), "$1aux");
/*
* -eau words such as rideau -> rideaux (curtain) -eu words such as ?meu ->
* ?meux (the bird)
*/
takeAnS(new String[]{"landau", "sarrau", "bleu", "?meu", "emposieu",
"enfeu", "feu" /* adj */, "lieu" /* le poisson */, "pneu",
"richelieu", "schleu"});
plural(endsWith("(au|eu|eau)"), "$1$2x");
/*
* -ou words take an s except the following exceptions
*/
takeAnX(new String[]{"bijou", "caillou", "chou", "genou", "hibou",
"joujou", "pou"});
/*
* -ail words take an S suche as portail -> portails except the
* following exceptions
*/
ailIrregulars(new String[]{"b", "cor", "?m", "soupir", "trav",
"vant", "vitr"});
/*
* Exceptions that doesn't fall in any category
*/
plural(endsWith("a?eul"), "$1a?eux");
plural(endsWith("ciel"), "$1cieux");
plural(endsWith("oeil"), "$1yeux");
/*
* COMPOSED WORDS Remains to be done. Requires type information only
* available from a dictionary
*/
}
/**
* Add a pattern that if matched return the original word
*
* @param pattern
*/
private static void uncountable(String pattern)
{
uncountables.add(Pattern.compile(pattern));
}
/**
* -ail words that don't follow the rule
*
* @param strings
*/
private static void ailIrregulars(String[] strings)
{
for (String string : strings)
{
plural("(\\S*)" + string + "ail$", "$1" + string + "aux");
}
}
/**
* Words that take an S
*
* @param patterns
*/
private static void takeAnS(String[] patterns)
{
for (String string : patterns)
{
plural(endsWith(string), "$1" + string + 's');
}
}
/**
* Words that take an X
*
* @param patterns
*/
private static void takeAnX(String[] patterns)
{
for (String string : patterns)
{
plural(endsWith(string), "$1" + string + 'x');
}
}
/**
* More complex pluralizations
*
* @param pattern
* @param replace
*/
private static void plural(String pattern, String replace)
{
plurals.add(new Inflection(pattern, replace));
}
/**
* @param end
* @return a pattern that matches words ending with the given parameter
*/
private static String endsWith(String end)
{
return "(\\S*)" + end + '$';
}
/**
* Converts an French word to plural form
*
* @param str
* @return plural form
*/
public static String pluralize(String str)
{
for (Pattern pattern : uncountables)
{
Matcher matcher = pattern.matcher(str);
if (matcher.matches())
{
return str;
}
}
List<Inflection> rules = FrenchInflector.getPluralRules();
for (Inflection inflection : rules)
{
Pattern pattern = inflection.getPattern();
String replace = inflection.getReplace();
Matcher matcher = pattern.matcher(str);
if (matcher.matches())
{
return matcher.replaceFirst(replace);
}
}
return str.replaceFirst("([\\w]+)([^s])$", "$1$2s");
}
/**
* Returns map of plural patterns
*/
private static List<Inflection> getPluralRules()
{
return plurals;
}
}