001/* 002 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE 003 * CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. 004 * PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY 005 * DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE 006 * AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" 007 * BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency 008 * API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights 009 * reserved. 010 */ 011package org.javamoney.moneta.function; 012 013import java.math.BigDecimal; 014import java.math.MathContext; 015import java.util.concurrent.atomic.AtomicLong; 016 017import javax.money.MonetaryOperator; 018import javax.money.MonetaryQuery; 019 020/** 021 * This singleton class provides access to the predefined monetary functions. 022 * <p> 023 * The class is thread-safe, which is also true for all functions returned by 024 * this class. 025 * 026 * @author Anatole Tresch 027 */ 028public final class MonetaryFunctions { 029 /** defaulkt Math context used. */ 030 private static final MathContext DEFAULT_MATH_CONTEXT = initDefaultMathContext(); 031 /** Shared reciprocal instance. */ 032 private static final Reciprocal RECIPROCAL = new Reciprocal(); 033 034 /** 035 * The shared instance of this class. 036 */ 037 private static final MinorPart MINORPART = new MinorPart(); 038 /** SHared minor units class. */ 039 private static final MinorUnits MINORUNITS = new MinorUnits(); 040 /** Shared major part instance. */ 041 private static final MajorPart MAJORPART = new MajorPart(); 042 /** Shared major units instance. */ 043 private static final MajorUnits MAJORUNITS = new MajorUnits(); 044 045 /** 046 * Private singleton constructor. 047 */ 048 private MonetaryFunctions() { 049 // Singleton constructor 050 } 051 052 /** 053 * Get {@link MathContext} for {@link Permil} instances. 054 * 055 * @return the {@link MathContext} to be used, by default 056 * {@link MathContext#DECIMAL64}. 057 */ 058 private static MathContext initDefaultMathContext() { 059 // TODO Initialize default, e.g. by system properties, or better: 060 // classpath properties! 061 return MathContext.DECIMAL64; 062 } 063 064 /** 065 * Return a {@link MonetaryAdjuster} realizing the recorpocal value of 066 * {@code f(R) = 1/R}. 067 * 068 * @return the reciprocal operator, never {@code null} 069 */ 070 public static MonetaryOperator reciprocal() { 071 return RECIPROCAL; 072 } 073 074/** 075 * Factory method creating a new instance with the given {@code BigDecimal) permil value; 076 * @param decimal the decimal value of the permil operator being created. 077 * @return a new {@code Permil} operator 078 */ 079 public static MonetaryOperator permil(BigDecimal decimal) { 080 return new Permil(decimal); 081 } 082 083/** 084 * Factory method creating a new instance with the given {@code Number) permil value; 085 * @param decimal the decimal value of the permil operator being created. 086 * @return a new {@code Permil} operator 087 */ 088 public static MonetaryOperator permil(Number number) { 089 return permil(number, DEFAULT_MATH_CONTEXT); 090 } 091 092/** 093 * Factory method creating a new instance with the given {@code Number) permil value; 094 * @param decimal the decimal value of the permil operator being created. 095 * @return a new {@code Permil} operator 096 */ 097 public static MonetaryOperator permil(Number number, MathContext mathContext) { 098 return new Permil(getBigDecimal(number, mathContext)); 099 } 100 101 /** 102 * Converts to {@link BigDecimal}, if necessary, or casts, if possible. 103 * 104 * @param number 105 * The {@link Number} 106 * @param mathContext 107 * the {@link MathContext} 108 * @return the {@code number} as {@link BigDecimal} 109 */ 110 private static final BigDecimal getBigDecimal(Number num, 111 MathContext mathContext) { 112 if (num instanceof BigDecimal) { 113 return (BigDecimal) num; 114 } 115 if (num instanceof Long || num instanceof Integer 116 || num instanceof Byte || num instanceof AtomicLong) { 117 return BigDecimal.valueOf(num.longValue()); 118 } 119 if (num instanceof Float || num instanceof Double) { 120 return new BigDecimal(num.toString()); 121 } 122 try { 123 // Avoid imprecise conversion to double value if at all possible 124 return new BigDecimal(num.toString(), mathContext); 125 } catch (NumberFormatException e) { 126 } 127 return BigDecimal.valueOf(num.doubleValue()); 128 } 129 130/** 131 * Factory method creating a new instance with the given {@code BigDecimal) percent value; 132 * @param decimal the decimal value of the percent operator being created. 133 * @return a new {@code Percent} operator 134 */ 135 public static MonetaryOperator percent(BigDecimal decimal) { 136 return new Percent(decimal); // TODO caching, e.g. array for 1-100 might 137 // work. 138 } 139 140/** 141 * Factory method creating a new instance with the given {@code Number) percent value; 142 * @param decimal the decimal value of the percent operator being created. 143 * 144 * @return a new {@code Percent} operator 145 */ 146 public static MonetaryOperator percent(Number number) { 147 return percent(getBigDecimal(number, DEFAULT_MATH_CONTEXT)); 148 } 149 150 /** 151 * Access the shared instance of {@link MinorPart} for use. 152 * 153 * @return the shared instance, never {@code null}. 154 */ 155 public static MonetaryOperator minorPart() { 156 return MINORPART; 157 } 158 159 /** 160 * Access the shared instance of {@link MajorPart} for use. 161 * 162 * @return the shared instance, never {@code null}. 163 */ 164 public static MonetaryOperator majorPart() { 165 return MAJORPART; 166 } 167 168 /** 169 * Access the shared instance of {@link MinorUnits} for use. 170 * 171 * @return the shared instance, never {@code null}. 172 */ 173 public static MonetaryQuery<Long> minorUnits() { 174 return MINORUNITS; 175 } 176 177 /** 178 * Access the shared instance of {@link MajorUnits} for use. 179 * 180 * @return the shared instance, never {@code null}. 181 */ 182 public static MonetaryQuery<Long> majorUnits() { 183 return MAJORUNITS; 184 } 185 186}