From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-lims/jnpf-lims-biz/src/test/java/jnpf/limsService/support/LimsSignUsageWiringProbe.java | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 302 insertions(+), 0 deletions(-)
diff --git a/jnpf-lims/jnpf-lims-biz/src/test/java/jnpf/limsService/support/LimsSignUsageWiringProbe.java b/jnpf-lims/jnpf-lims-biz/src/test/java/jnpf/limsService/support/LimsSignUsageWiringProbe.java
new file mode 100644
index 0000000..ae8bd91
--- /dev/null
+++ b/jnpf-lims/jnpf-lims-biz/src/test/java/jnpf/limsService/support/LimsSignUsageWiringProbe.java
@@ -0,0 +1,302 @@
+package jnpf.limsService.support;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+/** SIGN_USED 涓氬姟鍏ュ彛銆佹ā鍧楄涔夊拰鎶樺彔鎺ョ嚎鐨勬簮鐮佺骇鍥炲綊鎺㈤拡銆� */
+public final class LimsSignUsageWiringProbe {
+
+ private static int passed;
+ private static int failed;
+
+ public static void main(String[] args) throws Exception {
+ String qingyandanController = read("jnpf-lims/jnpf-lims-controller/src/main/java/"
+ + "jnpf/limsController/LimsQingyandanController.java");
+ String quyangController = read("jnpf-lims/jnpf-lims-controller/src/main/java/"
+ + "jnpf/limsController/LimsQuyangController.java");
+ String jieyangController = read("jnpf-lims/jnpf-lims-controller/src/main/java/"
+ + "jnpf/limsController/LimsJieyangController.java");
+ String huanjingController = read("jnpf-lims/jnpf-lims-controller/src/main/java/"
+ + "jnpf/limsController/LimsHuanjingJianceController.java");
+ String qingyandanService = read("jnpf-lims/jnpf-lims-biz/src/main/java/"
+ + "jnpf/limsService/impl/LimsQingyandanServiceImpl.java");
+ String signService = read("jnpf-lims/jnpf-lims-biz/src/main/java/"
+ + "jnpf/limsService/impl/LimsSignServiceImpl.java");
+ String signOpType = read("jnpf-lims/jnpf-lims-entity/src/main/java/"
+ + "jnpf/limsEntity/SignOpType.java");
+ String qingyandanEntity = read("jnpf-lims/jnpf-lims-entity/src/main/java/"
+ + "jnpf/limsEntity/LimsQingyandanEntity.java");
+
+ // 2026-07-31 retarget锛堝師涓� checkConsumption("璇烽獙鍗曟彁浜�", qingyandanController,
+ // "QINGYANDAN_SUBMIT")锛夛細鏃ф柇瑷�鏌ャ�宻ubmit 涔嬪悗璋冪敤浜� recordSignUsage銆嶏紝
+ // 鑰� D8 鏄庣‘琛ㄥ崟璺緞**鍋滃啓浜嬩欢銆佷繚鐣欏師瀛愯棰�**銆傝涔夊彉浜嗭紝鍒ゆ嵁璺熺潃鍙橈紱
+ // 璁ら杩欎欢浜�**蹇呴』缁х画鏈変汉瀹�**锛堥槻閲嶆斁鎶ゆ爮锛屽垹浜嗗悓涓�绛惧悕鍙弽澶嶄娇鐢級锛屾晠鏄� retarget 涓嶆槸鍒犻櫎銆�
+ checkQingyandanSubmitClaim(qingyandanController);
+ checkQingyandanFreshSign(qingyandanController);
+ checkCancelConsumption(qingyandanController);
+ checkConsumption("鍙栨牱", quyangController, "QUYANG_FETCH");
+ checkConsumption("鎺ユ牱", jieyangController, "JIEYANG_RECEIVE");
+ checkHuanjingFailureBoundary(huanjingController, "public R<String> quyangJilu(",
+ "limsHuanjingJianceService.quyangJilu", "HUANJING_QUYANG");
+ checkHuanjingFailureBoundary(huanjingController, "public R<String> terminateQuyangJilu(",
+ "limsHuanjingJianceService.terminateQuyangJilu", "HUANJING_QUYANG_TERMINATE");
+
+ // 鈹屸攢 2026-07-31 鍒犻櫎锛岀暀鐥曞涓嬶紙涓嶆槸鏈変汉鍒犳柇瑷�鎹㈢豢锛夆攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+ // 鈹� 鏇剧粡鏂█锛歝heck("璇烽獙鍗曟彁浜� Layer 2 涓庢秷璐逛簨浠跺叡浜嬪姟", 鈹�
+ // 鈹� annotatedBusinessAction(qingyandanService, 鈹�
+ // 鈹� "action = \"SUBMIT\"", "public void submit("), 鈹�
+ // 鈹� "submit 缂哄皯 @AuditLog"); 鈹�
+ // 鈹� 鍗筹細LimsQingyandanServiceImpl.submit() 蹇呴』甯� @AuditLog(action="SUBMIT")銆傗攤
+ // 鈹� 鈹�
+ // 鈹� 涓轰粈涔堣鍙栦唬锛歴pec D7 宸叉妸涓ゅ SUBMIT 鍩嬬偣鏁村潡鍒犻櫎鈥斺�斿鎴峰叧娉ㄧ殑鏄粬鑷繁瑙﹀彂 鈹�
+ // 鈹� 鐨勫姩浣滐紙琛ㄥ崟鐨勬柊澧�/淇敼锛夛紝閭e凡鐢卞眰 0 璁板綍锛泂ubmit() 鏄〃鍗曚繚瀛樹箣鍚庣殑鍚庣 鈹�
+ // 鈹� 鍐呴儴缂栨帓锛屽啀璁颁竴鏉°�岃楠屽崟 鎻愪氦銆嶅彧浼氳鍒楄〃鍑虹幇鐢ㄦ埛娌″仛杩囩殑鍔ㄤ綔琛屻�� 鈹�
+ // 鈹� 鎵�浠ヨ繖鏉℃柇瑷�鐨�**鍓嶆彁**锛坰ubmit 鏈夊眰 2 浜嬩欢锛変笉澶嶅瓨鍦紝涓嶆槸瑕嗙洊闈涪澶便�� 鈹�
+ // 鈹� 鈹�
+ // 鈹� 璋佹帴鏇匡細tasks/lims-sign-usage-checks.sh G 缁勩�孲UBMIT 鍩嬬偣宸插垹锛堟伆濂� 0 澶勶級銆嶏紝鈹�
+ // 鈹� 鍚屼竴涓綅缃粠銆屽繀椤诲湪銆嶅�掕浆鎴愩�屽繀椤讳笉鍦ㄣ�嶏紝涓斿仛杩囧弻鍚戝彉寮傞獙璇侊紙鍔犲洖鏉ヤ篃绾級銆� 鈹�
+ // 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+ check("鍙栨牱 Layer 2 涓庢秷璐逛簨浠跺叡浜嬪姟",
+ annotatedBusinessAction(qingyandanService, "action = \"FETCH\"", "public void fetch("),
+ "fetch 缂哄皯 @AuditLog");
+ check("鎺ユ牱 Layer 2 涓庢秷璐逛簨浠跺叡浜嬪姟",
+ annotatedBusinessAction(qingyandanService, "action = \"RECEIVE\"", "public void jieyangReceive("),
+ "jieyangReceive 缂哄皯 @AuditLog");
+ check("璇烽獙鍗曟挙鍥炰娇鐢ㄧǔ瀹氱鍚嶆搷浣滅爜",
+ signOpType.contains("QINGYANDAN_CANCEL(\"qingyandan_cancel\", \"璇烽獙鍗曟挙鍥瀄")"),
+ "缂哄皯 QINGYANDAN_CANCEL 绋冲畾 code");
+ checkCancelAffectedGuard(qingyandanService);
+ checkQingyandanEntityContract(qingyandanEntity);
+ check("SIGN_USED 鍐欏叆 bizModule",
+ signService.contains(".bizModule(group.getBizModule())"),
+ "AuditEventDTO builder 鏈啓 bizModule");
+ String publishSignUsed = methodBody(signService, "private void publishSignUsedEvents(");
+ check("SIGN_USED 灏嗙鍚� note 鍐欏叆 reason",
+ publishSignUsed.contains(".reason(sign.getNote())"),
+ "SIGN_USED AuditEventDTO 鏈妸 lims_sign.note 鏄犲皠鍒� reason");
+ checkSignClaimGuard(signService);
+ check("鍏ㄩ儴绛惧悕浣跨敤鐩爣鏄惧紡澹版槑 bizModule", allTargetsDeclareBizModule(),
+ "瀛樺湪鏈0鏄� bizModule 鐨� LimsSignUsageTarget.builder() 鍧�");
+
+ System.out.println("=== SIGN_USED 鎺ョ嚎鏂█锛�" + passed + " 閫氳繃 / " + failed + " 澶辫触 ===");
+ System.exit(failed == 0 ? 0 : 1);
+ }
+
+ /**
+ * 鍙栨牱 / 鎺ユ牱浠嶈蛋鏈柟娉曪紝璇箟鏈彉锛堟垚鍔熷悗浠嶅簲鍐� SIGN_USED锛夛紝2026-07-31 <b>涓�瀛楁湭鍔�</b>銆�
+ * 璇烽獙鍗曟彁浜ゅ凡 retarget 鍒� {@link #checkQingyandanSubmitClaim}銆�
+ */
+ private static void checkConsumption(String label, String source, String opType) {
+ check(label + "鏍¢獙绛惧悕", source.contains("SignOpType." + opType), opType + " 鏈帴鍏�");
+ int operation = source.indexOf("SignOpType." + opType);
+ int record = source.indexOf("recordSignUsage", operation);
+ check(label + "鎴愬姛鍚庤褰� SIGN_USED", operation >= 0 && record > operation,
+ opType + " 鍚庢湭璋冪敤 recordSignUsage");
+ }
+
+ /**
+ * 璇烽獙鍗曟彁浜わ細D8 涔嬪悗<b>鍙仛鍘熷瓙璁ら銆佷笉鍐嶅啓 SIGN_USED</b>銆�
+ *
+ * <p>鍙栦唬鍘熸潵鐨� {@code checkConsumption("璇烽獙鍗曟彁浜�", ...)} 璋冪敤銆傞櫎璇箟澶栬繕淇帀浜嗛偅杈圭殑
+ * <b>鑼冨洿缂洪櫡</b>锛歿@code source.indexOf("recordSignUsage", operation)} 鏄粠鏌愪綅缃線鍚�
+ * <b>鍦ㄦ暣涓枃浠堕噷</b>鎵撅紝鍛戒腑鐨勫叾瀹炴槸绉佹湁鏂规硶浣撳唴閭h {@code limsSignService.recordSignUsage(...)}锛�
+ * 涓� submit 绔偣娌℃湁浠讳綍缁戝畾鍏崇郴鈥斺�旀妸 submit 閲岀殑璋冪敤鏁磋鍒犳帀锛岄偅鏉℃柇瑷�鐓ф牱缁裤��
+ * 鏈柟娉曟妸鎼滅储鑼冨洿<b>澶瑰湪 submit 绔偣鏂规硶浣撳唴</b>锛屾敼鍧� submit 鎵嶄細绾€��
+ *
+ * <p>瀹堢殑鏄�<b>璁ら</b>涓嶆槸浜嬩欢锛氳棰嗘槸銆岀鍚嶅崟娆℃秷璐广�嶇殑闃查噸鏀炬姢鏍忥紙ed4d908锛夛紝
+ * 鍒犳帀绛変簬鍚屼竴涓鍚嶅彲浠ュ弽澶嶄娇鐢ㄣ�侱8 鍋滅殑鍙槸浜嬩欢銆�
+ *
+ * <p>鈿狅笍 鍙栨牱锛坽@code QUYANG_FETCH}锛�/ 鎺ユ牱锛坽@code JIEYANG_RECEIVE}锛夎涔夋湭鍙橈紝
+ * 浠嶈蛋 {@link #checkConsumption} 涓斾竴瀛楁湭鍔ㄣ�傚畠浠部鐢ㄧ殑鏁存枃浠� indexOf 鏈夊悓鏍风殑鑼冨洿缂洪櫡锛�
+ * 浣嗘湰鏈熶笉鍦ㄨ寖鍥村唴锛屽凡璁板叆 Task 8 鎶ュ憡寰呭鐞嗏�斺�斾笉鍦ㄨ繖閲岄『鎵嬫敼锛屾槸涓轰簡璁�
+ * 銆屽彇鏍� / 鎺ユ牱娌¤鏀瑰埌銆嶅湪 diff 涓婁竴鐪煎彲瑙併��
+ */
+ private static void checkQingyandanSubmitClaim(String source) {
+ String block = methodBody(source, "public R<String> qingyandanSubmit(");
+ // 鍒ゆ嵁鍐欐垚**瀹屾暣璋冪敤**鑰屼笉鏄厜涓�涓� SignOpType.QINGYANDAN_SUBMIT锛�
+ // 璁ら閭h涔熷甫鐫�鍚屼竴涓灇涓惧悕锛屽彧鏌ユ灇涓惧悕鐨勮瘽锛屾妸鏍¢獙鏀规垚浼� null 鐓ф牱缁匡紙鍙樺紓 N3 瀹炴祴锛夈��
+ int verify = block.indexOf(
+ "requireQingyandanSign(qingyandan, formData, SignOpType.QINGYANDAN_SUBMIT)");
+ int business = block.indexOf("limsQingyandanService.submit(", verify);
+ int claim = block.indexOf("claimQingyandanSignUsageOnly(", business);
+ check("璇烽獙鍗曟彁浜ゆ寜 QINGYANDAN_SUBMIT 鏍¢獙绛惧悕", verify >= 0,
+ "submit 绔偣鏈寜 QINGYANDAN_SUBMIT 鏍¢獙绛惧悕");
+ // 椤哄簭涔熼拤姝伙細璁ら蹇呴』鍦ㄤ笟鍔″啓搴�**涔嬪悗**銆傛彁鍓嶈棰� = 涓氬姟澶辫触鏃剁鍚嶅凡琚秷璐癸紝
+ // 姝f槸 ed4d908 淇帀鐨勯偅涓� bug銆�
+ check("璇烽獙鍗曟彁浜ゆ牎楠岀鍚嶅悗鎵ц銆佷笟鍔℃垚鍔熷悗鎵嶅師瀛愯棰嗭紙涓嶅啀鍐� SIGN_USED锛�",
+ verify >= 0 && business > verify && claim > business,
+ "submit 绔偣浣撳唴鏈湪涓氬姟鎴愬姛鍚庤皟鐢� claimQingyandanSignUsageOnly"
+ + " 鈥斺�� 闃查噸鏀炬姢鏍忎涪澶辨垨椤哄簭棰犲�掞紙ed4d908 鍥炲綊锛�");
+ check("璇烽獙鍗曟彁浜や笉鍐嶈蛋鍙戜簨浠惰矾寰�",
+ !block.isEmpty()
+ && !block.contains("recordQingyandanSignUsage(")
+ && !block.contains("limsSignService.recordSignUsage("),
+ "submit 绔偣浠嶅啓 SIGN_USED锛屼笌灞� 0 鎹鍚嶅瓧娈佃ˉ鍐欑殑绛惧悕浜嬩欢閲嶅锛圖8锛�");
+ }
+
+ /** 鎸夋柟娉曠鍚嶅す鍑烘柟娉曚綋锛堝埌鍚岀缉杩涚殑鏀跺熬澶ф嫭鍙凤級锛涘彇涓嶅埌鏃惰繑鍥炵┖涓诧紝璁╂柇瑷�鎸夌孩澶勭悊銆� */
+ private static String methodBody(String source, String signature) {
+ int start = source.indexOf(signature);
+ if (start < 0) {
+ return "";
+ }
+ int end = source.indexOf("\n }", start);
+ return end > start ? source.substring(start, end) : "";
+ }
+
+ private static void checkCancelConsumption(String source) {
+ int cancelCase = source.indexOf("case \"cancel\":");
+ int operation = source.indexOf("SignOpType.QINGYANDAN_CANCEL", cancelCase);
+ int cancel = source.indexOf("limsQingyandanService.cancel", operation);
+ int record = source.indexOf("recordQingyandanSignUsage", cancel);
+ check("璇烽獙鍗曟挙鍥炰粠璇锋眰璇诲彇绛惧悕",
+ source.contains("params.get(\"biz_sign\")") && source.contains("params.get(\"id\")"),
+ "鎾ゅ洖鏈鍙� biz_sign 鎴栧吋瀹� id");
+ check("璇烽獙鍗曟挙鍥炴牎楠岀鍚嶅悗鎵ц涓旀垚鍔熷悗璁板綍 SIGN_USED",
+ cancelCase >= 0 && operation > cancelCase && cancel > operation && record > cancel,
+ "鎾ゅ洖鐨勭鍚嶆牎楠屻�佷笟鍔℃洿鏂般�丼IGN_USED 椤哄簭閿欒");
+ }
+
+ private static void checkQingyandanFreshSign(String source) {
+ int start = source.indexOf("private LimsSignEntity requireQingyandanSign(");
+ int end = source.indexOf("private LimsSignEntity requireQingyandanActionSign(", start);
+ String block = start >= 0 && end > start ? source.substring(start, end) : "";
+ check("璇烽獙鍗曟彁浜ゅ拰缂栬緫蹇呴』鎼哄甫鏈绛惧悕",
+ block.contains("request.getBizSign()") && !block.contains("persisted.getBizSign()"),
+ "璇锋眰缂虹鍚嶆椂浠嶄細澶嶇敤涓氬姟琛ㄤ腑鐨勫巻鍙� biz_sign");
+ }
+
+ private static void checkHuanjingFailureBoundary(String source,
+ String method,
+ String businessCall,
+ String opType) {
+ int methodAt = source.indexOf(method);
+ int nextMethod = source.indexOf("\n public ", methodAt + method.length());
+ String block = methodAt >= 0
+ ? source.substring(methodAt, nextMethod > methodAt ? nextMethod : source.length())
+ : "";
+ int validation = block.indexOf("limsSignService.requireValidSign(");
+ int catchAt = block.indexOf("catch (DataException e)", validation);
+ int catchClose = block.indexOf("\n }", catchAt);
+ int business = block.indexOf(businessCall, catchClose);
+ int record = block.indexOf("recordHuanjingSignUsage", business);
+ check("鐜鐩戞祴 " + opType + " 鍙崟鑾风鍚嶆牎楠屽紓甯�",
+ validation >= 0 && catchAt > validation && catchClose > catchAt
+ && business > catchClose && record > business,
+ "涓氬姟鏇存柊鎴� SIGN_USED 浠嶅湪 DataException 鎹曡幏鑼冨洿鍐�");
+ }
+
+ private static void checkCancelAffectedGuard(String source) {
+ int start = source.indexOf("public boolean cancel(");
+ int end = source.indexOf("\n @Override", start);
+ String block = start >= 0 && end > start ? source.substring(start, end) : "";
+ int conditionalUpdate = block.indexOf("update.eq(\"biz_status\", BizStatus.CONFIRMED.getCode())");
+ int zeroReturn = block.indexOf("return false;");
+ int softDelete = block.indexOf("softDeleteJianyanXiangRecords");
+ check("璇烽獙鍗曟挙鍥炴寜 confirmed 鐘舵�佸師瀛愭洿鏂�",
+ block.contains("activeRowUpdate(qingyandan.getId())") && conditionalUpdate >= 0,
+ "cancel 缂哄皯鐘舵�佹垨鏈垹闄ゆ潯浠�");
+ check("affected=0 涓嶆墽琛屾挙鍥炲壇浣滅敤",
+ zeroReturn > conditionalUpdate && softDelete > zeroReturn,
+ "cancel 鍦ㄧ‘璁ゆ洿鏂板懡涓墠鎵ц浜嗚蒋鍒犻櫎");
+ check("affected=0 涓嶇敓鎴愪笟鍔′簨浠�",
+ source.substring(Math.max(0, source.lastIndexOf("@AuditLog(", start)), start)
+ .contains("#result ? #qingyandan.jianyanLiushuihao : null"),
+ "cancel 鐨� @AuditLog 鏈寜杩斿洖鍊艰烦杩� 0 琛屼簨浠�");
+ }
+
+ private static void checkQingyandanEntityContract(String entity) {
+ String[] fields = {"qingyan_fenlei", "zhouqi", "zhouqi_danwei"};
+ for (String field : fields) {
+ check("瀹炰綋鍖呭惈璇烽獙瀛楁 " + field,
+ entity.contains("@TableField(\"" + field + "\")"),
+ field + " 鐨勫疄浣撳绾︿笉瀹屾暣");
+ }
+ }
+
+ private static void checkSignClaimGuard(String source) {
+ int requireStart = source.indexOf("public LimsSignEntity requireValidSign(");
+ int recordStart = source.indexOf("public void recordSignUsage(", requireStart);
+ String requireBlock = requireStart >= 0 && recordStart > requireStart
+ ? source.substring(requireStart, recordStart) : "";
+ int claim = source.indexOf("claimSignUsage(sign, opType, usageJson)", recordStart);
+ int event = source.indexOf("auditClientProvider.ifAvailable", recordStart);
+ check("绛惧悕鏍¢獙涓嶆彁鍓嶅啓搴撹棰�",
+ !requireBlock.contains("updateById(") && !requireBlock.contains("this.update("),
+ "requireValidSign 浠嶄細鍦ㄤ笟鍔℃垚鍔熷墠鍐欑鍚�");
+ check("宸叉秷璐圭鍚嶄笉鍙法涓氬姟鍛ㄦ湡澶嶇敤",
+ requireBlock.contains("sign.getExtraJson()")
+ && requireBlock.contains("鐢靛瓙绛惧悕宸茶浣跨敤锛岃閲嶆柊绛惧悕")
+ && source.contains("w.isNull(\"extra_json\").or().eq(\"extra_json\", \"\")")
+ && !source.contains(".or().eq(\"extra_json\", usageJson)"),
+ "extra_json 宸叉湁鍊兼椂浠嶅彲鑳藉啀娆℃秷璐瑰悓涓�绛惧悕");
+ check("绛惧悕鎴愬姛鍚庡厛鍘熷瓙璁ら鍐嶈褰曚簨浠�",
+ claim > recordStart && event > claim
+ && source.contains("w.isNull(\"op_type\")")
+ && source.contains("w.isNull(\"data_id\")")
+ && source.contains("w.isNull(\"extra_json\")"),
+ "SIGN_USED 缂哄皯璁ら鍐茬獊鏉′欢鎴栦簨浠堕『搴忛敊璇�");
+ check("绛惧悕璁ら澶辫触鏍囪浜嬪姟鍥炴粴",
+ source.contains("currentTransactionStatus().setRollbackOnly()")
+ && source.contains("throw signUsageFailure("),
+ "controller 鎹曡幏 DataException 鏃朵簨鍔″彲鑳界户缁彁浜�");
+ }
+
+ private static boolean annotatedBusinessAction(String source, String action, String method) {
+ int methodAt = source.indexOf(method);
+ int actionAt = source.lastIndexOf(action, methodAt);
+ int annotationAt = source.lastIndexOf("@AuditLog(", methodAt);
+ return methodAt >= 0 && annotationAt >= 0 && actionAt > annotationAt
+ && methodAt - annotationAt < 600;
+ }
+
+ private static boolean allTargetsDeclareBizModule() throws IOException {
+ Path root = Paths.get("jnpf-lims");
+ try (Stream<Path> files = Files.walk(root)) {
+ return files.filter(path -> path.toString().contains("/src/main/java/")
+ && path.toString().endsWith(".java"))
+ .allMatch(LimsSignUsageWiringProbe::targetBlocksDeclareBizModule);
+ }
+ }
+
+ private static boolean targetBlocksDeclareBizModule(Path path) {
+ try {
+ String source = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
+ int from = 0;
+ while (true) {
+ int builder = source.indexOf("LimsSignUsageTarget.builder()", from);
+ if (builder < 0) {
+ return true;
+ }
+ int build = source.indexOf(".build()", builder);
+ if (build < 0 || !source.substring(builder, build).contains(".bizModule(")) {
+ return false;
+ }
+ from = build + 8;
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("璇诲彇婧愮爜澶辫触: " + path, e);
+ }
+ }
+
+ private static String read(String path) throws IOException {
+ return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
+ }
+
+ private static void check(String name, boolean ok, String detail) {
+ if (ok) {
+ passed++;
+ System.out.println(" [PASS] " + name);
+ } else {
+ failed++;
+ System.out.println(" [FAIL] " + name + " -- " + detail);
+ }
+ }
+
+ private LimsSignUsageWiringProbe() {
+ }
+}
--
Gitblit v1.8.0