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: */
017: package org.apache.commons.validator.routines;
018:
019: import java.text.DecimalFormat;
020: import java.text.Format;
021: import java.math.BigDecimal;
022:
023: /**
024: * <p><b>Percentage Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p>
025: *
026: * <p>This is one implementation of a percent validator that has the following features:</p>
027: * <ul>
028: * <li>It is <i>lenient</i> about the the presence of the <i>percent symbol</i></li>
029: * <li>It converts the percent to a <code>java.math.BigDecimal</code></li>
030: * </ul>
031: *
032: * <p>However any of the <i>number</i> validators can be used for <i>percent</i> validation.
033: * For example, if you wanted a <i>percent</i> validator that converts to a
034: * <code>java.lang.Float</code> then you can simply instantiate an
035: * <code>FloatValidator</code> with the appropriate <i>format type</i>:</p>
036: *
037: * <p><code>... = new FloatValidator(false, FloatValidator.PERCENT_FORMAT);</code></p>
038: *
039: * <p>Pick the appropriate validator, depending on the type (i.e Float, Double or BigDecimal)
040: * you want the percent converted to. Please note, it makes no sense to use
041: * one of the validators that doesn't handle fractions (i.e. byte, short, integer, long
042: * and BigInteger) since percentages are converted to fractions (i.e <code>50%</code> is
043: * converted to <code>0.5</code>).</p>
044: *
045: * @version $Revision: 478334 $ $Date: 2006-11-22 21:31:54 +0000 (Wed, 22 Nov 2006) $
046: * @since Validator 1.3.0
047: */
048: public class PercentValidator extends BigDecimalValidator {
049:
050: private static final PercentValidator VALIDATOR = new PercentValidator();
051:
052: /** DecimalFormat's percent (thousand multiplier) symbol */
053: private static final char PERCENT_SYMBOL = '%';
054:
055: private static final BigDecimal POINT_ZERO_ONE = new BigDecimal(
056: "0.01");
057:
058: /**
059: * Return a singleton instance of this validator.
060: * @return A singleton instance of the PercentValidator.
061: */
062: public static BigDecimalValidator getInstance() {
063: return VALIDATOR;
064: }
065:
066: /**
067: * Construct a <i>strict</i> instance.
068: */
069: public PercentValidator() {
070: this (true);
071: }
072:
073: /**
074: * Construct an instance with the specified strict setting.
075: *
076: * @param strict <code>true</code> if strict
077: * <code>Format</code> parsing should be used.
078: */
079: public PercentValidator(boolean strict) {
080: super (strict, PERCENT_FORMAT, true);
081: }
082:
083: /**
084: * <p>Parse the value with the specified <code>Format</code>.</p>
085: *
086: * <p>This implementation is lenient whether the currency symbol
087: * is present or not. The default <code>NumberFormat</code>
088: * behaviour is for the parsing to "fail" if the currency
089: * symbol is missing. This method re-parses with a format
090: * without the currency symbol if it fails initially.</p>
091: *
092: * @param value The value to be parsed.
093: * @param formatter The Format to parse the value with.
094: * @return The parsed value if valid or <code>null</code> if invalid.
095: */
096: protected Object parse(String value, Format formatter) {
097:
098: // Initial parse of the value
099: BigDecimal parsedValue = (BigDecimal) super .parse(value,
100: formatter);
101: if (parsedValue != null
102: || !(formatter instanceof DecimalFormat)) {
103: return parsedValue;
104: }
105:
106: // Re-parse using a pattern without the percent symbol
107: DecimalFormat decimalFormat = (DecimalFormat) formatter;
108: String pattern = decimalFormat.toPattern();
109: if (pattern.indexOf(PERCENT_SYMBOL) >= 0) {
110: StringBuffer buffer = new StringBuffer(pattern.length());
111: for (int i = 0; i < pattern.length(); i++) {
112: if (pattern.charAt(i) != PERCENT_SYMBOL) {
113: buffer.append(pattern.charAt(i));
114: }
115: }
116: decimalFormat.applyPattern(buffer.toString());
117: parsedValue = (BigDecimal) super
118: .parse(value, decimalFormat);
119:
120: // If parsed OK, divide by 100 to get percent
121: if (parsedValue != null) {
122: parsedValue = parsedValue.multiply(POINT_ZERO_ONE);
123: }
124:
125: }
126: return parsedValue;
127: }
128: }
|