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' => 0 et '9' => 9, et 'A' => 1 a 'Z' => 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 }