001/* 002 * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. Licensed under the Apache 003 * License, Version 2.0 (the "License"); you may not use this file except in compliance with the 004 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 005 * Unless required by applicable law or agreed to in writing, software distributed under the License 006 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 007 * or implied. See the License for the specific language governing permissions and limitations under 008 * the License. 009 */ 010package org.javamoney.moneta; 011 012import org.javamoney.moneta.internal.RoundedMoneyAmountFactory; 013import org.javamoney.moneta.spi.AbstractMoney; 014import org.javamoney.moneta.spi.DefaultNumberValue; 015 016import javax.money.*; 017import java.io.*; 018import java.math.BigDecimal; 019import java.math.BigInteger; 020import java.math.MathContext; 021import java.math.RoundingMode; 022import java.util.Objects; 023 024/** 025 * Platform RI: Default immutable implementation of {@link MonetaryAmount} based on 026 * {@link BigDecimal} for the numeric representation. 027 * <p/> 028 * As required by {@link MonetaryAmount} this class is final, thread-safe, immutable and 029 * serializable. 030 * 031 * @author Anatole Tresch 032 * @author Werner Keil 033 * @version 0.6.1 034 */ 035public final class RoundedMoney extends AbstractMoney implements Comparable<MonetaryAmount>, Serializable{ 036 037 /** 038 * serialVersionUID. 039 */ 040 private static final long serialVersionUID = 366517590511294389L; 041 /** 042 * The default {@link MonetaryContext} applied. 043 */ 044 public static final MonetaryContext DEFAULT_MONETARY_CONTEXT = 045 MonetaryContext.from(Money.DEFAULT_MONETARY_CONTEXT, RoundedMoney.class); 046 047 /** 048 * The numeric part of this amount. 049 */ 050 private BigDecimal number; 051 052 /** 053 * The rounding to be done. 054 */ 055 private MonetaryOperator rounding; 056 057 /** 058 * Required for deserialization only. 059 */ 060 private RoundedMoney(){ 061 } 062 063 /** 064 * Creates a new instance os {@link RoundedMoney}. 065 * 066 * @param currency the currency, not null. 067 * @param number the amount, not null. 068 */ 069 private RoundedMoney(CurrencyUnit currency, Number number, MonetaryContext monetaryContext, 070 MonetaryOperator rounding){ 071 super(currency, monetaryContext); 072 Objects.requireNonNull(number, "Number is required."); 073 checkNumber(number); 074 this.currency = currency; 075 if(rounding != null){ 076 this.rounding = rounding; 077 }else{ 078 this.rounding = MonetaryRoundings.getRounding(currency); 079 } 080 this.number = getBigDecimal(number, monetaryContext); 081 } 082 083 // Static Factory Methods 084 085 /** 086 * Translates a {@code BigDecimal} value and a {@code CurrencyUnit} currency into a 087 * {@code Money}. 088 * 089 * @param number numeric value of the {@code Money}. 090 * @param currency currency unit of the {@code Money}. 091 * @return a {@code Money} combining the numeric value and currency unit. 092 */ 093 public static RoundedMoney of(CurrencyUnit currency, BigDecimal number){ 094 return new RoundedMoney(currency, number, DEFAULT_MONETARY_CONTEXT, null); 095 } 096 097 /** 098 * Translates a {@code BigDecimal} value and a {@code CurrencyUnit} currency into a 099 * {@code Money}. 100 * 101 * @param number numeric value of the {@code Money}. 102 * @param currency currency unit of the {@code Money}. 103 * @param rounding The rounding to be applied. 104 * @return a {@code Money} combining the numeric value and currency unit. 105 */ 106 public static RoundedMoney of(CurrencyUnit currency, BigDecimal number, MonetaryOperator rounding){ 107 return new RoundedMoney(currency, number, DEFAULT_MONETARY_CONTEXT, rounding); 108 } 109 110 /** 111 * Translates a {@code BigDecimal} value and a {@code CurrencyUnit} currency into a 112 * {@code Money}. 113 * 114 * @param number numeric value of the {@code Money}. 115 * @param currency currency unit of the {@code Money}. 116 * @param monetaryContext the {@link MathContext} to be used. 117 * @return a {@code Money} combining the numeric value and currency unit. 118 */ 119 public static RoundedMoney of(CurrencyUnit currency, BigDecimal number, MonetaryContext monetaryContext){ 120 return new RoundedMoney(currency, number, MonetaryContext.from(monetaryContext, RoundedMoney.class), null); 121 } 122 123 /** 124 * Translates a {@code BigDecimal} value and a {@code CurrencyUnit} currency into a 125 * {@code Money}. 126 * 127 * @param number numeric value of the {@code Money}. 128 * @param currency currency unit of the {@code Money}. 129 * @param mathContext the {@link MathContext} to be used. 130 * @param rounding The rounding to be applied. 131 * @return a {@code Money} combining the numeric value and currency unit. 132 */ 133 public static RoundedMoney of(CurrencyUnit currency, BigDecimal number, MonetaryContext monetaryContext, 134 MonetaryOperator rounding){ 135 return new RoundedMoney(currency, number, MonetaryContext.from(monetaryContext, RoundedMoney.class), rounding); 136 } 137 138 /** 139 * Static factory method for creating a new instance of {@link RoundedMoney} . 140 * 141 * @param currency The target currency, not null. 142 * @param number The numeric part, not null. 143 * @return A new instance of {@link RoundedMoney}. 144 */ 145 public static RoundedMoney of(CurrencyUnit currency, Number number){ 146 return new RoundedMoney(currency, number, (MonetaryContext) null, null); 147 } 148 149 /** 150 * Static factory method for creating a new instance of {@link RoundedMoney} . 151 * 152 * @param currency The target currency, not null. 153 * @param number The numeric part, not null. 154 * @param rounding The rounding to be applied. 155 * @return A new instance of {@link RoundedMoney}. 156 */ 157 public static RoundedMoney of(CurrencyUnit currency, Number number, MonetaryOperator rounding){ 158 return new RoundedMoney(currency, number, (MonetaryContext) null, rounding); 159 } 160 161 /** 162 * Static factory method for creating a new instance of {@link RoundedMoney} . 163 * 164 * @param currency The target currency, not null. 165 * @param number The numeric part, not null. 166 * @return A new instance of {@link RoundedMoney}. 167 */ 168 public static RoundedMoney of(CurrencyUnit currency, Number number, MonetaryContext monetaryContext){ 169 return new RoundedMoney(currency, number, MonetaryContext.from(monetaryContext, RoundedMoney.class), null); 170 } 171 172 /** 173 * Static factory method for creating a new instance of {@link RoundedMoney} . 174 * 175 * @param currency The target currency, not null. 176 * @param number The numeric part, not null. 177 * @param monetaryContext the {@link MonetaryContext} to be used. 178 * @param rounding The rounding to be applied. 179 * @return A new instance of {@link RoundedMoney}. 180 */ 181 public static RoundedMoney of(CurrencyUnit currency, Number number, MonetaryContext monetaryContext, 182 MonetaryOperator rounding){ 183 return new RoundedMoney(currency, number, MonetaryContext.from(monetaryContext, RoundedMoney.class), rounding); 184 } 185 186 /** 187 * Static factory method for creating a new instance of {@link RoundedMoney} . 188 * 189 * @param isoCurrencyCode The target currency as ISO currency code. 190 * @param number The numeric part, not null. 191 * @return A new instance of {@link RoundedMoney}. 192 */ 193 public static RoundedMoney of(String currencyCode, Number number){ 194 return new RoundedMoney(MonetaryCurrencies.getCurrency(currencyCode), number, DEFAULT_MONETARY_CONTEXT, 195 MonetaryRoundings.getRounding(MonetaryCurrencies.getCurrency(currencyCode))); 196 } 197 198 /** 199 * Static factory method for creating a new instance of {@link RoundedMoney} . 200 * 201 * @param isoCurrencyCode The target currency as ISO currency code. 202 * @param number The numeric part, not null. 203 * @param rounding The rounding to be applied. 204 * @return A new instance of {@link RoundedMoney}. 205 */ 206 public static RoundedMoney of(String currencyCode, Number number, MonetaryOperator rounding){ 207 return new RoundedMoney(MonetaryCurrencies.getCurrency(currencyCode), number, DEFAULT_MONETARY_CONTEXT, 208 rounding); 209 } 210 211 /** 212 * Static factory method for creating a new instance of {@link RoundedMoney} . 213 * 214 * @param isoCurrencyCode The target currency as ISO currency code. 215 * @param number The numeric part, not null. 216 * @return A new instance of {@link RoundedMoney}. 217 */ 218 public static RoundedMoney of(String currencyCode, Number number, MonetaryContext monetaryContext){ 219 return new RoundedMoney(MonetaryCurrencies.getCurrency(currencyCode), number, 220 MonetaryContext.from(monetaryContext, RoundedMoney.class), 221 MonetaryRoundings.getRounding(monetaryContext)); 222 } 223 224 /** 225 * Static factory method for creating a new instance of {@link RoundedMoney} . 226 * 227 * @param isoCurrencyCode The target currency as ISO currency code. 228 * @param number The numeric part, not null. 229 * @param rounding The rounding to be applied. 230 * @return A new instance of {@link RoundedMoney}. 231 */ 232 public static RoundedMoney of(String currencyCode, Number number, MonetaryContext monetaryContext, 233 MonetaryOperator rounding){ 234 return new RoundedMoney(MonetaryCurrencies.getCurrency(currencyCode), number, 235 MonetaryContext.from(monetaryContext, RoundedMoney.class), rounding); 236 } 237 238 /* 239 * (non-Javadoc) 240 * @see javax.money.MonetaryAmount#getCurrency() 241 */ 242 public CurrencyUnit getCurrency(){ 243 return currency; 244 } 245 246 /** 247 * Access the {@link MathContext} used by this instance. 248 * 249 * @return the {@link MathContext} used, never null. 250 */ 251 public MonetaryContext getMonetaryContext(){ 252 return this.monetaryContext; 253 } 254 255 public RoundedMoney abs(){ 256 if(this.isPositiveOrZero()){ 257 return this; 258 } 259 return this.negate(); 260 } 261 262 // Arithmetic Operations 263 264 public RoundedMoney add(MonetaryAmount amount){ 265 checkAmountParameter(amount); 266 return (RoundedMoney) new RoundedMoney(this.currency, 267 this.number.add(amount.getNumber().numberValue(BigDecimal.class)), 268 this.monetaryContext, this.rounding).with(rounding); 269 } 270 271 /* 272 * (non-Javadoc) 273 * @see javax.money.MonetaryAmount#divide(javax.money.MonetaryAmount) 274 */ 275 public RoundedMoney divide(Number divisor){ 276 277 BigDecimal dec = this.number.divide(getBigDecimal(divisor), this.monetaryContext 278 .getAttribute(RoundingMode.class, RoundingMode.HALF_EVEN)); 279 return (RoundedMoney) new RoundedMoney(this.currency, dec, this.monetaryContext, this.rounding).with(rounding); 280 } 281 282 /* 283 * (non-Javadoc) 284 * @see javax.money.MonetaryAmount#divideAndRemainder(javax.money.MonetaryAmount) 285 */ 286 public RoundedMoney[] divideAndRemainder(Number divisor){ 287 BigDecimal[] dec = this.number.divideAndRemainder(getBigDecimal(divisor), this.monetaryContext 288 .getAttribute(MathContext.class, MathContext.DECIMAL64)); 289 return new RoundedMoney[]{new RoundedMoney(this.currency, dec[0], this.monetaryContext, this.rounding), 290 (RoundedMoney) new RoundedMoney(this.currency, dec[1], this.monetaryContext, this.rounding) 291 .with(rounding)}; 292 } 293 294 /* 295 * (non-Javadoc) 296 * @see javax.money.MonetaryAmount#divideToIntegralValue(Number) )D 297 */ 298 public RoundedMoney divideToIntegralValue(Number divisor){ 299 BigDecimal dec = this.number.divideToIntegralValue(getBigDecimal(divisor), this.monetaryContext 300 .getAttribute(MathContext.class, MathContext.DECIMAL64)); 301 return new RoundedMoney(this.currency, dec, this.monetaryContext, this.rounding); 302 } 303 304 /* 305 * (non-Javadoc) 306 * @see javax.money.MonetaryAmount#multiply(Number) 307 */ 308 public RoundedMoney multiply(Number multiplicand){ 309 BigDecimal dec = this.number.multiply(getBigDecimal(multiplicand), this.monetaryContext 310 .getAttribute(MathContext.class, MathContext.DECIMAL64)); 311 return (RoundedMoney) new RoundedMoney(this.currency, dec, this.monetaryContext, this.rounding).with(rounding); 312 } 313 314 /* 315 * (non-Javadoc) 316 * @see javax.money.MonetaryAmount#negate() 317 */ 318 public RoundedMoney negate(){ 319 return new RoundedMoney(this.currency, this.number 320 .negate(this.monetaryContext.getAttribute(MathContext.class, MathContext.DECIMAL64)), 321 this.monetaryContext, this.rounding); 322 } 323 324 /* 325 * (non-Javadoc) 326 * @see javax.money.MonetaryAmount#plus() 327 */ 328 public RoundedMoney plus(){ 329 return new RoundedMoney(this.currency, this.number 330 .plus(this.monetaryContext.getAttribute(MathContext.class, MathContext.DECIMAL64)), 331 this.monetaryContext, this.rounding); 332 } 333 334 /* 335 * (non-Javadoc) 336 * @see javax.money.MonetaryAmount#subtract(javax.money.MonetaryAmount) 337 */ 338 public RoundedMoney subtract(MonetaryAmount subtrahend){ 339 checkAmountParameter(subtrahend); 340 if(subtrahend.isZero()){ 341 return this; 342 } 343 return new RoundedMoney(this.currency, this.number 344 .subtract(subtrahend.getNumber().numberValue(BigDecimal.class), 345 this.monetaryContext.getAttribute(MathContext.class, MathContext.DECIMAL64)), 346 this.monetaryContext, this.rounding); 347 } 348 349 /* 350 * (non-Javadoc) 351 * @see javax.money.MonetaryAmount#pow(int) 352 */ 353 public RoundedMoney pow(int n){ 354 return new RoundedMoney(this.currency, this.number 355 .pow(n, this.monetaryContext.getAttribute(MathContext.class, MathContext.DECIMAL64)), 356 this.monetaryContext, this.rounding).with(rounding); 357 } 358 359 /* 360 * (non-Javadoc) 361 * @see javax.money.MonetaryAmount#ulp() 362 */ 363 public RoundedMoney ulp(){ 364 return new RoundedMoney(this.currency, this.number.ulp(), DEFAULT_MONETARY_CONTEXT, this.rounding); 365 } 366 367 /* 368 * (non-Javadoc) 369 * @see javax.money.MonetaryAmount#remainder(Number) 370 */ 371 public RoundedMoney remainder(Number divisor){ 372 return new RoundedMoney(this.currency, this.number.remainder(getBigDecimal(divisor), this.monetaryContext 373 .getAttribute(MathContext.class, MathContext.DECIMAL64)), this.monetaryContext, this.rounding); 374 } 375 376 /* 377 * (non-Javadoc) 378 * @see javax.money.MonetaryAmount#scaleByPowerOfTen(int) 379 */ 380 public RoundedMoney scaleByPowerOfTen(int n){ 381 return new RoundedMoney(this.currency, this.number.scaleByPowerOfTen(n), this.monetaryContext, this.rounding); 382 } 383 384 /* 385 * (non-Javadoc) 386 * @see javax.money.MonetaryAmount#isZero() 387 */ 388 public boolean isZero(){ 389 return this.number.signum() == 0; 390 } 391 392 /* 393 * (non-Javadoc) 394 * @see javax.money.MonetaryAmount#isPositive() 395 */ 396 public boolean isPositive(){ 397 return signum() == 1; 398 } 399 400 /* 401 * (non-Javadoc) 402 * @see javax.money.MonetaryAmount#isPositiveOrZero() 403 */ 404 public boolean isPositiveOrZero(){ 405 return signum() >= 0; 406 } 407 408 /* 409 * (non-Javadoc) 410 * @see javax.money.MonetaryAmount#isNegative() 411 */ 412 public boolean isNegative(){ 413 return signum() == -1; 414 } 415 416 /* 417 * (non-Javadoc) 418 * @see javax.money.MonetaryAmount#isNegativeOrZero() 419 */ 420 public boolean isNegativeOrZero(){ 421 return signum() <= 0; 422 } 423 424 /* 425 * (non-Javadoc) 426 * @see javax.money.MonetaryAmount#with(java.lang.Number) 427 */ 428 public RoundedMoney with(Number amount){ 429 checkNumber(amount); 430 return new RoundedMoney(this.currency, getBigDecimal(amount), this.monetaryContext, this.rounding); 431 } 432 433 /** 434 * Creates a new Money instance, by just replacing the {@link CurrencyUnit}. 435 * 436 * @param currency the currency unit to be replaced, not {@code null} 437 * @return the new amount with the same numeric value and {@link MathContext}, but the new 438 * {@link CurrencyUnit}. 439 */ 440 public RoundedMoney with(CurrencyUnit currency){ 441 Objects.requireNonNull(currency, "currency required"); 442 return new RoundedMoney(currency, asType(BigDecimal.class), this.monetaryContext, this.rounding); 443 } 444 445 /* 446 * (non-Javadoc) 447 * @see javax.money.MonetaryAmount#with(CurrencyUnit, java.lang.Number) 448 */ 449 public RoundedMoney with(CurrencyUnit currency, Number amount){ 450 checkNumber(amount); 451 return new RoundedMoney(currency, getBigDecimal(amount), this.monetaryContext, this.rounding); 452 } 453 454 /* 455 * (non-Javadoc) 456 * @see javax.money.MonetaryAmount#getScale() 457 */ 458 public int getScale(){ 459 return this.number.scale(); 460 } 461 462 /* 463 * (non-Javadoc) 464 * @see javax.money.MonetaryAmount#getPrecision() 465 */ 466 public int getPrecision(){ 467 return this.number.precision(); 468 } 469 470 /* 471 * (non-Javadoc) 472 * @see javax.money.MonetaryAmount#signum() 473 */ 474 475 public int signum(){ 476 return this.number.signum(); 477 } 478 479 /* 480 * (non-Javadoc) 481 * @see javax.money.MonetaryAmount#lessThan(javax.money.MonetaryAmount) 482 */ 483 public boolean isLessThan(MonetaryAmount amount){ 484 checkAmountParameter(amount); 485 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) < 0; 486 } 487 488 /* 489 * (non-Javadoc) 490 * @see javax.money.MonetaryAmount#lessThanOrEqualTo(javax.money.MonetaryAmount) 491 */ 492 public boolean isLessThanOrEqualTo(MonetaryAmount amount){ 493 checkAmountParameter(amount); 494 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) <= 0; 495 } 496 497 /* 498 * (non-Javadoc) 499 * @see javax.money.MonetaryAmount#greaterThan(javax.money.MonetaryAmount) 500 */ 501 public boolean isGreaterThan(MonetaryAmount amount){ 502 checkAmountParameter(amount); 503 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) > 0; 504 } 505 506 /* 507 * (non-Javadoc) 508 * @see javax.money.MonetaryAmount#greaterThanOrEqualTo(javax.money.MonetaryAmount ) #see 509 */ 510 public boolean isGreaterThanOrEqualTo(MonetaryAmount amount){ 511 checkAmountParameter(amount); 512 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) >= 0; 513 } 514 515 /* 516 * (non-Javadoc) 517 * @see javax.money.MonetaryAmount#isEqualTo(javax.money.MonetaryAmount) 518 */ 519 public boolean isEqualTo(MonetaryAmount amount){ 520 checkAmountParameter(amount); 521 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) == 0; 522 } 523 524 /* 525 * (non-Javadoc) 526 * @see javax.money.MonetaryAmount#isNotEqualTo(javax.money.MonetaryAmount) 527 */ 528 public boolean isNotEqualTo(MonetaryAmount amount){ 529 checkAmountParameter(amount); 530 return number.compareTo(amount.getNumber().numberValue(BigDecimal.class)) != 0; 531 } 532 533 /* 534 * }(non-Javadoc) 535 * @see javax.money.MonetaryAmount#adjust(javax.money.AmountAdjuster) 536 */ 537 @Override 538 public RoundedMoney with(MonetaryOperator operator){ 539 Objects.requireNonNull(operator); 540 try{ 541 return RoundedMoney.from(operator.apply(this)); 542 } 543 catch(Exception e){ 544 throw new MonetaryException("Query failed: " + operator, e); 545 } 546 } 547 548 public static RoundedMoney from(MonetaryAmount amt){ 549 if(amt.getClass() == RoundedMoney.class){ 550 return (RoundedMoney) amt; 551 } 552 if(amt.getClass() == FastMoney.class){ 553 return RoundedMoney.of(amt.getCurrency(), ((FastMoney) amt).getNumber().numberValue(BigDecimal.class), 554 DEFAULT_MONETARY_CONTEXT); 555 }else if(amt.getClass() == Money.class){ 556 return RoundedMoney 557 .of(amt.getCurrency(), amt.getNumber().numberValue(BigDecimal.class), DEFAULT_MONETARY_CONTEXT); 558 } 559 return RoundedMoney 560 .of(amt.getCurrency(), amt.getNumber().numberValue(BigDecimal.class), DEFAULT_MONETARY_CONTEXT); 561 } 562 563 /* 564 * }(non-Javadoc) 565 * @see javax.money.MonetaryAmount#adjust(javax.money.AmountAdjuster) 566 */ 567 @Override 568 public <T> T query(MonetaryQuery<T> query){ 569 Objects.requireNonNull(query); 570 try{ 571 return query.queryFrom(this); 572 } 573 catch(Exception e){ 574 throw new MonetaryException("Query failed: " + query, e); 575 } 576 } 577 578 /* 579 * @see javax.money.MonetaryAmount#asType(java.lang.Class) 580 */ 581 @SuppressWarnings("unchecked") 582 public <T> T asType(Class<T> type){ 583 if(BigDecimal.class.equals(type)){ 584 return (T) this.number; 585 } 586 if(Number.class.equals(type)){ 587 final T asType = (T) this.number; 588 return asType; 589 } 590 if(Double.class.equals(type)){ 591 return (T) Double.valueOf(this.number.doubleValue()); 592 } 593 if(Float.class.equals(type)){ 594 return (T) Float.valueOf(this.number.floatValue()); 595 } 596 if(Long.class.equals(type)){ 597 return (T) Long.valueOf(this.number.longValue()); 598 } 599 if(Integer.class.equals(type)){ 600 return (T) Integer.valueOf(this.number.intValue()); 601 } 602 if(Short.class.equals(type)){ 603 return (T) Short.valueOf(this.number.shortValue()); 604 } 605 if(Byte.class.equals(type)){ 606 return (T) Byte.valueOf(this.number.byteValue()); 607 } 608 if(BigInteger.class.equals(type)){ 609 return (T) this.number.toBigInteger(); 610 } 611 throw new IllegalArgumentException("Unsupported representation type: " + type); 612 } 613 614 /* 615 * }(non-Javadoc) 616 * @see javax.money.MonetaryAmount#asType(java.lang.Class, javax.money.Rounding) 617 */ 618 public <T> T asType(Class<T> type, MonetaryOperator adjuster){ 619 RoundedMoney amount = (RoundedMoney) adjuster.apply(this); 620 return amount.asType(type); 621 } 622 623 private void writeObject(ObjectOutputStream oos) throws IOException{ 624 oos.writeObject(this.number); 625 oos.writeObject(this.monetaryContext); 626 oos.writeObject(this.currency); 627 } 628 629 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{ 630 this.number = (BigDecimal) ois.readObject(); 631 this.monetaryContext = (MonetaryContext) ois.readObject(); 632 this.currency = (CurrencyUnit) ois.readObject(); 633 } 634 635 @SuppressWarnings("unused") 636 private void readObjectNoData() throws ObjectStreamException{ 637 if(this.number == null){ 638 this.number = BigDecimal.ZERO; 639 } 640 if(this.monetaryContext == null){ 641 this.monetaryContext = DEFAULT_MONETARY_CONTEXT; 642 } 643 if(this.currency == null){ 644 this.currency = MonetaryCurrencies.getCurrency("XXX"); // no 645 // currency 646 } 647 } 648 649 /* 650 * (non-Javadoc) 651 * @see java.lang.Object#toString() 652 */ 653 @Override 654 public String toString(){ 655 return currency.getCurrencyCode() + ' ' + number; 656 } 657 658 /* 659 * (non-Javadoc) 660 * @see java.lang.Object#hashCode() 661 */ 662 @Override 663 public int hashCode(){ 664 final int prime = 31; 665 int result = 1; 666 result = prime * result + ((currency == null) ? 0 : currency.hashCode()); 667 return prime * result + asNumberStripped().hashCode(); 668 } 669 670 /* 671 * (non-Javadoc) 672 * @see java.lang.Object#equals(java.lang.Object) 673 */ 674 @Override 675 public boolean equals(Object obj){ 676 if(this == obj) 677 return true; 678 if(obj == null) 679 return false; 680 if(getClass() != obj.getClass()) 681 return false; 682 RoundedMoney other = (RoundedMoney) obj; 683 if(currency == null){ 684 if(other.currency != null) 685 return false; 686 }else if(!currency.equals(other.currency)) 687 return false; 688 return asNumberStripped().equals(other.asNumberStripped()); 689 } 690 691 /* 692 * @see java.lang.Comparable#compareTo(java.lang.Object) 693 */ 694 public int compareTo(MonetaryAmount o){ 695 Objects.requireNonNull(o); 696 int compare = -1; 697 if(this.currency.equals(o.getCurrency())){ 698 compare = asNumberStripped().compareTo(RoundedMoney.from(o).asNumberStripped()); 699 }else{ 700 compare = this.currency.getCurrencyCode().compareTo(o.getCurrency().getCurrencyCode()); 701 } 702 return compare; 703 } 704 705 /* 706 * (non-Javadoc) 707 * @see javax.money.MonetaryAmount#getNumber() 708 */ 709 public NumberValue getNumber(){ 710 return new DefaultNumberValue(number); 711 } 712 713 /** 714 * Method that returns BigDecimal.ZERO, if {@link #isZero()}, and #number 715 * {@link #stripTrailingZeros()} in all other cases. 716 * 717 * @return the stripped number value. 718 */ 719 public BigDecimal asNumberStripped(){ 720 if(isZero()){ 721 return BigDecimal.ZERO; 722 } 723 return this.number.stripTrailingZeros(); 724 } 725 726 /** 727 * Internal method to check for correct number parameter. 728 * 729 * @param number 730 * @throws IllegalArgumentException If the number is null 731 */ 732 private void checkNumber(Number number){ 733 Objects.requireNonNull(number, "Number is required."); 734 } 735 736 @Override 737 public RoundedMoney multiply(long amount){ 738 return multiply(getBigDecimal(amount)); 739 } 740 741 @Override 742 public RoundedMoney multiply(double amount){ 743 return multiply(getBigDecimal(amount)); 744 } 745 746 @Override 747 public RoundedMoney divide(long amount){ 748 return divide(getBigDecimal(amount)); 749 } 750 751 @Override 752 public RoundedMoney divide(double amount){ 753 return divide(getBigDecimal(amount)); 754 } 755 756 @Override 757 public RoundedMoney remainder(long amount){ 758 return remainder(getBigDecimal(amount)); 759 } 760 761 @Override 762 public RoundedMoney remainder(double amount){ 763 return remainder(getBigDecimal(amount)); 764 } 765 766 @Override 767 public RoundedMoney[] divideAndRemainder(long amount){ 768 return divideAndRemainder(getBigDecimal(amount)); 769 } 770 771 @Override 772 public RoundedMoney[] divideAndRemainder(double amount){ 773 return divideAndRemainder(getBigDecimal(amount)); 774 } 775 776 @Override 777 public RoundedMoney stripTrailingZeros(){ 778 if(isZero()){ 779 return of(getCurrency(), BigDecimal.ZERO); 780 } 781 return of(getCurrency(), this.number.stripTrailingZeros()); 782 } 783 784 @Override 785 public RoundedMoney divideToIntegralValue(long divisor){ 786 return divideToIntegralValue(getBigDecimal(divisor)); 787 } 788 789 @Override 790 public RoundedMoney divideToIntegralValue(double divisor){ 791 return divideToIntegralValue(getBigDecimal(divisor)); 792 } 793 794 @Override 795 protected MonetaryContext getDefaultMonetaryContext(){ 796 return DEFAULT_MONETARY_CONTEXT; 797 } 798 799 @Override 800 public MonetaryAmountFactory<RoundedMoney> getFactory(){ 801 return new RoundedMoneyAmountFactory().setAmount(this); 802 } 803}