001: package org.andromda.utils.inflector;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005: import java.util.List;
006: import java.util.regex.Matcher;
007: import java.util.regex.Pattern;
008:
009: /**
010: * Language utility for transforming french words
011: *
012: * @author Cédric Vidal
013: */
014: public class FrenchInflector {
015: private static final List plurals = new ArrayList();
016:
017: private static final List uncountables = new ArrayList();
018:
019: static class Inflection {
020: private final Pattern pattern;
021:
022: private final String replace;
023:
024: public Inflection(Pattern pattern, String replace) {
025: super ();
026: this .pattern = pattern;
027: this .replace = replace;
028: }
029:
030: public Inflection(String regexp, String replace) {
031: super ();
032: this .pattern = Pattern.compile(regexp);
033: this .replace = replace;
034: }
035:
036: public Pattern getPattern() {
037: return pattern;
038: }
039:
040: public String getReplace() {
041: return replace;
042: }
043: }
044:
045: static {
046: /*
047: * NON COMPOSED WORDS
048: */
049:
050: uncountable(endsWith("(s|x|z)"));
051:
052: /*
053: * -al words such as cheval -> chevaux (horse)
054: */
055: takeAnS(new String[] { "bal", "carnaval", "c?r?monial",
056: "chacal", "choral", "festival", "nopal", "pal",
057: "r?cital", "r?gal", "santal" });
058: plural(endsWith("(al)"), "$1aux");
059:
060: /*
061: * -eau words such as rideau -> rideaux (curtain) -eu words such as ?meu ->
062: * ?meux (the bird)
063: */
064: takeAnS(new String[] { "landau", "sarrau", "bleu", "?meu",
065: "emposieu", "enfeu", "feu" /* adj */,
066: "lieu" /* le poisson */, "pneu", "richelieu", "schleu" });
067: plural(endsWith("(au|eu|eau)"), "$1$2x");
068:
069: /*
070: * -ou words take an s except the following exceptions
071: */
072: takeAnX(new String[] { "bijou", "caillou", "chou", "genou",
073: "hibou", "joujou", "pou" });
074:
075: /*
076: * -ail words take an S suche as portail -> portails except the
077: * following exceptions
078: */
079: ailIrregulars(new String[] { "b", "cor", "?m", "soupir",
080: "trav", "vant", "vitr" });
081:
082: /*
083: * Exceptions that doesn't fall in any category
084: */
085: plural(endsWith("a?eul"), "$1a?eux");
086: plural(endsWith("ciel"), "$1cieux");
087: plural(endsWith("oeil"), "$1yeux");
088:
089: /*
090: * COMPOSED WORDS Remains to be done. Requires type information only
091: * available from a dictionary
092: */
093: }
094:
095: /**
096: * Add a pattern that if matched return the original word
097: *
098: * @param pattern
099: */
100: private static void uncountable(String pattern) {
101: uncountables.add(Pattern.compile(pattern));
102: }
103:
104: /**
105: * -ail words that don't follow the rule
106: *
107: * @param strings
108: */
109: private static void ailIrregulars(String[] strings) {
110: for (int i = 0; i < strings.length; i++) {
111: String string = strings[i];
112: plural("(\\S*)" + string + "ail$", "$1" + string + "aux");
113: }
114: }
115:
116: /**
117: * Words that take an S
118: *
119: * @param patterns
120: */
121: private static void takeAnS(String[] patterns) {
122: for (int i = 0; i < patterns.length; i++) {
123: String string = patterns[i];
124: plural(endsWith(string), "$1" + string + "s");
125: }
126: }
127:
128: /**
129: * Words that take an X
130: *
131: * @param patterns
132: */
133: private static void takeAnX(String[] patterns) {
134: for (int i = 0; i < patterns.length; i++) {
135: String string = patterns[i];
136: plural(endsWith(string), "$1" + string + "x");
137: }
138: }
139:
140: /**
141: * More complex pluralizations
142: *
143: * @param pattern
144: * @param replace
145: */
146: private static void plural(String pattern, String replace) {
147: plurals.add(new Inflection(pattern, replace));
148: }
149:
150: /**
151: * @param end
152: * @return a pattern that matches words ending with the given parameter
153: */
154: private static String endsWith(String end) {
155: return "(\\S*)" + end + "$";
156: }
157:
158: /**
159: * Converts an french word to plural form
160: *
161: * @param str
162: */
163: public static String pluralize(String str) {
164:
165: for (Iterator i = uncountables.iterator(); i.hasNext();) {
166: Pattern pattern = (Pattern) i.next();
167: Matcher matcher = pattern.matcher(str);
168: if (matcher.matches()) {
169: return str;
170: }
171: }
172:
173: List rules = FrenchInflector.getPluralRules();
174: for (Iterator i = rules.iterator(); i.hasNext();) {
175: Inflection inflection = (Inflection) i.next();
176: Pattern pattern = inflection.getPattern();
177: String replace = inflection.getReplace();
178: Matcher matcher = pattern.matcher(str);
179: if (matcher.matches()) {
180: return matcher.replaceFirst(replace);
181: }
182: }
183: return str.replaceFirst("([\\w]+)([^s])$", "$1$2s");
184: }
185:
186: /**
187: * Returns map of plural patterns
188: */
189: private static List getPluralRules() {
190: return plurals;
191: }
192: }
|