package de.invesdwin.util.math.decimal; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.math3.dfp.Dfp; import de.invesdwin.util.math.decimal.internal.impl.ADecimalImpl; @SuppressWarnings({ "serial", "rawtypes", "unchecked" }) @ThreadSafe class ScaledDecimalDelegateImpl extends ADecimalImpl { private final AScaledDecimal<?, ?> parent; private final ADecimalImpl delegate; @GuardedBy("none for performance") private transient ADecimalImpl defaultScaledDelegate; ScaledDecimalDelegateImpl(final AScaledDecimal<?, ?> parent, final ADecimalImpl delegate) { super(false, false); this.parent = parent; if (delegate instanceof ScaledDecimalDelegateImpl) { throw new IllegalArgumentException("Delegate [" + delegate + "] should not be an instance of " + ScaledDecimalDelegateImpl.class.getSimpleName()); } this.delegate = delegate; } public ADecimalImpl getDelegate() { return delegate; } private ADecimalImpl getDefaultScaledDelegate() { if (defaultScaledDelegate == null) { defaultScaledDelegate = parent.getDefaultValue().getImpl(); } return defaultScaledDelegate; } @Override public ADecimalImpl round(final int scale, final RoundingMode roundingMode) { return getDelegate().round(scale, roundingMode); } @Override public int getWholeNumberDigits() { return getDefaultScaledDelegate().getWholeNumberDigits(); } @Override public int getDecimalDigits() { return getDefaultScaledDelegate().getDecimalDigits(); } @Override public int getDigits() { return getDefaultScaledDelegate().getDigits(); } @Override public boolean isZero() { return getDelegate().isZero(); } @Override public boolean isPositive() { return getDelegate().isPositive(); } @Override public int hashCode() { return getDefaultScaledDelegate().hashCode(); } @Override public boolean equals(final Object other) { final Object comparableOther = getComparableOther(other); return getDefaultScaledDelegate().equals(comparableOther); } @Override public int compareTo(final Object other) { final Object comparableOther = getComparableOther(other); return getDefaultScaledDelegate().compareTo(comparableOther); } @Override protected int internalCompareTo(final ADecimal decimalOther) { throw new UnsupportedOperationException(); } private Object getComparableOther(final Object other) { final Object comparableOther; if (other instanceof AScaledDecimal) { final AScaledDecimal<?, ?> cOther = (AScaledDecimal<?, ?>) other; comparableOther = cOther.getDefaultValue(); } else { comparableOther = other; } return comparableOther; } @Override public String toString() { return getDelegate().toString(); } @Override public ADecimalImpl abs() { return getDelegate().abs(); } @Override public ADecimalImpl scaleByPowerOfTen(final int n) { return getDelegate().scaleByPowerOfTen(n); } @Override public ADecimalImpl root(final Number n) { return getDelegate().root(n); } @Override public ADecimalImpl root(final ADecimal n) { return getDelegate().root(n); } @Override public ADecimalImpl sqrt() { return getDelegate().sqrt(); } @Override public ADecimalImpl log() { return getDelegate().log(); } @Override public ADecimalImpl exp() { return getDelegate().exp(); } @Override public ADecimalImpl log10() { return getDelegate().log10(); } @Override public ADecimalImpl exp10() { return getDelegate().exp10(); } @Override public ADecimalImpl cos() { return getDelegate().cos(); } @Override public ADecimalImpl sin() { return getDelegate().sin(); } @Override public ADecimalImpl pow(final Number exponent) { return getDelegate().pow(exponent); } @Override public ADecimalImpl pow(final ADecimal exponent) { return getDelegate().pow(exponent); } @Override public ADecimalImpl multiply(final Number multiplicant) { final ADecimalImpl newDefault = getDelegate().multiply(multiplicant); return parent.newValueCopy(newDefault).getImpl(); } @Override public ADecimalImpl divide(final Number divisor) { final ADecimalImpl newDefault = getDelegate().divide(divisor); return parent.newValueCopy(newDefault).getImpl(); } @Override public ADecimalImpl remainder(final Number divisor) { final ADecimalImpl newDefault = getDelegate().remainder(divisor); return parent.newValueCopy(newDefault).getImpl(); } @Override @Deprecated public ADecimalImpl subtract(final ADecimal subtrahend) { // final ADecimal<?> defaultScaledSubtrahend = maybeGetDefaultScaledNumber(subtrahend); // final ADecimalImpl newDefault = getDefaultScaledDelegate().subtract(defaultScaledSubtrahend); // return parent.fromDefaultValue(new Decimal(newDefault)).getImpl(); throw new UnsupportedOperationException(); } @Override @Deprecated public ADecimalImpl add(final ADecimal augend) { // final ADecimal<?> defaultScaledAugend = maybeGetDefaultScaledNumber(augend); // final ADecimalImpl newDefault = getDefaultScaledDelegate().add(defaultScaledAugend); // return parent.fromDefaultValue(new Decimal(newDefault)).getImpl(); throw new UnsupportedOperationException(); } @Override @Deprecated public ADecimalImpl multiply(final ADecimal multiplicant) { // final ADecimal<?> defaultScaledMultiplicant = maybeGetDefaultScaledNumber(multiplicant); // final ADecimalImpl newDefault = getDefaultScaledDelegate().multiply(defaultScaledMultiplicant); // return parent.fromDefaultValue(new Decimal(newDefault)).getImpl(); throw new UnsupportedOperationException(); } @Override @Deprecated public ADecimalImpl divide(final ADecimal divisor) { // final ADecimal<?> defaultScaledDivisor = maybeGetDefaultScaledNumber(divisor); // final ADecimalImpl newDefault = getDefaultScaledDelegate().divide(defaultScaledDivisor); // return parent.fromDefaultValue(new Decimal(newDefault)).getImpl(); throw new UnsupportedOperationException(); } @Override @Deprecated public ADecimalImpl remainder(final ADecimal divisor) { // final ADecimal<?> defaultScaledDivisor = maybeGetDefaultScaledNumber(divisor); // final ADecimalImpl newDefault = getDefaultScaledDelegate().remainder(defaultScaledDivisor); // return parent.fromDefaultValue(new Decimal(newDefault)).getImpl(); throw new UnsupportedOperationException(); } // private ADecimal<?> maybeGetDefaultScaledNumber(final ADecimal<?> number) { // if (number instanceof AScaledDecimal) { // final AScaledDecimal<?, ?> scaledNumber = (AScaledDecimal<?, ?>) number; // return scaledNumber.getDefaultValue(); // } else { // return number; // } // } @Override public BigDecimal bigDecimalValue() { return getDefaultScaledDelegate().bigDecimalValue(); } @Override public BigInteger bigIntegerValue() { return getDefaultScaledDelegate().bigIntegerValue(); } @Override public int intValue() { return getDefaultScaledDelegate().intValue(); } @Override public long longValue() { return getDefaultScaledDelegate().longValue(); } @Override public float floatValue() { return getDefaultScaledDelegate().floatValue(); } @Override public double doubleValue() { return getDefaultScaledDelegate().doubleValue(); } @Override public double doubleValueRaw() { return getDefaultScaledDelegate().doubleValueRaw(); } @Override public byte byteValue() { return getDefaultScaledDelegate().byteValue(); } @Override public short shortValue() { return getDefaultScaledDelegate().shortValue(); } @Override public Dfp dfpValue() { return getDefaultScaledDelegate().dfpValue(); } @Override protected Object internalRound(final Object value, final int scale, final RoundingMode roundingMode) { throw new UnsupportedOperationException(); } @Override protected Object getZero() { return null; } @Override protected ADecimalImpl newValueCopy(final Object value, final Object defaultRoundedValue) { throw new UnsupportedOperationException(); } @Override protected ADecimalImpl getGenericThis() { throw new UnsupportedOperationException(); } @Override public Number numberValue() { return getDefaultScaledDelegate().numberValue(); } @Override protected String internalToString() { throw new UnsupportedOperationException(); } }