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 * http://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 package org.apache.commons.validator.routines; 18 19 import java.math.BigDecimal; 20 import java.text.Format; 21 import java.text.NumberFormat; 22 import java.util.Locale; 23 24 /** 25 * <p><b>BigDecimal Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p> 26 * 27 * <p>This validator provides a number of methods for 28 * validating/converting a <code>String</code> value to 29 * a <code>BigDecimal</code> using <code>java.text.NumberFormat</code> 30 * to parse either:</p> 31 * <ul> 32 * <li>using the default format for the default <code>Locale</code></li> 33 * <li>using a specified pattern with the default <code>Locale</code></li> 34 * <li>using the default format for a specified <code>Locale</code></li> 35 * <li>using a specified pattern with a specified <code>Locale</code></li> 36 * </ul> 37 * 38 * <p>Use one of the <code>isValid()</code> methods to just validate or 39 * one of the <code>validate()</code> methods to validate and receive a 40 * <i>converted</i> <code>BigDecimal</code> value.</p> 41 * 42 * <p>Fraction/decimal values are automatically trimmed to the appropriate length.</p> 43 * 44 * <p>Once a value has been successfully converted the following 45 * methods can be used to perform minimum, maximum and range checks:</p> 46 * <ul> 47 * <li><code>minValue()</code> checks whether the value is greater 48 * than or equal to a specified minimum.</li> 49 * <li><code>maxValue()</code> checks whether the value is less 50 * than or equal to a specified maximum.</li> 51 * <li><code>isInRange()</code> checks whether the value is within 52 * a specified range of values.</li> 53 * </ul> 54 * 55 * <p>So that the same mechanism used for parsing an <i>input</i> value 56 * for validation can be used to format <i>output</i>, corresponding 57 * <code>format()</code> methods are also provided. That is you can 58 * format either:</p> 59 * <ul> 60 * <li>using the default format for the default <code>Locale</code></li> 61 * <li>using a specified pattern with the default <code>Locale</code></li> 62 * <li>using the default format for a specified <code>Locale</code></li> 63 * <li>using a specified pattern with a specified <code>Locale</code></li> 64 * </ul> 65 * 66 * @since 1.3.0 67 */ 68 public class BigDecimalValidator extends AbstractNumberValidator { 69 70 private static final long serialVersionUID = -670320911490506772L; 71 72 private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator(); 73 74 /** 75 * Gets the singleton instance of this validator. 76 * @return A singleton instance of the BigDecimalValidator. 77 */ 78 public static BigDecimalValidator getInstance() { 79 return VALIDATOR; 80 } 81 82 /** 83 * Constructs a <i>strict</i> instance. 84 */ 85 public BigDecimalValidator() { 86 this(true); 87 } 88 89 /** 90 * <p>Construct an instance with the specified strict setting.</p> 91 * 92 * @param strict {@code true} if strict 93 * <code>Format</code> parsing should be used. 94 */ 95 public BigDecimalValidator(final boolean strict) { 96 this(strict, STANDARD_FORMAT, true); 97 } 98 99 /** 100 * <p>Construct an instance with the specified strict setting 101 * and format type.</p> 102 * 103 * <p>The <code>formatType</code> specified what type of 104 * <code>NumberFormat</code> is created - valid types 105 * are:</p> 106 * <ul> 107 * <li>AbstractNumberValidator.STANDARD_FORMAT -to create 108 * <i>standard</i> number formats (the default).</li> 109 * <li>AbstractNumberValidator.CURRENCY_FORMAT -to create 110 * <i>currency</i> number formats.</li> 111 * <li>AbstractNumberValidator.PERCENT_FORMAT -to create 112 * <i>percent</i> number formats (the default).</li> 113 * </ul> 114 * 115 * @param strict {@code true} if strict 116 * <code>Format</code> parsing should be used. 117 * @param formatType The <code>NumberFormat</code> type to 118 * create for validation, default is STANDARD_FORMAT. 119 * @param allowFractions {@code true} if fractions are 120 * allowed or {@code false} if integers only. 121 */ 122 protected BigDecimalValidator(final boolean strict, final int formatType, 123 final boolean allowFractions) { 124 super(strict, formatType, allowFractions); 125 } 126 127 /** 128 * Check if the value is within a specified range. 129 * 130 * @param value The <code>Number</code> value to check. 131 * @param min The minimum value of the range. 132 * @param max The maximum value of the range. 133 * @return {@code true} if the value is within the 134 * specified range. 135 */ 136 public boolean isInRange(final BigDecimal value, final double min, final double max) { 137 return value.doubleValue() >= min && value.doubleValue() <= max; 138 } 139 140 /** 141 * Check if the value is less than or equal to a maximum. 142 * 143 * @param value The value validation is being performed on. 144 * @param max The maximum value. 145 * @return {@code true} if the value is less than 146 * or equal to the maximum. 147 */ 148 public boolean maxValue(final BigDecimal value, final double max) { 149 return value.doubleValue() <= max; 150 } 151 152 /** 153 * Check if the value is greater than or equal to a minimum. 154 * 155 * @param value The value validation is being performed on. 156 * @param min The minimum value. 157 * @return {@code true} if the value is greater than 158 * or equal to the minimum. 159 */ 160 public boolean minValue(final BigDecimal value, final double min) { 161 return value.doubleValue() >= min; 162 } 163 164 /** 165 * Convert the parsed value to a <code>BigDecimal</code>. 166 * 167 * @param value The parsed <code>Number</code> object created. 168 * @param formatter The Format used to parse the value with. 169 * @return The parsed <code>Number</code> converted to a 170 * <code>BigDecimal</code>. 171 */ 172 @Override 173 protected Object processParsedValue(final Object value, final Format formatter) { 174 BigDecimal decimal; 175 if (value instanceof Long) { 176 decimal = BigDecimal.valueOf(((Long) value).longValue()); 177 } else { 178 decimal = new BigDecimal(value.toString()); 179 } 180 181 final int scale = determineScale((NumberFormat) formatter); 182 if (scale >= 0) { 183 decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN); 184 } 185 186 return decimal; 187 } 188 189 /** 190 * <p>Validate/convert a <code>BigDecimal</code> using the default 191 * <code>Locale</code>. 192 * 193 * @param value The value validation is being performed on. 194 * @return The parsed <code>BigDecimal</code> if valid or {@code null} 195 * if invalid. 196 */ 197 public BigDecimal validate(final String value) { 198 return (BigDecimal) parse(value, (String) null, (Locale) null); 199 } 200 201 /** 202 * <p>Validate/convert a <code>BigDecimal</code> using the 203 * specified <code>Locale</code>. 204 * 205 * @param value The value validation is being performed on. 206 * @param locale The locale to use for the number format, system default if null. 207 * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid. 208 */ 209 public BigDecimal validate(final String value, final Locale locale) { 210 return (BigDecimal) parse(value, (String) null, locale); 211 } 212 213 /** 214 * <p>Validate/convert a <code>BigDecimal</code> using the 215 * specified <i>pattern</i>. 216 * 217 * @param value The value validation is being performed on. 218 * @param pattern The pattern used to validate the value against, or the 219 * default for the <code>Locale</code> if {@code null}. 220 * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid. 221 */ 222 public BigDecimal validate(final String value, final String pattern) { 223 return (BigDecimal) parse(value, pattern, (Locale) null); 224 } 225 226 /** 227 * <p>Validate/convert a <code>BigDecimal</code> using the 228 * specified pattern and/ or <code>Locale</code>. 229 * 230 * @param value The value validation is being performed on. 231 * @param pattern The pattern used to validate the value against, or the 232 * default for the <code>Locale</code> if {@code null}. 233 * @param locale The locale to use for the date format, system default if null. 234 * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid. 235 */ 236 public BigDecimal validate(final String value, final String pattern, final Locale locale) { 237 return (BigDecimal) parse(value, pattern, locale); 238 } 239 }