diff --git a/src/main/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumber.java b/src/main/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumber.java
index 7fe9fdc..d43fa6f 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumber.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumber.java
@@ -16,26 +16,39 @@
package xyz.zhouxy.plusone.commons.model;
+import java.io.Serializable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
+import java.util.Objects;
import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.Immutable;
+import xyz.zhouxy.plusone.commons.annotation.ReaderMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
+import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.commons.util.AssertTools;
import xyz.zhouxy.plusone.commons.util.StringTools;
/**
+ * Chinese2ndGenIDCardNumber
+ *
+ *
* 中国第二代居民身份证号
+ *
+ *
+ * @author ZhouXY
+ * @since 1.0
+ * @see xyz.zhouxy.plusone.commons.constant.PatternConsts#CHINESE_2ND_ID_CARD_NUMBER
*/
@ValueObject
@Immutable
-public class Chinese2ndGenIDCardNumber extends IDCardNumber {
+public class Chinese2ndGenIDCardNumber implements IDCardNumber, Serializable {
+
+ private final String value;
/** 省份编码 */
private final String provinceCode;
@@ -52,7 +65,7 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
private Chinese2ndGenIDCardNumber(String value, String provinceCode, String cityCode, String countyCode,
Gender gender, LocalDate birthDate) {
- super(value);
+ this.value = value;
this.provinceCode = provinceCode;
this.cityCode = cityCode;
this.countyCode = countyCode;
@@ -60,13 +73,11 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
this.birthDate = birthDate;
}
- public static final Pattern PATTERN = Pattern.compile("^(?(?(?\\d{2})\\d{2})\\d{2})(?\\d{8})\\d{2}(?\\d)([\\dXx])$");
-
public static Chinese2ndGenIDCardNumber of(final String value) {
AssertTools.checkArgument(StringTools.isNotBlank(value), "二代居民身份证校验失败:号码为空");
final String idNumber = value.toUpperCase();
- final Matcher matcher = Chinese2ndGenIDCardNumber.PATTERN.matcher(idNumber);
+ final Matcher matcher = PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher(idNumber);
AssertTools.checkArgument(matcher.matches(), () -> "二代居民身份证校验失败:" + value);
final String provinceCode = matcher.group("province");
@@ -98,39 +109,53 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
// #region - reader methods
// ================================
+ @ReaderMethod
+ public String value() {
+ return value;
+ }
+
+ @ReaderMethod
public String getProvinceCode() {
return provinceCode;
}
+ @ReaderMethod
public String getProvinceName() {
return PROVINCE_CODES.get(this.provinceCode);
}
+ @ReaderMethod
public String getFullProvinceCode() {
return Strings.padEnd(this.provinceCode, 12, '0');
}
+ @ReaderMethod
public String getCityCode() {
return cityCode;
}
+ @ReaderMethod
public String getFullCityCode() {
return Strings.padEnd(this.cityCode, 12, '0');
}
+ @ReaderMethod
public String getCountyCode() {
return countyCode;
}
+ @ReaderMethod
public String getFullCountyCode() {
return Strings.padEnd(this.countyCode, 12, '0');
}
+ @ReaderMethod
@Override
public Gender getGender() {
return gender;
}
+ @ReaderMethod
@Override
public LocalDate getBirthDate() {
return birthDate;
@@ -188,11 +213,18 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
@Override
public int hashCode() {
- return super.hashCode();
+ return Objects.hashCode(value);
}
@Override
public boolean equals(Object obj) {
- return super.equals(obj);
+ if (this == obj)
+ return true;
+ if (!(obj instanceof Chinese2ndGenIDCardNumber))
+ return false;
+ Chinese2ndGenIDCardNumber other = (Chinese2ndGenIDCardNumber) obj;
+ return Objects.equals(value, other.value);
}
+
+ private static final long serialVersionUID = 20241202095400L;
}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/model/IDCardNumber.java b/src/main/java/xyz/zhouxy/plusone/commons/model/IDCardNumber.java
index 361e0cc..76dcf1a 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/model/IDCardNumber.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/model/IDCardNumber.java
@@ -19,42 +19,31 @@ package xyz.zhouxy.plusone.commons.model;
import java.time.LocalDate;
import java.time.Period;
-import javax.annotation.Nonnull;
-
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
* 身份证号
*/
-public abstract class IDCardNumber {
+public interface IDCardNumber {
- @Nonnull
- private final String value;
+ static final char DEFAULT_REPLACED_CHAR = '*';
+ static final int DEFAULT_DISPLAY_FRONT = 1;
+ static final int DEFAULT_DISPLAY_END = 2;
- private static final char DEFAULT_REPLACED_CHAR = '*';
- private static final int DEFAULT_DISPLAY_FRONT = 1;
- private static final int DEFAULT_DISPLAY_END = 2;
-
- protected IDCardNumber(String value) {
- this.value = value;
- }
-
- public final String getValue() {
- return this.value;
- }
+ String value();
/**
* 根据身份证号判断性别
*/
- public abstract Gender getGender();
+ Gender getGender();
/**
* 获取出生日期
*/
- public abstract LocalDate getBirthDate();
+ LocalDate getBirthDate();
/** 计算年龄 */
- public final int calculateAge() {
+ default int calculateAge() {
LocalDate now = LocalDate.now();
return Period.between(getBirthDate(), now).getYears();
}
@@ -63,23 +52,19 @@ public abstract class IDCardNumber {
// #region - toString
// ================================
- @Override
- public String toString() {
- return toDesensitizedString();
- }
-
- public String toDesensitizedString() {
+ default String toDesensitizedString() {
return toDesensitizedString(DEFAULT_REPLACED_CHAR, DEFAULT_DISPLAY_FRONT, DEFAULT_DISPLAY_END);
}
- public String toDesensitizedString(int front, int end) {
+ default String toDesensitizedString(int front, int end) {
return toDesensitizedString(DEFAULT_REPLACED_CHAR, front, end);
}
- public String toDesensitizedString(char replacedChar, int front, int end) {
+ default String toDesensitizedString(char replacedChar, int front, int end) {
+ final String value = value();
AssertTools.checkArgument(front >= 0 && end >= 0);
- AssertTools.checkArgument((front + end) <= this.value.length(), "需要截取的长度不能大于身份证号长度");
- final char[] charArray = getValue().toCharArray();
+ AssertTools.checkArgument((front + end) <= value.length(), "需要截取的长度不能大于身份证号长度");
+ final char[] charArray = value.toCharArray();
for (int i = front; i < charArray.length - end; i++) {
charArray[i] = replacedChar;
}
diff --git a/src/test/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumberTests.java b/src/test/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumberTests.java
index ddeeda6..40bd5dc 100644
--- a/src/test/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumberTests.java
+++ b/src/test/java/xyz/zhouxy/plusone/commons/model/Chinese2ndGenIDCardNumberTests.java
@@ -26,13 +26,14 @@ import java.util.regex.Matcher;
import org.junit.jupiter.api.Test;
import lombok.extern.slf4j.Slf4j;
+import xyz.zhouxy.plusone.commons.constant.PatternConsts;
@Slf4j
public class Chinese2ndGenIDCardNumberTests {
@Test
void testPattern() {
- Matcher matcher = Chinese2ndGenIDCardNumber.PATTERN.matcher("11010520000101111X");
+ Matcher matcher = PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher("11010520000101111X");
assertTrue(matcher.matches());
for (int i = 0; i < matcher.groupCount(); i++) {
log.info("{}: {}", i, matcher.group(i));
@@ -42,7 +43,7 @@ public class Chinese2ndGenIDCardNumberTests {
@Test
void test() {
Chinese2ndGenIDCardNumber idCardNumber = Chinese2ndGenIDCardNumber.of("11010520000101111X");
- assertEquals("11010520000101111X", idCardNumber.getValue());
+ assertEquals("11010520000101111X", idCardNumber.value());
assertEquals(LocalDate.of(2000, 1, 1), idCardNumber.getBirthDate());
assertEquals(Gender.MALE, idCardNumber.getGender());
assertEquals("110105", idCardNumber.getCountyCode());