/* * Hibernate Validator, declare and validate application constraints * * License: Apache License, Version 2.0 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>. */ package org.hibernate.validator.internal.constraintvalidators.hv; import java.util.Collections; import java.util.List; import javax.validation.ConstraintValidator; import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.Mod11Check.ProcessingDirection; import org.hibernate.validator.internal.util.ModUtil; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Mod11 Check Digit validator * * http://en.wikipedia.org/wiki/Check_digit * * @author George Gastaldi * @author Hardy Ferentschik * @author Victor Rezende dos Santos */ public class Mod11CheckValidator extends ModCheckBase implements ConstraintValidator<Mod11Check, CharSequence> { private static final Log log = LoggerFactory.make(); private boolean reverseOrder; /** * The {@code char} that represents the check digit when mod11 * checksum equals 10. */ private char treatCheck10As; /** * The {@code char} that represents the check digit when mod11 * checksum equals 10. */ private char treatCheck11As; /** * The threshold for the algorithm multiplier multiplier growth */ private int threshold; /** * An array of custom weights to be used in the sum */ private int[] customWeights; @Override public void initialize(Mod11Check constraintAnnotation) { initialize( constraintAnnotation.startIndex(), constraintAnnotation.endIndex(), constraintAnnotation.checkDigitIndex(), constraintAnnotation.ignoreNonDigitCharacters(), constraintAnnotation.threshold(), constraintAnnotation.treatCheck10As(), constraintAnnotation.treatCheck11As(), constraintAnnotation.processingDirection() ); } public void initialize( int startIndex, int endIndex, int checkDigitIndex, boolean ignoreNonDigitCharacters, int threshold, char treatCheck10As, char treatCheck11As, ProcessingDirection direction, int... customWeights ) { super.initialize( startIndex, endIndex, checkDigitIndex, ignoreNonDigitCharacters ); this.threshold = threshold; this.reverseOrder = direction == ProcessingDirection.LEFT_TO_RIGHT; this.treatCheck10As = treatCheck10As; this.treatCheck11As = treatCheck11As; this.customWeights = customWeights; if ( !Character.isLetterOrDigit( this.treatCheck10As ) ) { throw log.getTreatCheckAsIsNotADigitNorALetterException( this.treatCheck10As ); } if ( !Character.isLetterOrDigit( this.treatCheck11As ) ) { throw log.getTreatCheckAsIsNotADigitNorALetterException( this.treatCheck11As ); } } /** * Validate check digit using Mod11 checksum * * @param digits The digits over which to calculate the checksum * @param checkDigit the check digit * * @return {@code true} if the mod11 result matches the check digit, {@code false} otherwise */ @Override public boolean isCheckDigitValid(List<Integer> digits, char checkDigit) { if ( reverseOrder ) { Collections.reverse( digits ); } int modResult = ModUtil.calculateModXCheckWithWeights( digits, 11, this.threshold, customWeights ); switch ( modResult ) { case 10: return checkDigit == this.treatCheck10As; case 11: return checkDigit == this.treatCheck11As; default: return Character.isDigit( checkDigit ) && modResult == extractDigit( checkDigit ); } } }