StringUtils Commons Lang

De EjnTricks
Révision de 31 janvier 2018 à 10:04 par Etienne (discussion | contributions)

(diff) ← Version précédente | Voir la version courante (diff) | Version suivante → (diff)

La classe org.apache.commons.lang3.StringUtils permet de faciliter la manipulation des chaînes de caractères. Dans les projets, il n'est pas rare d'effectuer toujours les mêmes tests, qui peuvent rendre la note de compléxité importante, alors que les actions ne présentent aucune difficulté. Cet article présente certaines fonctions uniquement à l'aide de tests unitaires, dans la classe fr.ejn.tutorial.apache.commons.lang3.StringUtilsTest.

Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Fork-icon.png Abréviation

Bien souvent, il est souhaité de couper une chaînes de caractères trop longues en complétant par des pointillés. Cela est assez courant lors d'affichage de description ou de commentaires. Ceci est réalisé très simplement à l'aide de la fonction abbreviate, mis en évidence dans le test testAbbreviate

  @Test
  public void testAbbreviate() {
    Assert.assertEquals(null, StringUtils.abbreviate(null, 4));
    Assert.assertEquals("Etienne ...", StringUtils.abbreviate("Etienne Jouvin", 11));
  }

Attention, le deuxième paramètre permet de spécifier la taille maximale du résultat, après intégration des pointillés.


Icon Personnalisation.png Complétion

Contrairement à l'abréviation, il peut être nécessaire de compléter une chaîne de caractères pour s'assurer qu'elle dispose d'une taille minimale. Pour cela, il existe les fonctions leftPad et rightPad. Une première signature accepte une chaîne de caractère et la taille minimale. Attention, aucune modificatio ne sera réalisée si la chaîne de caractères est un null.

Les tests testLeftPad et testRightPad mettent en évidence leurs utilisations.

  @Test
  public void testLeftPad() {
    Assert.assertEquals(null, StringUtils.leftPad(null, 3));
    Assert.assertEquals("   ", StringUtils.leftPad("", 3));
    Assert.assertEquals("Etienne", StringUtils.leftPad("Etienne", 7));
    Assert.assertEquals("  Etienne", StringUtils.leftPad("Etienne", 9));
    Assert.assertEquals("..Etienne", StringUtils.leftPad("Etienne", 9, '.'));
    Assert.assertEquals("Etienne", StringUtils.leftPad("Etienne", 2));
    Assert.assertEquals("Etienne", StringUtils.leftPad("Etienne", -1));
  }

  @Test
  public void testRightPad() {
    Assert.assertEquals(null, StringUtils.rightPad(null, 3));
    Assert.assertEquals("   ", StringUtils.rightPad("", 3));
    Assert.assertEquals("Etienne", StringUtils.rightPad("Etienne", 7));
    Assert.assertEquals("Etienne  ", StringUtils.rightPad("Etienne", 9));
    Assert.assertEquals("Etienne..", StringUtils.rightPad("Etienne", 9, '.'));
    Assert.assertEquals("Etienne", StringUtils.rightPad("Etienne", 2));
    Assert.assertEquals("Etienne", StringUtils.rightPad("Etienne", -1));
  }

A noter que ces deux fonctions possèdent une signature où le caractère ajouté peut être spécifié. Dans le cadre de ces tests, le caractère . est utilisé.


Il n'est pas rare de devoir une construire une chaîne de caractères avec une taille initiale, par exemple trois espaces. La fonction repeat va permettre de construire une instance de String avec un caractère.

  @Test
  public void testRepeat() {
    Assert.assertEquals("          ", StringUtils.repeat(' ', 10));
  }


Run-icon.png Contrôle taille

La fonction abbreviate permet d'extraire une partie de la chaîne de caractère en complétant avec trois petits points en cas de nécessité. Il existe le même style d'utilitaire afin d'extraire un nombre exact de caractères à partir de la gauche, fonction left, ou de la droite, fonction right.

  @Test
  public void testLeft() {
    Assert.assertEquals(null, StringUtils.left(null, 7));
    Assert.assertEquals("EJN", StringUtils.left("EJN", 7));
    Assert.assertEquals("Etienne", StringUtils.left("Etienne Jouvin", 7));
  }

  @Test
  public void testRight() {
    Assert.assertEquals(null, StringUtils.right(null, 6));
    Assert.assertEquals("EJN", StringUtils.right("EJN", 6));
    Assert.assertEquals("Jouvin", StringUtils.right("Etienne Jouvin", 6));
  }

L'avantage de ces fonctions résident dans le contrôle de la taille de la chaîne de caractères, la vérification est effectuée par celles-ci.


Il est également courant de devoir contrôler la taille d'une chaîne de caractères. Cependant, il est nécessaire de tester la valeur null pour éviter une exception, rendant le code un peu plus complexe. La fonction length va permettre de s'afranchir de cette dernière vérification, retournant 0 en cas d'un null.

  @Test
  public void testLength() {
    Assert.assertEquals(0, StringUtils.length(null));
    Assert.assertEquals(0, StringUtils.length(StringUtils.EMPTY));
    Assert.assertEquals(14, StringUtils.length("Etienne Jouvin"));
  }


Update icon.png Mise en majuscule

La mise en majuscule d'une chaîne de caractères est très simple. Cependant, il est nécessaire de tester sur la variable est null ou non. Grâce à cet utilitaire, ce test devient inutile et simplifie le code.

Le premier test testCapitalize illustre la mise ne majsucule de la première lettre d'une chaîne de caractères.

  @Test
  public void testCapitalize() {
    Assert.assertEquals(null, StringUtils.capitalize(null));
    Assert.assertEquals("Etienne jouvin", StringUtils.capitalize("etienne jouvin"));
    // Only affect the first letter
    Assert.assertEquals("Etienne jouVIN", StringUtils.capitalize("etienne jouVIN"));
  }

Attention, seul le premier caractère est modifié. Les autres sont inchangés.

Le test suivant testUpperCase permet de passer toute la chaîne de caractères en majscule, sans avoir à tester la valeur null.

  @Test
  public void testUpperCase() {
    Assert.assertEquals(null, StringUtils.upperCase(null));
    Assert.assertEquals("ETIENNE JOUVIN", StringUtils.upperCase("etienne jouvin"));
  }


Home icon.png Null et vide

Les exemples suivants vont permettrent d'illustrer la manipulation des chaînes null ou vide. Il est courant de devoir manipuler celle-ci.

Il est important de noter qu'il existe la constante EMPTY qui est une chaîne de caractères vides, ce qui permet de ne pas avoir à l'écrire dans le code source, comme illustré dans le test testEmptyString

  @Test
  public void testEmptyString() {
    String expected = "";
    String actual = StringUtils.EMPTY;
    Assert.assertEquals(expected, actual);
  }

Le premier test testDefaultIfBlank illustre la fonction defaultIfBlank, qui permet d'affecter une valeur par défaut si la source est null ou "blanche", à savoir qu'elle ne contient que des "espaces". Dans le cas contraire, la chaîne originale est retournée. Ceci est très pratique pour affecter une valeur par défaut.

  @Test
  public void testDefaultIfBlank() {
    Assert.assertEquals("MY DEFAULT", StringUtils.defaultIfBlank(null, "MY DEFAULT"));
    Assert.assertEquals("MY DEFAULT", StringUtils.defaultIfBlank("", "MY DEFAULT"));
    Assert.assertEquals("MY DEFAULT", StringUtils.defaultIfBlank("    ", "MY DEFAULT"));
    Assert.assertEquals("Etienne Jouvin", StringUtils
        .defaultIfBlank("Etienne Jouvin", "MY DEFAULT"));
  }

La fonction defaultIfEmpty effecue la même action, mais uniquement si la chaîne est null ou vide. Le test testDefaultIfEmpty illustre son utilisation.

  @Test
  public void testDefaultIfEmpty() {
    Assert.assertEquals("MY DEFAULT", StringUtils.defaultIfEmpty(null, "MY DEFAULT"));
    Assert.assertEquals("MY DEFAULT", StringUtils.defaultIfEmpty("", "MY DEFAULT"));
    Assert.assertEquals("    ", StringUtils.defaultIfEmpty("    ", "MY DEFAULT"));
    Assert.assertEquals("Etienne Jouvin", StringUtils
        .defaultIfBlank("Etienne Jouvin", "MY DEFAULT"));
  }

Mais bien souvent, ce type de vérification n'est réalisé que sur les chaîne null. La focntion defaultString ne prend que la chaîne de caractère en entrée et la convertir en chaîne vide si elle est nulle. Le test testDefaultString illustre cette utilisation.

  @Test
  public void testDefaultString() {
    Assert.assertEquals("", StringUtils.defaultString(null));
    Assert.assertEquals("Etienne Jouvin", StringUtils.defaultString("Etienne Jouvin"));

    Assert.assertEquals("MY DEFAULT", StringUtils.defaultString(null, "MY DEFAULT"));
    Assert
    .assertEquals("Etienne Jouvin", StringUtils.defaultString("Etienne Jouvin", "MY DEFAULT"));
  }


Il est également souvent nécessaire de tester si la chaîne de caractère est null, vide ou blanche. Tout ceci est facilité à l'aide des fonctions isEmpty ou isBlank, illustrées dans les tests testIsEmpty et testIsBlank.

  @Test
  public void testIsBlank() {
    Assert.assertTrue(StringUtils.isBlank(null));
    Assert.assertTrue(StringUtils.isBlank(""));
    Assert.assertTrue(StringUtils.isBlank("    "));
    Assert.assertFalse(StringUtils.isBlank("Etienne Jouvin"));
  }

  @Test
  public void testIsEmpty() {
    Assert.assertTrue(StringUtils.isEmpty(null));
    Assert.assertTrue(StringUtils.isEmpty(""));
    Assert.assertFalse(StringUtils.isEmpty("    "));
    Assert.assertFalse(StringUtils.isEmpty("Etienne Jouvin"));
  }

Inversement, il existe les deux fonctions isNotEmpty et isNotBlank, illustrées dans les deux tests suivants.

  @Test
  public void testIsNotBlank() {
    Assert.assertFalse(StringUtils.isNotBlank(null));
    Assert.assertFalse(StringUtils.isNotBlank(""));
    Assert.assertFalse(StringUtils.isNotBlank("    "));
    Assert.assertTrue(StringUtils.isNotBlank("Etienne Jouvin"));
  }

  @Test
  public void testIsNotEmpty() {
    Assert.assertFalse(StringUtils.isNotEmpty(null));
    Assert.assertFalse(StringUtils.isNotEmpty(""));
    Assert.assertTrue(StringUtils.isNotEmpty("    "));
    Assert.assertTrue(StringUtils.isNotEmpty("Etienne Jouvin"));
  }

Enfin, il existe des fonctions qui permettent d'effectuer une suppression des espaces inutiles en fin de chaîne. La fonction trim se contente de supprimer les espaces tout en étant sécurisé face à la valeur null, illustrée dans le test testTrim.

  @Test
  public void testTrim() {
    Assert.assertEquals(null, StringUtils.trim(null));
    Assert.assertEquals("", StringUtils.trim("    "));
    Assert.assertEquals("Etienne Jouvin", StringUtils.trim("    Etienne Jouvin    "));
  }

Cependant, cette fonction retourne la valeur null quand ceci est passé en argument. Il peut être nécessaire de s'assurer que la valeur ne soit pas nulle. La fonction defaultString pourrait être utilisée. Or, il existe la fonction trimToEmpty, qui permet de s'affranchir de cette opération. Le traitement est le même que la précédente, l'unique différence est qu'elle retourne une chaîne vide lorsque l'argument est null, illustrée par le test testTrimToEmpty.

  @Test
  public void testTrimToEmpty() {
    Assert.assertEquals("", StringUtils.trimToEmpty(null));
    Assert.assertEquals("", StringUtils.trimToEmpty("    "));
    Assert.assertEquals("Etienne Jouvin", StringUtils.trimToEmpty("    Etienne Jouvin    "));
  }

A l'inverse, il est possible d'optenir une valeur null lorsque l'argument est "vide", à l'aide de la fonction trimToNull, illustrée dans le test testTrimToNull

  @Test
  public void testTrimToNull() {
    Assert.assertEquals(null, StringUtils.trimToNull(null));
    Assert.assertEquals(null, StringUtils.trimToNull("    "));
    Assert.assertEquals("Etienne Jouvin", StringUtils.trimToNull("Etienne Jouvin    "));
  }


Robot-icon.png Suppression espaces inutiles

Sur des applications avec une interface utilisateurs, il peut être utile de supprimer les espaces inutiles, au début et fin de la saisie mais également ceux qui sont dupliqués afin de s'assurer que les mots ne sont séparés que par un seul espace. La fonction normalizeSpace permet d'effectuer ceci en un seul appel comme l'illustre le test unitaire testNormalizeSpace.

  @Test
  public void testNormalizeSpace() {
    Assert.assertEquals(null, StringUtils.normalizeSpace(null));
    Assert.assertEquals("", StringUtils.normalizeSpace(""));
    Assert.assertEquals("etienne jouvin", StringUtils.normalizeSpace("  etienne    jouvin   "));
    // Specific space characters
    Assert.assertEquals("etienne jouvin", StringUtils
        .normalizeSpace("  etienne \f \t \n \r   jouvin   "));
  }

A noter que cette fonction ne supprime pas uniquement les espaces mais aussi un ensemble de carcatères comme le retour chariot et la tabulation.


Icon-memory.png Concaténation chaînes caractères

Pour des projets où des requêtes SQL sont écrites, il n'est pas rare de traiter un tableau de chaînes pour construire les clauses SELECT, comme SELECT column1, column2, column3. Ceci est très facile à faire soit même mais nécessite une boucle, de tester si c'est le premier ou dernier élément traité. Or tout ceci peut s'effectuer par un simple appel à la fonction join donc l'argument peut être un tableau, un iterator. Un exemple simple permet de concaténer les chaînes de caractères d'un tableau, avec un séparateur comme la virgule, comme démontrer dans l'exemple suivant.

  @Test
  public void testJoin() {
    List<String> input = Arrays.asList("first", "second", "third");

    Assert.assertEquals("first,second,third", StringUtils.join(input, ','));
    Assert.assertEquals("first, second, third", StringUtils.join(input, ", "));
  }

Dans l'exemple suivant, cette fonction sera utilisée avec des transformer, de la librairie commons-collection, afin de doubler les quotes des valeurs, de les encadrer par une quote et de construire ainsi une clause utilisable dans un filtre de type IN.

  @Test
  public void testComplexJoin() {
    String[] filterValues = new String[] { "value'1", "value'2", "value'3" };

    Transformer<String, String> doubleQuoteTransformer = new Transformer<String, String>() {

      @Override
      public String transform(String input) {
        return StringUtils.replace(input, "'", "''");
      }

    };

    Transformer<String, String> toQuoteTransformer = new Transformer<String, String>() {

      @Override
      public String transform(String input) {
        return String.format("'%s'", input);
      }

    };

    List<Transformer<String, String>> transformers = new ArrayList<Transformer<String, String>>();
    transformers.add(doubleQuoteTransformer);
    transformers.add(toQuoteTransformer);

    Transformer<String, String> allTransformers = TransformerUtils.chainedTransformer(transformers);

    IteratorUtils.transformedIterator(IteratorUtils.arrayIterator(filterValues), allTransformers);

    String actual = StringUtils.join(IteratorUtils
        .transformedIterator(IteratorUtils.arrayIterator(filterValues), allTransformers), ", ");
    String expected = "'value''1', 'value''2', 'value''3'";

    Assert.assertEquals(expected, actual);
  }

Une petite explication est nécessaire. Le premier transformer doubleQuoteTransformer est en charge de modifier la chaîne de caractère pour doubler les quotes. Ainsi la valeur value'1 devient value''1.

Le second, toQuoteTransformer encadre une chaîne de caractère.

Ces deux transformers sont combinés à l'aide d'un transformer construit par TransformerUtils.chainedTransformer, ici l'argument est une liste pour éviter certains avertissements à la compilation. Les transformers sont tous exécutés l'un après l'autre. Ainsi, la valeur value'1 devient value''1, puis 'value''1' lors de la transformation.

Ensuite, un Iterator est construit sur le tableau de valeur à l'aide de la fonction IteratorUtils.arrayIterator. Lui même est converti en un Iterator effectuant une transformation lors de la récupération des valeurs, à l'aide de la fonction IteratorUtils.transformedIterator.

Bien entendu, les tranformers peuvent être externalisés dans des classes (où il sera possible de mettre ne place les tests unitaires) et réutilisables.