org.netxilia.api.impl.value.NumberParser.java Source code

Java tutorial

Introduction

Here is the source code for org.netxilia.api.impl.value.NumberParser.java

Source

/*******************************************************************************
 * 
 * Copyright 2010 Alexandru Craciun, and individual contributors as indicated
 * by the @authors tag. 
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This software 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 ******************************************************************************/
package org.netxilia.api.impl.value;

import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Currency;
import java.util.Locale;

import org.netxilia.api.value.IGenericValue;
import org.netxilia.api.value.IGenericValueParser;
import org.netxilia.api.value.NumberValue;
import org.springframework.beans.factory.InitializingBean;

/**
 * Taken from Stripes number converter
 * 
 * @author <a href='mailto:ax.craciun@gmail.com'>Alexandru Craciun</a>
 * 
 */
public class NumberParser implements IGenericValueParser, InitializingBean {
    private Locale locale;
    private NumberFormat[] formats;
    private String currencySymbol;

    private String localeId;

    /** Returns the Locale set on the object using setLocale(). */
    public Locale getLocale() {
        return locale;
    }

    public String getLocaleId() {
        return localeId;
    }

    public void setLocaleId(String localeId) {
        this.localeId = localeId;
    }

    /**
     * Fetches one or more NumberFormat instances that can be used to parse numbers for the current locale. The default
     * implementation returns two instances, one regular NumberFormat and a currency instance of NumberFormat.
     * 
     * @return one or more NumberFormats to use in parsing numbers
     */
    protected NumberFormat[] getNumberFormats() {
        return new NumberFormat[] { NumberFormat.getInstance(this.locale) };
    }

    @Override
    public IGenericValue parse(String text) {
        String input = preprocess(text);
        ParsePosition pp = new ParsePosition(0);

        for (NumberFormat format : this.formats) {
            pp.setIndex(0);
            Number number = format.parse(input, pp);
            if (number != null && input.length() == pp.getIndex()) {
                return new NumberValue(number.doubleValue());
            }
        }

        return null;
    }

    /**
     * Pre-processes the String to give the NumberFormats a better shot at parsing the input. The default implementation
     * trims the String for whitespace and then looks to see if the number is surrounded by parentheses, e.g. (800), and
     * if so removes the parentheses and prepends a minus sign. Lastly it will remove the currency symbol from the
     * String so that we don't have to use too many NumberFormats!
     * 
     * @param input
     *            the String as input by the user
     * @return the result of preprocessing the String
     */
    protected String preprocess(String input) {
        // Step 1: trim whitespace
        String output = input.trim();

        // Step 2: remove the currency symbol
        // The casts are to make sure we don't call replace(String regex, String replacement)
        output = output.replace(currencySymbol, "");

        // Step 3: replace parentheses with negation
        if (output.startsWith("(") && output.endsWith(")")) {
            output = "-" + output.substring(1, output.length() - 1);
        }

        return output;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.locale = localeId != null ? new Locale(localeId) : Locale.getDefault();
        this.formats = getNumberFormats();

        // Use the appropriate currency symbol if our locale has a country, otherwise try the dollar sign!
        if (locale.getCountry() != null && !"".equals(locale.getCountry())) {
            this.currencySymbol = Currency.getInstance(locale).getSymbol(locale);
        } else {
            this.currencySymbol = "$";
        }

    }
}