/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
public class RoundHalfUpDecimalFormat extends DecimalFormat
{
private static ConcurrentHashMap<Locale, DecimalFormatSymbols> decimalFormatSymbols = new ConcurrentHashMap<Locale, DecimalFormatSymbols>();
public static DecimalFormatSymbols getDecimalFormatSymbols(Locale locale)
{
DecimalFormatSymbols dfs = decimalFormatSymbols.get(locale);
if (dfs == null)
{
dfs = new DecimalFormatSymbols(locale);
decimalFormatSymbols.put(locale, dfs);
}
return dfs;
}
private boolean minusAtBack = false;
public RoundHalfUpDecimalFormat(Locale locale)
{
this("#,##0.###", locale); //$NON-NLS-1$
}
public RoundHalfUpDecimalFormat(String format, Locale locale)
{
super(checkPattern(format, locale), getDecimalFormatSymbols(locale));
setGroupingUsed(true);
format = checkPattern(format, locale);
if (format.endsWith("-")) //$NON-NLS-1$
{
applyPattern(format.substring(0, format.length() - 1));
minusAtBack = true;
}
setParseBigDecimal(true);
setRoundingMode(RoundingMode.HALF_UP);
}
@Override
public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition)
{
if (minusAtBack && number < 0 && !("%".equals(getPositiveSuffix()) || "%".equals(getPositivePrefix())))
{
StringBuffer sb = super.format(Math.abs(number), result, fieldPosition);
sb.append('-');
return sb;
}
return super.format(number, result, fieldPosition);
}
@Override
public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition)
{
if (minusAtBack && number < 0)
{
StringBuffer sb = super.format(Math.abs(number), result, fieldPosition);
sb.append('-');
return sb;
}
else
{
return super.format(number, result, fieldPosition);
}
}
/**
*
*/
@Override
public Number parse(String source, ParsePosition pos)
{
if (minusAtBack && source.endsWith("-")) //$NON-NLS-1$
{
Number o = super.parse(source.substring(0, source.length() - 1), pos);
if (o instanceof Double)
{
o = new Double(-((Double)o).doubleValue());
}
else if (o instanceof Long)
{
o = new Long(-((Long)o).longValue());
}
else if (o instanceof BigDecimal)
{
return ((BigDecimal)o).negate();
}
return o;
}
else if ("".equals(source)) //$NON-NLS-1$
{
return null;
}
else
{
return super.parse(source, pos);
}
}
private static String checkPattern(String format, Locale locale)
{
try
{
new DecimalFormat(format, getDecimalFormatSymbols(locale));
return format;
}
catch (Exception ex)
{
Debug.error("Invalid number pattern : '" + format + "', continue using default pattern ...", ex); //$NON-NLS-1$ //$NON-NLS-2$
return new DecimalFormat().toPattern();
}
}
}