Mega Code Archive

 
Categories / Java / Data Type
 

Money type

//package org.groovyflow.util; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.List; import java.util.Locale; public class Money  implements Comparable, java.io.Serializable {     private static final String ZERO_STRING = "0";     private static final Money ZERO_MONEY = new Money(ZERO_STRING);     private BigDecimal delegate;     public static Money getMoneyThatHasZeroValue(){         return ZERO_MONEY;     }     public static Money getInfiniteMoney(){       Long x = Long.MAX_VALUE;       return new Money(x.toString());     }     public Money(String val) {       this.delegate = new BigDecimal(val);         if(delegate.scale() > 2)             throw new IllegalArgumentException("Money can't have scale > 2");         delegate.setScale(2);     }     public Money(BigDecimal value){         this(value.toString());     }     public Money add(Money val){         return new Money(delegate.add(val.delegate));     }     public Money subtract(Money val){       return new Money(delegate.subtract(val.delegate));     }     public BigDecimal multiply(BigDecimal val){       return delegate.multiply(val);     }     /**      * returns Money .  If roundCeiling is true we rounded up to      * the nearest cent, otherwise we round down.  Note that rounding toward the ceiling      * always rounds to positive infinity (so, for example, -$0.031 becomes      * -$0.03).   When roundCeiling is false we round toward the floor, so in that case      * -$0.031 becomes-$0.04.  This is exactly as BigDecimal.ROUND_CEILING and      * BigDecimal.ROUND_FLOOR behave.      * @see java.math.BigDecimal.ROUND_CEILING      */     public Money multiplyAndRound(BigDecimal val, boolean roundCeiling){       BigDecimal product = delegate.multiply(val);             int rounding = roundCeiling ? BigDecimal.ROUND_CEILING : BigDecimal.ROUND_FLOOR;             return new Money(product.setScale(2, rounding));     }     /**      * Sets scale to 2 and returns a Money object.      */     public Money divideAndReturnMoney(BigDecimal val, int roundingMode){       return new Money(delegate.divide(val, 2, roundingMode));     }         /**     *Round the return value before turning it into a Money object by passing it into the Money constructor.     */     public BigDecimal divide(BigDecimal val, int scale, int roundingMode) {         return delegate.divide(val, scale, roundingMode);     }     public BigDecimal divide(Money val, int scale, int roundingMode){         return divide(val.delegate, scale, roundingMode);     }     public BigDecimal getBigDecimalValue(){         return new BigDecimal(delegate.toString());     }     // Comparison Operations     public boolean gt(Money val){       return compareTo(val) > 0;     }     public boolean gtEq(Money val){       return compareTo(val) >= 0;     }     public boolean lt(Money val){       return compareTo(val) < 0;     }     public boolean ltEq(Money val){       return compareTo(val) <= 0;     }            public boolean gtZero(){       return gt(ZERO_MONEY);     }     public boolean gtEqZero(){       return gtEq(ZERO_MONEY);     }     public boolean ltZero(){       return lt(ZERO_MONEY);     }     public boolean ltEqZero(){       return ltEq(ZERO_MONEY);     }     public int compareTo(Money val){         return delegate.compareTo(val.delegate);     }     public int compareTo(Object o) {       return compareTo((Money)o);     }     /**      * Will return true if x is a Money object and x's private BigDecimal delegate      * has the same value as our private BigDecimal delegate, regardless of scale.      * A subtle point:  BigDecimal's .equal() requires that the scale of the compared      * BigDecimals are the same, while the current class's .equals does not require that.      * In fact, this .equals behaves like BigDecimal's .compareTo().      */     public boolean equals(Object x){         if(!(x instanceof Money))             return false;         Money brother = (Money) x;         return (delegate.compareTo(brother.delegate) == 0);     }     public boolean equalsZeroMoney(){         return this.equals(ZERO_MONEY);     }     public Money negate(){         return ZERO_MONEY.subtract(this);     }     /**      * Returns -1 if this is less than zero money, 0 if equal to zero money, 1 if greater than zero money.      */     public int compareToZeroMoney(){         return this.compareTo(ZERO_MONEY);     }     public Money min(Money val){         return new Money((delegate.min(val.delegate)).toString());     }     public Money max(Money val){         return new Money((delegate.max(val.delegate)).toString());     }          public Money abs(){       return new Money( delegate.abs().toString() );     }          public int hashCode() {       return delegate.hashCode();     }     /**      *Prints money with two decimal points.      */     public String toString(){         if(delegate == null)             return null;         //setting scale to 2 won't really force scale to 2 if we have something like 10 or 10.0, so         //we have to do the following.         int realScale = delegate.scale();         if(realScale == 2)             return delegate.toString();         else if(realScale == 1)             return delegate.toString() + "0";         else if (realScale == 0)             return delegate.toString() + ".00";         else             throw new RuntimeException("Scale of money object is > 2, should never happen, Money object is faulty.");     }     /**      * Front end re-wrote displayAsDollars so that it displays a negative amount without the      * negative sign.  If you want something sensible, use displayAsDollarsCorrectly instead.      */     public String displayAsDollarsCorrectly(){         if ( delegate.signum() < 0 ) {             this.delegate = delegate.negate();             String dis = "-$" + this.toString();             this.delegate = this.delegate.negate();             return dis;         } else {             return "$" + toString();         }     }     public String displayAsDollars(){         NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);         if ( delegate.signum() < 0 ) {             this.delegate = delegate.negate();             //String dis = "-$" + this.toString();             this.delegate = this.delegate.negate();             //return dis;             return nf.format(this.delegate);         } else {             return nf.format(this.delegate);             //return "$" + toString();         }     }     public int intValue(){       return delegate.intValue();     }     /**     *Null elements in the argument array will not cause things to blow up with a NullPointerException.     *Instead they will be ignored, because we foresee some circumstances in which a caller     *might have a sparsely populated array it wants summed up.  Note that call this class's     *add(Money) method one at a time does not, as of this writing, share this behavior.  Instead     *it will just blow up.     */     public static Money add(Money[] moneys){       //Attempt to save on object creation by adding up the BigDecimal       //delegates.  So rather than creating a Money and a BigDecimal       //with each element of the sum, we're just creating a BigDecimal.       BigDecimal total = new BigDecimal("0");       for(int i = 0; i < moneys.length; i++){         if(moneys[i] != null){           total = total.add(moneys[i].getBigDecimalValue());         }       }             return new Money(total);     }          public static Money add(List moneys){         Money[] arr = (Money[]) moneys.toArray(new Money[moneys.size()]);         return add(arr);     }          public static Money returnNullAsZero(Money money){       return (money == null) ? getMoneyThatHasZeroValue() : money;     } }