001/** 002 * Copyright (c) 2012, 2015, 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; 017 018import java.io.IOException; 019import java.math.BigDecimal; 020import java.util.Objects; 021import java.util.Optional; 022 023import javax.money.CurrencyUnit; 024import javax.money.MonetaryAmount; 025import javax.money.Monetary; 026import javax.money.format.AmountFormatContext; 027import javax.money.format.AmountFormatContextBuilder; 028import javax.money.format.MonetaryAmountFormat; 029import javax.money.format.MonetaryParseException; 030 031/** 032 * class to format and parse a text string such as 'EUR 25.25' or vice versa. 033 * This class will used to toString and parse in all implementation on Moneta. 034 * {@link Money#toString()} 035 * {@link Money#parse(CharSequence)} 036 * {@link FastMoney#toString()} 037 * {@link FastMoney#parse(CharSequence)} 038 * {@link RoundedMoney#toString()} 039 * {@link RoundedMoney#parse(CharSequence)} 040 * @author Otavio Santana 041 */ 042public final class ToStringMonetaryAmountFormat implements MonetaryAmountFormat { 043 044 private static final String CONTEXT_PREFIX = "ToString_"; 045 046 private final ToStringMonetaryAmountFormatStyle style; 047 048 private final AmountFormatContext context; 049 050 private ToStringMonetaryAmountFormat(ToStringMonetaryAmountFormatStyle style) { 051 this.style = Objects.requireNonNull(style); 052 context = AmountFormatContextBuilder.of(CONTEXT_PREFIX + style).build(); 053 } 054 055 public static ToStringMonetaryAmountFormat of( 056 ToStringMonetaryAmountFormatStyle style) { 057 return new ToStringMonetaryAmountFormat(style); 058 } 059 060 @Override 061 public String queryFrom(MonetaryAmount amount) { 062 return Optional.ofNullable(amount).map(MonetaryAmount::toString) 063 .orElse("null"); 064 } 065 066 @Override 067 public AmountFormatContext getContext() { 068 return context; 069 } 070 071 @Override 072 public void print(Appendable appendable, MonetaryAmount amount) 073 throws IOException { 074 appendable.append(queryFrom(amount)); 075 076 } 077 078 @Override 079 public MonetaryAmount parse(CharSequence text) 080 throws MonetaryParseException { 081 try { 082 ParserMonetaryAmount amount = parserMonetaryAmount(text); 083 return style.to(amount); 084 } catch (Exception e) { 085 throw new MonetaryParseException(e.getMessage(), text, 0); 086 } 087 } 088 089 private ParserMonetaryAmount parserMonetaryAmount(CharSequence text) throws Exception { 090 String[] array = Objects.requireNonNull(text).toString().split(" "); 091 if(array.length != 2) { 092 throw new MonetaryParseException("An error happened when try to parse the Monetary Amount.",text,0); 093 } 094 CurrencyUnit currencyUnit = Monetary.getCurrency(array[0]); 095 BigDecimal number = new BigDecimal(array[1]); 096 return new ParserMonetaryAmount(currencyUnit, number); 097 } 098 099 private class ParserMonetaryAmount { 100 ParserMonetaryAmount(CurrencyUnit currencyUnit, BigDecimal number) { 101 this.currencyUnit = currencyUnit; 102 this.number = number; 103 } 104 105 private final CurrencyUnit currencyUnit; 106 private final BigDecimal number; 107 } 108 109 /** 110 * indicates with implementation will used to format or parser in 111 * ToStringMonetaryAmountFormat 112 */ 113 public enum ToStringMonetaryAmountFormatStyle { 114 /** 115 * {@link Money} 116 */ 117 MONEY { 118 @Override 119 MonetaryAmount to(ParserMonetaryAmount amount) { 120 return Money.of(amount.number, amount.currencyUnit); 121 } 122 }, 123 /** 124 * {@link FastMoney} 125 */ 126 FAST_MONEY { 127 @Override 128 MonetaryAmount to(ParserMonetaryAmount amount) { 129 return FastMoney.of(amount.number, amount.currencyUnit); 130 } 131 }, 132 /** 133 * {@link RoundedMoney} 134 */ 135 ROUNDED_MONEY { 136 @Override 137 MonetaryAmount to(ParserMonetaryAmount amount) { 138 return RoundedMoney.of(amount.number, amount.currencyUnit); 139 } 140 }; 141 142 private static final long serialVersionUID = 6606016328162974467L; 143 abstract MonetaryAmount to(ParserMonetaryAmount amount); 144 } 145 146}