1111package io .vertx .pgclient .data ;
1212
1313import java .math .BigDecimal ;
14- import java .math .BigInteger ;
14+ import java .text .DecimalFormat ;
15+ import java .util .Objects ;
1516
1617/**
1718 * The PostgreSQL <a href="https://www.postgresql.org/docs/9.1/datatype-money.html">MONEY</> type.
18- *
19- * This has the {@link #getIntegerPart() integer part} and {@link #getDecimalPart() decimal part} of the value without loss of information.
20- *
21- * {@link #bigDecimalValue()} returns the value without loss of information
22- * {@link #doubleValue()} ()} returns the value possible loss of information
19+ * <p>
20+ * {@link #bigDecimalValue()} returns the value without loss of information.
21+ * {@link #doubleValue()} returns the value possible loss of information.
2322 */
2423public class Money {
2524
26- private long integerPart ;
27- private int decimalPart ;
25+ private BigDecimal value ;
2826
27+ /**
28+ * @deprecated as of 4.5, use {@link #Money(Number)} instead
29+ */
30+ @ Deprecated
2931 public Money (long integerPart , int decimalPart ) {
30- setIntegerPart (integerPart );
31- setDecimalPart (decimalPart );
32+ this (new BigDecimal (integerPart + "." + new DecimalFormat ("00" ).format (decimalPart )));
3233 }
3334
3435 public Money (Number value ) {
35- if (value instanceof Double || value instanceof Float ) {
36- value = BigDecimal .valueOf ((double ) value );
36+ this .value = (value instanceof BigDecimal ? (BigDecimal ) value : new BigDecimal (String .valueOf (value ))).stripTrailingZeros ();
37+ if (this .value .toBigInteger ().abs ().longValue () > Long .MAX_VALUE / 100 ) {
38+ throw new IllegalArgumentException ("Value is too big: " + value );
3739 }
38- if (value instanceof BigDecimal ) {
39- BigInteger bd = ((BigDecimal ) value ).multiply (new BigDecimal (100 )).toBigInteger ();
40- setIntegerPart (bd .divide (BigInteger .valueOf (100 )).longValueExact ());
41- setDecimalPart (bd .remainder (BigInteger .valueOf (100 )).abs ().intValueExact ());
42- } else {
43- setIntegerPart (value .longValue ());
40+ if (this .value .scale () > 2 ) {
41+ throw new IllegalArgumentException ("Value has more than two decimal digits: " + value );
4442 }
4543 }
4644
4745 public Money () {
46+ value = BigDecimal .ZERO ;
4847 }
4948
49+ /**
50+ * @deprecated as of 4.5, use {@link #bigDecimalValue()} instead
51+ */
52+ @ Deprecated
5053 public long getIntegerPart () {
51- return integerPart ;
54+ return value . toBigInteger (). longValue () ;
5255 }
5356
57+ /**
58+ * @deprecated as of 4.5, use {@link #bigDecimalValue()} instead
59+ */
60+ @ Deprecated
5461 public int getDecimalPart () {
55- return decimalPart ;
62+ return value . remainder ( BigDecimal . ONE ). movePointRight ( value . scale ()). abs (). intValue () ;
5663 }
5764
5865 /**
59- * Set the integer part of the monetary value.
60- *
61- * <p> This value must belong to the range {@code ]Long.MAX_VALUE / 100, Long.MIN_VALUE / 100[}
62- *
63- * @param part the integer part of the value
64- * @return this object
66+ * @deprecated as of 4.5, create another instance instead
6567 */
68+ @ Deprecated
6669 public Money setIntegerPart (long part ) {
67- if (part > Long .MAX_VALUE / 100 || part < Long .MIN_VALUE / 100 ) {
68- throw new IllegalArgumentException ();
69- }
70- integerPart = part ;
70+ value = new Money (part , value .remainder (BigDecimal .ONE ).abs ().intValue ()).bigDecimalValue ();
7171 return this ;
7272 }
7373
7474 /**
75- * Set the decimal part of the monetary value.
76- *
77- * <p> This value must belong to the range {@code [0, 100]}
78- *
79- * @param part decimal part
80- * @return this object
75+ * @deprecated as of 4.5, create another instance instead
8176 */
77+ @ Deprecated
8278 public Money setDecimalPart (int part ) {
83- if (part > 99 || part < 0 ) {
84- throw new IllegalArgumentException ();
85- }
86- decimalPart = part ;
79+ value = new Money (value .longValue (), part ).bigDecimalValue ();
8780 return this ;
8881 }
8982
9083 /**
9184 * @return the monetary amount as a big decimal without loss of information
9285 */
9386 public BigDecimal bigDecimalValue () {
94- BigDecimal value = new BigDecimal (integerPart ).multiply (BigDecimal .valueOf (100 ));
95- if (integerPart >= 0 ) {
96- value = value .add (BigDecimal .valueOf (decimalPart ));
97- } else {
98- value = value .subtract (BigDecimal .valueOf (decimalPart ));
99- }
10087 return value ;
10188 }
10289
@@ -111,17 +98,17 @@ public double doubleValue() {
11198 public boolean equals (Object o ) {
11299 if (this == o ) return true ;
113100 if (o == null || getClass () != o .getClass ()) return false ;
114- Money that = (Money ) o ;
115- return decimalPart == that . decimalPart && integerPart == that . integerPart ;
101+ Money money = (Money ) o ;
102+ return Objects . equals ( value , money . value ) ;
116103 }
117104
118105 @ Override
119106 public int hashCode () {
120- return (( Long ) integerPart ). hashCode () ^ (( Integer ) decimalPart ). hashCode ( );
107+ return Objects . hash ( value );
121108 }
122109
123110 @ Override
124111 public String toString () {
125- return "Money(" + integerPart + "." + decimalPart + ")" ;
112+ return "Money(" + new DecimalFormat ( "#0.##" ). format ( value ) + ")" ;
126113 }
127114}
0 commit comments