001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of 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,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package javax.faces.convert;
017:
018: import javax.faces.component.UIComponent;
019: import javax.faces.component.StateHolder;
020: import javax.faces.context.FacesContext;
021: import java.text.DecimalFormat;
022: import java.text.DecimalFormatSymbols;
023: import java.text.NumberFormat;
024: import java.text.ParseException;
025: import java.util.Currency;
026: import java.util.Locale;
027:
028: /**
029: * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
030: *
031: * @author Thomas Spiegl (latest modification by $Author: matzew $)
032: * @version $Revision: 547337 $ $Date: 2007-06-14 19:58:04 +0200 (Do, 14 Jun 2007) $
033: */
034: public class NumberConverter implements Converter, StateHolder {
035: // API FIELDS
036: public static final String CONVERTER_ID = "javax.faces.Number";
037: public static final String STRING_ID = "javax.faces.converter.STRING";
038: public static final String CURRENCY_ID = "javax.faces.converter.NumberConverter.CURRENCY";
039: public static final String NUMBER_ID = "javax.faces.converter.NumberConverter.NUMBER";
040: public static final String PATTERN_ID = "javax.faces.converter.NumberConverter.PATTERN";
041: public static final String PERCENT_ID = "javax.faces.converter.NumberConverter.PERCENT";
042:
043: private static final boolean JAVA_VERSION_14;
044:
045: static {
046: JAVA_VERSION_14 = checkJavaVersion14();
047: }
048:
049: private String _currencyCode;
050: private String _currencySymbol;
051: private Locale _locale;
052: private int _maxFractionDigits;
053: private int _maxIntegerDigits;
054: private int _minFractionDigits;
055: private int _minIntegerDigits;
056: private String _pattern;
057: private String _type = "number";
058: private boolean _groupingUsed = true;
059: private boolean _integerOnly = false;
060: private boolean _transient;
061:
062: private boolean _maxFractionDigitsSet;
063: private boolean _maxIntegerDigitsSet;
064: private boolean _minFractionDigitsSet;
065: private boolean _minIntegerDigitsSet;
066:
067: // CONSTRUCTORS
068: public NumberConverter() {
069: }
070:
071: // METHODS
072: public Object getAsObject(FacesContext facesContext,
073: UIComponent uiComponent, String value) {
074: if (facesContext == null)
075: throw new NullPointerException("facesContext");
076: if (uiComponent == null)
077: throw new NullPointerException("uiComponent");
078:
079: if (value != null) {
080: value = value.trim();
081: if (value.length() > 0) {
082: NumberFormat format = getNumberFormat(facesContext);
083: format.setParseIntegerOnly(_integerOnly);
084: try {
085: return format.parse(value);
086: } catch (ParseException e) {
087: if (getPattern() != null)
088: throw new ConverterException(_MessageUtils
089: .getErrorMessage(facesContext,
090: PATTERN_ID, new Object[] {
091: value,
092: "$###,###",
093: _MessageUtils.getLabel(
094: facesContext,
095: uiComponent) }));
096: else if (getType().equals("number"))
097: throw new ConverterException(_MessageUtils
098: .getErrorMessage(facesContext,
099: NUMBER_ID, new Object[] {
100: value,
101: "21",
102: _MessageUtils.getLabel(
103: facesContext,
104: uiComponent) }));
105: else if (getType().equals("currency"))
106: throw new ConverterException(_MessageUtils
107: .getErrorMessage(facesContext,
108: CURRENCY_ID, new Object[] {
109: value,
110: "42.25",
111: _MessageUtils.getLabel(
112: facesContext,
113: uiComponent) }));
114: else if (getType().equals("percent"))
115: throw new ConverterException(_MessageUtils
116: .getErrorMessage(facesContext,
117: PERCENT_ID, new Object[] {
118: value,
119: ".90",
120: _MessageUtils.getLabel(
121: facesContext,
122: uiComponent) }));
123: }
124: }
125: }
126: return null;
127: }
128:
129: public String getAsString(FacesContext facesContext,
130: UIComponent uiComponent, Object value) {
131: if (facesContext == null)
132: throw new NullPointerException("facesContext");
133: if (uiComponent == null)
134: throw new NullPointerException("uiComponent");
135:
136: if (value == null) {
137: return "";
138: }
139: if (value instanceof String) {
140: return (String) value;
141: }
142:
143: NumberFormat format = getNumberFormat(facesContext);
144: format.setGroupingUsed(_groupingUsed);
145: if (_maxFractionDigitsSet)
146: format.setMaximumFractionDigits(_maxFractionDigits);
147: if (_maxIntegerDigitsSet)
148: format.setMaximumIntegerDigits(_maxIntegerDigits);
149: if (_minFractionDigitsSet)
150: format.setMinimumFractionDigits(_minFractionDigits);
151: if (_minIntegerDigitsSet)
152: format.setMinimumIntegerDigits(_minIntegerDigits);
153: formatCurrency(format);
154: try {
155: return format.format(value);
156: } catch (Exception e) {
157: throw new ConverterException(_MessageUtils.getErrorMessage(
158: facesContext, STRING_ID, new Object[] {
159: value,
160: _MessageUtils.getLabel(facesContext,
161: uiComponent) }), e);
162: }
163: }
164:
165: private NumberFormat getNumberFormat(FacesContext facesContext) {
166: Locale locale = _locale != null ? _locale : facesContext
167: .getViewRoot().getLocale();
168:
169: if (_pattern == null && _type == null) {
170: throw new ConverterException(
171: "Cannot get NumberFormat, either type or pattern needed.");
172: }
173:
174: // pattern
175: if (_pattern != null) {
176: return new DecimalFormat(_pattern,
177: new DecimalFormatSymbols(locale));
178: }
179:
180: // type
181: if (_type.equals("number")) {
182: return NumberFormat.getNumberInstance(locale);
183: } else if (_type.equals("currency")) {
184: return NumberFormat.getCurrencyInstance(locale);
185: } else if (_type.equals("percent")) {
186: return NumberFormat.getPercentInstance(locale);
187: }
188: throw new ConverterException(
189: "Cannot get NumberFormat, illegal type " + _type);
190: }
191:
192: private void formatCurrency(NumberFormat format) {
193: if (_currencyCode == null && _currencySymbol == null) {
194: return;
195: }
196:
197: boolean useCurrencyCode;
198: if (JAVA_VERSION_14) {
199: useCurrencyCode = _currencyCode != null;
200: } else {
201: useCurrencyCode = _currencySymbol == null;
202: }
203:
204: if (useCurrencyCode) {
205: // set Currency
206: try {
207: format.setCurrency(Currency.getInstance(_currencyCode));
208: } catch (Exception e) {
209: throw new ConverterException(
210: "Unable to get Currency instance for currencyCode "
211: + _currencyCode);
212: }
213: } else if (format instanceof DecimalFormat)
214:
215: {
216: DecimalFormat dFormat = (DecimalFormat) format;
217: DecimalFormatSymbols symbols = dFormat
218: .getDecimalFormatSymbols();
219: symbols.setCurrencySymbol(_currencySymbol);
220: dFormat.setDecimalFormatSymbols(symbols);
221: }
222: }
223:
224: // STATE SAVE/RESTORE
225: public void restoreState(FacesContext facesContext, Object state) {
226: Object values[] = (Object[]) state;
227: _currencyCode = (String) values[0];
228: _currencySymbol = (String) values[1];
229: _locale = (Locale) values[2];
230: Integer value = (Integer) values[3];
231: _maxFractionDigits = value != null ? value.intValue() : 0;
232: value = (Integer) values[4];
233: _maxIntegerDigits = value != null ? value.intValue() : 0;
234: value = (Integer) values[5];
235: _minFractionDigits = value != null ? value.intValue() : 0;
236: value = (Integer) values[6];
237: _minIntegerDigits = value != null ? value.intValue() : 0;
238: _pattern = (String) values[7];
239: _type = (String) values[8];
240: _groupingUsed = ((Boolean) values[9]).booleanValue();
241: _integerOnly = ((Boolean) values[10]).booleanValue();
242: _maxFractionDigitsSet = ((Boolean) values[11]).booleanValue();
243: _maxIntegerDigitsSet = ((Boolean) values[12]).booleanValue();
244: _minFractionDigitsSet = ((Boolean) values[13]).booleanValue();
245: _minIntegerDigitsSet = ((Boolean) values[14]).booleanValue();
246: }
247:
248: public Object saveState(FacesContext facesContext) {
249: Object values[] = new Object[15];
250: values[0] = _currencyCode;
251: values[1] = _currencySymbol;
252: values[2] = _locale;
253: values[3] = _maxFractionDigitsSet ? new Integer(
254: _maxFractionDigits) : null;
255: values[4] = _maxIntegerDigitsSet ? new Integer(
256: _maxIntegerDigits) : null;
257: values[5] = _minFractionDigitsSet ? new Integer(
258: _minFractionDigits) : null;
259: values[6] = _minIntegerDigitsSet ? new Integer(
260: _minIntegerDigits) : null;
261: values[7] = _pattern;
262: values[8] = _type;
263: values[9] = _groupingUsed ? Boolean.TRUE : Boolean.FALSE;
264: values[10] = _integerOnly ? Boolean.TRUE : Boolean.FALSE;
265: values[11] = _maxFractionDigitsSet ? Boolean.TRUE
266: : Boolean.FALSE;
267: values[12] = _maxIntegerDigitsSet ? Boolean.TRUE
268: : Boolean.FALSE;
269: values[13] = _minFractionDigitsSet ? Boolean.TRUE
270: : Boolean.FALSE;
271: values[14] = _minIntegerDigitsSet ? Boolean.TRUE
272: : Boolean.FALSE;
273: return values;
274: }
275:
276: // GETTER & SETTER
277: public String getCurrencyCode() {
278: return _currencyCode != null ? _currencyCode
279: : getDecimalFormatSymbols()
280: .getInternationalCurrencySymbol();
281: }
282:
283: public void setCurrencyCode(String currencyCode) {
284: _currencyCode = currencyCode;
285: }
286:
287: public String getCurrencySymbol() {
288: return _currencySymbol != null ? _currencySymbol
289: : getDecimalFormatSymbols().getCurrencySymbol();
290: }
291:
292: public void setCurrencySymbol(String currencySymbol) {
293: _currencySymbol = currencySymbol;
294: }
295:
296: public boolean isGroupingUsed() {
297: return _groupingUsed;
298: }
299:
300: public void setGroupingUsed(boolean groupingUsed) {
301: _groupingUsed = groupingUsed;
302: }
303:
304: public boolean isIntegerOnly() {
305: return _integerOnly;
306: }
307:
308: public void setIntegerOnly(boolean integerOnly) {
309: _integerOnly = integerOnly;
310: }
311:
312: public Locale getLocale() {
313: if (_locale != null)
314: return _locale;
315: FacesContext context = FacesContext.getCurrentInstance();
316: return context.getViewRoot().getLocale();
317: }
318:
319: public void setLocale(Locale locale) {
320: _locale = locale;
321: }
322:
323: public int getMaxFractionDigits() {
324: return _maxFractionDigits;
325: }
326:
327: public void setMaxFractionDigits(int maxFractionDigits) {
328: _maxFractionDigitsSet = true;
329: _maxFractionDigits = maxFractionDigits;
330: }
331:
332: public int getMaxIntegerDigits() {
333: return _maxIntegerDigits;
334: }
335:
336: public void setMaxIntegerDigits(int maxIntegerDigits) {
337: _maxIntegerDigitsSet = true;
338: _maxIntegerDigits = maxIntegerDigits;
339: }
340:
341: public int getMinFractionDigits() {
342: return _minFractionDigits;
343: }
344:
345: public void setMinFractionDigits(int minFractionDigits) {
346: _minFractionDigitsSet = true;
347: _minFractionDigits = minFractionDigits;
348: }
349:
350: public int getMinIntegerDigits() {
351: return _minIntegerDigits;
352: }
353:
354: public void setMinIntegerDigits(int minIntegerDigits) {
355: _minIntegerDigitsSet = true;
356: _minIntegerDigits = minIntegerDigits;
357: }
358:
359: public String getPattern() {
360: return _pattern;
361: }
362:
363: public void setPattern(String pattern) {
364: _pattern = pattern;
365: }
366:
367: public boolean isTransient() {
368: return _transient;
369: }
370:
371: public void setTransient(boolean aTransient) {
372: _transient = aTransient;
373: }
374:
375: public String getType() {
376: return _type;
377: }
378:
379: public void setType(String type) {
380: //TODO: validate type
381: _type = type;
382: }
383:
384: private static boolean checkJavaVersion14() {
385: String version = System.getProperty("java.version");
386: if (version == null) {
387: return false;
388: }
389: byte java14 = 0;
390: for (int idx = version.indexOf('.'), i = 0; idx > 0
391: || version != null; i++) {
392: if (idx > 0) {
393: byte value = Byte.parseByte(version.substring(0, 1));
394: version = version.substring(idx + 1, version.length());
395: idx = version.indexOf('.');
396: switch (i) {
397: case 0:
398: if (value == 1) {
399: java14 = 1;
400: break;
401: } else if (value > 1) {
402: java14 = 2;
403: }
404: case 1:
405: if (java14 > 0 && value >= 4) {
406: java14 = 2;
407: }
408: ;
409: default:
410: idx = 0;
411: version = null;
412: break;
413: }
414: } else {
415: byte value = Byte.parseByte(version.substring(0, 1));
416: if (java14 > 0 && value >= 4) {
417: java14 = 2;
418: }
419: break;
420: }
421: }
422: return java14 == 2;
423: }
424:
425: private DecimalFormatSymbols getDecimalFormatSymbols() {
426: return new DecimalFormatSymbols(getLocale());
427: }
428: }
|