[ 
https://jira.codehaus.org/browse/JBEHAVE-739?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=294175#comment-294175
 ] 

Daniel Schneller commented on JBEHAVE-739:
------------------------------------------

I suggest this implementation of {{canonicalize}}.
I don't have access to GitHub currently, so I cannot create a patch yet. I will 
do so, including the tests I have locally for it, when no objections come up:

{code:title="ParametersConverters.java"}
/**
         * Canonicalized a number represented as a String to a format suitable
         * for the BigDecimal(String) constructor. Takes into account the
         * settings of the currently configures NumberFormat.
         * 
         * @param value
         *            a localized number string
         * @return the same number, but as a String suitable for consumption by
         *         BigDecimal
         */
        String canonicalize(String value) {
                char decimalPointSeparator = '.'; // default
                char minusSign = '-'; // default
                String rxNotDigits = "[^0-9]";
                StringBuilder returnBuilder = new StringBuilder(value.length());

                // override defaults according to numberFormat's settings
                if (numberFormat instanceof DecimalFormat) {
                        DecimalFormatSymbols decimalFormatSymbols = 
((DecimalFormat) numberFormat)
                                        .getDecimalFormatSymbols();
                        minusSign = decimalFormatSymbols.getMinusSign();
                        decimalPointSeparator = decimalFormatSymbols
                                        .getDecimalSeparator();
                }

                value = value.trim();
                int decimalPointPosition = 
value.lastIndexOf(decimalPointSeparator);
                boolean isNegative = value.charAt(0) == minusSign;

                if (isNegative) {
                        returnBuilder.append('-'); // fixed "-" for BigDecimal
                                                                                
// constructor
                }

                if (decimalPointPosition != -1) {
                        String sf = value.substring(0, decimalPointPosition)
                                        .replaceAll(rxNotDigits, "");
                        String dp = value.substring(decimalPointPosition + 1)
                                        .replaceAll(rxNotDigits, "");

                        returnBuilder.append(sf);
                        returnBuilder.append('.'); // fixed "." for BigDecimal
                                                                                
// constructor
                        returnBuilder.append(dp);

                } else {
                        returnBuilder.append(value.replaceAll(rxNotDigits, ""));
                }
                return returnBuilder.toString();
        }
{code}
                
> NumberFormatException when trying to convert parameters to BigDecimal with 
> Locale
> ---------------------------------------------------------------------------------
>
>                 Key: JBEHAVE-739
>                 URL: https://jira.codehaus.org/browse/JBEHAVE-739
>             Project: JBehave
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 3.6
>            Reporter: Daniel Schneller
>
> When using a German localized number with group separators and decimals, a 
> conversion to BigDecimal fails with a {{NumberFormatException}}. For German, 
> group separators are dots, decimal separator is a comma (just the other way 
> round of the US version). 
> In the following test class, the first case is green, the second fails with
> {noformat}
> org.jbehave.core.steps.ParameterConverters$ParameterConvertionFailed: 
> 1.000.000,01
>       at 
> org.jbehave.core.steps.ParameterConverters$NumberConverter.convertValue(ParameterConverters.java:256)
>       at 
> de.westlb.jets.xce.jbehave.tools.NumberFormatTest.jbehaveConverter(NumberFormatTest.java:39)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>       at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>       at java.lang.reflect.Method.invoke(Method.java:597)
>       at 
> org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
>         ...
>       at 
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
> Caused by: java.lang.NumberFormatException
>       at java.math.BigDecimal.<init>(BigDecimal.java:453)
>       at java.math.BigDecimal.<init>(BigDecimal.java:728)
>       at 
> org.jbehave.core.steps.ParameterConverters$NumberConverter.convertValue(ParameterConverters.java:247)
>       ... 21 more
> {noformat}
> Putting a breakpoint in the BigDecimal constructor reveals it is fed a String 
> "1.000.000.000.00" which is obviously wrong. I suspect, the 
> "canonicalization" of the original String breaks it.
> {code:title=Test.java}
> public class NumberFormatTest {
>       private static final BigDecimal EXPECTED = new BigDecimal("1000000.01");
>       private final String localizedString = "1.000.000,01";
>       private DecimalFormat germanNumbers;
>       @Before
>       public void setup() {
>               germanNumbers = (DecimalFormat) DecimalFormat
>                               .getNumberInstance(Locale.GERMAN);
>               germanNumbers.setParseBigDecimal(true);
>       }
>       @Test
>       public void plainConverter() throws Exception {
>               Number parse = germanNumbers.parse(localizedString);
>               assertEquals(EXPECTED, parse);
>       }
>       @Test
>       public void jbehaveConverter() throws Exception {
>               ParameterConverters.NumberConverter numberConverter = new 
> ParameterConverters.NumberConverter(
>                               germanNumbers);
>               Object v = numberConverter.convertValue(localizedString,
>                               BigDecimal.class);
>               assertEquals(EXPECTED, v);
>       }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://jira.codehaus.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to