1 /* 2 * Copyright 2009-2013 Stephen Colebourne 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.joda.money.format; 17 18 import java.math.BigDecimal; 19 import java.text.ParsePosition; 20 import java.util.Locale; 21 22 import org.joda.money.BigMoney; 23 import org.joda.money.CurrencyUnit; 24 25 /** 26 * Context used when parsing money. 27 * <p> 28 * This class is mutable and intended for use by a single thread. 29 * A new instance is created for each parse. 30 */ 31 public final class MoneyParseContext { 32 33 /** 34 * The locale to parse using. 35 */ 36 private Locale locale; 37 /** 38 * The text to parse. 39 */ 40 private CharSequence text; 41 /** 42 * The text index. 43 */ 44 private int textIndex; 45 /** 46 * The text error index. 47 */ 48 private int textErrorIndex = -1; 49 /** 50 * The parsed currency. 51 */ 52 private CurrencyUnit currency; 53 /** 54 * The parsed amount. 55 */ 56 private BigDecimal amount; 57 58 /** 59 * Constructor. 60 * 61 * @param locale the locale, not null 62 * @param text the text to parse, not null 63 * @param index the current text index 64 */ 65 MoneyParseContext(Locale locale, CharSequence text, int index) { 66 this.locale = locale; 67 this.text = text; 68 this.textIndex = index; 69 } 70 71 //----------------------------------------------------------------------- 72 /** 73 * Gets the locale. 74 * 75 * @return the locale, not null 76 */ 77 public Locale getLocale() { 78 return locale; 79 } 80 81 /** 82 * Sets the locale. 83 * 84 * @param locale the locale, not null 85 */ 86 public void setLocale(Locale locale) { 87 MoneyFormatter.checkNotNull(locale, "Locale must not be null"); 88 this.locale = locale; 89 } 90 91 /** 92 * Gets the text being parsed. 93 * 94 * @return the text being parsed, never null 95 */ 96 public CharSequence getText() { 97 return text; 98 } 99 100 /** 101 * Sets the text. 102 * 103 * @param text the text being parsed, not null 104 */ 105 public void setText(CharSequence text) { 106 MoneyFormatter.checkNotNull(text, "Text must not be null"); 107 this.text = text; 108 } 109 110 /** 111 * Gets the length of the text being parsed. 112 * 113 * @return the length of the text being parsed 114 */ 115 public int getTextLength() { 116 return text.length(); 117 } 118 119 /** 120 * Gets a substring of the text being parsed. 121 * 122 * @param start the start index 123 * @param end the end index 124 * @return the substring, not null 125 */ 126 public String getTextSubstring(int start, int end) { 127 return text.subSequence(start, end).toString(); 128 } 129 130 //----------------------------------------------------------------------- 131 /** 132 * Gets the current parse position index. 133 * 134 * @return the current parse position index 135 */ 136 public int getIndex() { 137 return textIndex; 138 } 139 140 /** 141 * Sets the current parse position index. 142 * 143 * @param index the current parse position index 144 */ 145 public void setIndex(int index) { 146 this.textIndex = index; 147 } 148 149 //----------------------------------------------------------------------- 150 /** 151 * Gets the error index. 152 * 153 * @return the error index, negative if no error 154 */ 155 public int getErrorIndex() { 156 return textErrorIndex; 157 } 158 159 /** 160 * Sets the error index. 161 * 162 * @param index the error index 163 */ 164 public void setErrorIndex(int index) { 165 this.textErrorIndex = index; 166 } 167 168 /** 169 * Sets the error index from the current index. 170 */ 171 public void setError() { 172 this.textErrorIndex = textIndex; 173 } 174 175 //----------------------------------------------------------------------- 176 /** 177 * Gets the parsed currency. 178 * 179 * @return the parsed currency, null if not parsed yet 180 */ 181 public CurrencyUnit getCurrency() { 182 return currency; 183 } 184 185 /** 186 * Sets the parsed currency. 187 * 188 * @param currency the parsed currency, may be null 189 */ 190 public void setCurrency(CurrencyUnit currency) { 191 this.currency = currency; 192 } 193 194 //----------------------------------------------------------------------- 195 /** 196 * Gets the parsed amount. 197 * 198 * @return the parsed amount, null if not parsed yet 199 */ 200 public BigDecimal getAmount() { 201 return amount; 202 } 203 204 /** 205 * Sets the parsed currency. 206 * 207 * @param amount the parsed amount, may be null 208 */ 209 public void setAmount(BigDecimal amount) { 210 this.amount = amount; 211 } 212 213 //----------------------------------------------------------------------- 214 /** 215 * Checks if the parse has found an error. 216 * 217 * @return whether a parse error has occurred 218 */ 219 public boolean isError() { 220 return textErrorIndex >= 0; 221 } 222 223 /** 224 * Checks if the text has been fully parsed such that there is no more text to parse. 225 * 226 * @return true if fully parsed 227 */ 228 public boolean isFullyParsed() { 229 return textIndex == getTextLength(); 230 } 231 232 /** 233 * Checks if the context contains a currency and amount suitable for creating 234 * a monetary value. 235 * 236 * @return true if able to create a monetary value 237 */ 238 public boolean isComplete() { 239 return currency != null && amount != null; 240 } 241 242 //----------------------------------------------------------------------- 243 /** 244 * Converts the indexes to a parse position. 245 * 246 * @return the parse position, never null 247 */ 248 public ParsePosition toParsePosition() { 249 ParsePosition pp = new ParsePosition(textIndex); 250 pp.setErrorIndex(textErrorIndex); 251 return pp; 252 } 253 254 /** 255 * Converts the context to a {@code BigMoney}. 256 * 257 * @return the monetary value, never null 258 * @throws MoneyFormatException if either the currency or amount is missing 259 */ 260 public BigMoney toBigMoney() { 261 if (currency == null) { 262 throw new MoneyFormatException("Cannot convert to BigMoney as no currency found"); 263 } 264 if (amount == null) { 265 throw new MoneyFormatException("Cannot convert to BigMoney as no amount found"); 266 } 267 return BigMoney.of(currency, amount); 268 } 269 270 }