ESignFieldMappingUtils.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. package com.kingdee.eas.custom.esign.utils;
  2. import com.alibaba.fastjson.JSONException;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kingdee.bos.BOSException;
  5. import com.kingdee.bos.metadata.entity.EntityViewInfo;
  6. import com.kingdee.bos.metadata.entity.FilterInfo;
  7. import com.kingdee.bos.metadata.entity.FilterItemInfo;
  8. import com.kingdee.eas.custom.entryconfig.DataConfigSelectFieldEntryCollection;
  9. import com.kingdee.eas.custom.entryconfig.DataConfigSelectFieldEntryInfo;
  10. import com.kingdee.bos.Context;
  11. import com.kingdee.eas.custom.esign.*;
  12. import com.kingdee.shr.base.syssetting.MSFServiceFacadeFactory;
  13. import java.io.File;
  14. import java.io.FileInputStream;
  15. import java.io.IOException;
  16. import java.nio.charset.StandardCharsets;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. /**
  20. * 电子签名字段映射工具类
  21. * 提供电子签名相关的字段处理、SQL获取、模板信息获取、JSON合并等工具方法
  22. */
  23. public class ESignFieldMappingUtils {
  24. // /**
  25. // * 生成电子签名SQL字段字符串(已注释,备用逻辑)
  26. // * @param fields 字段映射集合
  27. // * @return 拼接后的SQL字段字符串(格式:数据库字段 as 映射键, ...)
  28. // */
  29. // public String getESignSqlField(FieldMappingEntryCollection fields){
  30. // String sqlField = "";
  31. // // 遍历字段映射集合
  32. // for (int i = 0; i < fields.size(); i++) {
  33. // // 获取当前字段映射信息
  34. // FieldMappingEntryInfo field = fields.get(i);
  35. // // 获取数据源字段信息
  36. // DataConfigSelectFieldEntryInfo dataSourceField = field.getDataSourceField();
  37. // // 获取映射键
  38. // String mappingKey = dataSourceField.getMappingKey();
  39. // // 获取数据库字段名
  40. // String databaseName = dataSourceField.getDatabaseName();
  41. // // 拼接SQL字段字符串(数据库字段 as 映射键)
  42. // sqlField+=databaseName+" as "+mappingKey;
  43. // // 判断是否为最后一个字段,最后一个字段后加换行,否则加逗号
  44. // if (i==fields.size()-1){
  45. // sqlField+="\n";
  46. // }else {
  47. // sqlField+=",";
  48. // }
  49. // }
  50. // // 返回拼接好的SQL字段字符串
  51. // return sqlField;
  52. // }
  53. /**
  54. * 从字段映射集合中提取数据源字段集合
  55. * @param fields 字段映射集合(包含字段映射关系)
  56. * @return 数据源字段集合(仅包含数据源字段信息)
  57. */
  58. public DataConfigSelectFieldEntryCollection getESignSqlField(FieldMappingEntryCollection fields){
  59. // 初始化数据源字段集合
  60. DataConfigSelectFieldEntryCollection dataConfigSelectFieldEntryCollection = new DataConfigSelectFieldEntryCollection();
  61. // 遍历字段映射集合
  62. for (int i = 0; i < fields.size(); i++) {
  63. // 获取当前字段映射信息
  64. FieldMappingEntryInfo field = fields.get(i);
  65. // 从字段映射中提取数据源字段
  66. DataConfigSelectFieldEntryInfo dataSourceField = field.getDataSourceField();
  67. // 将数据源字段添加到结果集合中
  68. if (dataSourceField!=null){
  69. dataConfigSelectFieldEntryCollection.add(dataSourceField);
  70. }
  71. }
  72. // 返回提取后的数据源字段集合
  73. return dataConfigSelectFieldEntryCollection;
  74. }
  75. /**
  76. * 根据数据配置编号获取电子签名相关SQL
  77. * @param dataConfigNumber 数据配置编号(用于标识特定的数据配置)
  78. * @param context 上下文对象(金蝶BOS框架上下文,包含环境信息)
  79. * @return 获取到的SQL字符串
  80. */
  81. public String getESignSql(String dataConfigNumber,Context context){
  82. // 初始化服务调用参数映射
  83. Map<String,Object> getSqlServiceMap = new HashMap<String,Object>();
  84. // 设置参数:数据配置编号
  85. getSqlServiceMap.put("number",dataConfigNumber);
  86. // 声明SQL结果变量
  87. Object sql = null;
  88. try {
  89. // 调用本地服务获取SQL,服务名为"getSqlService",传入参数映射
  90. sql = MSFServiceFacadeFactory.getLocalInstance(context).processService("getSqlService", getSqlServiceMap);
  91. } catch (Exception e) {
  92. // 捕获异常并包装为运行时异常抛出
  93. throw new RuntimeException(e);
  94. }
  95. // 将SQL结果转为字符串返回
  96. return sql.toString();
  97. }
  98. /**
  99. * 根据ID获取电子签名模板信息
  100. * @param id 模板ID(用于唯一标识模板)
  101. * @param context 上下文对象(金蝶BOS框架上下文)
  102. * @return 电子签名模板信息(当前逻辑未实现,返回null)
  103. * @throws BOSException 金蝶BOS框架异常
  104. */
  105. public ESignTemplateInfo getTemplateInfo(String id,Context context) throws BOSException {
  106. // 创建实体视图信息(用于查询时指定视图条件)
  107. EntityViewInfo entityViewInfo = new EntityViewInfo();
  108. // 创建过滤信息对象(用于设置查询过滤条件)
  109. FilterInfo filterInfo = new FilterInfo();
  110. // 向过滤信息中添加过滤项:根据ID过滤(字段名为"id",值为传入的id)
  111. filterInfo.getFilterItems().add(new FilterItemInfo("id",id));
  112. // 将过滤信息设置到实体视图中
  113. entityViewInfo.setFilter(filterInfo);
  114. // 调用电子签名模板工厂获取符合条件的模板集合(当前未使用返回的集合)
  115. ESignTemplateFactory.getLocalInstance(context).getESignTemplateCollection(entityViewInfo);
  116. // 方法暂未实现,返回null
  117. return null;
  118. }
  119. /**
  120. * 合并两个协议JSONObject对象的方法
  121. * @param baseJson 基础JSON对象(被合并的原始数据,优先级较低)
  122. * @param newJson 新JSON对象(待合并的数据,优先级较高,用于覆盖/补充原始数据)
  123. * @return 合并后的JSONObject
  124. * @throws IllegalArgumentException 当基础JSON为null时抛出
  125. */
  126. public JSONObject mergeAgreements(JSONObject baseJson, JSONObject newJson) {
  127. // 基础JSON非空校验
  128. if (baseJson == null) {
  129. throw new IllegalArgumentException("基础JSON数据不能为null");
  130. }
  131. // 若新JSON为null,直接返回基础JSON
  132. if (newJson == null) {
  133. return baseJson;
  134. }
  135. // 遍历新JSON中的所有协议Key
  136. for (String agreementKey : newJson.keySet()) {
  137. try {
  138. // 从新JSON中获取当前Key对应的协议对象
  139. JSONObject newAgreement = newJson.getJSONObject(agreementKey);
  140. // 若当前协议不是JSONObject类型,跳过处理
  141. if (newAgreement == null) {
  142. continue;
  143. }
  144. // 若基础JSON中已包含当前协议Key
  145. if (baseJson.containsKey(agreementKey)) {
  146. // 从基础JSON中获取对应协议对象
  147. JSONObject baseAgreement = baseJson.getJSONObject(agreementKey);
  148. // 合并两个协议对象的内部字段
  149. mergeSingleAgreement(baseAgreement, newAgreement);
  150. } else {
  151. // 若基础JSON中不包含当前协议Key,直接添加新协议到基础JSON
  152. baseJson.put(agreementKey, newAgreement);
  153. }
  154. } catch (JSONException e) {
  155. // 捕获JSON解析异常,打印错误信息后继续处理其他协议
  156. System.err.println("处理协议[" + agreementKey + "]时出错:" + e.getMessage());
  157. continue;
  158. }
  159. }
  160. // 返回合并后的基础JSON
  161. return baseJson;
  162. }
  163. // /**
  164. // * 合并两个单个协议对象的内部字段
  165. // * @param baseAgreement 基础协议对象(被合并的原始协议)
  166. // * @param newAgreement 新协议对象(待合并的协议,用于覆盖/补充原始协议)
  167. // */
  168. // private void mergeSingleAgreement(JSONObject baseAgreement, JSONObject newAgreement) {
  169. // // 合并协议的基础属性:name(若新协议有name则覆盖)
  170. // if (newAgreement.getString("name") != null) {
  171. // baseAgreement.put("name", newAgreement.getString("name"));
  172. // }
  173. // // 合并协议的基础属性:id(若新协议有id则覆盖)
  174. // if (newAgreement.getString("id") != null) {
  175. // baseAgreement.put("id", newAgreement.getString("id"));
  176. // }
  177. // // 合并协议的基础属性:dataType(dataType则覆盖)
  178. // if (newAgreement.getString("dataType") != null) {
  179. // baseAgreement.put("dataType", newAgreement.getString("dataType"));
  180. // }
  181. // // 合并协议的基础属性:dataFormat(dataFormat则覆盖)
  182. // if (newAgreement.getString("dataFormat") != null) {
  183. // baseAgreement.put("dataFormat", newAgreement.getString("dataFormat"));
  184. // }
  185. //
  186. // // 从新协议中获取fields字段(字段集合)
  187. // JSONObject newFields = newAgreement.getJSONObject("fields");
  188. // // 若新协议的fields为空或不存在,无需合并字段,直接返回
  189. // if (newFields == null || newFields.isEmpty()) {
  190. // return;
  191. // }
  192. //
  193. // // 从基础协议中获取fields字段(字段集合)
  194. // JSONObject baseFields = baseAgreement.getJSONObject("fields");
  195. // // 若基础协议中没有fields字段,直接将新协议的fields设置到基础协议
  196. // if (baseFields == null) {
  197. // baseAgreement.put("fields", newFields);
  198. // return;
  199. // }
  200. //
  201. // // 遍历新协议fields中的所有字段Key
  202. // for (String fieldKey : newFields.keySet()) {
  203. // // 从新协议fields中获取当前字段对象
  204. // JSONObject newField = newFields.getJSONObject(fieldKey);
  205. // if (newField != null) {
  206. // // 获取新字段的value值
  207. // Object value = newField.get("value");
  208. // // 若新字段value为null且基础fields中已存在该字段,则跳过(不覆盖现有有效数据)
  209. // if (value == null && baseFields.containsKey(fieldKey)) {
  210. // JSONObject jsonObject1 = baseFields.getJSONObject(fieldKey);
  211. // String dataType = jsonObject1.getString("dataType");
  212. // String dataFormat = jsonObject1.getString("dataFormat");
  213. // newField.put("dataType",dataType);
  214. // newField.put("dataFormat",dataFormat);
  215. // //continue;
  216. // }
  217. //// else {
  218. //// String dataType = baseFields.getString("dataType");
  219. //// String dataFormat = baseFields.getString("dataFormat");0
  220. //// newField.put("dataType",dataType);
  221. //// newField.put("dataFormat",dataFormat);
  222. //// }
  223. // // 将新字段添加/覆盖到基础fields中
  224. // baseFields.put(fieldKey, newField);
  225. // }
  226. // }
  227. // }
  228. /**
  229. * 合并单个协议对象内部的字段
  230. * @param baseAgreement 基础协议对象(被合并的原始协议)
  231. * @param newAgreement 新协议对象(要合并的协议,用于覆盖/补充原始协议)
  232. */
  233. private void mergeSingleAgreement(JSONObject baseAgreement, JSONObject newAgreement) {
  234. // 协议级字段:优先使用newAgreement的name、id、dataType、dataFormat
  235. if (newAgreement.getString("name") != null) {
  236. baseAgreement.put("name", newAgreement.getString("name"));
  237. }
  238. if (newAgreement.getString("id") != null) {
  239. baseAgreement.put("id", newAgreement.getString("id"));
  240. }
  241. if (newAgreement.getString("dataType") != null) {
  242. baseAgreement.put("dataType", newAgreement.getString("dataType"));
  243. }
  244. if (newAgreement.getString("dataFormat") != null) {
  245. baseAgreement.put("dataFormat", newAgreement.getString("dataFormat"));
  246. }
  247. // 从新协议中获取fields
  248. JSONObject newFields = newAgreement.getJSONObject("fields");
  249. if (newFields == null || newFields.isEmpty()) {
  250. return; // 新协议无fields,无需处理
  251. }
  252. // 从基础协议中获取fields(若不存在则直接使用新协议的fields)
  253. JSONObject baseFields = baseAgreement.getJSONObject("fields");
  254. if (baseFields == null) {
  255. baseAgreement.put("fields", newFields); // base无fields,直接用new的fields
  256. return;
  257. }
  258. // 基础协议存在fields,遍历新协议的fields进行合并
  259. for (String fieldKey : newFields.keySet()) {
  260. JSONObject newField = newFields.getJSONObject(fieldKey);
  261. if (newField == null) {
  262. continue;
  263. }
  264. // 若基础协议的fields中没有当前字段,直接添加新字段(以new为主)
  265. if (!baseFields.containsKey(fieldKey)) {
  266. baseFields.put(fieldKey, newField);
  267. continue;
  268. }
  269. // 基础协议存在当前字段,进行字段级合并
  270. JSONObject baseField = baseFields.getJSONObject(fieldKey);
  271. // 1. new的dataType和dataFormat优先覆盖base
  272. String newDataType = newField.getString("dataType");
  273. if (newDataType != null) {
  274. baseField.put("dataType", newDataType);
  275. }
  276. String newDataFormat = newField.getString("dataFormat");
  277. if (newDataFormat != null) {
  278. baseField.put("dataFormat", newDataFormat);
  279. }
  280. // 2. 其他字段(如name、value等):以base为主,new有非空值时覆盖
  281. for (String key : newField.keySet()) {
  282. if ("dataType".equals(key) || "dataFormat".equals(key)) {
  283. continue; // 已处理过的字段跳过
  284. }
  285. Object newValue = newField.get(key);
  286. if (newValue != null) {
  287. baseField.put(key, newValue); // 仅new有值时覆盖base
  288. }
  289. }
  290. // 将合并后的字段放回baseFields
  291. baseFields.put(fieldKey, baseField);
  292. }
  293. }
  294. // ---------- 以下为重载方法,支持JSON字符串的合并 ----------
  295. /**
  296. * 合并两个JSON字符串(重载方法)
  297. * @param baseJsonStr 基础JSON字符串
  298. * @param newJsonStr 新JSON字符串
  299. * @return 合并后的JSONObject
  300. * @throws IllegalArgumentException 当JSON字符串解析失败时抛出
  301. */
  302. public JSONObject mergeAgreements(String baseJsonStr, String newJsonStr) {
  303. try {
  304. // 将基础JSON字符串解析为JSONObject
  305. JSONObject baseJson = JSONObject.parseObject(baseJsonStr);
  306. // 将新JSON字符串解析为JSONObject
  307. JSONObject newJson = JSONObject.parseObject(newJsonStr);
  308. // 调用JSON对象合并方法
  309. return mergeAgreements(baseJson, newJson);
  310. } catch (JSONException e) {
  311. // 解析失败时抛出异常,包含错误信息
  312. throw new IllegalArgumentException("JSON字符串解析失败:" + e.getMessage(), e);
  313. }
  314. }
  315. // ---------- 以下为重载方法,支持从文件读取JSON并合并 ----------
  316. /**
  317. * 从文件读取JSON字符串并合并(重载方法)
  318. * @param baseFilePath 基础JSON文件路径
  319. * @param newFilePath 新JSON文件路径
  320. * @return 合并后的JSONObject
  321. * @throws IOException 当文件读取失败时抛出
  322. */
  323. public JSONObject mergeAgreementsFromFile(String baseFilePath, String newFilePath) throws IOException {
  324. // 读取基础JSON文件内容为字符串
  325. String baseJsonStr = readFileToString(baseFilePath);
  326. // 读取新JSON文件内容为字符串
  327. String newJsonStr = readFileToString(newFilePath);
  328. // 调用JSON字符串合并方法
  329. return mergeAgreements(baseJsonStr, newJsonStr);
  330. }
  331. /**
  332. * 将文件内容读取为字符串(使用UTF-8编码)
  333. * @param filePath 文件路径
  334. * @return 文件内容字符串
  335. * @throws IOException 当文件不存在或读取失败时抛出
  336. */
  337. private String readFileToString(String filePath) throws IOException {
  338. // 根据文件路径创建File对象
  339. File file = new File(filePath);
  340. // 使用try-with-resources自动关闭流:创建文件输入流和Scanner
  341. try (FileInputStream fis = new FileInputStream(file);
  342. java.util.Scanner scanner = new java.util.Scanner(fis, StandardCharsets.UTF_8.name())) {
  343. // 设置Scanner的分隔符为文件开始(即读取整个文件)
  344. scanner.useDelimiter("\\A");
  345. // 若有内容则返回内容,否则返回空字符串
  346. return scanner.hasNext() ? scanner.next() : "";
  347. }
  348. }
  349. // ---------- 测试方法入口 ----------
  350. /**
  351. * 主方法:测试入口
  352. * @param args 命令行参数
  353. */
  354. public static void main(String[] args) {
  355. // 测试场景1:基础合并 + 新增数据(被注释,可取消注释执行)
  356. // testBasicMerge();
  357. //
  358. // // 测试场景2:新JSON为null(被注释,可取消注释执行)
  359. // testNewJsonNull();
  360. // 测试场景3:字段value为null的处理(被注释,可取消注释执行)
  361. //testNullValueField();
  362. }
  363. /**
  364. * 测试场景1:基础合并逻辑
  365. * 验证已有协议字段覆盖、新增协议及字段的合并效果
  366. */
  367. // private static void testBasicMerge() {
  368. // System.out.println("===== 测试场景1:基础合并 =====");
  369. // // 基础JSON字符串(原始数据)
  370. // String baseJsonStr = " {\n" +
  371. // " \"借款协议_id\": {\n" +
  372. // " \"name\": \"借款协议\",\n" +
  373. // " \"id\": \"借款协议_id\",\n" +
  374. // " \"fields\": {\n" +
  375. // " \"借款协议_Field_id\": {\"dataType\": \"String\", \"name\": \"借款协议Field1\", \"value\": \"001\"},\n" +
  376. // " \"借款协议_Field_id1\": {\"dataType\": \"String\", \"name\": \"借款协议Field2\", \"value\": null}\n" +
  377. // " }\n" +
  378. // " },\n" +
  379. // " \"投资合同_id\": {\n" +
  380. // " \"name\": \"投资合同\",\n" +
  381. // " \"id\": \"投资合同_id\",\n" +
  382. // " \"fields\": {\"投资合同_Field_id1\": {\"dataType\": \"String\", \"name\": \"投资合同Field2\", \"value\": \"小明\"}}\n" +
  383. // " }\n" +
  384. // " }";
  385. //
  386. // // 新JSON字符串(待合并数据)
  387. // String newJsonStr = "{\n" +
  388. // " \"借款协议_id\": {\n" +
  389. // " \"name\": \"借款协议(修改)\",\n" +
  390. // " \"id\": \"借款协议_id\",\n" +
  391. // " \"fields\": {\n" +
  392. // " \"借款协议_Field_id1\": {\"dataType\": \"String\", \"name\": \"借款协议Field2\", \"value\": \"002\"},\n" +
  393. // " \"借款协议_Field_id2\": {\"dataType\": \"String\", \"name\": \"借款协议Field3\", \"value\": \"新字段\"}\n" +
  394. // " }\n" +
  395. // " },\n" +
  396. // " \"业务协议_id\": {\n" +
  397. // " \"name\": \"业务协议\",\n" +
  398. // " \"id\": \"业务协议_id\",\n" +
  399. // " \"fields\": {\"业务协议_Field_id\": {\"dataType\": \"String\", \"name\": \"业务协议Field1\", \"value\": \"19892761659\"}}\n" +
  400. // " }\n" +
  401. // " }";
  402. //
  403. // try {
  404. // // 执行合并
  405. // JSONObject mergedJson = mergeAgreements(baseJsonStr, newJsonStr);
  406. // // 打印合并结果(格式化输出)
  407. // System.out.println("合并结果\n" + JSONObject.toJSONString(mergedJson, true));
  408. // } catch (Exception e) {
  409. // // 捕获并打印合并失败信息
  410. // System.err.println("合并失败:" + e.getMessage());
  411. // }
  412. // System.out.println("------------------------\n");
  413. // }
  414. //
  415. // /**
  416. // * 测试场景2:新JSON为null的情况
  417. // * 验证当新数据为null时,是否返回基础数据
  418. // */
  419. // private static void testNewJsonNull() {
  420. // System.out.println("===== 测试场景2:新JSON为null =====");
  421. // // 基础JSON字符串
  422. // String baseJsonStr = "{\"投资合同_id\": {\"name\": \"投资合同\", \"id\": \"投资合同_id\"}}";
  423. // try {
  424. // // 传入新JSON为null,执行合并
  425. // JSONObject mergedJson = mergeAgreements(baseJsonStr, null);
  426. // // 打印合并结果
  427. // System.out.println("合并结果\n" + JSONObject.toJSONString(mergedJson, true));
  428. // } catch (Exception e) {
  429. // // 捕获并打印合并失败信息
  430. // System.err.println("合并失败:" + e.getMessage());
  431. // }
  432. // System.out.println("------------------------\n");
  433. // }
  434. /**
  435. * 测试场景3:字段value为null的处理
  436. * 验证当新字段value为null时,是否保留基础字段的有效数据
  437. */
  438. // private static void testNullValueField() {
  439. // System.out.println("===== 测试场景3:字段value为null =====");
  440. // // 基础JSON字符串(包含有效value的字段)
  441. // String baseJsonStr = """
  442. // {
  443. // "借款协议_id": {
  444. // "fields": {"借款协议_Field_id": {"value": "有效数据"}}
  445. // }
  446. // }""";
  447. //
  448. // // 新JSON字符串(包含value为null的字段和新增字段)
  449. // String newJsonStr = """
  450. // {
  451. // "借款协议_id": {
  452. // "fields": {"借款协议_Field_id": {"value": null}, "新字段": {"value": "新数据"}}
  453. // }
  454. // }""";
  455. //
  456. // try {
  457. // // 执行合并
  458. // JSONObject mergedJson = mergeAgreements(baseJsonStr, newJsonStr);
  459. // // 打印合并结果(验证value为null的字段是否被忽略)
  460. // System.out.println("合并结果(验证字段value为null时的处理):\n" + JSONObject.toJSONString(mergedJson, true));
  461. // } catch (Exception e) {
  462. // // 捕获并打印合并失败信息
  463. // System.err.println("合并失败:" + e.getMessage());
  464. // }
  465. // }
  466. }