Google

Jul 9, 2013

Core Java coding question - converting String to BigDecimal

There are times while coding you need to convert an entity of one data type to another or validate a given input.



Q. Can you write a generic function that converts an amount in String to double amount?
A.

Step 1: Ask the right questions and arrive at a more detailed requirements.
  • Handling negative amounts like -34.01 or (34.01) with a parenthesis. Parentheses denote a negative value. 
  • Handling commas in formatted values like 1,205.45, etc.
  • Handling negative scenarios like amount being  empty as in ( ).
Since, it is a requirement to write a generic function, all the above scenarios need to be taken care of.

Step 2: Let's use a TDD (Test Driven Development approach).

So, write a skeleton class so that all our unit tests fail.

  
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.ParseException;

public class ConvertingAmount
{
    
    public BigDecimal convert(String amount) throws ParseException
    {
        BigDecimal result = null;
        return result;
    }
}

Next, write the unit tests based on the above requirements so that all fail, but cover the requirements.

  
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.ParseException;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class ConvertingAmountTest
{   
    private ConvertingAmount ca;
    
    @Before
    public void setUp()
    {
        ca = new ConvertingAmount();
    }
    
    @Test
    public void testPositiveAmount() throws ParseException
    {
        BigDecimal converted = ca.convert("2255.001");
        Assert.assertEquals(new BigDecimal("2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmount() throws ParseException
    {
        BigDecimal converted = ca.convert("-2255.001");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountWithParanthes() throws ParseException
    {
        BigDecimal converted = ca.convert("(2255.001)");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testPosiotiveAmountFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("2,255.001");
        Assert.assertEquals(new BigDecimal("2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("-2,255.001");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountWithParenthesesFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("(2,255.001)");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test(expected = ParseException.class)
    public void testExceptionalScenario() throws ParseException
    {
        String amount = "()";
        ca.convert(amount);
    }
    
    @Test(expected = ParseException.class)
    public void testExceptionalScenario2() throws ParseException
    {
        String amount = "abc";
        ca.convert(amount);
    }
}




Step 3: Implement the functionality, so that all the above unit tests pass.

 
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;

import org.apache.commons.lang.StringUtils;

public class ConvertingAmount
{
    
    public BigDecimal convert(String amount) throws ParseException
    {
        BigDecimal result = null;
        
        DecimalFormat df = new DecimalFormat("#,#00.00;-#,#00.00"); //positive;negative 
        
        //convert (2255.001) to -2255.001 and (2,255.001) to  -2255.001 
        if (StringUtils.isNotBlank(amount) && amount.startsWith("(") && amount.endsWith(")"))
        {
            String valueStr = amount.substring(1, amount.length() - 1);
            Number valInParenthesis = df.parse(valueStr.trim());
            result = BigDecimal.valueOf(valInParenthesis.doubleValue()).negate();
            amount = result.toPlainString();
        }
        
        //parse 2,255.001 and -2,255.001
        Number val = df.parse(amount);
        result = BigDecimal.valueOf(val.doubleValue());
        
        return result;
    }
}

Now, all green.


Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home