Coverage Report - org.apache.commons.cli2.validation.DateValidator
 
Classes in this File Line Coverage Branch Coverage Complexity
DateValidator
89%
44/49
100%
24/24
1.632
 
 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.DateFormat;
 20  
 import java.text.ParsePosition;
 21  
 
 22  
 import java.util.Date;
 23  
 import java.util.List;
 24  
 import java.util.ListIterator;
 25  
 
 26  
 import org.apache.commons.cli2.resource.ResourceConstants;
 27  
 import org.apache.commons.cli2.resource.ResourceHelper;
 28  
 
 29  
 /**
 30  
  * The <code>DateValidator</code> validates the argument values
 31  
  * are date or time value(s).
 32  
  *
 33  
  * The following example shows how to validate that
 34  
  * an argument value(s) is a Date of the following
 35  
  * type: d/M/yy (see {@link java.text.DateFormat}).
 36  
  *
 37  
  * <pre>
 38  
  * DateFormat date = new SimpleDateFormat("d/M/yy");
 39  
  * ...
 40  
  * ArgumentBuilder builder = new ArgumentBuilder();
 41  
  * Argument dateFormat =
 42  
  *     builder.withName("date");
 43  
  *            .withValidator(new DateValidator(dateFormat));
 44  
  * </pre>
 45  
  *
 46  
  * The following example shows how to validate that
 47  
  * an argument value(s) is a time of the following
 48  
  * type: HH:mm:ss (see {@link java.text.DateFormat}).
 49  
  *
 50  
  * <pre>
 51  
  * DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
 52  
  * ...
 53  
  * ArgumentBuilder builder = new ArgumentBuilder();
 54  
  * Argument time =
 55  
  *     builder.withName("time");
 56  
  *            .withValidator(new DateValidator(timeFormat));
 57  
  * </pre>
 58  
  *
 59  
  * @author John Keyes
 60  
  *
 61  
  * @see java.text.DateFormat
 62  
  */
 63  
 public class DateValidator implements Validator {
 64  
     /** i18n */
 65  1
     private static final ResourceHelper resources = ResourceHelper.getResourceHelper();
 66  
 
 67  
     /** an array of permitted DateFormats */
 68  
     private DateFormat[] formats;
 69  
 
 70  
     /** minimum Date allowed i.e: a valid date occurs later than this date */
 71  
     private Date minimum;
 72  
 
 73  
     /** maximum Date allowed i.e: a valid date occurs earlier than this date */
 74  
     private Date maximum;
 75  
 
 76  
     /** leniant parsing */
 77  
     private boolean isLenient;
 78  
 
 79  
     /**
 80  
      * Creates a Validator for the default date/time format
 81  
      */
 82  
     public DateValidator() {
 83  0
         this(DateFormat.getInstance());
 84  0
     }
 85  
 
 86  
     /**
 87  
      * Creates a Validator for the specified DateFormat.
 88  
      *
 89  
      * @param format
 90  
      *            a DateFormat which dates must conform to
 91  
      */
 92  12
     public DateValidator(final DateFormat format) {
 93  12
         setFormat(format);
 94  12
     }
 95  
 
 96  
     /**
 97  
      * Creates a Validator for the List of specified DateFormats.
 98  
      *
 99  
      * @param formats
 100  
      *            a List of DateFormats which dates must conform to
 101  
      */
 102  4
     public DateValidator(final List formats) {
 103  4
         setFormats(formats);
 104  4
     }
 105  
 
 106  
     /**
 107  
      * Creates a Validator for dates.
 108  
      *
 109  
      * @return DateValidator a Validator for dates
 110  
      */
 111  
     public static DateValidator getDateInstance() {
 112  1
         return new DateValidator(DateFormat.getDateInstance());
 113  
     }
 114  
 
 115  
     /**
 116  
      * Creates a Validator for times.
 117  
      *
 118  
      * @return DateValidator a Validator for times
 119  
      */
 120  
     public static DateValidator getTimeInstance() {
 121  0
         return new DateValidator(DateFormat.getTimeInstance());
 122  
     }
 123  
 
 124  
     /**
 125  
      * Creates a Validator for date/times
 126  
      *
 127  
      * @return DateValidator a Validator for date/times
 128  
      */
 129  
     public static DateValidator getDateTimeInstance() {
 130  0
         return new DateValidator(DateFormat.getDateTimeInstance());
 131  
     }
 132  
 
 133  
     /**
 134  
      * Validate each String value in the specified List against this instances
 135  
      * permitted DateFormats.
 136  
      *
 137  
      * If a value is valid then it's <code>String</code> value in the list is
 138  
      * replaced with it's <code>Date</code> value.
 139  
      *
 140  
      * @see org.apache.commons.cli2.validation.Validator#validate(java.util.List)
 141  
      */
 142  
     public void validate(final List values)
 143  
         throws InvalidArgumentException {
 144  
         // for each value
 145  12
         for (final ListIterator i = values.listIterator(); i.hasNext();) {
 146  17
             final String value = (String) i.next();
 147  
 
 148  17
             Date date = null;
 149  
 
 150  
             // create a resuable ParsePosition instance
 151  17
             final ParsePosition pp = new ParsePosition(0);
 152  
 
 153  
             // for each permitted DateFormat
 154  39
             for (int f = 0; (f < this.formats.length) && (date == null); ++f) {
 155  
                 // reset the parse position
 156  22
                 pp.setIndex(0);
 157  22
                 date = this.formats[f].parse(value, pp);
 158  
 
 159  
                 // if the wrong number of characters have been parsed
 160  22
                 if (pp.getIndex() < value.length()) {
 161  6
                     date = null;
 162  
                 }
 163  
             }
 164  
 
 165  
             // if date has not been set throw an InvalidArgumentException
 166  17
             if (date == null) {
 167  1
                 throw new InvalidArgumentException(value);
 168  
             }
 169  
 
 170  
             // if the date is outside the bounds
 171  16
             if (isDateEarlier(date) || isDateLater(date)) {
 172  2
                 throw new InvalidArgumentException(resources.getMessage(ResourceConstants.DATEVALIDATOR_DATE_OUTOFRANGE,
 173  
                                                                         value));
 174  
             }
 175  
 
 176  
             // replace the value in the list with the actual Date
 177  14
             i.set(date);
 178  14
         }
 179  9
     }
 180  
 
 181  
     /**
 182  
      * Sets whether this validator uses lenient parsing.
 183  
      *
 184  
      * @param lenient whether this validator uses lenient parsing
 185  
      */
 186  
     public void setLenient(final boolean lenient) {
 187  36
         for (int i = 0; i < this.formats.length; i++) {
 188  20
             this.formats[i].setLenient(lenient);
 189  
         }
 190  
 
 191  16
         this.isLenient = lenient;
 192  16
     }
 193  
 
 194  
     /**
 195  
      * Returns whether this validator uses lenient parsing.
 196  
      *
 197  
      * @return whether this validator uses lenient parsing
 198  
      */
 199  
     public boolean isLenient() {
 200  0
         return this.isLenient;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Returns the maximum date permitted.
 205  
      *
 206  
      * @return Date the maximum date permitted. If no maximum date has been
 207  
      *         specified then return <code>null</code>.
 208  
      */
 209  
     public Date getMaximum() {
 210  2
         return maximum;
 211  
     }
 212  
 
 213  
     /**
 214  
      * Sets the maximum Date to the specified value.
 215  
      *
 216  
      * @param maximum
 217  
      *            the maximum Date permitted
 218  
      */
 219  
     public void setMaximum(final Date maximum) {
 220  2
         this.maximum = maximum;
 221  2
     }
 222  
 
 223  
     /**
 224  
      * Returns the minimum date permitted.
 225  
      *
 226  
      * @return Date the minimum date permitted. If no minimum date has been
 227  
      *         specified then return <code>null</code>.
 228  
      */
 229  
     public Date getMinimum() {
 230  2
         return minimum;
 231  
     }
 232  
 
 233  
     /**
 234  
      * Sets the minimum Date to the specified value.
 235  
      *
 236  
      * @param minimum
 237  
      *            the minimum Date permitted
 238  
      */
 239  
     public void setMinimum(Date minimum) {
 240  2
         this.minimum = minimum;
 241  2
     }
 242  
 
 243  
     /**
 244  
      * Returns whether the specified Date is later than the maximum date.
 245  
      *
 246  
      * @param date
 247  
      *            the Date to evaluate
 248  
      *
 249  
      * @return boolean whether <code>date</code> is earlier than the maximum
 250  
      *         date
 251  
      */
 252  
     private boolean isDateLater(Date date) {
 253  15
         return (maximum != null) && (date.getTime() > maximum.getTime());
 254  
     }
 255  
 
 256  
     /**
 257  
      * Returns whether the specified Date is earlier than the minimum date.
 258  
      *
 259  
      * @param date
 260  
      *            the Date to evaluate
 261  
      *
 262  
      * @return boolean whether <code>date</code> is earlier than the minimum
 263  
      *         date
 264  
      */
 265  
     private boolean isDateEarlier(Date date) {
 266  16
         return (minimum != null) && (date.getTime() < minimum.getTime());
 267  
     }
 268  
 
 269  
     /**
 270  
      * Sets the date format permitted.
 271  
      *
 272  
      * @param format
 273  
      *              the format to use
 274  
      */
 275  
     public void setFormat(final DateFormat format) {
 276  12
         setFormats(new DateFormat[] { format });
 277  12
     }
 278  
 
 279  
     /**
 280  
      * Sets the date formats permitted.
 281  
      *
 282  
      * @param formats
 283  
      *               the List of DateFormats to use
 284  
      */
 285  
     public void setFormats(final List formats) {
 286  4
         setFormats((DateFormat[]) formats.toArray(new DateFormat[formats.size()]));
 287  4
     }
 288  
 
 289  
     /**
 290  
      * Sets the date formats permitted.
 291  
      *
 292  
      * @param formats
 293  
      *               the array of DateFormats to use
 294  
      */
 295  
     public void setFormats(final DateFormat[] formats) {
 296  16
         this.formats = formats;
 297  16
         setLenient(this.isLenient);
 298  16
     }
 299  
 
 300  
     /**
 301  
      * Gets the date formats permitted.
 302  
      *
 303  
      * @return the permitted formats
 304  
      */
 305  
     public DateFormat[] getFormats() {
 306  2
         return this.formats;
 307  
     }
 308  
 }