View Javadoc
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.validator.routines.checkdigit;
18  
19  import java.io.BufferedReader;
20  import java.io.InputStreamReader;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import junit.framework.Assert;
25  
26  
27  /**
28   * EAN-13 Check Digit Test.
29   *
30   * @version $Revision: 1562801 $
31   * @since Validator 1.4
32   */
33  public class IBANCheckDigitTest extends AbstractCheckDigitTest {
34  
35      /**
36       * Constructor
37       * @param name test name
38       */
39      public IBANCheckDigitTest(String name) {
40          super(name);
41          checkDigitLth = 2;
42      }
43  
44      /**
45       * Set up routine & valid codes.
46       */
47      protected void setUp() throws Exception {
48          super.setUp();
49          routine = IBANCheckDigit.IBAN_CHECK_DIGIT;
50          valid  = new String[]  {
51                  "AD1200012030200359100100",      // Andorra
52                  "AT611904300234573201",          // Austria
53                  "BE62510007547061",              // Belgium
54                  "BE68539007547034",              // Belgium
55                  "CH3900700115201849173",         // Switzerland
56                  "CH9300762011623852957",         // Switzerland
57                  "CY17002001280000001200527600",  // Cyprus
58                  "CZ6508000000192000145399",      // Czechoslovakia
59                  "DE89370400440532013000",        // Germany
60                  "DK5000400440116243",            // Denmark
61                  "EE382200221020145685",          // Estonia
62                  "ES8023100001180000012345",      // Spain
63                  "FI2112345600000785",            // Finland
64                  "FR1420041010050500013M02606",   // France
65                  "GB29NWBK60161331926819",        // UK
66                  "GI75NWBK000000007099453",       // Gibraltar
67                  "GR1601101250000000012300695",   // Greece
68                  "HU42117730161111101800000000",  // Hungary
69                  "IE29AIBK93115212345678",        // Ireland
70                  "IS140159260076545510730339",    // Iceland
71                  "IT60X0542811101000000123456",   // Italy
72                  "LT121000011101001000",          // Lithuania
73                  "LU280019400644750000",          // Luxembourg
74                  "LV80BANK0000435195001",         // Latvia
75                  "MT84MALT011000012345MTLCAST001S",// Malta
76                  "NL39RABO0300065264",            // Netherlands
77                  "NL91ABNA0417164300",            // Netherlands
78                  "NO9386011117947",               // Norway
79                  "PL27114020040000300201355387",  // Poland
80                  "PL60102010260000042270201111",  // Poland
81                  "PT50000201231234567890154",     // Portugal
82                  "SE3550000000054910000003",      // Sweden
83                  "SI56191000000123438",           // Slovenia
84                  "SK3112000000198742637541",      // Slovak Republic
85                  
86                  // Codes AA and ZZ will never be used as ISO countries nor in IBANs
87                  // add some dummy calculated codes to test the limits
88                  // Current minimum length is Norway = 15
89                  // Current maximum length is Malta  = 31
90                  // N.B. These codes will fail online checkers which validate the IBAN format
91                  //234567890123456789012345678901
92                  "AA0200000000053",
93                  "AA9700000000089",
94                  "AA9800000000071",
95                  "ZZ02ZZZZZZZZZZZZZZZZZZZZZZZZZ04",
96                  "ZZ97ZZZZZZZZZZZZZZZZZZZZZZZZZ40",
97                  "ZZ98ZZZZZZZZZZZZZZZZZZZZZZZZZ22",
98                  };
99          /*
100          *  sources
101          *  https://intranet.birmingham.ac.uk/finance/documents/public/IBAN.pdf
102          *  http://www.paymentscouncil.org.uk/resources_and_publications/ibans_in_europe/
103          */
104         invalid = new String[] {"510007+47061BE63"};
105         zeroSum = null;
106         missingMessage = "Invalid Code length=0";
107 
108     }
109 
110     /**
111      * Test zero sum
112      */
113     public void testZeroSum() {
114         // ignore, don't run this test
115         
116         // example code used to create dummy IBANs
117 //        try {
118 //            for(int i=0; i<97;i++) {
119 //                String check = String.format("ZZ00ZZZZZZZZZZZZZZZZZZZZZZZZZ%02d", new Object[]{Integer.valueOf(i)});
120 //                String chk = routine.calculate(check);
121 //                if (chk.equals("97")||chk.equals("98")||chk.equals("02")) {
122 //                    System.out.println(check+ " "+chk);
123 //                }
124 //            }
125 //        } catch (CheckDigitException e) {
126 //            e.printStackTrace();
127 //        }
128     }
129 
130     /**
131      * Returns an array of codes with invalid check digits.
132      *
133      * @param codes Codes with valid check digits
134      * @return Codes with invalid check digits
135      */
136     protected String[] createInvalidCodes(String[] codes) {
137         List list = new ArrayList();
138 
139         // create invalid check digit values
140         for (int i = 0; i < codes.length; i++) {
141             String code = removeCheckDigit(codes[i]);
142             String check  = checkDigit(codes[i]);
143             for (int j = 2; j <= 98; j++) { // check digits can be from 02-98 (00 and 01 are not possible)
144                 String curr =  j > 9 ? "" + j : "0" + j;
145                 if (!curr.equals(check)) {
146                     list.add(code.substring(0, 2) + curr + code.substring(4));
147                 }
148             }
149         }
150         
151         return (String[])list.toArray(new String[list.size()]);
152     }
153 
154     /**
155      * Returns a code with the Check Digit (i.e. last character) removed.
156      *
157      * @param code The code
158      * @return The code without the check digit
159      */
160     protected String removeCheckDigit(String code) {
161         return code.substring(0, 2) + "00" + code.substring(4);
162     }
163 
164     /**
165      * Returns the check digit (i.e. last character) for a code.
166      *
167      * @param code The code
168      * @return The check digit
169      */
170     protected String checkDigit(String code) {
171         if (code == null || code.length() <= checkDigitLth) {
172             return "";
173         }
174        return code.substring(2, 4);
175     }
176 
177     public void testOther() throws Exception {
178         BufferedReader rdr = null;
179         try {
180             rdr = new BufferedReader(
181                     new InputStreamReader(
182                             this.getClass().getResourceAsStream("IBANtests.txt"),"ASCII"));
183             String line;
184             while((line=rdr.readLine()) != null) {
185                 if (!line.startsWith("#") && line.length() > 0) {
186                     Assert.assertTrue(line, routine.isValid(line.replace(" ", "")));
187                 }
188             }
189         } finally {
190             if (rdr != null) {
191                 rdr.close();
192             }
193         }
194     }
195 }