StringUtils Commons Lang
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
.
Sommaire
Votre avis
Nobody voted on this yet
|
|
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.
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));
}
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"));
}
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"));
}
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 "));
}
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.
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.