sábado, 12 de junho de 2010

Apache Commons: Lang

Continuando a série sobre as bibliotecas apache commons, Este post irá se aprofundar nos componentes da biblioteca Lang, cujo principal objetivo é estender as funcionalidades das classes do pacote java.lang. Além disso, a commons Lang inclui componentes de uso comum a outras bibliotecas.

Existem vários componentes do tipo “XXXUtils” na biblioteca commons Lang. Seus métodos, estáticos e autossuficientes, funcionam como funções globais presentes em outras tecnologias.

Devido a diversidade dos componentes desta biblioteca, examinaremo-os por categoria de acordo com as funcionalidades que julguei mais interessantes:

Manipulação de Strings

Suporte a manipulação de String é, sem dúvida, o ponto forte desta biblioteca. Existe uma série de componentes com este propósito, sendo os principais:
  • StringUtils - Encapsula uma série de funcionalidades null-safe de propósito geral que atuam sobre Strings. Minhas favoritas:
    • isEmpty/isBlank - Verifica se uma string contém texto. Uma string empty (vazia) seria o equivalente a “” e uma string blank (branca) cotém apenas caracteres brancos “    ”.
    • upperCase/lowerCase/swapCase/capitalize/uncaptalize - Mudam a capitalização de uma String. Atenção para o método captalize que coloca em caixa alta apenas o primeiro caractere. Nice hum?
    • isAlpha/isNumeric/isWhitespace/isAsciiPrintable - Faz verificações sobre uma string. IsNumeric é bem legal, mas seria mais útil se pudéssemos aferir sobre o tipo de numérico, algo como isInteger ou isShort.
    • abbreviate - Faz abreviação de uma string usando reticências.
    • difference - Compara duas Strings, retornando suas diferenças.
  • RandomStringUtils - Ajuda na criação de string randômicos, úteis na geração de senhas, por exemplo.
  • WordUtils  - Contém métodos que manipulam palavras de um texto, seja obtendo as iniciais (initials) ou colocando-as em caixa alta (captalize)
  • StrSubstitutor – Substitui variáveis em uma string por valores pré-definidos.

Exemplos StringUtils

String nullString = null;
String emptyString = "";
String blankString = "  ";
String regularString = "apache commons lang";

StringUtils.isEmpty(nullString); // true
StringUtils.isEmpty(emptyString);// true
StringUtils.isEmpty(blankString);// false
StringUtils.isEmpty(regularString);// false

StringUtils.isBlank(nullString); // true
StringUtils.isBlank(emptyString); // true
StringUtils.isBlank(blankString); // true
StringUtils.isBlank(regularString); // false


String lowcase = "lang";
  String uppercase = "LANG";
  String nullString = null;

  StringUtils.upperCase(lowcase); // LANG
  StringUtils.upperCase(uppercase); // LANG
  StringUtils.upperCase(nullString); // null

  StringUtils.lowerCase(lowcase); // lang
  StringUtils.lowerCase(uppercase);// lang
  StringUtils.lowerCase(nullString);// null

  StringUtils.swapCase(lowcase); // LANG
  StringUtils.swapCase(uppercase);// lang
  StringUtils.swapCase(nullString);// null

  StringUtils.capitalize(lowcase); // Lang
  StringUtils.capitalize(uppercase);// LANG
  StringUtils.capitalize(nullString);// null

  StringUtils.uncapitalize(lowcase); // lang
  StringUtils.uncapitalize(uppercase);// lANG
  StringUtils.uncapitalize(nullString);// null


String onlyAlphaString = "abcd";
  String onlyNumericString = "123";
  String mixString = "a1b 2c3";
  String blackString = "  ";

  StringUtils.isAlpha(onlyAlphaString); // true
  StringUtils.isAlpha(onlyNumericString); // false
  StringUtils.isAlpha(mixString); // false
  StringUtils.isAlpha(blackString); // false

  StringUtils.isNumeric(onlyAlphaString); // false
  StringUtils.isNumeric(onlyNumericString); // true
  StringUtils.isNumeric(mixString); // false
  StringUtils.isNumeric(blackString); // false

  StringUtils.isWhitespace(onlyAlphaString); // false
  StringUtils.isWhitespace(onlyNumericString); // false
  StringUtils.isWhitespace(mixString); // false
  StringUtils.isWhitespace(blackString); // true




String bigString = "this string is too big to fit you application's grid";

  String smallerString = StringUtils.abbreviate(bigString, 30);

  System.out.println(smallerString); // this string is too big to f...






String stringOne = "Luke, I'm your father!";
String stringTwo = "Luke, I'm your uncle!"; 
StringUtils.difference(stringOne, stringTwo); //uncle!
Exemplo WordUtils

String name = "carla gabriele batista dos santos";
  
  WordUtils.initials(name);//cgbds
  WordUtils.capitalize(name);//Carla Gabriele Batista Dos Santos



Exemplo StrSubstitutor

Map variablesMap = new HashMap();
   variablesMap.put("var1", "first variable");
   variablesMap.put("var2", "second variable");
   String templateString = "Let's print ${var1} and ${var2}";
   StrSubstitutor sub = new StrSubstitutor(variablesMap);
   String resolvedString = sub.replace(templateString);
   
System.out.println(resolvedString); //Let's print first variable and second variable



ObjectUtils e ClassUtils

Estes componentes merecem uma menção honrosa a parte. ObjectUtils pode ser usado para efetuar operações corriqueiras como comparações e obtenções de hashCode de forma null-safe. ClassUtils contém método para obtenção de uma série de informações a respeito de uma ou mais classes, como as interfaces que ela implementa e superclasses que estende, o pacote no qual se localiza, verificar se é uma classe interna, se pode ser assinalada para uma referência de um outro tipo, entre outros, e tudo isso de forma null-safe.

Integer intVariable = null;
  Integer anotherIntVariable = 5;
  
  ObjectUtils.hashCode(intVariable); //0
  
  ObjectUtils.toString(intVariable); //""
  
  ObjectUtils.equals(intVariable, anotherIntVariable); //false
  
 ObjectUtils.max(intVariable, anotherIntVariable); // 5 (podia ser genérico né?)



System.out.println(ClassUtils.getAllInterfaces(Integer.class)); // [interface java.lang.Comparable, interface java.io.Serializable]
  
  ClassUtils.getAllSuperclasses(Integer.class); //[class java.lang.Number, class java.lang.Object]
  
  ClassUtils.getPackageName(Integer.class); //java.lang
  
  ClassUtils.isInnerClass(Integer.class); //false
  
  ClassUtils.isInnerClass(Integer.class); //false

  ClassUtils.isAssignable(Integer.class, Number.class); //true





Builders

Esta categoria inclui 4 componentes que auxiliam na implementação de 4 métodos básicos, em especial para classes de domínio, de qualquer sistema: EqualsBuilder, HashCodeBuilder, CompareToBuilder e toStringBuilder. Através delas é possível obter uma implementação correta e eficiente dos métodos equals, hashCode, compareTo e toString, respectivamente, apenas informando as propriedades envolvidas.

Além disso, todos os componentes possuem métodos alternativos que permitem a execução de forma reflexiva, incluindo todas as propriedades. Nestes casos, é possível especificar propriedades a serem ignoradas, se for o caso.

public class Person implements Comparable {

 private String name;

 private Integer age;

 private Float weight;

 private Float height;

 private Person mother;

 /**
  * São consideradas iguais duas pessoas com mesmo nome, idade e filhas da
  * mesma mãe.
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Person other = (Person) obj;

  return new EqualsBuilder().append(age, other.age).append(mother,
    other.mother).append(name, other.name).isEquals();

  // Implementação alternativa que usa reflexão. É preciso informar os
  // campos a serem ignorados na compração para manter equivalência com a
  // implementação a cima.
  //
  // return EqualsBuilder.reflectionEquals(this, obj, Arrays.asList(
  // "weight", "height"));

 }

 /**
  * cálculo do hash code consistente com equals.
  */
 @Override
 public int hashCode() {

  return new HashCodeBuilder(17, 37).append(name).append(age).append(
    mother).toHashCode();

  // Implementação alternativa que usa reflexão. É preciso informar os
  // campos a serem ignorados. para manter equivalência com a
  // implementação a cima.
  //
  // return HashCodeBuilder.reflectionHashCode(this,
  // Arrays.asList("weight",
  // "height"));

 }

 /**
  * Define a representação em forma de String de um objeto da classe Person
  */
 @Override
 public String toString() {

  return new ToStringBuilder(this).append("name", name)
    .append("age", age).toString();

  // Implementação alternativa que usa reflexão. Não é possível informar
  // atributos a serem ignorados, portanto esta implementação não é
  // equivalente àquela a cima.
  //
  // return ToStringBuilder.reflectionToString(this);
 }

 /**
  * Determina forma de comparar objetos do tipo Person.
  */
 @Override
 public int compareTo(Person o) {
  return new CompareToBuilder().append(this.name, o.name).append(
    this.age, o.age).toComparison();

  // Implementação alternativa que usa reflexão. É preciso informar os
  // campos a serem ignorados. para manter equivalência com a
  // implementação a cima.
  //
  // return CompareToBuilder.reflectionCompare(this, o,
  // Arrays.asList("weight", "height","mother"));
 }

//getter e setter omitidos
} 

Math

A biblioteca commons lang inclui alguns componentes com funcionalidades matemáticas básicas. (as mais avançadas ficam na bilbioteca Math) Destaque para as classes que representam intervalos numéricos (IntRange, LongRange, FloatRange e DoubleRange), para a classe Fraction, que representa um número fracionário e para NumberUtils, que disponibiliza métodos utilitários interessantes.

IntRange firstRange = new IntRange(0, 10);
  IntRange secondRange = new IntRange(6,13);
  IntRange thirdRange = new IntRange(11,15);
  
  
  firstRange.containsInteger(5); //true
  firstRange.containsInteger(10); //true. ambos liites são inclusivos.
  firstRange.containsInteger(15); // false
  
  secondRange.getMaximumInteger(); //13
  secondRange.getMinimumInteger(); // 6
  
  firstRange.overlapsRange(secondRange); // true
  firstRange.overlapsRange(thirdRange); // false



Outros

Além dos componentes já mencinados, existem alguns outros que vale apena conferir, como aqueles relacioandos a tempo (destque para StopWatch) e para criação de tipe-safes enums que, devido a sua flexibilidade, continuam sendo muito utilizadas apesar das enumerações já terem sido padonizadas na versão 5 da linguagem.

Nenhum comentário:

Postar um comentário