r2171 - in trunk/nuiton-validator/src: main/java/org/nuiton/validator/xwork2/field test/java/org/nuiton/validator/xwork2/field
Author: bpoussin Date: 2011-08-19 17:56:03 +0200 (Fri, 19 Aug 2011) New Revision: 2171 Url: http://nuiton.org/repositories/revision/nuiton-utils/2171 Log: Evolution #1686: Add new standard validators - SIRET can be in other format that String (int, long, array, collection, ...) - use Luhn checksum for SIRET Modified: trunk/nuiton-validator/src/main/java/org/nuiton/validator/xwork2/field/SiretFieldValidator.java trunk/nuiton-validator/src/test/java/org/nuiton/validator/xwork2/field/SiretFieldValidatorTest.java Modified: trunk/nuiton-validator/src/main/java/org/nuiton/validator/xwork2/field/SiretFieldValidator.java =================================================================== --- trunk/nuiton-validator/src/main/java/org/nuiton/validator/xwork2/field/SiretFieldValidator.java 2011-08-19 13:18:58 UTC (rev 2170) +++ trunk/nuiton-validator/src/main/java/org/nuiton/validator/xwork2/field/SiretFieldValidator.java 2011-08-19 15:56:03 UTC (rev 2171) @@ -26,19 +26,26 @@ import com.opensymphony.xwork2.validator.ValidationException; import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; +import java.lang.reflect.Array; +import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Validator for French SIRET numbers + * + * Siret can be in: + * <li>String format: "44211670300038" + * <li>long, int: 44211670300038 + * <li>Array or Collection of something: [4,4,2,1,1,6,7,0,,3,0,0,0,3,8] or ["442","116","703", "0003", "8"] + * + * Validation do the Luhn checksum too */ public class SiretFieldValidator extends FieldValidatorSupport { - protected static String LAST_NAME_REGEXP = "[0-9]{14}"; - protected static Pattern p = Pattern.compile(LAST_NAME_REGEXP); + protected static final String SIRET_REGEXP = "[0-9]{14}"; + protected static final Pattern p = Pattern.compile(SIRET_REGEXP); - //TODO JC-19082011- Need to validate the numbers too cf: http://fr.wikipedia.org/wiki/SIRET - @Override public void validate(Object object) throws ValidationException { @@ -49,15 +56,30 @@ // no value defined return; } - if (value instanceof String) { - Matcher m = p.matcher((String) value); - if (!m.matches()) { - addFieldError(fieldName, object); - return; + String siret; + + if (value.getClass().isArray()) { + // le siret est stocker dans un tableau, par exemple un byte[] + siret = ""; + for (int i=0; i<Array.getLength(value); i++) { + siret += String.valueOf(Array.get(value, i)); } + } else if (value instanceof Collection) { + // le siret est stocker dans une collection, + // ca doit pas arriver souvent :D, mais autant le gerer + siret = ""; + for (Object o : (Collection)value) { + siret += String.valueOf(o); + } } else { + // sinon dans tous les autres cas (String, int, long, BigInteger ...) + // on prend le toString + siret = String.valueOf(value); + } + + Matcher m = p.matcher(siret); + if (!m.matches() || !luhnChecksum(siret)) { addFieldError(fieldName, object); - return; } } @@ -65,4 +87,66 @@ public String getValidatorType() { return "siret"; } + + /** + * Verifie la validite d'un numero en suivant l'algorithme Luhn tel que d'ecrit + * dans <a href="http://fr.wikipedia.org/wiki/Luhn">wikipedia</a> + * + * Algo: + * en fonction de la position du numero dans la sequence, + * on multiplie pas 1 (pour les impaires) ou par 2 pour les paires + * (1 etant le numero le plus a droite) + * On fait la somme de tous les chiffres qui resulte de ces multiplications + * (si un resultat etait 14, on ne fait pas +14 mais +1+4) + * + * Si le résultat de cette somme donne un reste de 0 une fois divisé par 10 + * le numero est valide. + * + * @param siret une chaine composer que de chiffre + * @return vrai si on a reussi a valider le numero + */ + static public boolean luhnChecksum(String siret) { + // variable intermediaire pour stocker le resultat de la 1ere multiplication + // on restocke dans une chaine, car il faut additionner les composantes + // des nombres et non pas les nombres eux meme. + String tmp = ""; + for (int i=siret.length()-1; i>=0; i--) { + int n = getDigit(siret, i); + // il faut faire x1 pour les paires et x2 sur les impaires. + // en prenant en compte que le numero siret le plus a droite est le + // 1 et le plus a gauche le 14. + // mais comme en informatique on commence a 0 :D + // il faut faire +1 sur l'indice puis un simple module 2 + 1 + // nous convient + n *= (i+1)%2+1; + tmp = n + tmp; + } + + // 2eme phase on additionne tous les chiffres + int sum = 0; + for (int i=0; i<tmp.length(); i++) { + int n = getDigit(tmp, i); + sum += n; + } + + // 3eme phase on verifie que c'est bien un multiple de 10 + boolean result = (sum % 10 == 0); + + return result; + } + + + /** + * Recupere un des chiffres de la string qui ne contient que des chiffres + * + * @param s une chaine ne contenant que des chiffres ex: 1234455688 + * @param indice la position du chiffre a recuperer, l'indice doit etre entre + * 0 et s.length()-1 + * @return le chiffre + */ + static public int getDigit(String s, int indice) { + String d = s.substring(indice, indice+1); + int result = Integer.parseInt(d); + return result; + } } Modified: trunk/nuiton-validator/src/test/java/org/nuiton/validator/xwork2/field/SiretFieldValidatorTest.java =================================================================== --- trunk/nuiton-validator/src/test/java/org/nuiton/validator/xwork2/field/SiretFieldValidatorTest.java 2011-08-19 13:18:58 UTC (rev 2170) +++ trunk/nuiton-validator/src/test/java/org/nuiton/validator/xwork2/field/SiretFieldValidatorTest.java 2011-08-19 15:56:03 UTC (rev 2171) @@ -38,6 +38,18 @@ } @Test + public void TestLuhnChecksum () throws Exception { + // verification sur de vrai numero siret (ca doit passer :) + assertTrue(SiretFieldValidator.luhnChecksum("44211670300038")); + assertTrue(SiretFieldValidator.luhnChecksum("73282932000074")); + + // verification avec les memes, en ne modifiant que le dernier chiffre + // ca doit failer + assertFalse(SiretFieldValidator.luhnChecksum("44211670300030")); + assertFalse(SiretFieldValidator.luhnChecksum("73282932000070")); + } + + @Test @Override public void testValidator() throws Exception { @@ -48,6 +60,16 @@ assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", false); + // Valid siret + bean.setSiret("73282932000074"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + // Not Valid siret, because bad checksum + bean.setSiret("73282932000071"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + true); + // Not valid siret bean.setSiret("4421167030003"); assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format",
participants (1)
-
bpoussin@users.nuiton.org