001package org.javamoney.moneta.function; 002 003import java.util.Comparator; 004import java.util.List; 005import java.util.Map; 006import java.util.Objects; 007import java.util.function.BinaryOperator; 008import java.util.function.Predicate; 009import java.util.function.Supplier; 010import java.util.stream.Collector; 011import java.util.stream.Collectors; 012 013import javax.money.CurrencyUnit; 014import javax.money.MonetaryAmount; 015import javax.money.MonetaryException; 016 017import org.javamoney.moneta.spi.MoneyUtils; 018 019/** 020 * This singleton class provides access to the predefined monetary functions. 021 * 022 * @author otaviojava 023 * @author anatole 024 */ 025public final class MonetaryFunctions { 026 027 028 /** 029 * Collector to group by CurrencyUnit 030 * 031 * @return the Collector to of Map<CurrencyUnit, List<MonetaryAmount>> 032 */ 033 public static Collector<MonetaryAmount,?,Map<CurrencyUnit,List<MonetaryAmount>>> groupByCurrencyUnit(){ 034 return Collectors.groupingBy(MonetaryAmount::getCurrency); 035 } 036 037 /** 038 * of the summary of the MonetaryAmount 039 * 040 * @param currencyUnit the target {@link javax.money.CurrencyUnit} 041 * @return the MonetarySummaryStatistics 042 */ 043 public static Collector<MonetaryAmount,MonetarySummaryStatistics,MonetarySummaryStatistics> summarizingMonetary( 044 CurrencyUnit currencyUnit){ 045 Supplier<MonetarySummaryStatistics> supplier = () -> new MonetarySummaryStatistics(currencyUnit); 046 return Collector.of(supplier, MonetarySummaryStatistics::accept, MonetarySummaryStatistics::combine); 047 } 048 049 /** 050 * of MonetaryAmount group by MonetarySummary 051 * 052 * @return the MonetarySummaryStatistics 053 */ 054 public static Collector<MonetaryAmount,GroupMonetarySummaryStatistics,GroupMonetarySummaryStatistics> 055 groupBySummarizingMonetary(){ 056 return Collector.of(GroupMonetarySummaryStatistics::new, GroupMonetarySummaryStatistics::accept, 057 GroupMonetarySummaryStatistics::combine); 058 } 059 060 /** 061 * Get a comparator for sorting CurrencyUnits ascending. 062 * 063 * @return the Comparator to sort by CurrencyUnit in ascending order, not null. 064 */ 065 public static Comparator<MonetaryAmount> sortCurrencyUnit(){ 066 return Comparator.comparing(MonetaryAmount::getCurrency); 067 } 068 069 /** 070 * Get a comparator for sorting CurrencyUnits descending. 071 * 072 * @return the Comparator to sort by CurrencyUnit in descending order, not null. 073 */ 074 public static Comparator<MonetaryAmount> sortCurrencyUnitDesc(){ 075 return sortCurrencyUnit().reversed(); 076 } 077 078 /** 079 * Get a comparator for sorting amount by number value ascending. 080 * 081 * @return the Comparator to sort by number in ascending way, not null. 082 */ 083 public static Comparator<MonetaryAmount> sortNumber(){ 084 return Comparator.comparing(MonetaryAmount::getNumber); 085 } 086 087 /** 088 * Get a comparator for sorting amount by number value descending. 089 * 090 * @return the Comparator to sort by number in descending way, not null. 091 */ 092 public static Comparator<MonetaryAmount> sortNumberDesc(){ 093 return sortNumber().reversed(); 094 } 095 096 /** 097 * Create predicate that filters by CurrencyUnit. 098 * @param currencies 099 * the target {@link javax.money.CurrencyUnit} 100 * @return the predicate from CurrencyUnit 101 */ 102 public static Predicate<MonetaryAmount> isCurrency( 103 CurrencyUnit... currencies) { 104 105 if (Objects.isNull(currencies) || currencies.length == 0) { 106 return m -> true; 107 } 108 Predicate<MonetaryAmount> predicate = null; 109 110 for (CurrencyUnit currencyUnit : currencies) { 111 if (Objects.isNull(predicate)) { 112 predicate = m -> m.getCurrency().equals(currencyUnit); 113 } else { 114 predicate = predicate.or(m -> m.getCurrency().equals( 115 currencyUnit)); 116 } 117 } 118 return predicate; 119 } 120 121 /** 122 * Create predicate that filters by CurrencyUnit. 123 * 124 * @param currencies the target {@link javax.money.CurrencyUnit} instances to be filtered. 125 * @return the predicate from CurrencyUnit 126 */ 127 public static Predicate<MonetaryAmount> fiterByExcludingCurrency( 128 CurrencyUnit... currencies) { 129 130 if (Objects.isNull(currencies) || currencies.length == 0) { 131 return m -> true; 132 } 133 return isCurrency(currencies).negate(); 134 } 135 136 /** 137 * Creates filter using isGreaterThan in MonetaryAmount. 138 * 139 * @param amount the amount to be compared, not null. 140 * @return the filter with isGreaterThan conditions 141 */ 142 public static Predicate<MonetaryAmount> isGreaterThan(MonetaryAmount amount){ 143 return m -> m.isGreaterThan(amount); 144 } 145 146 /** 147 * Creates filter using isGreaterThanOrEqualTo in MonetaryAmount 148 * 149 * @param amount the amount to be compared, not null. 150 * @return the filter with isGreaterThanOrEqualTo conditions 151 */ 152 public static Predicate<MonetaryAmount> isGreaterThanOrEqualTo(MonetaryAmount amount){ 153 return m -> m.isGreaterThanOrEqualTo(amount); 154 } 155 156 /** 157 * Creates filter using isLessThan in MonetaryAmount 158 * 159 * @param amount the amount to be compared, not null. 160 * @return the filter with isLessThan conditions 161 */ 162 public static Predicate<MonetaryAmount> isLessThan(MonetaryAmount amount){ 163 return m -> m.isLessThan(amount); 164 } 165 166 /** 167 * Creates filter using isLessThanOrEqualTo in MonetaryAmount 168 * 169 * @param amount the amount to be compared, not null. 170 * @return the filter with isLessThanOrEqualTo conditions 171 */ 172 public static Predicate<MonetaryAmount> isLessThanOrEqualTo(MonetaryAmount amount){ 173 return m -> m.isLessThanOrEqualTo(amount); 174 } 175 176 /** 177 * Creates a filter using the isBetween predicate. 178 * 179 * @param min min value inclusive, not null. 180 * @param max max value inclusive, not null. 181 * @return the Predicate between min and max. 182 */ 183 public static Predicate<MonetaryAmount> isBetween(MonetaryAmount min, MonetaryAmount max){ 184 return isLessThanOrEqualTo(max).and(isGreaterThanOrEqualTo(min)); 185 } 186 187 /** 188 * Adds two monetary together 189 * 190 * @param a the first operand 191 * @param b the second operand 192 * @return the sum of {@code a} and {@code b} 193 * @throws NullPointerException if a o b be null 194 * @throws MonetaryException if a and b have different currency 195 */ 196 public static MonetaryAmount sum(MonetaryAmount a, MonetaryAmount b){ 197 MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency())); 198 return a.add(b); 199 } 200 201 /** 202 * Returns the smaller of two {@code MonetaryAmount} values. If the arguments 203 * have the same value, the result is that same value. 204 * 205 * @param a an argument. 206 * @param b another argument. 207 * @return the smaller of {@code a} and {@code b}. 208 */ 209 public static MonetaryAmount min(MonetaryAmount a, MonetaryAmount b){ 210 MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency())); 211 return a.isLessThan(b) ? a : b; 212 } 213 214 /** 215 * Returns the greater of two {@code MonetaryAmount} values. If the 216 * arguments have the same value, the result is that same value. 217 * 218 * @param a an argument. 219 * @param b another argument. 220 * @return the larger of {@code a} and {@code b}. 221 */ 222 public static MonetaryAmount max(MonetaryAmount a, MonetaryAmount b){ 223 MoneyUtils.checkAmountParameter(Objects.requireNonNull(a), Objects.requireNonNull(b.getCurrency())); 224 return a.isGreaterThan(b) ? a : b; 225 } 226 227 /** 228 * Creates a BinaryOperator to sum. 229 * 230 * @return the sum BinaryOperator, not null. 231 */ 232 public static BinaryOperator<MonetaryAmount> sum(){ 233 return MonetaryFunctions::sum; 234 } 235 236 /** 237 * Creates a BinaryOperator to calculate the minimum amount 238 * 239 * @return the min BinaryOperator, not null. 240 */ 241 public static BinaryOperator<MonetaryAmount> min(){ 242 return MonetaryFunctions::min; 243 } 244 245 /** 246 * Creates a BinaryOperator to calculate the maximum amount. 247 * 248 * @return the max BinaryOperator, not null. 249 */ 250 public static BinaryOperator<MonetaryAmount> max(){ 251 return MonetaryFunctions::max; 252 } 253}