10 outubro 2008

Convertendo valores financeiros no Wicket

É muito comum a necessidade de se converter valores no desenvolvimento Web. E quando precisamos disso, é importante que o framework aplicado no projeto possua uma facilidade enorme para que a solução desta necessidade não se torne em um pesadelo.

No Apache Wicket, muitas conversões são já automáticas, graças aos conversores-padrão. Mas, às vezes é necessário customizar alguns destes conversores para algo mais específico. Como a conversão de valores monetários, por exemplo. E a boa notícia é que, apesar de existirem 3 formas de se obter o mesmo resultado, todas elas são fáceis de serem implementadas e cada uma possui a sua utilidade.

A primeira e mais objetiva é prover um conversor customizado, reaproveitando-se de um já existente, a um componente específico:

        PropertyModel pm = new PropertyModel(pojo,
"valor");

add(new Label("valor1", pm) {
public IConverter getConverter(Class type) {
return (IConverter) new BigDecimalConverter() {
public NumberFormat getNumberFormat(Locale locale) {
return NumberFormat.getCurrencyInstance(locale);
}
};
}
});


A segunda, é criar um conversor customizado para poder reutilizá-lo em outros componentes:

public class BigDecimalCurrencyConverter extends BigDecimalConverter {

public NumberFormat getNumberFormat(Locale locale) {
NumberFormat format = NumberFormat.getCurrencyInstance(locale);
return format;
}

}


        add(new Label("currency2", new Model(new BigDecimal("99"))) {
public IConverter getConverter(Class type) {
return (IConverter) new BigDecimalCurrencyConverter();
}
});


E a terceira opção, um pouco mais complexa, consiste em definir um tipo para valores monetários, , um conversor específico para este tipo e registrar este conversor na aplicação Wicket, para que sempre que este tipo passar por algum componente, será automaticamente convertido. Vamos ver como fica.

Como não se pretende aqui sobrescrever o conversor padrão para BigDecimal, cria-se o tipo Currency:

public class Currency extends BigDecimal {

public Currency(BigDecimal value) {
super(value.toString());
}

}


Isto serve para que, em lugares onde não se quer definir literalmente um valor monetário, mas apenas um BigDecimal, seja posssível utilizar-se do BigDecimalConverter, fornecido automaticamente pelo framework. Sem conflitos! :-) Agora é preciso definir o CurrencyConverter:

public class CurrencyConverter extends AbstractDecimalConverter {

private BigDecimalConverter converter = new BigDecimalConverter() {
public NumberFormat getNumberFormat(Locale locale) {
return CurrencyConverter.this.getNumberFormat(locale);
}
};

public NumberFormat getNumberFormat(Locale locale) {
return NumberFormat.getCurrencyInstance(locale);
}

protected Class getTargetType() {
return Currency.class;
}

public Currency convertToObject(String value, Locale locale) {
return new Currency(converter.convertToObject(value, locale));
}

}


Talvez você se perguntou "porque não herdar de BigDecimalConverter?". Simples: por causa de algumas definições de Generics, não é possível herdar de BigDecimalConverter, pois este já está atrelado ao tipo BigDecimal. Veja o fonte da classe. :-)

Agora, só basta registrar este conversor para o tipo Currency. Isto é feito lá na sua classe que herda de WebApplication. Sobrescreva o método newConverterLocator() desta forma:

    protected IConverterLocator newConverterLocator() {
ConverterLocator locator = new ConverterLocator();
locator.set(Currency.class, new CurrencyConverter());
return locator;
}


E pronto! Veja como fica o uso neste terceiro caso:

add(new Label("currency3", new Model(new Currency(new BigDecimal("99")))));


Agora, como utilizar isso com outros componentes além do Label, só fuçando!! Para mais informações sobre conversores, clica aqui.

Dúvidas? Sugestões? Elogios? Comentem! :-)

[]'s!
Postar um comentário
Contato

Email:bruno.borges(at)gmail.com

LinkedIn: www.linkedin.com/in/brunocborges
Twitter: www.twitter.com/brunoborges
Comprei e Não Vou
Rio de Janeiro, RJ Brasil
Oracle
São Paulo, SP Brasil