using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Developpez.Dotnet.Language;
using Developpez.Dotnet.Language.Grammar;
using Developpez.Dotnet.Properties;
#if !NETFX_CORE
using Developpez.Dotnet.Reflection;
#endif
using CH = Developpez.Dotnet.CompatibilityHelper;
namespace Developpez.Dotnet
{
///
/// Fournit des méthodes de conversion d'un nombre en toutes lettres.
///
public static class NumberConverter
{
#region Private data
private static readonly object _spellerLock = new object();
private static readonly IDictionary _spellers;
private static readonly IDictionary _bestSpellers;
#endregion
#region Constructor
static NumberConverter()
{
_spellers = new Dictionary(CH.StringComparer.InvariantCultureIgnoreCase);
_bestSpellers = new Dictionary(CH.StringComparer.InvariantCulture);
#if NETFX_CORE
LoadSpellers(typeof (NumberConverter).GetTypeInfo().Assembly);
#else
LoadSpellers(typeof (NumberConverter).Assembly);
#endif
}
#endregion
#region Private methods
private static INumberSpeller GetSpeller()
{
return GetSpeller(CultureInfo.CurrentCulture);
}
///
/// Renvoie un convertisseur de nombre en toutes lettres pour la culture spécifiée
///
/// Culture pour laquelle obtenir un convertisseur
/// Un convertisseur de nombre en toutes lettres pour la culture spécifiée
public static INumberSpeller GetSpeller(CultureInfo culture)
{
culture.CheckArgumentNull("culture");
INumberSpeller bestAvailable;
lock (_spellerLock)
{
if (!_bestSpellers.TryGetValue(culture.Name, out bestAvailable))
{
bestAvailable = FindBestAvailableSpeller(culture);
_bestSpellers[culture.Name] = bestAvailable;
}
}
return bestAvailable;
}
///
/// Renvoie un convertisseur de nombre en toutes lettres pour la culture spécifiée
///
/// Culture pour laquelle obtenir un convertisseur
/// Un convertisseur de nombre en toutes lettres pour la culture spécifiée
public static INumberSpeller GetSpeller(string culture)
{
#if SILVERLIGHT || NETFX_CORE
var c = new CultureInfo(culture);
#else
var c = CultureInfo.GetCultureInfo(culture);
#endif
return GetSpeller(c);
}
private static INumberSpeller FindBestAvailableSpeller(CultureInfo culture)
{
var candidates = SpellerHelper.GetCultureAndParents(culture).Join(
_spellers,
c => c.Name,
kvp => kvp.Key,
(c, kvp) => kvp.Value,
CH.StringComparer.InvariantCultureIgnoreCase);
INumberSpeller bestAvailable = candidates.FirstOrDefault();
if (bestAvailable == null)
throw new NotSupportedException(string.Format(ExceptionMessages.NumberConverter_NoSpellerAvailable, culture.Name));
return bestAvailable;
}
#endregion
#region Public methods
///
/// Recherche tous les convertisseurs de nombre en lettres
/// dans l'assembly spécifié. Utilisez cette méthode pour
/// détecter un convertisseur personnalisé.
///
/// L'assembly dans lequel les convertisseurs sont définis
///
/// Les convertisseurs prédéfinis sont chargés automatiquement,
/// il n'est donc pas nécessaire d'appeler LoadSpellers pour
/// les utiliser.
///
public static void LoadSpellers(Assembly assembly)
{
var spellers =
#if NETFX_CORE
from a in assembly.GetCustomAttributes()
#else
from a in assembly.GetAttributes()
#endif
group a.Culture by a.Implementation into g
let speller = (INumberSpeller)Activator.CreateInstance(g.Key)
from culture in g
select new
{
Culture = culture,
Speller = speller
};
lock (_spellerLock)
{
foreach (var s in spellers)
{
_spellers[s.Culture] = s.Speller;
}
// Clear best choice cache in case a better speller is
// now available for a language
_bestSpellers.Clear();
}
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Le nombre en toutes lettres.
public static string Spell(long value)
{
return Spell(value, Gender.Masculine);
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Genre du nombre entier.
/// Le nombre en toutes lettres.
public static string Spell(long value, Gender gender)
{
return Spell(value, gender, NumeralAdjective.Cardinal);
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Genre du nombre entier.
/// Nature de l'adjectif numéral.
/// Le nombre en toutes lettres.
public static string Spell(long value, Gender gender, NumeralAdjective numeralAdjective)
{
return GetSpeller().Spell(value, gender, numeralAdjective);
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Le nombre en toutes lettres.
public static string Spell(ulong value)
{
return Spell(value, Gender.Masculine);
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Genre du nombre entier.
/// Le nombre en toutes lettres.
public static string Spell(ulong value, Gender gender)
{
return Spell(value, gender, NumeralAdjective.Cardinal);
}
///
/// Convertit un nombre entier en toutes lettres.
///
/// Nombre entier.
/// Genre du nombre entier.
/// Nature de l'adjectif numéral.
/// Le nombre en toutes lettres.
public static string Spell(ulong value, Gender gender, NumeralAdjective numeralAdjective)
{
return GetSpeller().Spell(value, gender, numeralAdjective);
}
///
/// Convertit un nombre en virgule flottante en toutes lettres, avec le nombre de chiffres spécifié après la virgule.
///
/// Nombre en virgule flottante
/// Nombre de chiffres après la virgule
/// Le nombre en toutes lettres
public static string Spell(double value, int decimalPlaces)
{
return GetSpeller().Spell(value, decimalPlaces);
}
///
/// Convertit un nombre décimal en toutes lettres, avec le nombre de chiffres spécifié après la virgule.
///
/// Nombre décimal
/// Nombre de chiffres après la virgule
/// Le nombre en toutes lettres
public static string Spell(decimal value, int decimalPlaces)
{
return GetSpeller().Spell(value, decimalPlaces);
}
///
/// Convertit un montant en toutes lettres, avec la devise spécifiée.
///
/// Montant en virgule flottante
/// Devise utilisée
/// Le montant en toutes lettres
public static string SpellAmount(double value, CurrencyDescriptor currency)
{
return GetSpeller().SpellAmount(value, currency);
}
///
/// Convertit un montant en toutes lettres, avec la devise spécifiée.
///
/// Montant décimal
/// Devise utilisée
/// Le montant en toutes lettres
public static string SpellAmount(decimal value, CurrencyDescriptor currency)
{
return GetSpeller().SpellAmount(value, currency);
}
#endregion
}
}