Frames | No Frames |
1: /* 2: * Copyright 2003-2005 The Apache Software Foundation 3: * Copyright 2005 Stephen McConnell 4: * 5: * Licensed under the Apache License, Version 2.0 (the "License"); 6: * you may not use this file except in compliance with the License. 7: * 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 net.dpml.cli.validation; 18: 19: import java.text.NumberFormat; 20: import java.text.ParsePosition; 21: 22: import java.util.List; 23: import java.util.ListIterator; 24: 25: import net.dpml.cli.resource.ResourceConstants; 26: import net.dpml.cli.resource.ResourceHelper; 27: 28: /** 29: * The <code>NumberValidator</code> validates the string argument 30: * values are numbers. If the value is a number, the string value in 31: * the {@link java.util.List} of values is replaced with the 32: * {@link java.lang.Number} instance. 33: * 34: * A maximum and minimum value can also be specified using 35: * the {@link #setMaximum setMaximum}, and the 36: * {@link #setMinimum setMinimum} methods. 37: * 38: * The following example shows how to limit the valid values 39: * for the age attribute to integers less than 100. 40: * 41: * <pre> 42: * ... 43: * ArgumentBuilder builder = new ArgumentBuilder(); 44: * NumberValidator validator = NumberValidator.getIntegerInstance(); 45: * validator.setMaximum(new Integer(100)); 46: * 47: * Argument age = 48: * builder.withName("age"); 49: * .withValidator(validator); 50: * </pre> 51: * 52: * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a> 53: * @version @PROJECT-VERSION@ 54: */ 55: public class NumberValidator implements Validator 56: { 57: /** the <code>NumberFormat</code> being used. */ 58: private NumberFormat m_format; 59: 60: /** the lower bound for argument values. */ 61: private Number m_minimum = null; 62: 63: /** the upper bound for argument values */ 64: private Number m_maximum = null; 65: 66: /** 67: * Creates a new NumberValidator based on the specified NumberFormat 68: * @param format the format of numbers to accept 69: */ 70: public NumberValidator( final NumberFormat format ) 71: { 72: setFormat( format ); 73: } 74: 75: /** 76: * Returns a <code>NumberValidator</code> for a currency format 77: * for the current default locale. 78: * @return a <code>NumberValidator</code> for a currency format 79: * for the current default locale. 80: */ 81: public static NumberValidator getCurrencyInstance() 82: { 83: return new NumberValidator( NumberFormat.getCurrencyInstance() ); 84: } 85: 86: /** 87: * Returns a <code>NumberValidator</code> for an integer number format 88: * for the current default locale. 89: * @return a <code>NumberValidator</code> for an integer number format 90: * for the current default locale. 91: */ 92: public static NumberValidator getIntegerInstance() 93: { 94: final NumberFormat format = NumberFormat.getNumberInstance(); 95: format.setParseIntegerOnly( true ); 96: return new NumberValidator( format ); 97: } 98: 99: /** 100: * Returns a <code>NumberValidator</code> for a percentage format 101: * for the current default locale. 102: * @return a <code>NumberValidator</code> for a percentage format 103: * for the current default locale. 104: */ 105: public static NumberValidator getPercentInstance() 106: { 107: return new NumberValidator( NumberFormat.getPercentInstance() ); 108: } 109: 110: /** 111: * Returns a <code>NumberValidator</code> for a general-purpose 112: * number format for the current default locale. 113: * @return a <code>NumberValidator</code> for a general-purpose 114: * number format for the current default locale. 115: */ 116: public static NumberValidator getNumberInstance() 117: { 118: return new NumberValidator( NumberFormat.getNumberInstance() ); 119: } 120: 121: /** 122: * Validate the list of values against the list of permitted values. 123: * If a value is valid, replace the string in the <code>values</code> 124: * {@link java.util.List} with the {@link java.lang.Number} instance. 125: * 126: * @param values the list of values to validate 127: * @exception InvalidArgumentException if a value is invalid 128: * @see net.dpml.cli.validation.Validator#validate(java.util.List) 129: */ 130: public void validate( final List values ) throws InvalidArgumentException 131: { 132: for( final ListIterator i = values.listIterator(); i.hasNext();) 133: { 134: final Object next = i.next(); 135: if( next instanceof Number ) 136: { 137: return; 138: } 139: final String value = (String) next; 140: final ParsePosition pp = new ParsePosition( 0 ); 141: final Number number = m_format.parse( value, pp ); 142: if( pp.getIndex() < value.length() ) 143: { 144: throw new InvalidArgumentException( value ); 145: } 146: if( 147: ( ( m_minimum != null ) && ( number.doubleValue() < m_minimum.doubleValue() ) ) 148: || ( ( m_maximum != null ) && ( number.doubleValue() > m_maximum.doubleValue() ) ) 149: ) 150: { 151: throw new InvalidArgumentException( 152: ResourceHelper.getResourceHelper().getMessage( 153: ResourceConstants.NUMBERVALIDATOR_NUMBER_OUTOFRANGE, 154: new Object[]{value} ) ); 155: } 156: i.set( number ); 157: } 158: } 159: 160: /** 161: * Return the format being used to validate argument values against. 162: * 163: * @return the format being used to validate argument values against. 164: */ 165: public NumberFormat getFormat() 166: { 167: return m_format; 168: } 169: 170: /** 171: * Specify the format being used to validate argument values against. 172: * 173: * @param format the format being used to validate argument values against. 174: */ 175: protected void setFormat( NumberFormat format ) 176: { 177: m_format = format; 178: } 179: 180: /** 181: * Return the maximum value allowed for an argument value. 182: * 183: * @return the maximum value allowed for an argument value. 184: */ 185: public Number getMaximum() 186: { 187: return m_maximum; 188: } 189: 190: /** 191: * Specify the maximum value allowed for an argument value. 192: * 193: * @param maximum the maximum value allowed for an argument value. 194: */ 195: public void setMaximum( Number maximum ) 196: { 197: m_maximum = maximum; 198: } 199: 200: /** 201: * Return the minimum value allowed for an argument value. 202: * 203: * @return the minimum value allowed for an argument value. 204: */ 205: public Number getMinimum() 206: { 207: return m_minimum; 208: } 209: 210: /** 211: * Specify the minimum value allowed for an argument value. 212: * 213: * @param minimum the minimum value allowed for an argument value. 214: */ 215: public void setMinimum( Number minimum ) 216: { 217: m_minimum = minimum; 218: } 219: }