Source for net.dpml.cli.validation.NumberValidator

   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: }