001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.validator.routines; 018 019import java.math.BigDecimal; 020import java.text.Format; 021import java.text.NumberFormat; 022import java.util.Locale; 023 024/** 025 * <p><b>BigDecimal Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p> 026 * 027 * <p>This validator provides a number of methods for 028 * validating/converting a <code>String</code> value to 029 * a <code>BigDecimal</code> using <code>java.text.NumberFormat</code> 030 * to parse either:</p> 031 * <ul> 032 * <li>using the default format for the default <code>Locale</code></li> 033 * <li>using a specified pattern with the default <code>Locale</code></li> 034 * <li>using the default format for a specified <code>Locale</code></li> 035 * <li>using a specified pattern with a specified <code>Locale</code></li> 036 * </ul> 037 * 038 * <p>Use one of the <code>isValid()</code> methods to just validate or 039 * one of the <code>validate()</code> methods to validate and receive a 040 * <i>converted</i> <code>BigDecimal</code> value.</p> 041 * 042 * <p>Fraction/decimal values are automatically trimmed to the appropriate length.</p> 043 * 044 * <p>Once a value has been successfully converted the following 045 * methods can be used to perform minimum, maximum and range checks:</p> 046 * <ul> 047 * <li><code>minValue()</code> checks whether the value is greater 048 * than or equal to a specified minimum.</li> 049 * <li><code>maxValue()</code> checks whether the value is less 050 * than or equal to a specified maximum.</li> 051 * <li><code>isInRange()</code> checks whether the value is within 052 * a specified range of values.</li> 053 * </ul> 054 * 055 * <p>So that the same mechanism used for parsing an <i>input</i> value 056 * for validation can be used to format <i>output</i>, corresponding 057 * <code>format()</code> methods are also provided. That is you can 058 * format either:</p> 059 * <ul> 060 * <li>using the default format for the default <code>Locale</code></li> 061 * <li>using a specified pattern with the default <code>Locale</code></li> 062 * <li>using the default format for a specified <code>Locale</code></li> 063 * <li>using a specified pattern with a specified <code>Locale</code></li> 064 * </ul> 065 * 066 * @since 1.3.0 067 */ 068public class BigDecimalValidator extends AbstractNumberValidator { 069 070 private static final long serialVersionUID = -670320911490506772L; 071 072 private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator(); 073 074 /** 075 * Gets the singleton instance of this validator. 076 * @return A singleton instance of the BigDecimalValidator. 077 */ 078 public static BigDecimalValidator getInstance() { 079 return VALIDATOR; 080 } 081 082 /** 083 * Constructs a <i>strict</i> instance. 084 */ 085 public BigDecimalValidator() { 086 this(true); 087 } 088 089 /** 090 * <p>Construct an instance with the specified strict setting.</p> 091 * 092 * @param strict {@code true} if strict 093 * <code>Format</code> parsing should be used. 094 */ 095 public BigDecimalValidator(final boolean strict) { 096 this(strict, STANDARD_FORMAT, true); 097 } 098 099 /** 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}