package org.cryptocoinpartners.schema; import java.math.BigDecimal; import javax.persistence.Embeddable; import javax.persistence.Transient; import org.cryptocoinpartners.util.RemainderHandler; /** Best used for I/O */ @SuppressWarnings("ConstantConditions") @Embeddable public class DecimalAmount extends Amount { public static final DecimalAmount ZERO = new DecimalAmount(BigDecimal.ZERO); public static final DecimalAmount ONE = new DecimalAmount(BigDecimal.ONE); public static DecimalAmount of(Amount amount) { return new DecimalAmount(amount.asBigDecimal()); } public static DecimalAmount of(BigDecimal bigDecimal) { return new DecimalAmount(bigDecimal); } public static DecimalAmount of(String decimalStr) { return new DecimalAmount(new BigDecimal(decimalStr)); } public DecimalAmount(BigDecimal bd) { this.bd = bd; } @Override public DecimalAmount negate() { return new DecimalAmount(bd.negate()); } @Override public DecimalAmount invert() { return bd.compareTo(BigDecimal.ZERO) == 0 ? new DecimalAmount(BigDecimal.ZERO) : new DecimalAmount(BigDecimal.ONE.divide(bd, mc)); } @Override public Amount plus(Amount o) { return new DecimalAmount(bd.add(o.asBigDecimal())); } @Override public Amount minus(Amount o) { return new DecimalAmount(bd.subtract(o.asBigDecimal())); } @Override public Amount times(Amount o, RemainderHandler remainderHandler) { return new DecimalAmount(bd.multiply(o.asBigDecimal())); } @Override public Amount dividedBy(Amount o, RemainderHandler remainderHandler) { int scale = Math.max(o.asBigDecimal().scale(), mc.getPrecision()); return new DecimalAmount(bd.divide(o.asBigDecimal(), remainderHandler.getRoundingMode()).setScale(scale, remainderHandler.getRoundingMode())); } @Override public int compareTo(@SuppressWarnings("NullableProblems") Amount o) { if (o instanceof DecimalAmount) { DecimalAmount decimalAmount = (DecimalAmount) o; return bd.compareTo(decimalAmount.bd); } return bd.compareTo(o.asBigDecimal()); } @Override public void assertIBasis(long otherIBasis) { throw new BasisError(); } @Override @Transient public boolean isPositive() { return bd.compareTo(BigDecimal.ZERO) > 0; } @Override @Transient public boolean isZero() { return bd.compareTo(BigDecimal.ZERO) == 0; } @Override @Transient public boolean isNegative() { return bd.compareTo(BigDecimal.ZERO) < 0; } /** This should be used for display purposes only, not calculation! */ @Override public double asDouble() { return bd.doubleValue(); } @Override public BigDecimal asBigDecimal() { return bd; } @Override public DiscreteAmount toIBasis(long newIBasis, RemainderHandler remainderHandler) { BigDecimal oldAmount = bd; long newCount = oldAmount.multiply(new BigDecimal(newIBasis), remainderHandler.getMathContext()).longValue(); DiscreteAmount newAmount = new DiscreteAmount(newCount, newIBasis); BigDecimal remainder = oldAmount.subtract(newAmount.asBigDecimal(), remainderHandler.getMathContext()); remainderHandler.handleRemainder(newAmount, remainder); return newAmount; } @Override public String toString() { return bd.toString(); } // JPA protected DecimalAmount() { } // @Column(name = "bd", columnDefinition = "varchar(255)") // @Basic(optional = false) @Transient protected BigDecimal getBd() { return bd; } protected void setBd(BigDecimal bd) { this.bd = bd; } private BigDecimal bd; @Override @Transient public int getScale() { final BigDecimal bigDecimal = new BigDecimal("" + bd); final String s = bigDecimal.toPlainString(); final int index = s.indexOf('.'); if (index < 0) { return 0; } return s.length() - 1 - index; } }