EN · DE · RU · FR · ES

#1381 : PhoneNumberUtils.kt

projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt Classe Kotlin, projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt 289 lignes · 165 code · 84 commentaires · 40 vides
Objectif : Fichier source : projectforge/framework/utils/PhoneNumberUtils.kt. PhoneNumberUtils.kt fait partie de l'application open-source de gestion de projet ProjectForge.

Source (100 premières lignes)

/////////////////////////////////////////////////////////////////////////////
//
// Projet ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2026 Micromata GmbH, Allemagne (www.micromata.com)
//
// ProjectForge est sous double licence.
//
// Cette édition communautaire est un logiciel libre ; vous pouvez la redistribuer et/ou
// la modifier selon les termes de la GNU General Public License telle que publiée
// par la Free Software Foundation ; version 3 de la Licence.
//
// Cette édition communautaire est distribuée dans l'espoir qu'elle sera utile,
// mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de
// COMMERCIALISATION ou D'ADAPTATION À UN USAGE PARTICULIER. Voir la GNU General
// Public License pour plus de détails.
//
// Vous devriez avoir reçu une copie de la GNU General Public License avec
// ce programme ; sinon, consultez http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.framework.utils

import org.projectforge.framework.configuration.Configuration
import org.projectforge.framework.configuration.ConfigurationParam

/**
 * Fonctions utilitaires pour la normalisation et le formatage des numéros de téléphone.
 *
 * @author Kai Reinhard (k.reinhard@micromata.de)
 */
object PhoneNumberUtils {

    // Codes de pays courants (1 à 3 chiffres)
    private val KNOWN_COUNTRY_CODES = setOf(
        "1",   // États-Unis, Canada
        "7",   // Russie, Kazakhstan
        "20", "27",  // Égypte, Afrique du Sud
        "30", "31", "32", "33", "34", "36", "39", "40", "41", "43", "44", "45", "46", "47", "48", "49", // Europe
        "51", "52", "53", "54", "55", "56", "57", "58", // Amérique du Sud
        "60", "61", "62", "63", "64", "65", "66", // Asie/Océanie
        "81", "82", "84", "86", "90", "91", "92", "93", "94", "95", "98", // Asie
        "212", "213", "216", "218", "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", // Afrique
        "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", // Afrique
        "250", "251", "252", "253", "254", "255", "256", "257", "258", "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", // Afrique
        "290", "291", "297", "298", "299", // Atlantique
        "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", // Europe
        "370", "371", "372", "373", "374", "375", "376", "377", "378", "380", "381", "382", "383", "385", "386", "387", "389", // Europe
        "420", "421", "423", // Europe
        "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", // Amériques
        "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", "690", "691", "692", // Pacifique
        "850", "852", "853", "855", "856", "880", "886", // Asie
        "960", "961", "962", "963", "964", "965", "966", "967", "968", "970", "971", "972", "973", "974", "975", "976", "977", "992", "993", "994", "995", "996", "998" // Asie/Moyen-Orient
    )

    /**
     * Normalise un numéro de téléphone dans un format standardisé et lisible.
     *
     * Format : +[Pays] [Zone] [Numéro][-Extension]
     *
     * Exemples :
     * - "0561 316793-0" → "+49 561 316793-0"
     * - "+49 (0) 561 / 316793-0" → "+49 561 316793-0"
     * - "0170 1234567" → "+49 170 1234567"
     * - "+1 415 555-1234" → "+1 415 5551234"
     *
     * @param phoneNumber Le numéro de téléphone à normaliser (peut contenir des espaces, barres obliques, parenthèses, etc.)
     * @param defaultCountryPrefix Le préfixe de pays par défaut à utiliser si aucun n'est présent (par défaut : depuis la configuration ou "+49")
     * @return Numéro de téléphone normalisé au format "+CC AAA NNNNNNN[-EXT]" ou null si l'entrée est nulle/vide
     */
    fun normalizePhoneNumber(
        phoneNumber: String?,
        defaultCountryPrefix: String = getDefaultCountryPrefix()
    ): String? {
        if (phoneNumber.isNullOrBlank()) {
            return null
        }

        var cleaned = phoneNumber.trim()

        // Supprime les préfixes comme "Tel:", "Phone:", "Fax:", etc.
        cleaned = cleaned.replace(Regex("^(?:Tel\\.?:|Telefon:|Phone:|Mobil:|Mobile:|Fax:)\\s*", RegexOption.IGNORE_CASE), "")

        // Supprime les caractères de contrôle UTF
        cleaned = cleaned.replace("\\p{C}".toRegex(), "")

        // Supprime (0) dans +49 (0) 123456789
        cleaned = cleaned.replace(Regex("\\(0\\)"), "")

        // Supprime les parenthèses et barres obliques tôt pour la détection du code pays
        cleaned = cleaned.replace(Regex("[/()]"), "")

        if (cleaned.isEmpty()) {
            return null
        }

        // Retourne les numéros très courts (3 chiffres ou moins) inchangés - numéros d'urgence, codes courts, etc.
        // Exemples : 0, 00, 110, 112

Historique Git

868d6abb7 2025 -> 2026
2b9888261 Refactorisation du formatage des numéros dans Sipgate et de la gestion vcard.
a2608ee2e PhoneNumberUtils...
c624d79b8 PhoneNumberUtils.formatPhoneNumber et AddressTextParser

868d6abb7

2025 -> 2026
868d6abb75cd191a892911ac8e45058932cf9074
diff --git a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
index 320fb1c99..37ee6ed30 100644
--- a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
+++ b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
@@ -3,7 +3,7 @@
 // Projet ProjectForge Community Edition
 //         www.projectforge.org
 //
-// Copyright (C) 2001-2025 Micromata GmbH, Allemagne (www.micromata.com)
+// Copyright (C) 2001-2026 Micromata GmbH, Allemagne (www.micromata.com)
 //
 // ProjectForge est sous double licence.
 //

2b9888261

Refactorisation du formatage des numéros dans Sipgate et de la gestion vcard.
2b9888261f5880a0d9bda8d7343c4367bd32d7c9
diff --git a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
index 506ea65ab..320fb1c99 100644
--- a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
+++ b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
@@ -89,21 +89,50 @@ object PhoneNumberUtils {
         // Supprime (0) dans +49 (0) 123456789
         cleaned = cleaned.replace(Regex("\\(0\\)"), "")
 
+        // Supprime les parenthèses et barres obliques tôt pour la détection du code pays
+        cleaned = cleaned.replace(Regex("[/()]"), "")
+
         if (cleaned.isEmpty()) {
             return null
         }
 
+        // Retourne les numéros très courts (3 chiffres ou moins) inchangés - numéros d'urgence, codes courts, etc.
+        // Exemples : 0, 00, 110, 112
+        // Mais PAS s'ils commencent par 00X (préfixe international) ou +X
+        val digitCount = cleaned.count { it.isDigit() }
+        if (digitCount in 1..3) {
+            // Autorise "0", "00", "110", "112" etc. à passer inchangés
+            // Mais bloque "001", "0049" etc. (format international) - ils nécessitent un traitement
+            if (cleaned == "0" || cleaned == "00" || !cleaned.startsWith("00") && !cleaned.startsWith("+")) {
+                return cleaned
+            }
+        }
+
         // Extrait le code pays
-        val (countryCode, remainingPart) = extractCountryCode(cleaned, defaultCountryPrefix)
+        val (countryCode, remainingPart, hasPrefix) = extractCountryCode(cleaned, defaultCountryPrefix)
+
+        // Si aucun préfixe n'a été détecté (pas de +, pas de 00, pas de 0 initial), retourne le numéro nettoyé inchangé
+        if (!hasPrefix) {
+            // Nettoie simplement les caractères spéciaux et normalise les espaces
+            val result = cleaned
+                .replace(".", " ")
+                .replace(Regex("\\s+"), " ")
+                .trim()
+            // Mais vérifie qu'il contient au moins quelques chiffres
+            if (!result.contains(Regex("\\d"))) {
+                return null
+            }
+            return result
+        }
 
         if (remainingPart.isBlank()) {
-            return null
+            // Si seul le code pays existe (ex. "001" -> "+1"), retourne uniquement le code pays
+            return countryCode
         }
 
-        // Nettoie la partie restante : supprime les barres obliques, points, parenthèses d'abord, puis normalise les espaces
+        // Nettoie la partie restante : remplace les points par des espaces (séparateur), puis normalise les espaces
         var remaining = remainingPart.trim()
             .replace(".", " ") // Le point est un séparateur entre les blocs de numéros
-            .replace(Regex("[/()]"), "") // Supprime les barres obliques, parenthèses
             .replace(Regex("\\s+"), " ") // Normalise les espaces multiples en un seul espace
             .trim()
 

a2608ee2e

PhoneNumberUtils...
a2608ee2e9bf20343a26a5543fc0f06176735862
diff --git a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
index 41a89f714..506ea65ab 100644
--- a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
+++ b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
@@ -100,9 +100,10 @@ object PhoneNumberUtils {
             return null
         }
 
-        // Nettoie la partie restante : supprime les barres obliques, points, parenthèses d'abord, puis normalise les espaces
+        // Nettoie la partie restante : remplace les points par des espaces (séparateur), supprime les barres obliques/parenthèses, puis normalise les espaces
         var remaining = remainingPart.trim()
-            .replace(Regex("[/().]"), "") // Supprime les barres obliques, parenthèses, points
+            .replace(".", " ") // Le point est un séparateur entre les blocs de numéros
+            .replace(Regex("[/()]"), "") // Supprime les barres obliques, parenthèses
             .replace(Regex("\\s+"), " ") // Normalise les espaces multiples en un seul espace
             .trim()
 

c624d79b8

PhoneNumberUtils.formatPhoneNumber et AddressTextParser
c624d79b8c005f4f746148f647e9eb1dbff3226f
diff --git a/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
new file mode 100644
index 000000000..41a89f714
--- /dev/null
+++ b/projectforge-business/src/main/kotlin/org/projectforge/framework/utils/PhoneNumberUtils.kt
@@ -0,0 +1,256 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Projet ProjectForge Community Edition
+//         www.projectforge.org
+//
+// Copyright (C) 2001-2025 Micromata GmbH, Allemagne (www.micromata.com)
+//
+// ProjectForge est sous double licence.
+//
+// Cette édition communautaire est un logiciel libre ; vous pouvez la redistribuer et/ou
+// la modifier selon les termes de la GNU General Public License telle que publiée
+// par la Free Software Foundation ; version 3 de la Licence.
+//
+// Cette édition communautaire est distribuée dans l'espoir qu'elle sera utile,
+// mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de
+// COMMERCIALISATION ou D'ADAPTATION À UN USAGE PARTICULIER. Voir la GNU General
+// Public License pour plus de détails.
+//
+// Vous devriez avoir reçu une copie de la GNU General Public License avec
+// ce programme ; sinon, consultez http://www.gnu.org/licenses/.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+package org.projectforge.framework.utils
+
+import org.projectforge.framework.configuration.Configuration
+import org.projectforge.framework.configuration.ConfigurationParam
+
+/**
+ * Fonctions utilitaires pour la normalisation et le formatage des numéros de téléphone.
+ *
+ * @author Kai Reinhard (k.reinhard@micromata.de)
+ */
+object PhoneNumberUtils {
+
+    // Codes de pays courants (1 à 3 chiffres)
+    private val KNOWN_COUNTRY_CODES = setOf(
+        "1",   // États-Unis, Canada
+        "7",   // Russie, Kazakhstan
+        "20", "27",  // Égypte, Afrique du Sud
+        "30", "31", "32", "33", "34", "36", "39", "40", "41", "43", "44", "45", "46", "47", "48", "49", // Europe
+        "51", "52", "53", "54", "55", "56", "57", "58", // Amérique du Sud
+        "60", "61", "62", "63", "64", "65", "66", // Asie/Océanie
+        "81", "82", "84", "86", "90", "91", "92", "93", "94", "95", "98", // Asie
+        "212", "213", "216", "218", "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", // Afrique
+        "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", // Afrique
+        "250", "251", "252", "253", "254", "255", "256", "257", "258", "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", // Afrique
+        "290", "291", "297", "298", "299", // Atlantique
+        "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", // Europe
+        "370", "371", "372", "373", "374", "375", "376", "377", "378", "380", "381", "382", "383", "385", "386", "387", "389", // Europe
+        "420", "421", "423", // Europe
+        "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", // Amériques
+        "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", "690", "691", "692", // Pacifique