50 lines
1.8 KiB
Java
50 lines
1.8 KiB
Java
package com.baiyue.firstleg.domain;
|
|
|
|
import com.baiyue.common.core.api.ResultCode;
|
|
import com.baiyue.common.core.exception.BizException;
|
|
|
|
import java.util.Locale;
|
|
|
|
/** ISO 6346 真实集装箱号的唯一规范化与校验入口。 */
|
|
public final class Iso6346ContainerNumber {
|
|
private static final int[] LETTER_VALUES = {
|
|
10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24,
|
|
25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38
|
|
};
|
|
|
|
private Iso6346ContainerNumber() {
|
|
}
|
|
|
|
public static String require(String raw) {
|
|
String value = normalizeWhitespace(raw);
|
|
if (value == null || !value.matches("[A-Z]{3}[UJZ][0-9]{7}")) {
|
|
throw invalid();
|
|
}
|
|
int sum = 0;
|
|
for (int index = 0; index < 10; index++) {
|
|
char current = value.charAt(index);
|
|
int number = Character.isDigit(current)
|
|
? current - '0' : LETTER_VALUES[current - 'A'];
|
|
sum += number * (1 << index);
|
|
}
|
|
int expected = sum % 11 % 10;
|
|
if (value.charAt(10) - '0' != expected) throw invalid();
|
|
return value;
|
|
}
|
|
|
|
private static String normalizeWhitespace(String raw) {
|
|
if (raw == null) return null;
|
|
StringBuilder value = new StringBuilder(raw.length());
|
|
raw.codePoints().filter(codePoint -> !Character.isWhitespace(codePoint)
|
|
&& !Character.isSpaceChar(codePoint))
|
|
.forEach(value::appendCodePoint);
|
|
String normalized = value.toString().toUpperCase(Locale.ROOT);
|
|
return normalized.isEmpty() ? null : normalized;
|
|
}
|
|
|
|
private static BizException invalid() {
|
|
return new BizException(ResultCode.BAD_REQUEST,
|
|
"真实集装箱号必须符合ISO 6346结构、设备类别和校验位");
|
|
}
|
|
}
|