Coverage report

  %line %branch
org.apache.commons.validator.CreditCardValidator$Discover
100% 
100% 

 1  
 /*
 2  
  * $Id: CreditCardValidator.java 366867 2006-01-07 17:55:14Z niallp $
 3  
  * $Rev: 366867 $
 4  
  * $Date: 2006-01-07 17:55:14 +0000 (Sat, 07 Jan 2006) $
 5  
  *
 6  
  * ====================================================================
 7  
  * Copyright 2001-2006 The Apache Software Foundation
 8  
  *
 9  
  * Licensed under the Apache License, Version 2.0 (the "License");
 10  
  * you may not use this file except in compliance with the License.
 11  
  * You may obtain a copy of the License at
 12  
  *
 13  
  *     http://www.apache.org/licenses/LICENSE-2.0
 14  
  *
 15  
  * Unless required by applicable law or agreed to in writing, software
 16  
  * distributed under the License is distributed on an "AS IS" BASIS,
 17  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 18  
  * See the License for the specific language governing permissions and
 19  
  * limitations under the License.
 20  
  */
 21  
 
 22  
 package org.apache.commons.validator;
 23  
 
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collection;
 26  
 import java.util.Iterator;
 27  
 
 28  
 import org.apache.commons.validator.util.Flags;
 29  
 
 30  
 /**
 31  
  * <p>Perform credit card validations.</p>
 32  
  * <p>
 33  
  * By default, all supported card types are allowed.  You can specify which 
 34  
  * cards should pass validation by configuring the validation options.  For 
 35  
  * example,<br/><code>CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.AMEX + CreditCardValidator.VISA);</code>
 36  
  * configures the validator to only pass American Express and Visa cards.
 37  
  * If a card type is not directly supported by this class, you can implement
 38  
  * the CreditCardType interface and pass an instance into the 
 39  
  * <code>addAllowedCardType</code> method.
 40  
  * </p>
 41  
  * For a similar implementation in Perl, reference Sean M. Burke's
 42  
  * <a href="http://www.speech.cs.cmu.edu/~sburke/pub/luhn_lib.html">script</a>.
 43  
  * More information is also available
 44  
  * <a href="http://www.merriampark.com/anatomycc.htm">here</a>.
 45  
  *
 46  
  * @since Validator 1.1
 47  
  */
 48  
 public class CreditCardValidator {
 49  
 
 50  
     /**
 51  
      * Option specifying that no cards are allowed.  This is useful if
 52  
      * you want only custom card types to validate so you turn off the
 53  
      * default cards with this option.
 54  
      * <br/>
 55  
      * <pre>
 56  
      * CreditCardValidator v = new CreditCardValidator(CreditCardValidator.NONE);
 57  
      * v.addAllowedCardType(customType);
 58  
      * v.isValid(aCardNumber);
 59  
      * </pre>
 60  
      * @since Validator 1.1.2
 61  
      */
 62  
     public static final int NONE = 0;
 63  
 
 64  
     /**
 65  
      * Option specifying that American Express cards are allowed.
 66  
      */
 67  
     public static final int AMEX = 1 << 0;
 68  
 
 69  
     /**
 70  
      * Option specifying that Visa cards are allowed.
 71  
      */
 72  
     public static final int VISA = 1 << 1;
 73  
 
 74  
     /**
 75  
      * Option specifying that Mastercard cards are allowed.
 76  
      */
 77  
     public static final int MASTERCARD = 1 << 2;
 78  
 
 79  
     /**
 80  
      * Option specifying that Discover cards are allowed.
 81  
      */
 82  
     public static final int DISCOVER = 1 << 3;
 83  
     
 84  
     /**
 85  
      * The CreditCardTypes that are allowed to pass validation.
 86  
      */
 87  
     private Collection cardTypes = new ArrayList();
 88  
 
 89  
     /**
 90  
      * Create a new CreditCardValidator with default options.
 91  
      */
 92  
     public CreditCardValidator() {
 93  
         this(AMEX + VISA + MASTERCARD + DISCOVER);
 94  
     }
 95  
 
 96  
     /**
 97  
      * Create a new CreditCardValidator with the specified options.
 98  
      * @param options Pass in
 99  
      * CreditCardValidator.VISA + CreditCardValidator.AMEX to specify that 
 100  
      * those are the only valid card types.
 101  
      */
 102  
     public CreditCardValidator(int options) {
 103  
         super();
 104  
 
 105  
         Flags f = new Flags(options);
 106  
         if (f.isOn(VISA)) {
 107  
             this.cardTypes.add(new Visa());
 108  
         }
 109  
 
 110  
         if (f.isOn(AMEX)) {
 111  
             this.cardTypes.add(new Amex());
 112  
         }
 113  
 
 114  
         if (f.isOn(MASTERCARD)) {
 115  
             this.cardTypes.add(new Mastercard());
 116  
         }
 117  
 
 118  
         if (f.isOn(DISCOVER)) {
 119  
             this.cardTypes.add(new Discover());
 120  
         }
 121  
     }
 122  
 
 123  
     /**
 124  
      * Checks if the field is a valid credit card number.
 125  
      * @param card The card number to validate.
 126  
      * @return Whether the card number is valid.
 127  
      */
 128  
     public boolean isValid(String card) {
 129  
         if ((card == null) || (card.length() < 13) || (card.length() > 19)) {
 130  
             return false;
 131  
         }
 132  
 
 133  
         if (!this.luhnCheck(card)) {
 134  
             return false;
 135  
         }
 136  
         
 137  
         Iterator types = this.cardTypes.iterator();
 138  
         while (types.hasNext()) {
 139  
             CreditCardType type = (CreditCardType) types.next();
 140  
             if (type.matches(card)) {
 141  
                 return true;
 142  
             }
 143  
         }
 144  
 
 145  
         return false;
 146  
     }
 147  
     
 148  
     /**
 149  
      * Add an allowed CreditCardType that participates in the card 
 150  
      * validation algorithm.
 151  
      * @param type The type that is now allowed to pass validation.
 152  
      * @since Validator 1.1.2
 153  
      */
 154  
     public void addAllowedCardType(CreditCardType type){
 155  
         this.cardTypes.add(type);
 156  
     }
 157  
 
 158  
     /**
 159  
      * Checks for a valid credit card number.
 160  
      * @param cardNumber Credit Card Number.
 161  
      * @return Whether the card number passes the luhnCheck.
 162  
      */
 163  
     protected boolean luhnCheck(String cardNumber) {
 164  
         // number must be validated as 0..9 numeric first!!
 165  
         int digits = cardNumber.length();
 166  
         int oddOrEven = digits & 1;
 167  
         long sum = 0;
 168  
         for (int count = 0; count < digits; count++) {
 169  
             int digit = 0;
 170  
             try {
 171  
                 digit = Integer.parseInt(cardNumber.charAt(count) + "");
 172  
             } catch(NumberFormatException e) {
 173  
                 return false;
 174  
             }
 175  
 
 176  
             if (((count & 1) ^ oddOrEven) == 0) { // not
 177  
                 digit *= 2;
 178  
                 if (digit > 9) {
 179  
                     digit -= 9;
 180  
                 }
 181  
             }
 182  
             sum += digit;
 183  
         }
 184  
 
 185  
         return (sum == 0) ? false : (sum % 10 == 0);
 186  
     }
 187  
     
 188  
     /**
 189  
      * CreditCardType implementations define how validation is performed
 190  
      * for one type/brand of credit card.
 191  
      * @since Validator 1.1.2
 192  
      */
 193  
     public interface CreditCardType {
 194  
         
 195  
         /**
 196  
          * Returns true if the card number matches this type of credit
 197  
          * card.  Note that this method is <strong>not</strong> responsible
 198  
          * for analyzing the general form of the card number because 
 199  
          * <code>CreditCardValidator</code> performs those checks before 
 200  
          * calling this method.  It is generally only required to valid the
 201  
          * length and prefix of the number to determine if it's the correct 
 202  
          * type. 
 203  
          * @param card The card number, never null.
 204  
          * @return true if the number matches.
 205  
          */
 206  
         boolean matches(String card);
 207  
         
 208  
     }
 209  
     
 210  
     /**
 211  
      *  Change to support Visa Carte Blue used in France
 212  
      *  has been removed - see Bug 35926
 213  
      */
 214  
     private class Visa implements CreditCardType {
 215  
         private static final String PREFIX = "4";
 216  
         public boolean matches(String card) {
 217  
             return (
 218  
                 card.substring(0, 1).equals(PREFIX)
 219  
                     && (card.length() == 13 || card.length() == 16));
 220  
         }
 221  
     }
 222  
             
 223  
     private class Amex implements CreditCardType {
 224  
         private static final String PREFIX = "34,37,";
 225  
         public boolean matches(String card) {
 226  
             String prefix2 = card.substring(0, 2) + ",";
 227  
             return ((PREFIX.indexOf(prefix2) != -1) && (card.length() == 15));
 228  
         }
 229  
     }
 230  
     
 231  32
     private class Discover implements CreditCardType {
 232  
         private static final String PREFIX = "6011";
 233  
         public boolean matches(String card) {
 234  1
             return (card.substring(0, 4).equals(PREFIX) && (card.length() == 16));
 235  
         }
 236  
     }
 237  
     
 238  
     private class Mastercard implements CreditCardType {
 239  
         private static final String PREFIX = "51,52,53,54,55,";
 240  
         public boolean matches(String card) {
 241  
             String prefix2 = card.substring(0, 2) + ",";
 242  
             return ((PREFIX.indexOf(prefix2) != -1) && (card.length() == 16));
 243  
         }
 244  
     }
 245  
 
 246  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.