001/**
002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.function;
017
018import java.util.Comparator;
019import java.util.Objects;
020
021import javax.money.MonetaryAmount;
022import javax.money.MonetaryException;
023import javax.money.convert.CurrencyConversion;
024import javax.money.convert.ExchangeRate;
025import javax.money.convert.ExchangeRateProvider;
026
027import org.javamoney.moneta.spi.MoneyUtils;
028
029/**
030 * This singleton class provides access to the predefined monetary functions.
031 *
032 * @author otaviojava
033 * @author anatole
034 */
035public final class MonetaryFunctions {
036    private static final Comparator<MonetaryAmount> NUMBER_COMPARATOR = new Comparator<MonetaryAmount>() {
037        @Override
038        public int compare(MonetaryAmount o1, MonetaryAmount o2) {
039            return o1.getNumber().compareTo(o2.getNumber());
040        }
041    };
042
043    private static final Comparator<MonetaryAmount> CURRENCY_COMPARATOR = new Comparator<MonetaryAmount>() {
044        @Override
045        public int compare(MonetaryAmount o1, MonetaryAmount o2) {
046            return o1.getCurrency().compareTo(o2.getCurrency());
047        }
048    };
049
050    /**
051     * Get a comparator for sorting CurrencyUnits ascending.
052     *
053     * @return the Comparator to sort by CurrencyUnit in ascending order, not null.
054     */
055    public static Comparator<MonetaryAmount> sortCurrencyUnit(){
056        return CURRENCY_COMPARATOR;
057    }
058
059        /**
060         * comparator to sort the {@link MonetaryAmount} considering the
061         * {@link ExchangeRate}
062         * @param provider the rate provider to be used.
063         * @return the sort of {@link MonetaryAmount} using {@link ExchangeRate}
064         */
065        public static Comparator<? super MonetaryAmount> sortValuable(
066            final ExchangeRateProvider provider) {
067        return new Comparator<MonetaryAmount>() {
068            @Override
069            public int compare(MonetaryAmount m1, MonetaryAmount m2) {
070                CurrencyConversion conversor = provider.getCurrencyConversion(m1
071                        .getCurrency());
072                return m1.compareTo(conversor.apply(m2));
073            }
074        };
075        }
076
077        /**
078         * Descending order of
079         * {@link MonetaryFunctions#sortValuable(ExchangeRateProvider)}
080         * @param provider the rate provider to be used.
081         * @return the Descending order of
082         *         {@link MonetaryFunctions#sortValuable(ExchangeRateProvider)}
083         */
084        public static Comparator<? super MonetaryAmount> sortValuableDesc(
085            final ExchangeRateProvider provider) {
086                return new Comparator<MonetaryAmount>() {
087            @Override
088            public int compare(MonetaryAmount o1, MonetaryAmount o2) {
089                return sortValuable(provider).compare(o1, o2) * -1;
090            }
091        };
092        }
093
094    /**
095     * Get a comparator for sorting CurrencyUnits descending.
096     * @return the Comparator to sort by CurrencyUnit in descending order, not null.
097     */
098    public static Comparator<MonetaryAmount> sortCurrencyUnitDesc(){
099        return new Comparator<MonetaryAmount>() {
100            @Override
101            public int compare(MonetaryAmount o1, MonetaryAmount o2) {
102                return sortCurrencyUnit().compare(o1, o2) * -1;
103            }
104        };
105    }
106
107    /**
108     * Get a comparator for sorting amount by number value ascending.
109     * @return the Comparator to sort by number in ascending way, not null.
110     */
111    public static Comparator<MonetaryAmount> sortNumber(){
112        return NUMBER_COMPARATOR;
113    }
114
115    /**
116     * Get a comparator for sorting amount by number value descending.
117     * @return the Comparator to sort by number in descending way, not null.
118     */
119    public static Comparator<MonetaryAmount> sortNumberDesc(){
120        return new Comparator<MonetaryAmount>() {
121            @Override
122            public int compare(MonetaryAmount o1, MonetaryAmount o2) {
123                return sortNumber().compare(o1, o2) * -1;
124            }
125        };
126    }
127
128    /**
129     * Adds two monetary together
130     * @param a the first operand
131     * @param b the second operand
132     * @return the sum of {@code a} and {@code b}
133     * @throws NullPointerException if a o b be null
134     * @throws MonetaryException    if a and b have different currency
135     */
136    public static MonetaryAmount sum(MonetaryAmount a, MonetaryAmount b){
137        MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency()));
138        return a.add(b);
139    }
140
141    /**
142     * Returns the smaller of two {@code MonetaryAmount} values. If the arguments
143     * have the same value, the result is that same value.
144     * @param a an argument.
145     * @param b another argument.
146     * @return the smaller of {@code a} and {@code b}.
147     */
148        static MonetaryAmount min(MonetaryAmount a, MonetaryAmount b) {
149        MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency()));
150        return a.isLessThan(b) ? a : b;
151    }
152
153    /**
154     * Returns the greater of two {@code MonetaryAmount} values. If the
155     * arguments have the same value, the result is that same value.
156     * @param a an argument.
157     * @param b another argument.
158     * @return the larger of {@code a} and {@code b}.
159     */
160        static MonetaryAmount max(MonetaryAmount a, MonetaryAmount b) {
161        MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency()));
162        return a.isGreaterThan(b) ? a : b;
163    }
164
165}