001/** 002 * Copyright (c) 2012, 2015, 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.math.BigDecimal; 019import java.math.MathContext; 020import java.math.RoundingMode; 021import java.util.Objects; 022 023import javax.money.CurrencyUnit; 024import javax.money.MonetaryAmount; 025import javax.money.MonetaryOperator; 026 027import org.javamoney.moneta.spi.DefaultNumberValue; 028 029/** 030 * This singleton class provides access to the predefined monetary functions. 031 * <p> 032 * The class is thread-safe, which is also true for all functions returned by 033 * this class. 034 * <pre> 035 * {@code 036 * MonetaryAmount money = Money.parse("EUR 2.35"); 037 * MonetaryAmount result = operator.apply(money); 038 * } 039 * </pre> 040 * <p>Or using: </p> 041 * <pre> 042 * {@code 043 * MonetaryAmount money = Money.parse("EUR 2.35"); 044 * MonetaryAmount result = money.with(operator); 045 * } 046 * </pre> 047 * @see {@link MonetaryAmount#with(MonetaryOperator)} 048 * @see {@link MonetaryOperator} 049 * @see {@link MonetaryOperator#apply(MonetaryAmount)} 050 * @author Anatole Tresch 051 * @author Otavio Santana 052 * @since 1.0.1 053 */ 054public final class MonetaryOperators { 055 056 private static final MathContext DEFAULT_MATH_CONTEXT = MathContext.DECIMAL64; 057 058 private static final ReciprocalOperator RECIPROCAL = new ReciprocalOperator(); 059 060 private static final ExtractorMinorPartOperator EXTRACTOR_MINOR_PART = new ExtractorMinorPartOperator(); 061 062 private static final ExtractorMajorPartOperator EXTRACTOR_MAJOR_PART = new ExtractorMajorPartOperator(); 063 064 private static final RoudingMonetaryAmountOperator ROUNDING_MONETARY_AMOUNT = new RoudingMonetaryAmountOperator(); 065 066 private MonetaryOperators() { 067 } 068 069 /** 070 * Gets the reciprocal of {@link MonetaryAmount} 071 * <p> 072 * Gets the amount as reciprocal, multiplicative inverse value (1/n). 073 * <p> 074 *<pre> 075 *{@code 076 *MonetaryAmount money = Money.parse("EUR 2.0"); 077 *MonetaryAmount result = ConversionOperators.reciprocal().apply(money);//EUR 0.5 078 *} 079 *</pre> 080 * @return the reciprocal part as {@link MonetaryOperator} 081 */ 082 public static MonetaryOperator reciprocal() { 083 return RECIPROCAL; 084 } 085 086 /** 087 * Gets the permil of the amount. 088 * <p> 089 * This returns the monetary amount in permil. For example, for 10% 'EUR 090 * 2.35' will return 0.235. 091 * <p> 092 *<pre> 093 *{@code 094 *MonetaryAmount money = Money.parse("EUR EUR 2.35"); 095 *MonetaryAmount result = ConversionOperators.permil(BigDecimal.TEN).apply(money);//EUR 0.0235 096 *} 097 *</pre> 098 * @return the permil as {@link MonetaryOperator} 099 */ 100 public static MonetaryOperator permil(BigDecimal decimal) { 101 return new PermilOperator(decimal); 102 } 103 104 /** 105 * Returns the {@link #percent(BigDecimal)} converting 106 * this number to {@link BigDecimal} and using the {@link org.javamoney.moneta.convert.ConversionOperators#DEFAULT_MATH_CONTEXT} 107 * @param number to be converted to {@link BigDecimal} 108 * @see {@link #permil(BigDecimal)} 109 * @return the permil {@link MonetaryOperator} 110 */ 111 public static MonetaryOperator permil(Number number) { 112 return permil(number, DEFAULT_MATH_CONTEXT); 113 } 114 115 116 /** 117 * Returns the {@link #percent(BigDecimal)} converting 118 * this number to {@link BigDecimal} and using the {@link MathContext} in parameters 119 * @param number to be converted to {@link BigDecimal} 120 * @param mathContext the mathContext to be used 121 * @see {@link #permil(BigDecimal)} 122 * @return the permil {@link MonetaryOperator} 123 */ 124 public static MonetaryOperator permil(Number number, MathContext mathContext) { 125 return new PermilOperator(new DefaultNumberValue(number).numberValue(BigDecimal.class)); 126 } 127 128 /** 129 * Gets the percentage of the amount. 130 * <p> 131 * This returns the monetary amount in percent. For example, for 10% 'EUR 132 * 2.35' will return 0.235. 133 * <p> 134 *<pre> 135 *{@code 136 *MonetaryAmount money = Money.parse("EUR 200.0"); 137 *MonetaryAmount result = ConversionOperators.percent(BigDecimal.TEN).apply(money);//EUR 20.0 138 *} 139 *</pre> 140 * @param decimal the value to percent 141 * @return the percent of {@link MonetaryOperator} 142 */ 143 public static MonetaryOperator percent(BigDecimal decimal) { 144 return new PercentOperator(decimal); 145 } 146 147 /** 148 * Gets the percentage of the amount. 149 * @param number to be used in percent 150 * @see {@link #percent(BigDecimal)} 151 * @return the percent of {@link MonetaryOperator} 152 */ 153 public static MonetaryOperator percent(Number number) { 154 return percent(new DefaultNumberValue(number).numberValue(BigDecimal.class)); 155 } 156 157 /** 158 * Extract minor part of {@link MonetaryAmount} 159 * <p> 160 * This returns the monetary amount in terms of the minor units of the 161 * currency, truncating the whole part if necessary. For example, 'EUR 2.35' 162 * will return 'EUR 0.35', and 'BHD -1.345' will return 'BHD -0.345'. 163 * <p> 164 *<pre> 165 *{@code 166 *MonetaryAmount money = Money.parse("EUR 2.35"); 167 *MonetaryAmount result = ConversionOperators.minorPart().apply(money);//EUR 0.35 168 *} 169 *</pre> 170 * @return the minor part as {@link MonetaryOperator} 171 */ 172 public static MonetaryOperator minorPart() { 173 return EXTRACTOR_MINOR_PART; 174 } 175 176 /** 177 * Extract major part of {@link MonetaryAmount} 178 * <p> 179 * This returns the monetary amount in terms of the minor units of the 180 * currency, truncating the whole part if necessary. For example, 'EUR 2.35' 181 * will return 'EUR 0.35', and 'BHD -1.345' will return 'BHD -0.345'. 182 * <p> 183 *<pre> 184 *{@code 185 *MonetaryAmount money = Money.parse("EUR 2.35"); 186 *MonetaryAmount result = ConversionOperators.majorPart().apply(money);//EUR 2.0 187 *} 188 *</pre> 189 * @return the major part as {@link MonetaryOperator} 190 */ 191 public static MonetaryOperator majorPart() { 192 return EXTRACTOR_MAJOR_PART; 193 } 194 195 /** 196 * Rounding the {@link MonetaryAmount} using {@link CurrencyUnit#getDefaultFractionDigits()} 197 * and {@link RoundingMode#HALF_EVEN}. 198 * <p> 199 * For example, 'EUR 2.3523' will return 'EUR 2.35', 200 * and 'BHD -1.34534432' will return 'BHD -1.345'. 201 * <p> 202 *<pre> 203 *{@code 204 *MonetaryAmount money = Money.parse("EUR 2.355432"); 205 *MonetaryAmount result = ConversionOperators.rounding().apply(money);//EUR 2.36 206 *} 207 *</pre> 208 * @return the major part as {@link MonetaryOperator} 209 */ 210 public static MonetaryOperator rounding() { 211 return ROUNDING_MONETARY_AMOUNT; 212 } 213 214 /** 215 * Rounding the {@link MonetaryAmount} using {@link CurrencyUnit#getDefaultFractionDigits()} 216 * and {@link RoundingMode}. 217 * <p> 218 * For example, 'EUR 2.3523' will return 'EUR 2.35', 219 * and 'BHD -1.34534432' will return 'BHD -1.345'. 220 * <p> 221 *<pre> 222 *{@code 223 *MonetaryAmount money = Money.parse("EUR 2.355432"); 224 *MonetaryAmount result = ConversionOperators.rounding(RoundingMode.HALF_EVEN).apply(money);//EUR 2.35 225 *} 226 *</pre> 227 * @param roundingMode rounding to be used 228 * @return the major part as {@link MonetaryOperator} 229 */ 230 public static MonetaryOperator rounding(RoundingMode roundingMode) { 231 return new RoudingMonetaryAmountOperator(Objects.requireNonNull(roundingMode)); 232 } 233 234 /** 235 * Rounding the {@link MonetaryAmount} using {@link CurrencyUnit#getDefaultFractionDigits()} 236 * and {@link RoundingMode}. 237 * <p> 238 * For example, 'EUR 2.3523' will return 'EUR 2.35', 239 * and 'BHD -1.34534432' will return 'BHD -1.345'. 240 * <p> 241 *<pre> 242 *{@code 243 *MonetaryAmount money = Money.parse("EUR 2.355432"); 244 *MonetaryAmount result = ConversionOperators.rounding(RoundingMode.HALF_EVEN, 3).apply(money);//EUR 2.352 245 *} 246 *</pre> 247 * @param roundingMode rounding to be used 248 * @param scale to be used 249 * @return the major part as {@link MonetaryOperator} 250 */ 251 public static MonetaryOperator rounding(RoundingMode roundingMode, int scale) { 252 return new RoudingMonetaryAmountOperator(Objects.requireNonNull(roundingMode), scale); 253 } 254 255 /** 256 * Rounding the {@link MonetaryAmount} using the scale informed 257 * and {@link RoundingMode#HALF_EVEN}. 258 * <p> 259 * For example, 'EUR 2.3523' will return 'EUR 2.35', 260 * and 'BHD -1.34534432' will return 'BHD -1.345'. 261 * <p> 262 *<pre> 263 *{@code 264 *MonetaryAmount money = Money.parse("EUR 2.355432"); 265 *MonetaryAmount result = ConversionOperators.rounding(2).apply(money);//EUR 2.35 266 *} 267 *</pre> 268 * @param scale scale to be used 269 * @return the major part as {@link MonetaryOperator} 270 */ 271 public static MonetaryOperator rounding(int scale) { 272 return new RoudingMonetaryAmountOperator(RoudingMonetaryAmountOperator.DEFAULT_ROUDING_MONETARY_AMOUNT, scale); 273 } 274 275 /** 276 * Do exchange of currency, in other words, create the monetary amount with the 277 * same value but with currency different. 278 * <p> 279 * For example, 'EUR 2.35', using the currency 'USD' as exchange parameter, will return 'USD 2.35', 280 * and 'BHD -1.345', using the currency 'USD' as exchange parameter, will return 'BHD -1.345'. 281 * <p> 282 *<pre> 283 *{@code 284 *Currency real = Monetary.getCurrency("BRL"); 285 *MonetaryAmount money = Money.parse("EUR 2.355"); 286 *MonetaryAmount result = MonetaryOperators.exchangeCurrency(real).apply(money);//BRL 2.355 287 *} 288 *</pre> 289 * @param currencyUnit currency to be used 290 * @return the major part as {@link MonetaryOperator} 291 * @deprecated 292 */ 293 @Deprecated 294 public static MonetaryOperator exchangeCurrency(CurrencyUnit currencyUnit){ 295 return new ExchangeCurrencyOperator(Objects.requireNonNull(currencyUnit)); 296 } 297}