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 }