/* * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.javamoney.calc; import javax.money.CurrencyUnit; import javax.money.MonetaryAmount; import javax.money.MonetaryAmountFactory; import javax.money.MonetaryContext; import javax.money.MonetaryOperator; import javax.money.MonetaryQuery; import javax.money.NumberValue; import org.javamoney.moneta.Money; import java.util.function.Predicate; /** * Platform RI: This class decorates an arbitrary {@link MonetaryAmount} * instance and ensure the given {@link Predicate} is always * {@code true}. * <p> * As required by the {@link MonetaryAmount} interface, this class is * <ul> * <li>immutable</li> * <li>final</li> * <li>thread-safe/li> * <li>serializable</li> * </ul> * <p> * As a consequence all this attributes must also be true for the * {@link Predicate} used. * * @author Anatole Tresch * @author Werner Keil */ final class ValidatedMoney implements MonetaryAmount { /** * The amount's predicate. */ private Predicate<MonetaryAmount> predicate; /** * The underlying amount. */ private final MonetaryAmount amount; /** * Creates a new wrapper instance. * * @param amount the underlying amount, not null and not negative. * @throws IllegalArgumentException if the amount passed is negative. */ ValidatedMoney(MonetaryAmount amount, Predicate<MonetaryAmount> predicate) { if (amount == null) { throw new IllegalArgumentException("Amount required."); } if (predicate == null) { throw new IllegalArgumentException("predicate required."); } if (!predicate.test(amount)) { throw new IllegalArgumentException("Constraint failed: " + predicate + " with " + amount); } this.amount = amount; this.predicate = predicate; } /** * Access an {@link ValidatedMoney} based on the given * {@link MonetaryAmount}. * * @param amount * @return */ private static ValidatedMoney of(MonetaryAmount amount, Predicate<MonetaryAmount> predicate) { return new ValidatedMoney(amount, predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#getCurrency() */ @Override public CurrencyUnit getCurrency() { return this.amount.getCurrency(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#abs() */ public ValidatedMoney abs() { return of(this.amount.abs(), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#add(javax.money.MonetaryAmount) */ public ValidatedMoney add(MonetaryAmount augend) { return of(this.amount.add(augend), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#divide(java.lang.Number) */ public ValidatedMoney divide(Number divisor) { return of(this.amount.divide(divisor), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#divideAndRemainder(java.lang.Number) */ public ValidatedMoney[] divideAndRemainder(Number divisor) { MonetaryAmount[] res = this.amount.divideAndRemainder(divisor); return new ValidatedMoney[]{of(res[0], predicate), of(res[1], predicate)}; } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#divideToIntegralValue(java.lang.Number) */ public ValidatedMoney divideToIntegralValue(Number divisor) { return of(this.amount.divideToIntegralValue(divisor), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#multiply(java.lang.Number) */ public ValidatedMoney multiply(Number multiplicand) { return of(this.amount.multiply(multiplicand), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#negate() */ public ValidatedMoney negate() { return of(this.amount.negate(), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#plus() */ public ValidatedMoney plus() { return of(this.amount.plus(), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#subtract(javax.money.MonetaryAmount) */ public ValidatedMoney subtract(Money subtrahend) { return of(this.amount.subtract(subtrahend), predicate); } // /* // * (non-Javadoc) // * // * @see javax.money.MonetaryAmount#ulp() // */ // public ConstraintMoney ulp() { // return of(this.amount.ulp(), predicate); // } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#remainder(java.lang.Number) */ public ValidatedMoney remainder(Number divisor) { return of(this.amount.remainder(divisor), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#scaleByPowerOfTen(int) */ public ValidatedMoney scaleByPowerOfTen(int n) { return of(this.amount.scaleByPowerOfTen(n), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isZero() */ public boolean isZero() { return this.amount.isZero(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isPositive() */ public boolean isPositive() { return this.amount.isPositive(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isPositiveOrZero() */ public boolean isPositiveOrZero() { return this.amount.isPositiveOrZero(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isNegative() */ public boolean isNegative() { return this.amount.isNegative(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isNegativeOrZero() */ public boolean isNegativeOrZero() { return this.amount.isNegativeOrZero(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#with(javax.money.MonetaryOperator) */ @Override public ValidatedMoney with(MonetaryOperator adjuster) { return of(this.amount.with(adjuster), predicate); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#signum() */ public int signum() { return this.amount.signum(); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isLessThan(javax.money.MonetaryAmount) */ public boolean isLessThan(MonetaryAmount amount) { return this.amount.isLessThan(amount); } /* * (non-Javadoc) * * @see * javax.money.MonetaryAmount#isLessThanOrEqualTo(javax.money.MonetaryAmount * ) */ public boolean isLessThanOrEqualTo(MonetaryAmount amount) { return this.amount.isLessThanOrEqualTo(amount); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isGreaterThan(javax.money.MonetaryAmount) */ public boolean isGreaterThan(MonetaryAmount amount) { return this.amount.isGreaterThan(amount); } /* * (non-Javadoc) * * @see * javax.money.MonetaryAmount#isGreaterThanOrEqualTo(javax.money.MonetaryAmount * ) */ public boolean isGreaterThanOrEqualTo(MonetaryAmount amount) { return this.amount.isGreaterThanOrEqualTo(amount); } /* * (non-Javadoc) * * @see javax.money.MonetaryAmount#isEqualTo(javax.money.MonetaryAmount) */ public boolean isEqualTo(MonetaryAmount amount) { return this.amount.isEqualTo(amount); } @Override public MonetaryContext getContext() { return this.amount.getContext(); } @Override public NumberValue getNumber() { return this.amount.getNumber(); } @Override public <R> R query(MonetaryQuery<R> query) { return query.queryFrom(this); } @Override public ValidatedMoney subtract(MonetaryAmount amount) { return new ValidatedMoney(this.amount.subtract(amount), predicate); } @Override public ValidatedMoney multiply(long multiplicand) { return new ValidatedMoney(amount.multiply(multiplicand), predicate); } @Override public ValidatedMoney multiply(double multiplicand) { return new ValidatedMoney(amount.multiply(multiplicand), predicate); } @Override public ValidatedMoney divide(long divisor) { return new ValidatedMoney(amount.divide(divisor), predicate); } @Override public ValidatedMoney divide(double divisor) { return new ValidatedMoney(amount.divide(divisor), predicate); } @Override public ValidatedMoney remainder(long divisor) { return new ValidatedMoney(amount.remainder(divisor), predicate); } @Override public ValidatedMoney remainder(double divisor) { return new ValidatedMoney(amount.remainder(divisor), predicate); } @Override public ValidatedMoney[] divideAndRemainder(long divisor) { MonetaryAmount[] result = this.amount.divideAndRemainder(divisor); return new ValidatedMoney[]{ new ValidatedMoney(result[0], predicate), new ValidatedMoney(result[1], predicate)}; } @Override public ValidatedMoney[] divideAndRemainder(double divisor) { MonetaryAmount[] result = this.amount.divideAndRemainder(divisor); return new ValidatedMoney[]{ new ValidatedMoney(result[0], predicate), new ValidatedMoney(result[1], predicate)}; } @Override public ValidatedMoney divideToIntegralValue(long divisor) { return new ValidatedMoney( amount.divideToIntegralValue(divisor), predicate); } @Override public ValidatedMoney divideToIntegralValue(double divisor) { return new ValidatedMoney( amount.divideToIntegralValue(divisor), predicate); } @Override public ValidatedMoney stripTrailingZeros() { return new ValidatedMoney(amount.stripTrailingZeros(), predicate); } @Override public MonetaryAmountFactory<ValidatedMoney> getFactory() { return null; // return new ConstraintMoneyFactory(this); } @Override public int compareTo(MonetaryAmount o) { return this.amount.compareTo(o); } }