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 org.junit.Assert;
25  import org.junit.jupiter.api.BeforeEach;
26  import org.junit.jupiter.api.Test;
27  
28  /**
29   * IBAN Check Digit Test.
30   */
31  public class IBANCheckDigitTest extends AbstractCheckDigitTest {
32  
33      public IBANCheckDigitTest() {
34          checkDigitLth = 2;
35      }
36  
37      /**
38       * Returns the check digit (i.e. last character) for a code.
39       *
40       * @param code The code
41       * @return The check digit
42       */
43      @Override
44      protected String checkDigit(final String code) {
45          if (code == null || code.length() <= checkDigitLth) {
46              return "";
47          }
48          return code.substring(2, 4);
49      }
50  
51      /**
52       * Returns an array of codes with invalid check digits.
53       *
54       * @param codes Codes with valid check digits
55       * @return Codes with invalid check digits
56       */
57      @Override
58      protected String[] createInvalidCodes(final String[] codes) {
59          final List<String> list = new ArrayList<>();
60  
61          // create invalid check digit values
62          for (final String code2 : codes) {
63              final String code = removeCheckDigit(code2);
64              final String check = checkDigit(code2);
65              for (int j = 2; j <= 98; j++) { // check digits can be from 02-98 (00 and 01 are not possible)
66                  final String curr = j > 9 ? "" + j : "0" + j;
67                  if (!curr.equals(check)) {
68                      list.add(code.substring(0, 2) + curr + code.substring(4));
69                  }
70              }
71          }
72  
73          return list.toArray(new String[0]);
74      }
75  
76      /**
77       * Returns a code with the Check Digits (i.e. characters 3&4) set to "00".
78       *
79       * @param code The code
80       * @return The code with the zeroed check digits
81       */
82      @Override
83      protected String removeCheckDigit(final String code) {
84          return code.substring(0, 2) + "00" + code.substring(4);
85      }
86  
87      /**
88       * Sets up routine & valid codes.
89       */
90      @BeforeEach
91      protected void setUp() {
92          routine = IBANCheckDigit.IBAN_CHECK_DIGIT;
93          valid = new String[] { "AD1200012030200359100100", // Andorra
94                  "AE070331234567890123456", // United Arab Emirates
95                  "AL47212110090000000235698741", // Albania
96                  "AT611904300234573201", // Austria
97                  "AZ21NABZ00000000137010001944", // Azerbaijan
98                  "BA391290079401028494", // Bosnia and Herzegovina
99                  "BE62510007547061", // Belgium
100                 "BE68539007547034", // Belgium
101                 "BG80BNBG96611020345678", // Bulgaria
102                 "BH67BMAG00001299123456", // Bahrain
103                 "BI4210000100010000332045181", // Burundi
104                 "BR1800000000141455123924100C2", // Brazil
105                 "BY13NBRB3600900000002Z00AB00", // Belarus
106                 "CH3900700115201849173", // Switzerland
107                 "CH9300762011623852957", // Switzerland
108                 "CR05015202001026284066", // Costa Rica
109                 "CY17002001280000001200527600", // Cyprus
110                 "CZ6508000000192000145399", // Czechoslovakia
111                 "DE89370400440532013000", // Germany
112                 "DJ2110002010010409943020008", // Djibouti
113                 "DK5000400440116243", // Denmark
114                 "DO28BAGR00000001212453611324", // Dominican Republic
115                 "EE382200221020145685", // Estonia
116                 "ES8023100001180000012345", // Spain
117                 "FI2112345600000785", // Finland
118                 "FO6264600001631634", // Denmark (Faroes)
119                 "FR1420041010050500013M02606", // France
120                 "GB29NWBK60161331926819", // UK
121                 "GI75NWBK000000007099453", // Gibraltar
122                 "GL8964710001000206", // Denmark (Greenland)
123                 "GR1601101250000000012300695", // Greece
124                 "GT82TRAJ01020000001210029690", // Guatemala
125                 "HR1210010051863000160", // Croatia
126                 "HU42117730161111101800000000", // Hungary
127                 "IE29AIBK93115212345678", // Ireland
128                 "IL620108000000099999999", // Israel
129                 "IQ98NBIQ850123456789012", // Iraq
130                 "IS140159260076545510730339", // Iceland
131                 "IT60X0542811101000000123456", // Italy
132                 "JO94CBJO0010000000000131000302", // Jordan
133                 "KW81CBKU0000000000001234560101", // Kuwait
134                 "KZ86125KZT5004100100", // Kazakhstan
135                 "LB62099900000001001901229114", // Lebanon
136                 "LC55HEMM000100010012001200023015", // Saint Lucia
137                 "LI21088100002324013AA", // Liechtenstein (Principality of)
138                 "LT121000011101001000", // Lithuania
139                 "LU280019400644750000", // Luxembourg
140                 "LV80BANK0000435195001", // Latvia
141                 "MC5811222000010123456789030", // Monaco
142                 "MD24AG000225100013104168", // Moldova
143                 "ME25505000012345678951", // Montenegro
144                 "MK07250120000058984", // Macedonia, Former Yugoslav Republic of
145                 "MR1300020001010000123456753", // Mauritania
146                 "MT84MALT011000012345MTLCAST001S", // Malta
147                 "MU17BOMM0101101030300200000MUR", // Mauritius
148                 "NL39RABO0300065264", // Netherlands
149                 "NL91ABNA0417164300", // Netherlands
150                 "NO9386011117947", // Norway
151                 "PK36SCBL0000001123456702", // Pakistan
152                 "PL27114020040000300201355387", // Poland
153                 "PL60102010260000042270201111", // Poland
154                 "PS92PALS000000000400123456702", // Palestine, State of
155                 "PT50000201231234567890154", // Portugal
156                 "QA58DOHB00001234567890ABCDEFG", // Qatar
157                 "RO49AAAA1B31007593840000", // Romania
158                 "RS35260005601001611379", // Serbia
159                 "RU0204452560040702810412345678901", // Russia
160                 "SA0380000000608010167519", // Saudi Arabia
161                 "SC18SSCB11010000000000001497USD", // Seychelles
162                 "SD8811123456789012", // Sudan
163                 "SE3550000000054910000003", // Sweden
164                 "SD2129010501234001", // Sudan
165                 "SI56191000000123438", // Slovenia
166                 "SK3112000000198742637541", // Slovak Republic
167                 "SM86U0322509800000000270100", // San Marino
168                 "ST68000100010051845310112", // Sao Tome and Principe
169                 "SV62CENR00000000000000700025", // El Salvador
170                 "TL380080012345678910157", // Timor-Leste
171                 "TN5910006035183598478831", // Tunisia
172                 "TR330006100519786457841326", // Turkey
173                 "UA213223130000026007233566001", // Ukraine
174                 "VA59001123000012345678", // Vatican City State
175                 "VG96VPVG0000012345678901", // Virgin Islands, British
176                 "XK051212012345678906", // Republic of Kosovo
177 
178                 // Codes AA and ZZ will never be used as ISO countries nor in IBANs
179                 // add some dummy calculated codes to test the limits
180                 // Current minimum length is Norway = 15
181                 // Current maximum length is Malta = 31
182                 // N.B. These codes will fail online checkers which validate the IBAN format
183                 // 234567890123456789012345678901
184                 "AA0200000000053", "AA9700000000089", "AA9800000000071", "ZZ02ZZZZZZZZZZZZZZZZZZZZZZZZZ04", "ZZ97ZZZZZZZZZZZZZZZZZZZZZZZZZ40",
185                 "ZZ98ZZZZZZZZZZZZZZZZZZZZZZZZZ22", };
186         /*
187          * sources https://intranet.birmingham.ac.uk/finance/documents/public/IBAN.pdf
188          * http://www.paymentscouncil.org.uk/resources_and_publications/ibans_in_europe/
189          */
190         invalid = new String[] { "510007+47061BE63", "IE01AIBK93118702569045", "AA0000000000089", "AA9900000000053", };
191         zeroSum = null;
192         missingMessage = "Invalid Code length=0";
193 
194     }
195 
196     @Test
197     public void testOther() throws Exception {
198         try (BufferedReader rdr = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("IBANtests.txt"), "ASCII"))) {
199             String line;
200             while ((line = rdr.readLine()) != null) {
201                 if (!line.startsWith("#") && !line.isEmpty()) {
202                     if (line.startsWith("-")) {
203                         line = line.substring(1);
204                         Assert.assertFalse(line, routine.isValid(line.replace(" ", "")));
205                     } else {
206                         Assert.assertTrue(line, routine.isValid(line.replace(" ", "")));
207                     }
208                 }
209             }
210         }
211     }
212 
213     /**
214      * Test zero sum
215      */
216     @Override
217     @Test
218     public void testZeroSum() {
219         // ignore, don't run this test
220 
221         // example code used to create dummy IBANs
222 //        try {
223 //            for(int i=0; i<97;i++) {
224 //                String check = String.format("ZZ00ZZZZZZZZZZZZZZZZZZZZZZZZZ%02d", new Object[]{Integer.valueOf(i)});
225 //                String chk = routine.calculate(check);
226 //                if (chk.equals("97")||chk.equals("98")||chk.equals("02")) {
227 //                    System.out.println(check+ " "+chk);
228 //                }
229 //            }
230 //        } catch (CheckDigitException e) {
231 //            e.printStackTrace();
232 //        }
233     }
234 }