All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.univocity.parsers.conversions.NumericConversion Maven / Gradle / Ivy

Go to download

univocity's open source parsers for processing different text formats using a consistent API

The newest version!
/*******************************************************************************
 * Copyright 2014 Univocity Software Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.univocity.parsers.conversions;

import com.univocity.parsers.annotations.helpers.*;
import com.univocity.parsers.common.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.*;
import java.util.*;

/**
 * Converts Strings to instances of {@link java.lang.Number} and vice versa.
 *
 * 

This class supports multiple Number formats. For example, you can define conversions from Numbers represented by different Strings such as "1,000,000.00 and $5.00". *

Extending classes must implement the {@link NumericConversion#configureFormatter(DecimalFormat)} method to provide specific configuration to the DecimalFormat instance. *

The reverse conversion from a Number to String (in {@link NumericConversion#revert(Number)} will return a formatted String using the pattern provided in this class constructor *

The numeric patterns must follows the pattern rules of {@link java.text.DecimalFormat} * * @param The type of numbers supported by this conversion class. * * @author Univocity Software Pty Ltd - [email protected] * @see java.text.DecimalFormat */ public abstract class NumericConversion extends ObjectConversion implements FormattedConversion { private DecimalFormat[] formatters = new DecimalFormat[0]; private String[] formats = new String[0]; private final ParsePosition position = new ParsePosition(0); private Class numberType = Number.class; /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. * This constructor assumes the output of a conversion should be null when input is null * * @param valueIfStringIsNull default Number to be returned when the input String is null. Used when {@link ObjectConversion#execute(String)} is invoked. * @param valueIfObjectIsNull default String value to be returned when a Number input is null. Used when {@link NumericConversion#revert(Number)} is invoked. * @param numericFormats list of acceptable numeric patterns. The first pattern in this sequence will be used to convert a Number into a String in {@link NumericConversion#revert(Number)}. */ public NumericConversion(T valueIfStringIsNull, String valueIfObjectIsNull, String... numericFormats) { super(valueIfStringIsNull, valueIfObjectIsNull); ArgumentUtils.noNulls("Numeric formats", numericFormats); this.formats = numericFormats.clone(); this.formatters = new DecimalFormat[numericFormats.length]; for (int i = 0; i < numericFormats.length; i++) { String numericFormat = numericFormats[i]; formatters[i] = new DecimalFormat(numericFormat); configureFormatter(formatters[i]); } } /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. * * @param valueIfStringIsNull default Number to be returned when the input String is null. Used when {@link ObjectConversion#execute(String)} is invoked. * @param valueIfObjectIsNull default String value to be returned when a Number input is null. Used when {@link NumericConversion#revert(Number)} is invoked. * @param numericFormatters list formatters of acceptable numeric patterns. The first formatter in this sequence will be used to convert a Number into a String in {@link NumericConversion#revert(Number)}. */ public NumericConversion(T valueIfStringIsNull, String valueIfObjectIsNull, DecimalFormat... numericFormatters) { super(valueIfStringIsNull, valueIfObjectIsNull); ArgumentUtils.noNulls("Numeric formatters", numericFormatters); this.formatters = numericFormatters.clone(); this.formats = new String[numericFormatters.length]; for (int i = 0; i < numericFormatters.length; i++) { formats[i] = numericFormatters[i].toPattern(); } } /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. The patterns * must be added to this conversion class through the {@link #addFormat(String, String...)} method. * * @param valueIfStringIsNull default Number to be returned when the input String is null. Used when {@link ObjectConversion#execute(String)} is invoked. * @param valueIfObjectIsNull default String value to be returned when a Number input is null. Used when {@link NumericConversion#revert(Number)} is invoked. */ public NumericConversion(T valueIfStringIsNull, String valueIfObjectIsNull) { super(valueIfStringIsNull, valueIfObjectIsNull); } /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. * This constructor assumes the output of a conversion should be null when input is null * * @param numericFormats list of acceptable numeric patterns. The first pattern in this sequence will be used to convert a Number into a String in {@link NumericConversion#revert(Number)}. */ public NumericConversion(String... numericFormats) { this(null, null, numericFormats); } /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. * This constructor assumes the output of a conversion should be null when input is null * * @param numericFormatters list formatters of acceptable numeric patterns. The first formatter in this sequence will be used to convert a Number into a String in {@link NumericConversion#revert(Number)}. */ public NumericConversion(DecimalFormat... numericFormatters) { this(null, null, numericFormatters); } /** * Defines a conversion from String to {@link java.lang.Number} using a sequence of acceptable numeric patterns. The patterns * must be added to this conversion class through the {@link #addFormat(String, String...)} method. * * This constructor assumes the output of a conversion should be null when input is null */ public NumericConversion() { super(); } /** * Returns the implementation of {@code Number} that should be used when converting numeric data. * * @return the implementation of {@code Number} that should be used when converting numeric data. */ public Class getNumberType() { return this.numberType; } /** * Defines a specific implementation of {@code Number} that should be used when converting numeric data. * * @param numberType the implementation of {@code Number} that should be used when converting numeric data. */ public void setNumberType(Class numberType) { this.numberType = numberType; } @Override public DecimalFormat[] getFormatterObjects() { return formatters; } /** * Method called by the constructor of this class to apply custom configurations to each formatter instantiated with the numeric formats provided. * * @param formatter a DecimalFormat instance initialized with one of the patterns provided in the constructor of this class. */ protected abstract void configureFormatter(DecimalFormat formatter); /** * Converts a formatted numeric String to an instance of Number. *

The pattern in the formatted input must match one of the numeric patterns provided in the constructor of this class. * * @param input the String containing a formatted number which must be converted to a number * * @return the Number instance containing the value represented by the given String, or the value of {@link ObjectConversion#getValueIfStringIsNull()} if the String input is null. */ @SuppressWarnings("unchecked") @Override protected T fromString(String input) { for (int i = 0; i < formatters.length; i++) { position.setIndex(0); T out = (T) formatters[i].parse(input, position); if (formatters.length == 1 || position.getIndex() == input.length()) { if (out == null || numberType == Number.class) { return out; } else if (numberType == Double.class) { return (T) Double.valueOf(out.doubleValue()); } else if (numberType == Float.class) { return (T) Float.valueOf(out.floatValue()); } else if (numberType == BigDecimal.class) { if (out instanceof BigDecimal) { return out; } return (T) new BigDecimal(String.valueOf(out)); } else if (numberType == BigInteger.class) { if (out instanceof BigInteger) { return out; } return (T) BigInteger.valueOf(out.longValue()); } else if (numberType == Long.class) { return (T) Long.valueOf(out.longValue()); } else if (numberType == Integer.class) { return (T) Integer.valueOf(out.intValue()); } else if (numberType == Short.class) { return (T) Short.valueOf(out.shortValue()); } else if (numberType == Byte.class) { return (T) Byte.valueOf(out.byteValue()); } return out; } } DataProcessingException exception = new DataProcessingException("Cannot parse '{value}' as a valid number. Supported formats are: " + Arrays.toString(formats)); exception.setValue(input); throw exception; } /** * Converts Number to a formatted numeric String. *

The pattern used to generate the formatted number is the first numeric pattern provided in the constructor of this class * * @param input the Number to be converted to a String * * @return a formatted numeric String representing the value provided by the given Number, or the value of {@link ObjectConversion#getValueIfObjectIsNull()} if the Number parameter is null. */ @Override public String revert(T input) { if (input == null) { return super.revert(null); } for (DecimalFormat formatter : formatters) { try { return formatter.format(input); } catch (Throwable ex) { //ignore and continue } } DataProcessingException exception = new DataProcessingException("Cannot format '{value}'. No valid formatters were defined."); exception.setValue(input); throw exception; } /** * Adds a new numeric pattern to be used to parse input Strings and convert them to numbers. * * @param format a numeric pattern. The first pattern added to this class will be used to convert a Number into a String in {@link NumericConversion#revert(Number)}. * @param formatOptions a sequence of properties and their values, used to configure the underlying formatter. Each element must be specified as {@code property_name=property_value}, * e.g. options={"decimalSeparator=,", "maximumFractionDigits=3"} */ public void addFormat(String format, String... formatOptions) { DecimalFormat formatter = new DecimalFormat(format); configureFormatter(formatter); AnnotationHelper.applyFormatSettings(formatter, formatOptions); this.formats = Arrays.copyOf(formats, formats.length + 1); this.formatters = Arrays.copyOf(formatters, formatters.length + 1); formats[formats.length - 1] = format; formatters[formatters.length - 1] = formatter; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy