package jnpf.elnService.impl;
|
|
import com.huaban.analysis.jieba.JiebaSegmenter;
|
import net.sourceforge.pinyin4j.PinyinHelper;
|
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
|
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
|
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
|
|
import java.util.Locale;
|
import java.util.function.Supplier;
|
|
public final class ElnFieldCodeGenerator {
|
|
private static final int MAX_CODE_LENGTH = 80;
|
private static final int DEFAULT_SUFFIX_LENGTH = 6;
|
private final Supplier<String> suffixSupplier;
|
private final int suffixLength;
|
|
public ElnFieldCodeGenerator(Supplier<String> suffixSupplier) {
|
this(suffixSupplier, DEFAULT_SUFFIX_LENGTH);
|
}
|
|
public ElnFieldCodeGenerator(Supplier<String> suffixSupplier, int suffixLength) {
|
this.suffixSupplier = suffixSupplier;
|
if (suffixLength < 1) {
|
throw new IllegalArgumentException("字段编码随机后缀长度必须大于 0");
|
}
|
this.suffixLength = suffixLength;
|
}
|
|
public String generate(String label, boolean templateField) {
|
return buildCode(normalizeSegmented(label), "field", "f", templateField);
|
}
|
|
public String generate(String label, String fallback, String numericPrefix) {
|
return generate(label, fallback, numericPrefix, false);
|
}
|
|
public String generateSegmented(String label, String fallback, String numericPrefix) {
|
return buildCode(normalizeSegmented(label), fallback, numericPrefix, false);
|
}
|
|
public static String suggestSegmentedCode(String text) {
|
String normalized = normalizeSegmented(text);
|
if (normalized.length() <= MAX_CODE_LENGTH) {
|
return normalized;
|
}
|
int segmentBoundary = normalized.lastIndexOf('_', MAX_CODE_LENGTH);
|
if (segmentBoundary > 0) {
|
return normalized.substring(0, segmentBoundary);
|
}
|
return trimTrailingUnderscore(normalized.substring(0, MAX_CODE_LENGTH));
|
}
|
|
private String generate(String label, String fallback, String numericPrefix,
|
boolean alwaysPrefix) {
|
return buildCode(normalize(label), fallback, numericPrefix, alwaysPrefix);
|
}
|
|
private String buildCode(String normalizedLabel, String fallback, String numericPrefix,
|
boolean alwaysPrefix) {
|
String base = normalizedLabel;
|
if (base.isEmpty()) {
|
base = fallback;
|
}
|
if (Character.isDigit(base.charAt(0))) {
|
base = numericPrefix + "_" + base;
|
}
|
if (alwaysPrefix) {
|
base = "p_" + base;
|
}
|
String suffix = normalizeSuffix(suffixSupplier.get());
|
int baseLimit = MAX_CODE_LENGTH - suffixLength - 1;
|
if (base.length() > baseLimit) {
|
base = trimTrailingUnderscore(base.substring(0, baseLimit));
|
}
|
return base + "_" + suffix;
|
}
|
|
private static String normalizeSegmented(String value) {
|
if (value == null) {
|
return "";
|
}
|
StringBuilder result = new StringBuilder();
|
for (String segment : SegmenterHolder.INSTANCE.sentenceProcess(value)) {
|
String normalized = normalizeWord(segment);
|
if (!normalized.isEmpty()) {
|
appendSeparator(result);
|
result.append(normalized);
|
}
|
}
|
return trimTrailingUnderscore(result.toString()).replaceAll("_+", "_");
|
}
|
|
private static String normalizeWord(String value) {
|
HanyuPinyinOutputFormat format = pinyinFormat();
|
StringBuilder result = new StringBuilder();
|
for (char character : value.toCharArray()) {
|
if (character < 128 && Character.isLetterOrDigit(character)) {
|
result.append(Character.toLowerCase(character));
|
continue;
|
}
|
String[] pinyin = toPinyin(character, format);
|
if (pinyin != null && pinyin.length > 0) {
|
result.append(pinyin[0]);
|
}
|
}
|
return result.toString();
|
}
|
|
private static String normalize(String value) {
|
if (value == null) {
|
return "";
|
}
|
HanyuPinyinOutputFormat format = pinyinFormat();
|
StringBuilder result = new StringBuilder();
|
for (char character : value.toCharArray()) {
|
if (character < 128 && Character.isLetterOrDigit(character)) {
|
result.append(Character.toLowerCase(character));
|
continue;
|
}
|
String[] pinyin = toPinyin(character, format);
|
if (pinyin != null && pinyin.length > 0) {
|
appendSeparator(result);
|
result.append(pinyin[0]);
|
appendSeparator(result);
|
} else {
|
appendSeparator(result);
|
}
|
}
|
return trimTrailingUnderscore(result.toString()).replaceAll("_+", "_");
|
}
|
|
private static HanyuPinyinOutputFormat pinyinFormat() {
|
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
format.setVCharType(HanyuPinyinVCharType.WITH_V);
|
return format;
|
}
|
|
private static String[] toPinyin(char character, HanyuPinyinOutputFormat format) {
|
try {
|
return PinyinHelper.toHanyuPinyinStringArray(character, format);
|
} catch (BadHanyuPinyinOutputFormatCombination ignored) {
|
// format is fixed and valid
|
return null;
|
}
|
}
|
|
private String normalizeSuffix(String suffix) {
|
String value = suffix == null ? "" : suffix.toLowerCase(Locale.ROOT)
|
.replaceAll("[^a-z0-9]", "");
|
if (value.length() < suffixLength) {
|
throw new IllegalStateException("字段编码随机后缀必须至少包含 " + suffixLength + " 位字母或数字");
|
}
|
return value.substring(0, suffixLength);
|
}
|
|
private static void appendSeparator(StringBuilder value) {
|
if (value.length() > 0 && value.charAt(value.length() - 1) != '_') {
|
value.append('_');
|
}
|
}
|
|
private static String trimTrailingUnderscore(String value) {
|
int end = value.length();
|
while (end > 0 && value.charAt(end - 1) == '_') {
|
end--;
|
}
|
return value.substring(0, end);
|
}
|
|
private static final class SegmenterHolder {
|
private static final JiebaSegmenter INSTANCE = new JiebaSegmenter();
|
}
|
}
|