-
Notifications
You must be signed in to change notification settings - Fork 573
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HV-1822 add russian specific INN annotation
- Loading branch information
1 parent
3304647
commit d8c8faa
Showing
28 changed files
with
525 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
engine/src/main/java/org/hibernate/validator/cfg/defs/ru/INNDef.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* 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.cfg.defs.ru; | ||
|
||
import org.hibernate.validator.cfg.ConstraintDef; | ||
import org.hibernate.validator.constraints.ru.INN; | ||
|
||
/** | ||
* @author Artem Boiarshinov | ||
*/ | ||
public class INNDef extends ConstraintDef<INNDef, INN> { | ||
|
||
public INNDef() { | ||
super( INN.class ); | ||
} | ||
|
||
public INNDef type(INN.Type type) { | ||
addParameter( "type", type ); | ||
return this; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
engine/src/main/java/org/hibernate/validator/cfg/defs/ru/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* 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>. | ||
*/ | ||
|
||
/** | ||
* <p>Russian specific constraint definition classes for programmatic constraint definition API.</p> | ||
* <p>This package is part of the public Hibernate Validator API.</p> | ||
*/ | ||
|
||
package org.hibernate.validator.cfg.defs.ru; |
76 changes: 76 additions & 0 deletions
76
engine/src/main/java/org/hibernate/validator/constraints/ru/INN.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* 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.constraints.ru; | ||
|
||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE; | ||
import static java.lang.annotation.ElementType.CONSTRUCTOR; | ||
import static java.lang.annotation.ElementType.FIELD; | ||
import static java.lang.annotation.ElementType.METHOD; | ||
import static java.lang.annotation.ElementType.PARAMETER; | ||
import static java.lang.annotation.ElementType.TYPE_USE; | ||
import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.Target; | ||
|
||
import javax.validation.Constraint; | ||
import javax.validation.Payload; | ||
import javax.validation.ReportAsSingleViolation; | ||
|
||
import org.hibernate.validator.constraints.ru.INN.List; | ||
|
||
/** | ||
* Checks that the annotated character sequence is a valid russian taxpayer | ||
* identification number (INN in russian transliteration). | ||
* | ||
* @author Artem Boiarshinov | ||
* @see <a href="https://www.nalog.ru/rn77/fl/interest/inn/">russian taxpayer identification number</a> | ||
*/ | ||
@Documented | ||
@Constraint(validatedBy = {}) | ||
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) | ||
@Retention(RUNTIME) | ||
@Repeatable(List.class) | ||
@ReportAsSingleViolation | ||
public @interface INN { | ||
|
||
String message() default "{org.hibernate.validator.constraints.ru.INN.message}"; | ||
|
||
Class<?>[] groups() default {}; | ||
|
||
Class<? extends Payload>[] payload() default {}; | ||
|
||
Type type() default Type.ANY; | ||
|
||
/** | ||
* Defines several {@code @INN} annotations on the same element. | ||
*/ | ||
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) | ||
@Retention(RUNTIME) | ||
@Documented | ||
public @interface List { | ||
|
||
INN[] value(); | ||
} | ||
|
||
/** | ||
* Defines the INN length. Valid lengths of INN are {@code 12} for individual usage | ||
* and {@code 10} for juridical which are represented as {@link INN.Type#INDIVIDUAL} | ||
* and {@link INN.Type#JURIDICAL} respectively. | ||
* <p> | ||
* Using {@link INN.Type#ANY} allows to validate values that could either be personal | ||
* or juridical. | ||
* In such case, INN type would be determined by the length of the corresponding value. | ||
*/ | ||
enum Type { | ||
INDIVIDUAL, | ||
JURIDICAL, | ||
ANY | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
engine/src/main/java/org/hibernate/validator/constraints/ru/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* 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>. | ||
*/ | ||
|
||
/** | ||
* <p>Hibernate Validator Russian constraints.</p> | ||
* <p>This package is part of the public Hibernate Validator API.</p> | ||
*/ | ||
package org.hibernate.validator.constraints.ru; |
157 changes: 157 additions & 0 deletions
157
...c/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ru/INNValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* 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.ru; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
import org.hibernate.validator.constraints.ru.INN; | ||
import org.hibernate.validator.internal.util.Contracts; | ||
|
||
import javax.validation.ConstraintValidator; | ||
import javax.validation.ConstraintValidatorContext; | ||
|
||
/** | ||
* Checks that a given character sequence (e.g. string) is a valid INN. | ||
* | ||
* @author Artem Boiarshinov | ||
*/ | ||
public class INNValidator implements ConstraintValidator<INN, CharSequence> { | ||
|
||
private static final Pattern NUMBERS_ONLY_PATTERN = Pattern.compile( "[0-9]+" ); | ||
private static final int RADIX = 10; | ||
|
||
private INNValidationAlgorithm innValidationAlgorithm; | ||
|
||
@Override | ||
public void initialize(INN constraintAnnotation) { | ||
this.innValidationAlgorithm = INNValidationAlgorithm.from( constraintAnnotation.type() ); | ||
} | ||
|
||
@Override | ||
public boolean isValid(CharSequence innCharSeq, ConstraintValidatorContext context) { | ||
if ( innCharSeq == null ) { | ||
return true; | ||
} | ||
|
||
final String inn = innCharSeq.toString(); | ||
|
||
final boolean hasOnlyNumbers = NUMBERS_ONLY_PATTERN.matcher( inn ).matches(); | ||
if ( !hasOnlyNumbers ) { | ||
return false; | ||
} | ||
|
||
if ( !innValidationAlgorithm.isValidLength( inn.length() ) ) { | ||
return false; | ||
} | ||
|
||
final int[] digits = inn.codePoints().map( symbol -> Character.digit( symbol, RADIX ) ).toArray(); | ||
|
||
return innValidationAlgorithm.isValidChecksum( digits ); | ||
|
||
} | ||
|
||
private interface INNValidationAlgorithm { | ||
boolean isValidLength(int length); | ||
|
||
boolean isValidChecksum(int[] digits); | ||
|
||
static INNValidationAlgorithm from(org.hibernate.validator.constraints.ru.INN.Type type) { | ||
Contracts.assertNotNull( type ); | ||
switch ( type ) { | ||
case JURIDICAL: | ||
return INNValidationAlgorithmImpl.JURIDICAL; | ||
case INDIVIDUAL: | ||
return INNValidationAlgorithmImpl.INDIVIDUAL; | ||
case ANY: | ||
default: | ||
return INNValidationAlgorithmImpl.ANY; | ||
} | ||
} | ||
} | ||
|
||
private enum INNValidationAlgorithmImpl implements INNValidationAlgorithm { | ||
|
||
INDIVIDUAL { | ||
@Override | ||
public boolean isValidLength(int length) { | ||
return 12 == length; | ||
} | ||
|
||
@Override | ||
public boolean isValidChecksum(int[] digits) { | ||
return checkChecksumPersonalINN( digits ); | ||
} | ||
}, | ||
JURIDICAL { | ||
@Override | ||
public boolean isValidLength(int length) { | ||
return 10 == length; | ||
} | ||
|
||
@Override | ||
public boolean isValidChecksum(int[] digits) { | ||
return checkChecksumJuridicalINN( digits ); | ||
} | ||
}, | ||
ANY { | ||
@Override | ||
public boolean isValidLength(int length) { | ||
return 10 == length || 12 == length; | ||
} | ||
|
||
@Override | ||
public boolean isValidChecksum(int[] digits) { | ||
final int length = digits.length; | ||
if ( length == 12 ) { | ||
return checkChecksumPersonalINN( digits ); | ||
} | ||
else if ( length == 10 ) { | ||
return checkChecksumJuridicalINN( digits ); | ||
} | ||
throw new IllegalStateException( "Invalid/unsupported inn value length" ); | ||
} | ||
}; | ||
|
||
private static final int[] INDIVIDUAL_WEIGHTS_11 = { 7, 2, 4, 10, 3, 5, 9, 4, 6, 8 }; | ||
private static final int[] INDIVIDUAL_WEIGHTS_12 = { 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8 }; | ||
private static final int[] JURIDICAL_WEIGHTS = { 2, 4, 10, 3, 5, 9, 4, 6, 8 }; | ||
|
||
private static final int MOD_11 = 11; | ||
private static final int MOD_10 = 10; | ||
|
||
/** | ||
* Check the digits for personal INN using algorithm from | ||
* <a href="https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80_%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%BF%D0%BB%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%89%D0%B8%D0%BA%D0%B0#%D0%92%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D1%86%D0%B8%D1%84%D1%80">Wikipedia</a>. | ||
*/ | ||
private static boolean checkChecksumPersonalINN(int[] digits) { | ||
final int checkSum11 = getCheckSum( digits, INDIVIDUAL_WEIGHTS_11 ); | ||
final int checkSum12 = getCheckSum( digits, INDIVIDUAL_WEIGHTS_12 ); | ||
|
||
final boolean isCheckSum11Correct = checkSum11 == digits[digits.length - 2]; | ||
final boolean isCheckSum12Correct = checkSum12 == digits[digits.length - 1]; | ||
|
||
return isCheckSum11Correct && isCheckSum12Correct; | ||
} | ||
|
||
/** | ||
* Check the digits for juridical INN using algorithm from | ||
* <a href="https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80_%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%BF%D0%BB%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%89%D0%B8%D0%BA%D0%B0#%D0%92%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D1%86%D0%B8%D1%84%D1%80">Wikipedia</a>. | ||
*/ | ||
private static boolean checkChecksumJuridicalINN(int[] digits) { | ||
final int checkSum = getCheckSum( digits, JURIDICAL_WEIGHTS ); | ||
return digits[digits.length - 1] == checkSum; | ||
} | ||
|
||
private static int getCheckSum(int[] digits, int[] weights) { | ||
int sum = 0; | ||
for ( int i = 0; i < weights.length; i++ ) { | ||
sum += digits[i] * weights[i]; | ||
} | ||
return ( sum % MOD_11 ) % MOD_10; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.