All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.time4j.format.PluralRules Maven / Gradle / Ivy

There is a newer version: 4.38
Show newest version
/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2015 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (PluralRules.java) is part of project Time4J.
 *
 * Time4J is free software: You can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Time4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Time4J. If not, see .
 * -----------------------------------------------------------------------
 */

package net.time4j.format;

import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

import static net.time4j.format.PluralCategory.FEW;
import static net.time4j.format.PluralCategory.ONE;
import static net.time4j.format.PluralCategory.OTHER;
import static net.time4j.format.PluralCategory.TWO;


/**
 * 

Helps to determine the plural category for a given number of units.

* *

The predefined rules for any given language are based on * CLDR-version 26 but can be overridden if necessary. The source data * of the underlying algorithms to determine the plural category can be * found in CLDR-repository-file "core.zip" along the path * "common/supplemental/plurals.xml" for cardinal numbers and * "common/supplemental/ordinals.xml" for ordinal numbers.

* * @author Meno Hochschild * @since 1.2 * @doctags.spec All concrete classes must be immutable. */ /*[deutsch] *

Hilfsklasse zur Bestimmung der Pluralkategorie für eine gegebene * Sprache und eine entsprechende Anzahl von Zeiteinheiten.

* *

Die vordefinierten Regeln für irgendeine Sprache basieren auf * der CLDR-Version 26, können bei Bedarf aber überschrieben * werden. Die Quelldaten der zugrundeliegenden Algorithmen, die die * Pluralkategorie zu bestimmen helfen, können im CLDR-Repositorium * "core.zip" und dem Pfad "common/supplemental/plurals.xml" * (für Grundzahlen) gefunden werden. Ordinalzahlregeln sind in der * Datei "common/supplemental/ordinals.xml" zu finden.

* * @author Meno Hochschild * @since 1.2 * @doctags.spec All concrete classes must be immutable. */ public abstract class PluralRules { //~ Statische Felder/Initialisierungen -------------------------------- private static final PluralRules FALLBACK_CARDINAL_ENGLISH = new FallbackRules(NumberType.CARDINALS, true); private static final PluralRules FALLBACK_CARDINAL_OTHER = new FallbackRules(NumberType.CARDINALS, false); private static final PluralRules FALLBACK_ORDINAL_ENGLISH = new FallbackRules(NumberType.ORDINALS, true); private static final PluralRules FALLBACK_ORDINAL_OTHER = new FallbackRules(NumberType.ORDINALS, false); private static final PluralProvider PROVIDER; static { PluralProvider p = null; ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = PluralProvider.class.getClassLoader(); } if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } for ( PluralProvider tmp : ServiceLoader.load(PluralProvider.class, cl) ) { p = tmp; break; } if (p == null) { p = new FallbackProvider(); } PROVIDER = p; } private static final Map CARDINAL_MAP = new ConcurrentHashMap(); private static final Map ORDINAL_MAP = new ConcurrentHashMap(); //~ Methoden ---------------------------------------------------------- /** *

Gets the localized plural rules for given language or * country.

* *

If no rules can be found then Time4J will choose the default rules * for cardinals which apply {@code PluralCategory.ONE} to n=1 and else * apply the fallback category {@code PluralCategory.OTHER}.

* * @param locale locale which specifies the suitable plural rules * @param numType number type * @return localized plural rules * @since 1.2 */ /*[deutsch] *

Ermittelt die Pluralregeln für die angegebene Sprache oder * das Land.

* *

Wenn keine Regeln gefunden werden können, dann wird Time4J * die Standardregeln wählen, die bei Kardinalzahlen * {@code PluralCategory.ONE} auf n=1 und sonst die Kategorie * {@code PluralCategory.OTHER} anwenden.

* * @param locale locale which specifies the suitable plural rules * @param numType number type * @return localized plural rules * @since 1.2 */ public static PluralRules of( Locale locale, NumberType numType ) { Map map = getRuleMap(numType); PluralRules rules = null; if (!map.isEmpty()) { if (!locale.getCountry().equals("")) { rules = map.get(toKey(locale)); } if (rules == null) { rules = map.get(locale.getLanguage()); } } if (rules == null) { rules = PROVIDER.load(locale, numType); } return rules; } /** *

Registers given plural rules for a language, possibly overriding * CLDR-default setting.

* * @param locale language or country which the rules shall be assigned to * @param rules localized plural rules * @since 1.2 */ /*[deutsch] *

Registriert die angegebenen Pluralregeln für eine Sprache, * wobei die CLDR-Vorgabe überschrieben werden kann.

* * @param locale language or country which the rules shall be assigned to * @param rules localized plural rules * @since 1.2 */ public static void register( Locale locale, PluralRules rules ) { Map map = getRuleMap(rules.getNumberType()); String key = locale.getLanguage(); if (!locale.getCountry().equals("")) { key = toKey(locale); } map.put(key, rules); } /** *

Determines the plural category for given number of units.

* * @param count integral number of units * @return plural category, never {@code null} * @since 1.2 */ /*[deutsch] *

Bestimmt die Pluralkategorie für die angegebene Anzahl von * Zeiteinheiten.

* * @param count integral number of units * @return plural category, never {@code null} * @since 1.2 */ public abstract PluralCategory getCategory(long count); /** *

Yields the number type these rules are referring to.

* * @return number type * @since 1.2 */ /*[deutsch] *

Liefert den Zahltyp, auf den sich diese Regeln beziehen.

* * @return number type * @since 1.2 */ public abstract NumberType getNumberType(); private static Map getRuleMap(NumberType numType) { switch (numType) { case CARDINALS: return CARDINAL_MAP; case ORDINALS: return ORDINAL_MAP; default: throw new UnsupportedOperationException(numType.name()); } } private static String toKey(Locale country) { StringBuilder kb = new StringBuilder(); kb.append(country.getLanguage()); kb.append('_'); kb.append(country.getCountry()); return kb.toString(); } //~ Innere Klassen ---------------------------------------------------- private static class FallbackRules extends PluralRules { //~ Instanzvariablen ---------------------------------------------- private final NumberType numType; private final boolean english; //~ Konstruktoren ------------------------------------------------- private FallbackRules( NumberType numType, boolean english ) { super(); this.numType = numType; this.english = english; } //~ Methoden ------------------------------------------------------ @Override public PluralCategory getCategory(long count) { switch (this.numType) { case CARDINALS: return (count == 1 ? ONE : OTHER); case ORDINALS: if (this.english) { long mod10 = count % 10; long mod100 = count % 100; if ((mod10 == 1) && (mod100 != 11)) { return ONE; } else if ((mod10 == 2) && (mod100 != 12)) { return TWO; } else if ((mod10 == 3) && (mod100 != 13)) { return FEW; } } return OTHER; default: throw new UnsupportedOperationException( this.numType.name()); } } @Override public NumberType getNumberType() { return this.numType; } } private static class FallbackProvider implements PluralProvider { //~ Methoden ------------------------------------------------------ @Override public PluralRules load( Locale country, NumberType numType ) { boolean english = country.getLanguage().equals("en"); switch (numType) { case CARDINALS: return ( english ? FALLBACK_CARDINAL_ENGLISH : FALLBACK_CARDINAL_OTHER); case ORDINALS: return ( english ? FALLBACK_ORDINAL_ENGLISH : FALLBACK_ORDINAL_OTHER); default: throw new UnsupportedOperationException(numType.name()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy