1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.beanutils2.locale.converters; 19 20 import java.text.DecimalFormat; 21 import java.text.NumberFormat; 22 import java.text.ParseException; 23 import java.util.Locale; 24 25 import org.apache.commons.beanutils2.ConversionException; 26 import org.apache.commons.beanutils2.locale.BaseLocaleConverter; 27 import org.apache.commons.beanutils2.locale.LocaleConverter; 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 31 /** 32 * Standard {@link LocaleConverter} implementation that converts an incoming locale-sensitive String into a {@link Number} object, optionally using a default 33 * value or throwing a {@link ConversionException} if a conversion error occurs. 34 * 35 * @param <T> The converter type. 36 * @since 1.7 37 */ 38 public class DecimalLocaleConverter<T extends Number> extends BaseLocaleConverter<T> { 39 40 /** 41 * Builds instances of {@link DateLocaleConverter}. 42 * 43 * @param <B> The builder type. 44 * @param <T> The Number type. 45 */ 46 public static class Builder<B extends Builder<B, T>, T extends Number> extends BaseLocaleConverter.Builder<B, T> { 47 48 /** 49 * Constructs a new instance. 50 */ 51 public Builder() { 52 // empty 53 } 54 55 /** 56 * Constructs a new instance. 57 * <p> 58 * By default, construct a {@link LocaleConverter} that will throw a {@link ConversionException} if a conversion error occurs. The locale is the default 59 * locale for this instance of the Java Virtual Machine and an unlocalized pattern is used for the conversion. 60 * </p> 61 * 62 * @return a new instance. 63 */ 64 @Override 65 public DecimalLocaleConverter<?> get() { 66 return new DecimalLocaleConverter<>(defaultValue, locale, pattern, useDefault || defaultValue != null, localizedPattern); 67 } 68 69 } 70 71 /** All logging goes through this logger */ 72 private static final Log LOG = LogFactory.getLog(DecimalLocaleConverter.class); 73 74 /** 75 * Constructs a new builder. 76 * 77 * @param <B> The builder type. 78 * @param <T> The Number type. 79 * @return a new builder. 80 */ 81 @SuppressWarnings("unchecked") 82 public static <B extends Builder<B, T>, T extends Number> B builder() { 83 return (B) new Builder<>(); 84 } 85 86 /** 87 * Constructs a new instance. 88 * 89 * @param defaultValue default value. 90 * @param locale locale. 91 * @param pattern pattern. 92 * @param useDefault use the default. 93 * @param locPattern localized pattern. 94 */ 95 protected DecimalLocaleConverter(final T defaultValue, final Locale locale, final String pattern, final boolean useDefault, final boolean locPattern) { 96 super(defaultValue, locale, pattern, useDefault, locPattern); 97 } 98 99 /** 100 * Converts the specified locale-sensitive input object into an output object of the specified type. 101 * 102 * @param value The input object to be converted 103 * @param pattern The pattern is used for the conversion 104 * @return The converted value 105 * @throws ConversionException if conversion cannot be performed successfully 106 * @throws ParseException if an error occurs parsing a String to a Number 107 */ 108 @Override 109 protected T parse(final Object value, final String pattern) throws ParseException { 110 if (value instanceof Number) { 111 return (T) value; 112 } 113 114 // Note that despite the ambiguous "getInstance" name, and despite the 115 // fact that objects returned from this method have the same toString 116 // representation, each call to getInstance actually returns a new 117 // object. 118 final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(locale); 119 120 // if some constructors default pattern to null, it makes only sense 121 // to handle null pattern gracefully 122 if (pattern != null) { 123 if (localizedPattern) { 124 formatter.applyLocalizedPattern(pattern); 125 } else { 126 formatter.applyPattern(pattern); 127 } 128 } else { 129 LOG.debug("No pattern provided, using default."); 130 } 131 132 return (T) formatter.parse((String) value); 133 } 134 }