OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 144 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.utils.i18n;

import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.jcip.annotations.Immutable;

@Immutable
public class Grammar_fr extends Grammar {

    static private final Grammar_fr INSTANCE = new Grammar_fr();

    public static Grammar_fr getInstance() {
        return INSTANCE;
    }

    private Grammar_fr() {
        this(Locale.FRENCH);
    }

    protected Grammar_fr(final Locale l) {
        super(l);
    }

    @Override
    protected Collection<? extends VariantKey> createVariantKeys() {
        return Arrays.asList(SINGULAR, PLURAL, INDEFINITE_ARTICLE_SINGULAR, INDEFINITE_ARTICLE_PLURAL, DEFINITE_ARTICLE_SINGULAR, DEFINITE_ARTICLE_PLURAL, DEMONSTRATIVE_SINGULAR, DEMONSTRATIVE_PLURAL,
                INDEFINITE_NUMERAL, DEFINITE_NUMERAL, DEMONSTRATIVE_NUMERAL, INDEFINITE_ORDINAL, DEFINITE_ORDINAL);
    }

    @Override
    protected Collection<? extends NounClass> createNounClasses() {
        return Arrays.asList(NounClass.FEMININE, NounClass.MASCULINE);
    }

    public final Phrase createPhrase(final NounClass nounClass, final String singular) {
        return this.createPhrase(nounClass, singular, null);
    }

    public final Phrase createPhrase(final NounClass nounClass, final String singular, final String plural) {
        if (!this.getNounClasses().contains(nounClass))
            throw new IllegalArgumentException("invalid nounClass : " + nounClass);
        final Phrase res = new Phrase(this, singular, nounClass);
        if (plural != null)
            res.putVariant(PLURAL, plural);
        return res;
    }

    @Override
    public String getVariant(Phrase noun, VariantKey key) {
        final String res;
        if (key.equals(SINGULAR)) {
            res = noun.getBase();
        } else if (key.equals(INDEFINITE_ARTICLE_SINGULAR)) {
            res = (noun.getNounClass() == NounClass.FEMININE ? "une " : "un ") + getSingular(noun);
        } else if (key.equals(DEFINITE_ARTICLE_SINGULAR)) {
            res = getDefiniteArticle(noun) + getSingular(noun);
        } else if (key.equals(DEMONSTRATIVE_SINGULAR)) {
            res = getCe(noun) + getSingular(noun);
        } else if (key.equals(PLURAL)) {
            res = getPlural(noun.getBase());
        } else if (key.equals(INDEFINITE_ARTICLE_PLURAL)) {
            res = "des " + getPlural(noun);
        } else if (key.equals(DEFINITE_ARTICLE_PLURAL)) {
            res = "les " + getPlural(noun);
        } else if (key.equals(DEMONSTRATIVE_PLURAL)) {
            res = "ces " + getPlural(noun);
        } else if (key.equals(INDEFINITE_NUMERAL)) {
            res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {# " + getSingular(noun) + "} other {# " + getPlural(noun) + "}}";
        } else if (key.equals(DEFINITE_NUMERAL)) {
            res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {" + noun.getVariant(DEFINITE_ARTICLE_SINGULAR) + "} other {les # " + getPlural(noun) + "}}";
        } else if (key.equals(DEMONSTRATIVE_NUMERAL)) {
            res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {" + noun.getVariant(DEMONSTRATIVE_SINGULAR) + "} other {ces # " + getPlural(noun) + "}}";
        } else if (key.equals(DEFINITE_ORDINAL) || key.equals(INDEFINITE_ORDINAL)) {
            final boolean estFéminin = noun.getNounClass() == NounClass.FEMININE;
            final String article = key.equals(DEFINITE_ORDINAL) ? (estFéminin ? "la " : "le ") : "";
            res = article + "{0, ordinal, %digits-ordinal" + (estFéminin ? "-feminine" : "") + "} " + getSingular(noun);
        } else {
            res = null;
        }

        return res;
    }

    protected String getDefiniteArticle(Phrase noun) {
        if (startsWithVowel(noun.getBase()))
            return "l’";
        else if (noun.getNounClass() == NounClass.MASCULINE)
            return "le ";
        else
            return "la ";
    }

    protected boolean startsWithVowel(String s) {
        String firstLetter = s.substring(0, 1).toLowerCase(getLocale());
        // handle "habitude", MAYBE handle h aspiré (e.g. "haricot")
        if (firstLetter.equals("h"))
            firstLetter = s.substring(1, 2).toLowerCase(getLocale());
        // handle "éclairage"
        final char char0 = Normalizer.normalize(firstLetter, Form.NFD).charAt(0);
        return char0 == 'a' || char0 == 'e' || char0 == 'i' || char0 == 'o' || char0 == 'u' || char0 == 'y';
    }

    protected String getSingular(Phrase noun) {
        final String res = noun.getVariant(SINGULAR);
        return res == null ? noun.getBase() : res;
    }

    protected String getPlural(Phrase noun) {
        final String res = noun.getVariant(PLURAL);
        return res == null ? getPlural(noun.getBase()) : res;
    }

    protected String getPlural(String noun) {
        final int l = noun.length();
        final char lastChar = noun.charAt(l - 1);
        if (lastChar == 's' || lastChar == 'x' || lastChar == 'z')
            return noun;
        else if (noun.endsWith("al"))
            return noun.substring(0, l - 2) + "aux";
        else
            return noun + 's';
    }

    private String getCe(Phrase noun) {
        if (noun.getNounClass().equals(NounClass.FEMININE))
            return "cette ";
        else if (startsWithVowel(noun.getBase()))
            return "cet ";
        else
            return "ce ";
    }

    private static final Pattern LE_LES = Pattern.compile("(\\p{javaWhitespace}*)([Ll][Ee][Ss]?)\\p{javaWhitespace}+");

    public String de(final String phrase) {
        final Matcher matcher = LE_LES.matcher(phrase);
        if (matcher.lookingAt()) {
            final String le_les_group = matcher.group(2);
            final char d = le_les_group.charAt(0) == 'L' ? 'D' : 'd';
            final String de;
            if (le_les_group.length() == 3)
                de = d + le_les_group.substring(1);
            else
                de = d + (le_les_group.charAt(1) == 'E' ? "U" : "u");
            return matcher.group(1) + de + phrase.substring(matcher.end(2));
        } else if (startsWithVowel(phrase.trim())) {
            return "d’" + phrase;
        } else {
            return "de " + phrase;
        }
    }

    public String à(final String phrase) {
        final Matcher matcher = LE_LES.matcher(phrase);
        if (matcher.lookingAt()) {
            final String le_les_group = matcher.group(2);
            final String au = (le_les_group.charAt(0) == 'L' ? "A" : "a") + (le_les_group.charAt(1) == 'E' ? "U" : "u");
            final String de;
            if (le_les_group.length() == 3)
                de = au + (le_les_group.charAt(2) == 'S' ? "X" : "x");
            else
                de = au;
            return matcher.group(1) + de + phrase.substring(matcher.end(2));
        } else {
            return "à " + phrase;
        }
    }
}