package org.smartly.commons.util; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParseException; import java.util.Locale; /** * Symbol Meaning<br> * 0 a digit<br> * # a digit, zero shows as absent<br> * . placeholder for decimal separator<br> * , placeholder for grouping separator.<br> * E separates mantissa and exponent for exponential formats.<br> * - default negative prefix.<br> * % multiply by 100 and show as percentage<br> * X any other characters can be used in the prefix or suffix<br> * ' used to quote special characters in a prefix or suffix.<br> * <p/> * <p>A <code>NumberWrapper</code> pattern contains a positive and negative * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>. Each * subpattern has a prefix, numeric part, and suffix. The negative subpattern * is optional; if absent, then the positive subpattern prefixed with the * localized minus sign (code>'-'</code> in most locales) is used as the * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to * <code>"0.00;-0.00"</code>. If there is an explicit negative subpattern, it * serves only to specify the negative prefix and suffix; the number of digits, * minimal digits, and other characteristics are all the same as the positive * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>. * <p/> * <blockquote> * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol, * location, localized, and meaning."> * <tr bgcolor="#ccccff"> * <th align=left>Symbol * <th align=left>Location * <th align=left>Localized? * <th align=left>Meaning * <tr valign=top> * <td><code>0</code> * <td>Number * <td>Yes * <td>Digit * <tr valign=top bgcolor="#eeeeff"> * <td><code>#</code> * <td>Number * <td>Yes * <td>Digit, zero shows as absent * <tr valign=top> * <td><code>.</code> * <td>Number * <td>Yes * <td>Decimal separator or monetary decimal separator * <tr valign=top bgcolor="#eeeeff"> * <td><code>-</code> * <td>Number * <td>Yes * <td>Minus sign * <tr valign=top> * <td><code>,</code> * <td>Number * <td>Yes * <td>Grouping separator * <tr valign=top bgcolor="#eeeeff"> * <td><code>E</code> * <td>Number * <td>Yes * <td>Separates mantissa and exponent in scientific notation. * <em>Need not be quoted in prefix or suffix.</em> * <tr valign=top> * <td><code>;</code> * <td>Subpattern boundary * <td>Yes * <td>Separates positive and negative subpatterns * <tr valign=top bgcolor="#eeeeff"> * <td><code>%</code> * <td>Prefix or suffix * <td>Yes * <td>Multiply by 100 and show as percentage * <tr valign=top> * <td><code>\u2030</code> * <td>Prefix or suffix * <td>Yes * <td>Multiply by 1000 and show as per mille * <tr valign=top bgcolor="#eeeeff"> * <td><code>¤</code> (<code>\u00A4</code>) * <td>Prefix or suffix * <td>No * <td>Currency sign, replaced by currency symbol. If * doubled, replaced by international currency symbol. * If present in a pattern, the monetary decimal separator * is used instead of the decimal separator. * <tr valign=top> * <td><code>'</code> * <td>Prefix or suffix * <td>No * <td>Used to quote special characters in a prefix or suffix, * for example, <code>"'#'#"</code> formats 123 to * <code>"#123"</code>. To create a single quote * itself, use two in a row: <code>"# o''clock"</code>. * </table> * </blockquote> */ public class NumberWrapper { private Number _value; private String _pattern = "#,##0.00;(#,##0.00)"; private Locale _locale = Locale.ENGLISH; public NumberWrapper() { } public NumberWrapper(final Number value) { _value = value; } public NumberWrapper(final String value, final String pattern, final Locale locale, final Number defValue) { _pattern = pattern; _locale = locale; this.setValue(value, pattern, locale, defValue); } public void setValue(Number value) { _value = value; } public Number getValue() { return _value; } public void setPattern(String pattern) { _pattern = pattern; } public String getPattern() { return _pattern; } public void setLocale(Locale locale) { _locale = locale; } public Locale getLocale() { return _locale; } public void setValue(final Object value) { this.setValue(value, _pattern, _locale, 0); } public void setValue(final Object value, final String pattern) { this.setValue(value, pattern, _locale, 0); } public void setValue(final Object value, final String pattern, final Locale locale) { this.setValue(value, pattern, locale, 0); } public void setValue(final Object value, final String pattern, final Locale locale, final Number defValue) { if (null != value) { try { final DecimalFormat f = new DecimalFormat(pattern, new DecimalFormatSymbols(locale)); if (value instanceof String && StringUtils.hasText((String) value)) { _value = f.parse((String) value); } else if (value instanceof Number) { _value = (Number) value; } else { _value = defValue; } } catch (ParseException ex) { _value = defValue; } } } public double getValueAsDouble() { if (null != _value) { return _value.doubleValue(); } return 0.0; } public long getValueAsLong() { if (null != _value) { return _value.longValue(); } return 0L; } public long getValueAsInteger() { if (null != _value) { return _value.intValue(); } return 0; } @Override public String toString() { return toString(_pattern, _locale); } public String toString(Locale locale) { return toString(_pattern, locale); } public String toString(String pattern) { return toString(pattern, _locale); } public String toString(String pattern, Locale locale) { final DecimalFormat f = new DecimalFormat(pattern, new DecimalFormatSymbols(locale)); return f.format(_value); } }