Annotation
package com.gss.gmo.cao.validator.constraints;
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.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.gss.gmo.cao.validator.constraints.impl.IdentificationNumberValidator;
/**
* The annotated element has to represent a valid identification number.
*
* @author linus_chien
*
*/
@Documented
@Constraint(validatedBy = IdentificationNumberValidator.class)
@Target(value = { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(value = RUNTIME)
public @interface IdentificationNumber {
/**
* Default key:
* com.gss.gmo.cao.validator.constraints.IdentificationNumber.message.
*
* @return
*/
String message() default "{com.gss.gmo.cao.validator.constraints.IdentificationNumber.message}";
/**
* Default {}.
*
* @return
*/
Class<?>[] groups() default {};
/**
* Default {}.
*
* @return
*/
Class<? extends Payload>[] payload() default {};
/**
* Defines several @IdentificationNumber annotations on the same element.
*
* @author linus_chien
*
*/
@Documented
@Target(value = { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(value = RUNTIME)
public @interface List {
/**
* @return
*/
IdentificationNumber[] values();
}
}
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.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.gss.gmo.cao.validator.constraints.impl.IdentificationNumberValidator;
/**
* The annotated element has to represent a valid identification number.
*
* @author linus_chien
*
*/
@Documented
@Constraint(validatedBy = IdentificationNumberValidator.class)
@Target(value = { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(value = RUNTIME)
public @interface IdentificationNumber {
/**
* Default key:
* com.gss.gmo.cao.validator.constraints.IdentificationNumber.message.
*
* @return
*/
String message() default "{com.gss.gmo.cao.validator.constraints.IdentificationNumber.message}";
/**
* Default {}.
*
* @return
*/
Class<?>[] groups() default {};
/**
* Default {}.
*
* @return
*/
Class<? extends Payload>[] payload() default {};
/**
* Defines several @IdentificationNumber annotations on the same element.
*
* @author linus_chien
*
*/
@Documented
@Target(value = { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(value = RUNTIME)
public @interface List {
/**
* @return
*/
IdentificationNumber[] values();
}
}
ConstraintValidator Implementation
package com.gss.gmo.cao.validator.constraints.impl;
import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.gss.gmo.cao.validator.constraints.IdentificationNumber;
/**
* 身份證字號檢查程式,身份證字號規則: 字母(ABCDEFGHJKLMNPQRSTUVXYWZIO)對應一組數(10~35),
* 令其十位數為X1,個位數為X2;( 如A:X1=1 , X2=0 );D?表示2~9數字 Y = X1 + 9*X2 + 8*D1 + 7*D2 +
* 6*D3 + 5*D4 + 4*D5 + 3*D6 + 2*D7+ 1*D8 + D9 如Y能被10整除,則表示該身份證號碼為正確,否則為錯誤。
* 臺北市(A)、臺中市(B)、基隆市(C)、臺南市(D)、高雄市(E)、臺北縣(F)、
* 宜蘭縣(G)、桃園縣(H)、嘉義市(I)、新竹縣(J)、苗栗縣(K)、臺中縣(L)、
* 南投縣(M)、彰化縣(N)、新竹市(O)、雲林縣(P)、嘉義縣(Q)、臺南縣(R)、
* 高雄縣(S)、屏東縣(T)、花蓮縣(U)、臺東縣(V)、金門縣(W)、澎湖縣(X)、 陽明山(Y)、連江縣(Z)
*
* @author linus_chien
*
*/
public class IdentificationNumberValidator implements ConstraintValidator<IdentificationNumber, String> {
/**
* Id pattern.
*/
public static final Pattern ID_PATTERN = Pattern.compile("[A-Z][12]\\d{8}");
/**
* The first chars of a valid id.
*/
public static final String ID_FIRST_CHARS = "ABCDEFGHJKLMNPQRSTUVXYWZIO";
@Override
public void initialize(IdentificationNumber annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
value = value.toUpperCase();
if (!ID_PATTERN.matcher(value).matches()) {
return false;
}
char[] numbers = value.toCharArray();
int code = ID_FIRST_CHARS.indexOf(numbers[0]) + 10;
int sum = (int) (code / 10) + 9 * (code % 10);
for (int i = 1; i <= 8; i++) {
sum += ((numbers[i] - '0') * (9 - i));
}
sum += (numbers[9] - '0');
if (sum % 10 == 0) {
return true;
} else {
return false;
}
}
}
import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.gss.gmo.cao.validator.constraints.IdentificationNumber;
/**
* 身份證字號檢查程式,身份證字號規則: 字母(ABCDEFGHJKLMNPQRSTUVXYWZIO)對應一組數(10~35),
* 令其十位數為X1,個位數為X2;( 如A:X1=1 , X2=0 );D?表示2~9數字 Y = X1 + 9*X2 + 8*D1 + 7*D2 +
* 6*D3 + 5*D4 + 4*D5 + 3*D6 + 2*D7+ 1*D8 + D9 如Y能被10整除,則表示該身份證號碼為正確,否則為錯誤。
* 臺北市(A)、臺中市(B)、基隆市(C)、臺南市(D)、高雄市(E)、臺北縣(F)、
* 宜蘭縣(G)、桃園縣(H)、嘉義市(I)、新竹縣(J)、苗栗縣(K)、臺中縣(L)、
* 南投縣(M)、彰化縣(N)、新竹市(O)、雲林縣(P)、嘉義縣(Q)、臺南縣(R)、
* 高雄縣(S)、屏東縣(T)、花蓮縣(U)、臺東縣(V)、金門縣(W)、澎湖縣(X)、 陽明山(Y)、連江縣(Z)
*
* @author linus_chien
*
*/
public class IdentificationNumberValidator implements ConstraintValidator<IdentificationNumber, String> {
/**
* Id pattern.
*/
public static final Pattern ID_PATTERN = Pattern.compile("[A-Z][12]\\d{8}");
/**
* The first chars of a valid id.
*/
public static final String ID_FIRST_CHARS = "ABCDEFGHJKLMNPQRSTUVXYWZIO";
@Override
public void initialize(IdentificationNumber annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
value = value.toUpperCase();
if (!ID_PATTERN.matcher(value).matches()) {
return false;
}
char[] numbers = value.toCharArray();
int code = ID_FIRST_CHARS.indexOf(numbers[0]) + 10;
int sum = (int) (code / 10) + 9 * (code % 10);
for (int i = 1; i <= 8; i++) {
sum += ((numbers[i] - '0') * (9 - i));
}
sum += (numbers[9] - '0');
if (sum % 10 == 0) {
return true;
} else {
return false;
}
}
}