Povo,
Desenvolvi uma classe que representa dinheiro. Gostaria da sugestões de vocês, mas tenham em mente que:
1 - não preciso trabalhar com mais de um tipo de moeda.
2 - não preciso trabalhar com uma sacola (bag) de moedas.
3 - não quero utilizar library de terceiros (mas as sugestões são bem-vindas).
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import javax.persistence.Embeddable;
@Embeddable
public class Dinheiro implements Serializable, Comparable<Dinheiro> {
private static final long serialVersionUID = 1L;
private static final String mensagemDinheiroNull = "Dinheiro não pode ser null";
private static MathContext CONTEXTO = new MathContext(15,
RoundingMode.HALF_UP);
private static int DECIMAIS = 2;
private static int MENOR = -1;
private static int IGUAL = 0;
private static int MAIOR = 1;
public static Dinheiro ZERO = new Dinheiro(0.00);
private BigDecimal montante = BigDecimal.ZERO;
protected Dinheiro() {
this.montante = this.montante.setScale(Dinheiro.DECIMAIS,
RoundingMode.HALF_UP);
}
public Dinheiro(String dinheiro) {
if (dinheiro == null)
throw new NullPointerException(Dinheiro.mensagemDinheiroNull);
this.montante = new BigDecimal(dinheiro);
if (this.montante.scale() > Dinheiro.DECIMAIS) {
throw new IllegalArgumentException("Número de decimais superior a "
+ Dinheiro.DECIMAIS);
}
}
public Dinheiro(BigDecimal montante) {
if (montante == null)
throw new NullPointerException("Montante não pode ser null");
if (montante.scale() > Dinheiro.DECIMAIS) {
throw new IllegalArgumentException("Número de decimais superior a "
+ Dinheiro.DECIMAIS);
}
this.montante = montante.setScale(Dinheiro.DECIMAIS,
RoundingMode.HALF_UP);
}
public Dinheiro(double montante) {
String[] partes = String.valueOf(montante).split("\\.");
if (partes.length == 2 && partes[1].length() > Dinheiro.DECIMAIS) {
throw new IllegalArgumentException("Número de decimais superior a "
+ Dinheiro.DECIMAIS);
}
this.montante = BigDecimal.valueOf(montante).setScale(
Dinheiro.DECIMAIS, RoundingMode.HALF_UP);
}
public Dinheiro(long montante) {
this.montante = BigDecimal.valueOf(montante).setScale(
Dinheiro.DECIMAIS, RoundingMode.HALF_UP);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((montante == null) ? 0 : montante.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dinheiro other = (Dinheiro) obj;
if (montante == null) {
if (other.montante != null)
return false;
} else if (montante.compareTo(other.montante) != 0)
return false;
return true;
}
@Override
public String toString() {
return "Dinheiro [montante=" + montante + "]";
}
public BigDecimal getMontante() {
return this.montante;
}
public Dinheiro somar(Dinheiro valorSoma) {
if (valorSoma == null)
throw new NullPointerException(Dinheiro.mensagemDinheiroNull);
return new Dinheiro(this.montante
.add(valorSoma.getMontante(), CONTEXTO).setScale(DECIMAIS,
RoundingMode.HALF_UP));
}
public Dinheiro subtrair(Dinheiro valorSubtrair) {
if (valorSubtrair == null)
throw new NullPointerException(Dinheiro.mensagemDinheiroNull);
return new Dinheiro(this.montante.subtract(valorSubtrair.getMontante(),
CONTEXTO).setScale(DECIMAIS, RoundingMode.HALF_UP));
}
public Dinheiro multiplicar(long valorMultiplicador) {
return new Dinheiro(this.montante.multiply(
BigDecimal.valueOf(valorMultiplicador), CONTEXTO).setScale(
DECIMAIS, RoundingMode.HALF_UP));
}
public Dinheiro multiplicar(double valorMultiplicador) {
return new Dinheiro(this.montante.multiply(
BigDecimal.valueOf(valorMultiplicador), CONTEXTO).setScale(
DECIMAIS, RoundingMode.HALF_UP));
}
public Dinheiro dividir(long valorDivisor) {
return new Dinheiro(this.montante.divide(
BigDecimal.valueOf(valorDivisor), CONTEXTO).setScale(DECIMAIS,
RoundingMode.HALF_UP));
}
public Dinheiro dividir(double valorDivisor) {
return new Dinheiro(this.montante.divide(
BigDecimal.valueOf(valorDivisor), CONTEXTO).setScale(DECIMAIS,
RoundingMode.HALF_UP));
}
public boolean isZero() {
return this.montante.compareTo(BigDecimal.ZERO) == IGUAL;
}
public boolean isMaior(Dinheiro dinheiro) {
return this.montante.compareTo(dinheiro.getMontante()) == MAIOR;
}
public boolean isMenor(Dinheiro dinheiro) {
return this.montante.compareTo(dinheiro.getMontante()) == MENOR;
}
public boolean isMaiorIgual(Dinheiro dinheiro) {
return (this.montante.compareTo(dinheiro.getMontante()) == MAIOR
|| this.montante.compareTo(dinheiro.getMontante()) == IGUAL);
}
public boolean isMenorIgual(Dinheiro dinheiro) {
return (this.montante.compareTo(dinheiro.getMontante()) == MENOR
|| this.montante.compareTo(dinheiro.getMontante()) == IGUAL);
}
public Dinheiro percentual(double perc) {
return new Dinheiro(this.montante
.multiply(BigDecimal.valueOf(perc), CONTEXTO)
.divide(BigDecimal.valueOf(100))
.setScale(DECIMAIS, RoundingMode.HALF_UP));
}
public int dividirParaInteiro(double divisor) {
return this.montante.divideToIntegralValue(BigDecimal.valueOf(divisor))
.intValue();
}
public int dividirParaInteiro(long divisor) {
return this.montante.divideToIntegralValue(BigDecimal.valueOf(divisor))
.intValue();
}
public int dividirParaInteiro(BigDecimal divisor) {
return this.montante.divideToIntegralValue(divisor).intValue();
}
public long dividirParaLong(double divisor) {
return this.montante.divideToIntegralValue(BigDecimal.valueOf(divisor))
.longValue();
}
public long dividirParaLong(long divisor) {
return this.montante.divideToIntegralValue(BigDecimal.valueOf(divisor))
.longValue();
}
public long dividirParaLong(BigDecimal divisor) {
return this.montante.divideToIntegralValue(divisor).longValue();
}
public double doubleValue() {
return this.montante.doubleValue();
}
public long longValue() {
return this.montante.longValue();
}
public Dinheiro inverter() {
return new Dinheiro(this.getMontante().negate(Dinheiro.CONTEXTO));
}
public Dinheiro max(Dinheiro dinheiro) {
return new Dinheiro(this.montante.max(dinheiro.montante));
}
public Dinheiro min(Dinheiro dinheiro) {
return new Dinheiro(this.montante.min(dinheiro.montante));
}
@Override
public int compareTo(Dinheiro dinheiro) {
if (dinheiro == null)
throw new NullPointerException(Dinheiro.mensagemDinheiroNull);
return this.montante.compareTo(dinheiro.getMontante());
}
}