package de.jpaw.fixedpoint.money;

import java.io.Serializable;

import de.jpaw.api.iso.CurrencyData;
import de.jpaw.fixedpoint.FixedPointBase;
import de.jpaw.fixedpoint.FixedPointSelector;

/** Class to store the notion of a currency, with the option to override the number of decimals (fractional digits).
 * By default, the number of decimals corresponds to the one of the real currency as defined by ISO 4217.
 * Instances of this class are immutable.
 */
public final class FPCurrency implements Serializable {
    private static final long serialVersionUID = -626929186120783201L;

    /** The currency's feature provider. */
    private final CurrencyData currency;
    
    /** The numeric reference object, of value 0. */
    private final FixedPointBase<?> zero;

    /** The result of the toString() operation, after first execution. */
    private transient String asString = null;

    /** Constructs a new FPCurreny instance for a given currency and precision / storage type. */
    public FPCurrency(CurrencyData currency, FixedPointBase<?> referenceType) {
        if (currency == null || referenceType == null)
            throw new NullPointerException("currency and reference type must be non-null");
        this.currency = currency;
        this.zero = referenceType.getZero();
    }

    /** Constructs a new FPCurreny instance for a given currency, selecting the precision / storage type by the currency. */
    public FPCurrency(CurrencyData currency) {
        if (currency == null)
            throw new NullPointerException("currency must be non-null");
        this.currency = currency;
        this.zero = FixedPointSelector.getZeroForScale(currency.getDefaultFractionDigits());
    }

    @Override
    public String toString() {
        if (asString == null) {
            // build a hashed string
            asString = (zero.getScale() == currency.getDefaultFractionDigits())
                    ? currency.getCurrencyCode()
                    : currency.getCurrencyCode() + ":" + zero.getScale();
        }
        return asString;
    }

    // default Eclipse autogenerated methods below

    /** Returns a FixedPointBase<?> type representing 0 in the currency's scale. */
    public FixedPointBase<?> getZero() {
        return zero;
    }
    
    public CurrencyData getCurrency() {
        return currency;
    }

    // derived getters for convenience
    public String getCurrencyCode() {
        return currency.getCurrencyCode();
    }

    public int getDecimals() {
        return zero.getScale();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        return (prime * currency.hashCode()) * prime + zero.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FPCurrency other = (FPCurrency) obj;
        return currency == other.currency && zero == other.zero;
    }

}

@@ -2650,16 +2650,34 @@
 urrency.
+getCurrencyCode().
 hashCode
@@ -3036,53 +3036,208 @@
     
-return currency == other.currency && zero == 
+// Equals should be avoided because we don't know the object behind. Just compare the currency codes.%0A        return currency.getCurrencyCode().equals(other.currency.getCurrencyCode()) && zero.equals(
 othe
@@ -3238,23 +3238,24 @@
 s(other.zero
+)
 ;%0A    %7D%0A%0A%7D%0A

fix equals and hash