View Javadoc
1   package org.nuiton.validator.xwork2.field;
2   
3   /*
4    * #%L
5    * Nuiton Validator
6    * %%
7    * Copyright (C) 2013 - 2014 Code Lutin, Tony Chemit
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as 
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Util tool for Field validator.
27   *
28   * @author Sylvain Bavencoff - bavencoff@codelutin.com
29   * @since 3.0
30   */
31  public class FieldValidatorUtil {
32  
33      /**
34       * Verifie la validite d'un numero en suivant l'algorithme Luhn tel que d'ecrit
35       * dans <a href="http://fr.wikipedia.org/wiki/Luhn">wikipedia</a>
36       *
37       * Algo:
38       * en fonction de la position du numero dans la sequence,
39       * on multiplie pas 1 (pour les impaires) ou par 2 pour les paires
40       * (1 etant le numero le plus a droite)
41       * On fait la somme de tous les chiffres qui resulte de ces multiplications
42       * (si un resultat etait 14, on ne fait pas +14 mais +1+4)
43       *
44       * Si le résultat de cette somme donne un reste de 0 une fois divisé par 10
45       * le numero est valide.
46       *
47       * @param value une chaine composer que de chiffre
48       * @return vrai si on a reussi a valider le numero
49       */
50      public static boolean luhnChecksum(String value) {
51  
52          char[] tab = value.toCharArray();
53          int sum = 0;
54  
55          // on multiple alternativement par 1 ou par 2 les chiffres
56          // sachant que le chiffre le plus à droite est multiplié par 1
57  
58          // l'offset permet de savoir si le premier chiffre( le plus a gauche) doit etre
59          // multiplier par 1 ( offset = 0)
60          // multiplier par 2 (offset = 1)
61          int offset = (tab.length + 1) % 2;
62  
63  
64          for (int i = 0; i < tab.length; i++) {
65  
66              // recuperation de la valeur
67              int n = getDigit(tab[i]);
68  
69              // multiplication par 1 ou 2 en fonction de l'index et de l'offset
70              n *= (i + offset) % 2 + 1;
71  
72              // si une fois multiplie il est superieur a 9, il faut additionner
73              // toutes ces constituante, mais comme il ne peut pas etre superieur
74              // a 18, cela revient a retrancher 9
75              if (n > 9) {
76                  n -= 9;
77              }
78  
79              // on peut directement faire la somme
80              sum += n;
81          }
82  
83          // 3eme phase on verifie que c'est bien un multiple de 10
84          boolean result = sum % 10 == 0;
85  
86          return result;
87      }
88  
89  
90      /**
91       * Converti un char en un entier '0' =&gt; 0 et '9' =&gt; 9, et 'A' =&gt; 1 a 'Z' =&gt; 36,
92       * les autres caractere sont aussi convertis pour que
93       * A|B|C|D|E|F|G|H|I|J
94       * K|L|M|N|O|P|Q|R|S|T
95       * U|V|W|X|Y|Z| | | |
96       * -+-+-+-+-+-+-+-+-+
97       * 1|2|3|4|5|6|7|8|9|0.
98       * Pour les autres c'est un indedermine
99       *
100      * @param c le caractere qui doit etre converti
101      * @return le chiffre
102      */
103     public static int getDigit(char c) {
104         int result = 0;
105         if (c >= '0' && c <= '9') {
106             result = c - '0';
107         } else if (c >= 'A' && c <= 'Z') {
108             result = (c - 'A' + 1) % 10;
109         } else {
110             result = (c - 'a' + 1) % 10;
111         }
112         return result;
113     }
114 }