001/*
002 * Copyright 2011 Atteo.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014package org.atteo.evo.inflector;
015
016import java.util.ArrayList;
017import java.util.List;
018import java.util.regex.Matcher;
019import java.util.regex.Pattern;
020
021public abstract class TwoFormInflector {
022    private static class Rule {
023        private Pattern singular;
024        private String plural;
025        private Rule(Pattern singular, String plural) {
026            this.singular = singular;
027            this.plural = plural;
028        }
029
030        public Pattern getSingular() {
031            return singular;
032        }
033
034        public String getPlural() {
035            return plural;
036        }
037    }
038    
039    private List<Rule> rules = new ArrayList<Rule>();
040    
041    protected String getPlural(String word) {
042        StringBuffer buffer = new StringBuffer();
043
044        for (Rule rule : rules) {
045            Matcher matcher = rule.getSingular().matcher(word);
046            if (matcher.find()) {
047                matcher.appendReplacement(buffer, rule.getPlural());
048                matcher.appendTail(buffer);
049                return buffer.toString();
050            }
051        }
052        return null;
053    }
054    
055    protected void uncountable(String word) {
056        rules.add(new Rule(Pattern.compile("(?i)(" + word + ")$"), "$1"));
057    }
058    
059    protected void uncountable(String[] list) {
060        StringBuilder builder = new StringBuilder();
061        builder.append("(?i)(");
062        builder.append(list[0]);
063        for (String word : list) {
064            builder.append("|").append(word);
065        }
066        builder.append(")$");
067        rules.add(new Rule(Pattern.compile(builder.toString()), "$1"));
068    }
069    
070    protected void irregular(String singular, String plural) {
071        if (singular.charAt(0) == plural.charAt(0)) {
072            rules.add(new Rule(Pattern.compile("(?i)(" + singular.charAt(0) + ")" + singular.substring(1)
073                    + "$"), "$1" + plural.substring(1)));
074        } else {
075            rules.add(new Rule(Pattern.compile(Character.toUpperCase(singular.charAt(0)) + "(?i)"
076                    + singular.substring(1) + "$"), Character.toUpperCase(plural.charAt(0))
077                    + plural.substring(1)));
078            rules.add(new Rule(Pattern.compile(Character.toLowerCase(singular.charAt(0)) + "(?i)"
079                    + singular.substring(1) + "$"), Character.toLowerCase(plural.charAt(0))
080                    + plural.substring(1)));
081        }
082    }
083    
084    protected void irregular(String[][] list) {
085        for (String[] pair : list) {
086            irregular(pair[0], pair[1]);
087        }
088    }
089    
090    protected void rule(String singular, String plural) {
091        rules.add(new Rule(Pattern.compile(singular, Pattern.CASE_INSENSITIVE), plural));
092    }
093    
094    protected void rule(String[][] list) {
095        for (String[] pair : list) {
096            rules.add(new Rule(Pattern.compile(pair[0], Pattern.CASE_INSENSITIVE), pair[1]));
097        }
098    }
099    
100    protected void categoryRule(String[] list, String singular, String plural) {
101        StringBuilder builder = new StringBuilder();
102        
103        builder.append("(?=").append(list[0]);
104        for (String word : list) {
105            builder.append("|").append(word);
106        }
107        builder.append(")");
108        builder.append(singular);
109        rules.add(new Rule(Pattern.compile(builder.toString(), Pattern.CASE_INSENSITIVE), plural));
110    }
111}