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.cli2.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 org.apache.commons.cli2.resource.ResourceConstants; 26 import org.apache.commons.cli2.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 Rob Oxspring 53 * @author John Keyes 54 */ 55 public class NumberValidator implements Validator { 56 /** the <code>NumberFormat</code> being used. */ 57 private NumberFormat format; 58 59 /** the lower bound for argument values. */ 60 private Number minimum = null; 61 62 /** the upper bound for argument values */ 63 private Number maximum = null; 64 65 /** 66 * Creates a new NumberValidator based on the specified NumberFormat 67 * @param format the format of numbers to accept 68 */ 69 public NumberValidator(final NumberFormat format) { 70 setFormat(format); 71 } 72 73 /** 74 * Returns a <code>NumberValidator</code> for a currency format 75 * for the current default locale. 76 * @return a <code>NumberValidator</code> for a currency format 77 * for the current default locale. 78 */ 79 public static NumberValidator getCurrencyInstance() { 80 return new NumberValidator(NumberFormat.getCurrencyInstance()); 81 } 82 83 /** 84 * Returns a <code>NumberValidator</code> for an integer number format 85 * for the current default locale. 86 * @return a <code>NumberValidator</code> for an integer number format 87 * for the current default locale. 88 */ 89 public static NumberValidator getIntegerInstance() { 90 final NumberFormat format = NumberFormat.getNumberInstance(); 91 format.setParseIntegerOnly(true); 92 93 return new NumberValidator(format); 94 } 95 96 /** 97 * Returns a <code>NumberValidator</code> for a percentage format 98 * for the current default locale. 99 * @return a <code>NumberValidator</code> for a percentage format 100 * for the current default locale. 101 */ 102 public static NumberValidator getPercentInstance() { 103 return new NumberValidator(NumberFormat.getPercentInstance()); 104 } 105 106 /** 107 * Returns a <code>NumberValidator</code> for a general-purpose 108 * number format for the current default locale. 109 * @return a <code>NumberValidator</code> for a general-purpose 110 * number format for the current default locale. 111 */ 112 public static NumberValidator getNumberInstance() { 113 return new NumberValidator(NumberFormat.getNumberInstance()); 114 } 115 116 /** 117 * Validate the list of values against the list of permitted values. 118 * If a value is valid, replace the string in the <code>values</code> 119 * {@link java.util.List} with the {@link java.lang.Number} instance. 120 * 121 * @see org.apache.commons.cli2.validation.Validator#validate(java.util.List) 122 */ 123 public void validate(final List values) 124 throws InvalidArgumentException { 125 for (final ListIterator i = values.listIterator(); i.hasNext();) { 126 final String value = (String) i.next(); 127 128 final ParsePosition pp = new ParsePosition(0); 129 final Number number = format.parse(value, pp); 130 131 if (pp.getIndex() < value.length()) { 132 throw new InvalidArgumentException(value); 133 } 134 135 if (((minimum != null) && (number.doubleValue() < minimum.doubleValue())) || 136 ((maximum != null) && (number.doubleValue() > maximum.doubleValue()))) { 137 throw new InvalidArgumentException(ResourceHelper.getResourceHelper().getMessage(ResourceConstants.NUMBERVALIDATOR_NUMBER_OUTOFRANGE, 138 new Object[] { 139 value 140 })); 141 } 142 143 i.set(number); 144 } 145 } 146 147 /** 148 * Return the format being used to validate argument values against. 149 * 150 * @return the format being used to validate argument values against. 151 */ 152 public NumberFormat getFormat() { 153 return format; 154 } 155 156 /** 157 * Specify the format being used to validate argument values against. 158 * 159 * @param format the format being used to validate argument values against. 160 */ 161 protected void setFormat(NumberFormat format) { 162 this.format = format; 163 } 164 165 /** 166 * Return the maximum value allowed for an argument value. 167 * 168 * @return the maximum value allowed for an argument value. 169 */ 170 public Number getMaximum() { 171 return maximum; 172 } 173 174 /** 175 * Specify the maximum value allowed for an argument value. 176 * 177 * @param maximum the maximum value allowed for an argument value. 178 */ 179 public void setMaximum(Number maximum) { 180 this.maximum = maximum; 181 } 182 183 /** 184 * Return the minimum value allowed for an argument value. 185 * 186 * @return the minimum value allowed for an argument value. 187 */ 188 public Number getMinimum() { 189 return minimum; 190 } 191 192 /** 193 * Specify the minimum value allowed for an argument value. 194 * 195 * @param minimum the minimum value allowed for an argument value. 196 */ 197 public void setMinimum(Number minimum) { 198 this.minimum = minimum; 199 } 200 }