Ver código fonte

引入点号规则算法

欧阳劲驰 1 mês atrás
pai
commit
98d779b6da

+ 6 - 0
pom.xml

@@ -355,6 +355,12 @@
             <artifactId>gt-epsg-hsql</artifactId>
             <version>${geotools.version}</version>
         </dependency>
+        <!--pinyin-->
+        <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
     </dependencies>
 
     <repositories>

+ 15 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/norule/JPSurveyApplyColumn.java

@@ -0,0 +1,15 @@
+package com.shkpr.service.alambizplugin.commtools.norule;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+@Getter
+@Setter
+public class JPSurveyApplyColumn {
+    private String property = "";
+    private String value = "";
+
+    public JPSurveyApplyColumn() {
+    }
+}

+ 21 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/norule/RuleFormatSetting.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.alambizplugin.commtools.norule;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class RuleFormatSetting {
+    private String name = "";
+    private String functions = "";
+    private int ordering = 0;
+
+    public RuleFormatSetting() {
+    }
+
+    public RuleFormatSetting(String name, String functions, int ordering) {
+        this.name = name;
+        this.functions = functions;
+        this.ordering = ordering;
+    }
+}

+ 49 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/norule/ShortIDUtil.java

@@ -0,0 +1,49 @@
+package com.shkpr.service.alambizplugin.commtools.norule;
+
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class ShortIDUtil {
+    private static final String CHARSET = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";//remove {0,O} 
+    private static final int RADIX = CHARSET.length();
+
+    /**
+     * 通过输入生成固定规则的短ID
+     *
+     * @param input:           输入字符串
+     * @param outLen:输出长度6-16位
+     * @param salt:            附属加盐值
+     * @return
+     */
+    public static String genId(String input, int outLen, String salt) {
+        try {
+            if (salt == null)
+                salt = "";
+            if (outLen < 6)
+                outLen = 6;
+            else if (outLen > 16)
+                outLen = 16;
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            byte[] hash = digest.digest((input + salt).getBytes(StandardCharsets.UTF_8));
+
+            BigInteger bigInt = new BigInteger(1, hash);
+            StringBuilder baseString = new StringBuilder();
+            BigInteger zero = BigInteger.ZERO;
+            while (bigInt.compareTo(zero) > 0) {
+                BigInteger[] divAndRem = bigInt.divideAndRemainder(BigInteger.valueOf(RADIX));
+                bigInt = divAndRem[0];
+                baseString.insert(0, CHARSET.charAt(divAndRem[1].intValue()));
+            }
+
+            while (baseString.length() < outLen) {
+                baseString.insert(0, CHARSET.charAt(0));
+            }
+            return baseString.substring(0, outLen);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

+ 157 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/norule/StrToFirstCharTool.java

@@ -0,0 +1,157 @@
+package com.shkpr.service.alambizplugin.commtools.norule;
+
+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.exception.BadHanyuPinyinOutputFormatCombination;
+
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+
+public class StrToFirstCharTool {
+
+    private static final Pattern FILTER_PATTERN = Pattern.compile("[\\u4e00-\\u9fffA-Za-z0-9]");//过滤非中文字符、非字母、非数字
+    private static final HanyuPinyinOutputFormat PINYIN_FORMAT = new HanyuPinyinOutputFormat();
+    private static final Map<Character, String> POLYPHONE_MAP = new HashMap<>();//多音字映射
+    private static final Map<Character, SoftReference<String>> PINYIN_CACHE = new ConcurrentHashMap<>();
+
+    static {
+        PINYIN_FORMAT.setCaseType(HanyuPinyinCaseType.LOWERCASE);
+        PINYIN_FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+    }
+
+    public static String processMixedString(String input) {
+        if (input == null || input.trim().isEmpty()) {
+            return "";
+        }
+
+        String normalized = normalizeFullWidthChars(input);
+        String filtered = filterSpecialChars(normalized);
+        return capitalizeFirstLetters(filtered);
+    }
+
+    private static String normalizeFullWidthChars(String str) {
+        char[] chars = str.toCharArray();
+        for (int i = 0; i < chars.length; i++) {
+            if (chars[i] >= '\uff00' && chars[i] <= '\uff5e') {
+                chars[i] = (char) (chars[i] - 0xfee0);
+            } else if (chars[i] == '\u3000') {
+                chars[i] = ' ';
+            }
+        }
+        return new String(chars);
+    }
+
+    private static String filterSpecialChars(String str) {
+        StringBuilder sb = new StringBuilder();
+        for (char c : str.toCharArray()) {
+            if (FILTER_PATTERN.matcher(String.valueOf(c)).matches()) {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static String capitalizeFirstLetters(String str) {
+        if (str.isEmpty()) return "";
+
+        List<String> words = new ArrayList<>();
+        StringBuilder currentWord = new StringBuilder();
+        CharType currentType = getCharType(str.charAt(0));
+        currentWord.append(str.charAt(0));
+
+        for (int i = 1; i < str.length(); i++) {
+            char c = str.charAt(i);
+            CharType type = getCharType(c);
+
+            if (type == currentType && (currentType == CharType.LETTER || currentType == CharType.DIGIT)) {
+                currentWord.append(c);
+            } else if (type == CharType.CHINESE) {
+                if (currentWord.length() > 0) {
+                    words.add(currentWord.toString());
+                    currentWord = new StringBuilder();
+                }
+                words.add(String.valueOf(c));
+                currentType = type;
+            } else {
+                if (currentWord.length() > 0) {
+                    words.add(currentWord.toString());
+                    currentWord = new StringBuilder();
+                }
+                currentWord.append(c);
+                currentType = type;
+            }
+        }
+        if (currentWord.length() > 0) {
+            words.add(currentWord.toString());
+        }
+
+        StringBuilder result = new StringBuilder();
+        for (String word : words) {
+            CharType type = getCharType(word.charAt(0));
+            if (type == CharType.CHINESE) {
+                StringBuilder sb = new StringBuilder();
+                for (char c : word.toCharArray()) {
+                    sb.append(getCachedFirstLetter(c).toUpperCase());
+                }
+                result.append(sb);
+            } else if (type == CharType.LETTER) {
+                if (!word.isEmpty()) {
+                    result.append(word.toUpperCase());
+                    //result.append(Character.toUpperCase(word.charAt(0)));
+                    //if (word.length() > 1) {
+                    //    result.append(word.substring(1));
+                    //}
+                }
+            } else {
+                result.append(word);
+            }
+        }
+        return result.toString();
+    }
+
+    private static CharType getCharType(char c) {
+        if (isChineseChar(c)) {
+            return CharType.CHINESE;
+        } else if (Character.isLetter(c)) {
+            return CharType.LETTER;
+        } else if (Character.isDigit(c)) {
+            return CharType.DIGIT;
+        }
+        return CharType.OTHER;
+    }
+
+    private static boolean isChineseChar(char c) {
+        Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
+        return block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
+                || block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS;
+    }
+
+    private static String getCachedFirstLetter(char c) {
+        SoftReference<String> ref = PINYIN_CACHE.get(c);
+        String value = (ref != null) ? ref.get() : null;
+
+        if (value == null) {
+            if (POLYPHONE_MAP.containsKey(c)) {
+                value = POLYPHONE_MAP.get(c);
+            } else {
+                try {
+                    String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(c, PINYIN_FORMAT);
+                    value = (pinyin != null && pinyin.length > 0) ? pinyin[0].substring(0, 1) : String.valueOf(c);
+                } catch (BadHanyuPinyinOutputFormatCombination e) {
+                    value = String.valueOf(c);
+                }
+            }
+            PINYIN_CACHE.put(c, new SoftReference<>(value));
+        }
+        return value;
+    }
+
+    private enum CharType {CHINESE, LETTER, DIGIT, OTHER}
+}

+ 97 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/norule/SurveyCommonAssistant.java

@@ -0,0 +1,97 @@
+package com.shkpr.service.alambizplugin.commtools.norule;
+
+import com.global.base.tools.CastUtil;
+import com.global.base.tools.RandomUtil;
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import com.shkpr.service.alambizplugin.commtools.TimeTool;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+
+public class SurveyCommonAssistant {
+
+    /**
+     * 点号生成算法函数
+     *
+     * @param code:GIS元素唯一编码
+     * @param column:GIS元素属性值列表,如:[{"property":"address","value":"长江路"}]
+     * @param ruleSetting:点号规则列表
+     * @return *) 点号规则列表为空时,返回code编码作为点号
+     * ) 实际点号生成失败,返回code编码作为点号
+     */
+    public static String genNo(String code, List<JPSurveyApplyColumn> column, List<RuleFormatSetting> ruleSetting) {
+        final String STR_FUN_TAG = "str(";
+        final String DATE_FUN_TAG = "date(";
+        final String RANDOM_FUN_TAG = "random(";
+        final String PP_FUN_TAG = "pp(";
+        StringBuilder result = new StringBuilder();
+        do {
+            if (CollectionUtils.isEmpty(ruleSetting))
+                break;
+
+            for (RuleFormatSetting ruleItem : ruleSetting) {
+                if (StringUtils.isEmpty(ruleItem.getFunctions()))
+                    continue;
+
+                int start = ruleItem.getFunctions().indexOf('(');
+                if (start <= -1)
+                    continue;
+                start += 1;
+
+                int end = ruleItem.getFunctions().indexOf(')', start);
+                if (end <= -1)
+                    continue;
+
+                String content = ruleItem.getFunctions().substring(start, end);
+                int commaPos = content.indexOf(',');
+
+                String param1 = (commaPos > 0) ? content.substring(0, commaPos).trim() : content;
+                String param2 = (commaPos > 0) ? content.substring(commaPos + 1).trim() : "";
+
+                if (ruleItem.getFunctions().startsWith(STR_FUN_TAG)) {
+                    if (result.length() > 0)
+                        result.append("-");
+
+                    int paramLen = CastUtil.castInt(param2, 0);
+                    if (CommTool.lenString(param1) > paramLen)
+                        result.append(param1, 0, paramLen);
+                    else
+                        result.append(param1);
+                } else if (ruleItem.getFunctions().startsWith(DATE_FUN_TAG)) {
+                    if (result.length() > 0)
+                        result.append("-");
+                    int paramLen = CastUtil.castInt(param2, 0);
+                    if (paramLen <= 0 || paramLen > 8)
+                        paramLen = 6;
+                    String dateStr = TimeTool.convertUTC2DateStr(System.currentTimeMillis(), "yyyyMMdd");
+                    result.append(dateStr.substring(dateStr.length() - paramLen));
+                } else if (ruleItem.getFunctions().startsWith(RANDOM_FUN_TAG)) {
+                    if (result.length() > 0)
+                        result.append("-");
+                    result.append(ShortIDUtil.genId(code, CastUtil.castInt(param1, 0), RandomUtil.getDigitalRandomStr(6)));
+                } else if (ruleItem.getFunctions().startsWith(PP_FUN_TAG)) {
+                    if (!CollectionUtils.isEmpty(column)) {
+                        for (JPSurveyApplyColumn columnItem : column) {
+                            if (columnItem.getProperty().equals(param1) && !StringUtils.isEmpty(columnItem.getValue())) {
+                                String ppFirstChar = StrToFirstCharTool.processMixedString(columnItem.getValue());
+                                if (!StringUtils.isEmpty(ppFirstChar)) {
+                                    if (result.length() > 0)
+                                        result.append("-");
+                                    int paramLen = CastUtil.castInt(param2, 0);
+                                    if (CommTool.lenString(ppFirstChar) > paramLen)
+                                        result.append(ppFirstChar, 0, paramLen);
+                                    else
+                                        result.append(ppFirstChar);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        } while (false);
+        return result.length() <= 0 ? code : result.toString();
+    }
+
+}	

+ 10 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyJobInfoMapper.java

@@ -1,9 +1,11 @@
 package com.shkpr.service.alambizplugin.dbdao.mapper;
 
+import com.shkpr.service.alambizplugin.commtools.norule.RuleFormatSetting;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 采集任务基本信息mapper
@@ -22,6 +24,14 @@ public interface GisSurveyJobInfoMapper {
     LocalDateTime findRefreshTimeByUid(@Param("uid") String uid);
 
     /**
+     * 根据uid查询点号规则
+     *
+     * @param uid uid
+     * @return 点号规则
+     */
+    List<RuleFormatSetting> findRuleFormatByUid(@Param("uid") String uid);
+
+    /**
      * 根据uid更新:刷新时间,流转状态,当前状态
      *
      * @param uid         uid

+ 11 - 0
src/main/resources/mapper/GisSurveyJobInfoMapper.xml

@@ -7,6 +7,17 @@
         where uid = #{uid,jdbcType=VARCHAR};
     </select>
 
+    <select id="findRuleFormatByUid" resultType="com.shkpr.service.alambizplugin.commtools.norule.RuleFormatSetting">
+        select
+        rf->>'name' as name,
+        rf->>'functions' as functions,
+        (rf->>'ordering')::int2 as ordering
+        from
+        v_k3_gis_survey_job_info,
+        jsonb_array_elements(rule_format::jsonb) as rf
+        where uid = #{uid,jdbcType=VARCHAR};
+    </select>
+
     <update id="updateRefreshTimeActionStatusByUid">
         update k3_gis_survey_job_info
         set refresh_time = #{refreshTime,jdbcType=BIGINT},