AssistSynchronizingUtils.java 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. package com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kingdee.bos.BOSException;
  5. import com.kingdee.bos.BOSObjectFactory;
  6. import com.kingdee.bos.Context;
  7. import com.kingdee.bos.dao.IObjectCollection;
  8. import com.kingdee.bos.dao.IObjectValue;
  9. import com.kingdee.bos.dao.query.IQueryExecutor;
  10. import com.kingdee.bos.dao.query.QueryExecutorFactory;
  11. import com.kingdee.bos.metadata.MetaDataPK;
  12. import com.kingdee.bos.metadata.data.SortType;
  13. import com.kingdee.bos.metadata.entity.*;
  14. import com.kingdee.bos.metadata.query.util.CompareType;
  15. import com.kingdee.bos.sql.ParserException;
  16. import com.kingdee.bos.util.BOSObjectType;
  17. import com.kingdee.bos.util.BOSUuid;
  18. import com.kingdee.eas.common.EASBizException;
  19. import com.kingdee.eas.custom.thirdpartysystemsyn.config.viewconfig.*;
  20. import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.DataTypeEnum;
  21. import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.EntityAttributeEnum;
  22. import com.kingdee.eas.framework.CoreBaseCollection;
  23. import com.kingdee.eas.framework.CoreBaseInfo;
  24. import com.kingdee.eas.framework.ICoreBase;
  25. import com.kingdee.shr.attachment.SHRAttachmentExtCollection;
  26. import com.kingdee.shr.attachment.SHRAttachmentExtFactory;
  27. import com.kingdee.shr.attachment.SHRAttachmentExtInfo;
  28. import com.kingdee.shr.base.syssetting.MSFServiceFacadeFactory;
  29. import com.kingdee.shr.base.syssetting.context.SHRContext;
  30. import com.kingdee.shr.base.syssetting.exception.SHRWebException;
  31. import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
  32. import com.kingdee.shr.base.syssetting.model.VirtualDataFetcher;
  33. import com.kingdee.shr.base.syssetting.util.MetaDataUtil;
  34. import com.kingdee.util.Uuid;
  35. import com.kingdee.util.enums.EnumUtils;
  36. import org.apache.log4j.Logger;
  37. import java.util.*;
  38. public class AssistSynchronizingUtils {
  39. // 日志记录器,用于记录系统操作日志
  40. private static final Logger logger = Logger.getLogger("com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils.AssistSynchronizingUtils");
  41. /**
  42. * 重写父类方法,根据配置编号和过滤条件获取数据
  43. * 该方法主要执行以下步骤:
  44. * 1. 解析过滤条件JSON字符串
  45. * 2. 获取头部配置信息
  46. * 3. 构建查询条件并执行查询
  47. * 4. 处理查询结果并转换为JSON格式
  48. * 5. 处理分录数据(如果存在)
  49. *
  50. * @param ctx 上下文对象
  51. * @param configNumber 配置编号,用于定位具体的同步配置
  52. * @param filterInfos 过滤条件信息,JSON格式字符串
  53. * @return 处理后的结果数据,JSON格式字符串
  54. * @throws BOSException 当操作过程中发生业务异常时抛出
  55. */
  56. public JSONArray getData(Context ctx, String configNumber, String filterInfos) throws BOSException {
  57. // 记录方法调用日志,包含入参信息
  58. logger.info("Starting getData method with configNumber: " + configNumber + ", filterInfos: " + filterInfos);
  59. // 用于记录处理统计信息
  60. int totalRecords = 0;
  61. int successRecords = 0;
  62. int failedRecords = 0;
  63. JSONArray errorDetails = new JSONArray();
  64. // 解析过滤条件JSON字符串为JSONObject
  65. JSONObject jsonObject = JSONObject.parseObject(filterInfos);
  66. JSONArray resultArray = new JSONArray(); // 创建结果数组
  67. try {
  68. // 获取头部配置信息
  69. logger.debug("Getting head configuration for configNumber: " + configNumber);
  70. EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE);
  71. ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry);
  72. // 验证条目信息是否唯一
  73. if (entries.size() != 1) {
  74. String errorMsg = "头部信息配置异常,期望1条配置但找到" + entries.size() + "条";
  75. logger.error(errorMsg);
  76. throw new RuntimeException(errorMsg); // 抛出配置异常
  77. }
  78. // 获取唯一的条目信息
  79. ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0);
  80. String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称
  81. logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber);
  82. // 创建实体查询视图并设置查询条件
  83. EntityViewInfo headEntityViewInfo = new EntityViewInfo();
  84. String filterExpr = jsonObject.getString(entityName); // 获取实体对应的过滤条件
  85. if (filterExpr != null && !filterExpr.trim().isEmpty()) { // 检查过滤条件是否非空
  86. headEntityViewInfo.setFilter(filterExpr); // 设置过滤条件
  87. logger.debug("Set filter for entity " + entityName + ": " + filterExpr);
  88. }
  89. // 设置查询字段
  90. ConfigInfoEntryFieldCollection fields = configInfoEntryInfo.getFields();
  91. SelectorItemCollection selectorItem = getSelectorItem(fields); // 获取选择器项目
  92. headEntityViewInfo.setSelector(selectorItem); // 设置选择器
  93. logger.debug("Set selector with " + selectorItem.size() + " fields");
  94. // 设置排序
  95. String sortField = configInfoEntryInfo.getSortField(); // 获取排序字段
  96. SorterItemCollection sorterItemCollection = sorterProcessing(sortField); // 处理排序字段
  97. if (sorterItemCollection != null) {
  98. headEntityViewInfo.setSorter(sorterItemCollection); // 设置排序器
  99. logger.debug("Set sorter with " + sorterItemCollection.size() + " fields");
  100. }
  101. // 执行查询获取数据集合
  102. boolean isQuery = configInfoEntryInfo.isIsQuery(); // 判断是否为查询类型
  103. CoreBaseCollection collection; // 声明数据集合
  104. if (isQuery) {
  105. logger.debug("Initializing collection using query for entity: " + entityName);
  106. collection = this.initCollection(entityName, headEntityViewInfo, ctx); // 初始化集合
  107. } else {
  108. String bosType = configInfoEntryInfo.getBosType(); // 获取BOS类型
  109. BOSObjectType bosObjectType = BOSObjectType.create(bosType); // 创建BOS对象类型
  110. logger.debug("Getting collection using BOS object type: " + bosType);
  111. // 根据BOS类型创建对应的业务对象实例
  112. ICoreBase bosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, bosObjectType);
  113. collection = bosObject.getCollection(headEntityViewInfo); // 获取数据集合
  114. }
  115. totalRecords = collection.size();
  116. logger.info("Retrieved " + totalRecords + " records for processing");
  117. // 处理查询结果
  118. processCollectionData(ctx, configNumber, jsonObject, resultArray, collection,
  119. configInfoEntryInfo, fields, errorDetails);
  120. successRecords = resultArray.size();
  121. failedRecords = totalRecords - successRecords;
  122. logger.info("Data processing completed. Success: " + successRecords +
  123. ", Failed: " + failedRecords + ", Total: " + totalRecords);
  124. } catch (Exception e) {
  125. e.printStackTrace();
  126. String errorMsg = "Error occurred while getting data for configNumber: " + configNumber;
  127. logger.error(errorMsg, e);
  128. // 创建错误详情记录
  129. JSONObject errorDetail = new JSONObject();
  130. errorDetail.put("configNumber", configNumber);
  131. errorDetail.put("errorType", "MAIN_PROCESS_ERROR");
  132. errorDetail.put("errorMessage", e.getMessage());
  133. errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
  134. errorDetails.add(errorDetail);
  135. failedRecords = totalRecords; // 所有记录都标记为失败
  136. successRecords = 0;
  137. throw new BOSException("数据获取失败: " + e.getMessage(), e); // 抛出业务异常
  138. } finally {
  139. // 记录最终处理结果统计
  140. JSONObject processSummary = new JSONObject();
  141. processSummary.put("configNumber", configNumber);
  142. processSummary.put("totalRecords", totalRecords);
  143. processSummary.put("successRecords", successRecords);
  144. processSummary.put("failedRecords", failedRecords);
  145. processSummary.put("errorDetails", errorDetails);
  146. logger.info("Process summary: " + processSummary.toJSONString());
  147. }
  148. logger.info("Successfully retrieved data, result size: " + resultArray.size());
  149. return resultArray;
  150. }
  151. public void saveData(Context ctx, String configNumber, String controllerBeanEx) throws BOSException {
  152. EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE);
  153. ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry);
  154. // 验证条目信息是否唯一
  155. if (entries.size() != 1) {
  156. String errorMsg = "头部信息配置异常,期望1条配置但找到" + entries.size() + "条";
  157. logger.error(errorMsg);
  158. throw new RuntimeException(errorMsg); // 抛出配置异常
  159. }
  160. // 获取唯一的条目信息
  161. ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0);
  162. String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称
  163. logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber);
  164. ConfigInfoInfo parent = configInfoEntryInfo.getParent();
  165. //osf服务名
  166. String osfName = parent.getOsfName();
  167. String osfParam = parent.getOsfParam();
  168. Object o = null;
  169. try {
  170. o = MSFServiceFacadeFactory.getLocalInstance(ctx).processService(osfName, this.getOSFParam(osfParam));
  171. } catch (EASBizException e) {
  172. throw new RuntimeException(e);
  173. }
  174. JSONArray osfReturnData = JSONArray.parseArray(o.toString());
  175. for (int i = 0; i < osfReturnData.size(); i++) {
  176. JSONObject osfReturnDataEntry = osfReturnData.getJSONObject(i);
  177. //处理头部信息
  178. boolean isCreateData = configInfoEntryInfo.isIsCreateData();//是否创建数据
  179. String thirdUniqueValue = configInfoEntryInfo.getThirdUniqueValue();//第三方唯一值
  180. String hrUniqueValue = configInfoEntryInfo.getHrUniqueValue();//hr唯一值
  181. String bosType = configInfoEntryInfo.getBosType();
  182. Class objectValueClass1 = null;
  183. try {
  184. objectValueClass1 = MetaDataUtil.getObjectValueClass(entityName);
  185. // 创建对应的实体对象
  186. CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(objectValueClass1, entityName);
  187. if (!isCreateData){
  188. String value = getThirdUniqueValue(osfReturnDataEntry, thirdUniqueValue);
  189. if (value!=null){
  190. CoreBaseInfo coreBaseInfo1 = findCoreBaseInfo(ctx, coreBaseInfo.getBOSType(), value, hrUniqueValue);
  191. if (coreBaseInfo1!=null){
  192. coreBaseInfo = coreBaseInfo1;
  193. }
  194. }
  195. }
  196. } catch (ShrWebBizException e) {
  197. throw new RuntimeException(e);
  198. }
  199. }
  200. }
  201. public String getThirdUniqueValue(JSONObject jsonObject,String thirdUniqueValue){
  202. String[] split = thirdUniqueValue.split("\\.");
  203. Object value = null;
  204. for (int i = 0; i < split.length; i++) {
  205. String s = split[i];
  206. value = jsonObject.get(s);
  207. if (value instanceof JSONArray){
  208. JSONArray jsonArray = jsonObject.getJSONArray(s);
  209. value = jsonArray.get(0);
  210. }
  211. }
  212. return value==null?null:value.toString();
  213. }
  214. public CoreBaseInfo findCoreBaseInfo(Context ctx,BOSObjectType bosObjectType,
  215. String thirdUniqueValue,
  216. String hrUniqueValue) throws BOSException {
  217. ICoreBase bosObject = (ICoreBase) (BOSObjectFactory.createBOSObject(ctx,bosObjectType));
  218. CoreBaseCollection collection = bosObject.getCollection("where " + hrUniqueValue + " = '" + thirdUniqueValue + "' ");
  219. if (collection.size()>1){
  220. throw new RuntimeException("");
  221. } else if (collection.size()==0) {
  222. return null;
  223. }else {
  224. return collection.get(0);
  225. }
  226. }
  227. public Map<String,Object> getOSFParam(String jsonData){
  228. if (jsonData!=null&&!jsonData.equals("")){
  229. JSONObject param = JSONObject.parseObject(jsonData);
  230. Set<String> strings = param.keySet();
  231. Iterator<String> iterator = strings.iterator();
  232. Map<String,Object> map = new HashMap<String,Object>();
  233. while (iterator.hasNext()){
  234. String next = iterator.next();
  235. map.put(next,param.get(next));
  236. }
  237. return map;
  238. }else {
  239. return null;
  240. }
  241. }
  242. /**
  243. * 处理查询结果集合数据
  244. * 遍历集合中的每个CoreBaseInfo对象,将其转换为JSON格式,并处理相关的分录数据
  245. *
  246. * @param ctx 上下文对象
  247. * @param configNumber 配置编号
  248. * @param jsonObject 过滤条件JSON对象
  249. * @param resultArray 结果数组
  250. * @param collection 查询结果集合
  251. * @param configInfoEntryInfo 配置条目信息
  252. * @param fields 字段配置集合
  253. * @param errorDetails 错误详情数组,用于记录处理过程中的错误
  254. * @throws BOSException 业务异常
  255. * @throws ClassNotFoundException 类未找到异常
  256. * @throws ParserException 解析异常
  257. * @throws SHRWebException SHR Web异常
  258. */
  259. public void processCollectionData(Context ctx, String configNumber, JSONObject jsonObject,
  260. JSONArray resultArray, CoreBaseCollection collection,
  261. ConfigInfoEntryInfo configInfoEntryInfo,
  262. ConfigInfoEntryFieldCollection fields,
  263. JSONArray errorDetails)
  264. throws BOSException, ClassNotFoundException, ParserException, SHRWebException {
  265. for (int i = 0; i < collection.size(); i++) { // 遍历集合中的每个元素
  266. String recordId = "unknown";
  267. try {
  268. CoreBaseInfo coreBaseInfo = collection.get(i); // 获取当前元素
  269. recordId = coreBaseInfo.getId() != null ? coreBaseInfo.getId().toString() : "unknown";
  270. logger.debug("Processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId);
  271. JSONObject resultData = new JSONObject(); // 创建结果数据对象
  272. JSONObject mainData = new JSONObject(); // 创建主数据对象
  273. // 处理单条数据,转换为JSON格式
  274. dataProcessing(mainData, coreBaseInfo, fields, recordId, ctx);
  275. String name = configInfoEntryInfo.getName(); // 获取配置名称
  276. resultData.put(name, mainData); // 将主数据添加到结果数据
  277. // 处理分录数据
  278. processEntryData(ctx, configNumber, jsonObject, resultData, coreBaseInfo, recordId, errorDetails);
  279. resultArray.add(resultData); // 将结果数据添加到结果数组
  280. logger.debug("Successfully processed record ID: " + recordId);
  281. } catch (Exception e) {
  282. e.printStackTrace();
  283. String errorMsg = "Error processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId;
  284. logger.error(errorMsg, e);
  285. // 创建错误详情记录
  286. JSONObject errorDetail = new JSONObject();
  287. errorDetail.put("configNumber", configNumber);
  288. errorDetail.put("recordId", recordId);
  289. errorDetail.put("recordIndex", i);
  290. errorDetail.put("errorType", "RECORD_PROCESSING_ERROR");
  291. errorDetail.put("errorMessage", e.getMessage());
  292. errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
  293. errorDetails.add(errorDetail);
  294. // 继续处理下一条记录
  295. continue;
  296. }
  297. }
  298. }
  299. /**
  300. * 处理分录数据
  301. * 获取配置中的分录信息,根据关联字段查询相关的分录数据,并将其转换为JSON格式
  302. *
  303. * @param ctx 上下文对象
  304. * @param configNumber 配置编号
  305. * @param jsonObject 过滤条件JSON对象
  306. * @param resultData 结果数据对象
  307. * @param coreBaseInfo 核心基础信息对象
  308. * @param recordId 当前处理的主记录ID
  309. * @param errorDetails 错误详情数组,用于记录处理过程中的错误
  310. * @throws BOSException 业务异常
  311. * @throws ClassNotFoundException 类未找到异常
  312. * @throws ParserException 解析异常
  313. * @throws SHRWebException SHR Web异常
  314. */
  315. public void processEntryData(Context ctx, String configNumber, JSONObject jsonObject,
  316. JSONObject resultData, CoreBaseInfo coreBaseInfo,
  317. String recordId, JSONArray errorDetails)
  318. throws BOSException, ClassNotFoundException, ParserException, SHRWebException {
  319. try {
  320. // 获取分录为 boy类型的配置
  321. EntityViewInfo boyEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.BOY_VALUE);
  322. ConfigInfoEntryCollection entryCollection = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(boyEntry);
  323. for (int j = 0; j < entryCollection.size(); j++) { // 遍历分录配置集合
  324. ConfigInfoEntryInfo configInfoEntryInfo1 = entryCollection.get(j); // 获取当前分录配置
  325. String boyEntityName = configInfoEntryInfo1.getEntityName(); // 获取分录实体名称
  326. ConfigInfoEntryFieldCollection boyFields = configInfoEntryInfo1.getFields(); // 获取分录字段配置
  327. logger.debug("Processing entry data for entity: " + boyEntityName + ", main record ID: " + recordId);
  328. // 创建分录查询视图
  329. EntityViewInfo boyEntityViewInfo = new EntityViewInfo();
  330. String boyFilterExpr = jsonObject.getString(boyEntityName); // 获取分录过滤条件
  331. // 设置关联字段过滤条件
  332. String crelatedField = configInfoEntryInfo1.getCrelatedField(); // 获取关联字段
  333. FilterInfo filter = new FilterInfo(); // 创建过滤器
  334. String id = coreBaseInfo.getId().toString(); // 获取主数据ID
  335. filter.getFilterItems().add(new FilterItemInfo(crelatedField, id, CompareType.EQUALS)); // 添加关联字段过滤条件
  336. if (boyFilterExpr != null && !boyFilterExpr.trim().isEmpty()) { // 检查分录过滤条件是否非空
  337. filter.getFilterItems().add(new FilterItemInfo(boyFilterExpr)); // 添加分录过滤条件
  338. }
  339. boyEntityViewInfo.setFilter(filter); // 设置过滤器
  340. // 设置查询字段
  341. SelectorItemCollection boySelectorItem = getSelectorItem(boyFields); // 获取分录选择器
  342. boyEntityViewInfo.setSelector(boySelectorItem); // 设置选择器
  343. // 执行查询获取分录数据
  344. boolean isQuery1 = configInfoEntryInfo1.isIsQuery(); // 判断是否为查询类型
  345. CoreBaseCollection boyCollection; // 声明分录数据集合
  346. if (isQuery1) {
  347. boyCollection = this.initCollection(boyEntityName, boyEntityViewInfo, ctx); // 初始化分录集合
  348. } else {
  349. String boyDosType = configInfoEntryInfo1.getBosType(); // 获取分录BOS类型
  350. BOSObjectType boyBosObjectType = BOSObjectType.create(boyDosType); // 创建BOS对象类型
  351. ICoreBase boyBosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, boyBosObjectType); // 创建业务对象
  352. boyCollection = boyBosObject.getCollection(boyEntityViewInfo); // 获取分录数据集合
  353. }
  354. logger.debug("Retrieved " + boyCollection.size() + " entry records for entity: " +
  355. boyEntityName + ", main record ID: " + recordId);
  356. // 处理分录数据
  357. JSONArray entryDataArray = new JSONArray(); // 创建分录数据数组
  358. for (int k = 0; k < boyCollection.size(); k++) { // 遍历分录数据集合
  359. try {
  360. CoreBaseInfo coreBaseInfo1 = boyCollection.get(k); // 获取当前分录数据
  361. String entryRecordId = coreBaseInfo1.getId() != null ? coreBaseInfo1.getId().toString() : "unknown";
  362. JSONObject entryData = new JSONObject(); // 创建分录数据对象
  363. dataProcessing(entryData, coreBaseInfo1, boyFields, entryRecordId, ctx); // 处理分录数据
  364. entryDataArray.add(entryData); // 将分录数据添加到数组
  365. logger.debug("Processed entry record " + (k+1) + "/" + boyCollection.size() +
  366. ", ID: " + entryRecordId + " for main record ID: " + recordId);
  367. } catch (Exception e) {
  368. e.printStackTrace();
  369. String errorMsg = "Error processing entry record " + (k+1) + "/" + boyCollection.size() +
  370. " for main record ID: " + recordId;
  371. logger.error(errorMsg, e);
  372. // 创建错误详情记录
  373. JSONObject errorDetail = new JSONObject();
  374. errorDetail.put("configNumber", configNumber);
  375. errorDetail.put("mainRecordId", recordId);
  376. errorDetail.put("entryEntity", boyEntityName);
  377. errorDetail.put("entryIndex", k);
  378. errorDetail.put("errorType", "ENTRY_RECORD_PROCESSING_ERROR");
  379. errorDetail.put("errorMessage", e.getMessage());
  380. errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
  381. errorDetails.add(errorDetail);
  382. // 继续处理下一条分录记录
  383. continue;
  384. }
  385. }
  386. String name1 = configInfoEntryInfo1.getName(); // 获取分录配置名称
  387. resultData.put(name1, entryDataArray); // 将分录数据添加到结果数据
  388. logger.debug("Completed processing entry data for entity: " + boyEntityName +
  389. ", main record ID: " + recordId + ", records: " + entryDataArray.size());
  390. }
  391. } catch (Exception e) {
  392. e.printStackTrace();
  393. String errorMsg = "Error processing entry data for main record ID: " + recordId;
  394. logger.error(errorMsg, e);
  395. // 创建错误详情记录
  396. JSONObject errorDetail = new JSONObject();
  397. errorDetail.put("configNumber", configNumber);
  398. errorDetail.put("mainRecordId", recordId);
  399. errorDetail.put("errorType", "ENTRY_PROCESSING_ERROR");
  400. errorDetail.put("errorMessage", e.getMessage());
  401. errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
  402. errorDetails.add(errorDetail);
  403. // 抛出异常,由上层处理
  404. throw new RuntimeException(e);
  405. }
  406. }
  407. /**
  408. * 处理单条CoreBaseInfo数据,将其字段信息转换为JSONObject
  409. * 根据字段类型的不同,采用不同的处理方式:
  410. * 1. 枚举类型:获取枚举列表和当前值的别名
  411. * 2. 对象值类型:提取对象的名称和编号
  412. * 3. 对象集合类型:提取集合中每个对象的名称和编号
  413. * 4. 其他类型:直接使用字段值
  414. * 5. 最后处理附件信息
  415. *
  416. * @param jsonObject 用于存储处理后数据的JSON对象
  417. * @param coreBaseInfo 待处理的业务数据对象
  418. * @param fieldCollection 配置的字段集合,包含需要处理的字段信息
  419. * @param recordId 当前处理的记录ID,用于日志记录
  420. * @param context 上下文对象,用于获取附件信息
  421. * @throws ClassNotFoundException 当枚举类找不到时抛出
  422. */
  423. public void dataProcessing(JSONObject jsonObject, CoreBaseInfo coreBaseInfo,
  424. ConfigInfoEntryFieldCollection fieldCollection, String recordId, Context context)
  425. throws ClassNotFoundException {
  426. for (int i = 0; i < fieldCollection.size(); i++) { // 遍历字段配置集合
  427. String fieldName = "unknown";
  428. try {
  429. ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fieldCollection.get(i); // 获取当前字段配置
  430. ConfigInfoEntryInfo parent = configInfoEntryFieldInfo.getParent1(); // 获取父配置信息
  431. fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
  432. Object fieldValue = coreBaseInfo.get(fieldName); // 获取字段值
  433. logger.debug("Processing field: " + fieldName + " for record ID: " + recordId);
  434. // 封装字段信息为JSON对象
  435. JSONObject fieldJson = createFieldJson(configInfoEntryFieldInfo, fieldValue);
  436. // 将字段JSON对象存入结果JSON中
  437. jsonObject.put(fieldName, fieldJson);
  438. logger.debug("Successfully processed field: " + fieldName + " for record ID: " + recordId);
  439. } catch (Exception e) {
  440. e.printStackTrace();
  441. String errorMsg = "Error processing field: " + fieldName + " for record ID: " + recordId;
  442. logger.error(errorMsg, e);
  443. // 创建错误字段标记
  444. JSONObject errorField = new JSONObject();
  445. errorField.put("fieldName", fieldName);
  446. errorField.put("error", true);
  447. errorField.put("errorMessage", e.getMessage());
  448. jsonObject.put(fieldName, errorField);
  449. // 继续处理下一个字段
  450. continue;
  451. }
  452. }
  453. // 处理附件信息
  454. String id = coreBaseInfo.getId().toString();
  455. fileProcessor(id, jsonObject, context);
  456. }
  457. /**
  458. * 处理业务对象的附件信息
  459. * 根据业务对象ID查询关联的附件信息,并将附件详情添加到结果JSON对象中
  460. * 该方法通常在dataProcessing方法的最后调用,用于补充附件数据
  461. *
  462. * 处理流程:
  463. * 1. 根据业务ID查询关联的附件信息
  464. * 2. 提取附件名称和ID等关键信息
  465. * 3. 将附件信息组织成JSON格式并添加到结果集中
  466. * 4. 异常情况下记录错误日志并添加错误标记
  467. *
  468. * @param id 业务对象ID,用于查询关联的附件
  469. * @param jsonObject 结果数据集,附件信息将添加到该对象的"file"字段中
  470. * @param context 上下文对象,用于获取数据库连接和执行环境
  471. */
  472. public void fileProcessor(String id, JSONObject jsonObject, Context context) {
  473. JSONArray jsonArray = new JSONArray();
  474. try {
  475. JSONObject file = new JSONObject();
  476. // 查询与业务对象ID关联的所有附件信息
  477. SHRAttachmentExtCollection shrAttachmentExtCollection = SHRAttachmentExtFactory
  478. .getLocalInstance(context)
  479. .getSHRAttachmentExtCollection("select *,attachment.* where boid = '" + id + "'");
  480. // 遍历所有附件,提取关键信息
  481. for (int i = 0; i < shrAttachmentExtCollection.size(); i++) {
  482. SHRAttachmentExtInfo shrAttachmentExtInfo = shrAttachmentExtCollection.get(i);
  483. file.put("name", shrAttachmentExtInfo.getName()); // 附件名称
  484. file.put("id", shrAttachmentExtInfo.getAttachment().getId().toString()); // 附件ID
  485. jsonArray.add(file);
  486. }
  487. // 将附件信息数组添加到结果集
  488. jsonObject.put("file", jsonArray);
  489. } catch (BOSException e) {
  490. e.printStackTrace();
  491. // 记录附件处理错误日志
  492. String errorMsg = "Error processing file for business object ID: " + id;
  493. logger.error(errorMsg, e);
  494. // 创建错误字段标记,便于前端识别和处理
  495. JSONObject errorField = new JSONObject();
  496. errorField.put("field", "file");
  497. errorField.put("error", true);
  498. errorField.put("errorMessage", e.getMessage());
  499. jsonObject.put("file", errorField);
  500. }
  501. }
  502. /**
  503. * 创建字段JSON对象
  504. * 包含字段的基本信息(名称、别名、第三方字段名)和类型信息,以及根据类型处理后的字段值
  505. *
  506. * @param configInfoEntryFieldInfo 配置信息条目字段信息
  507. * @param fieldValue 字段值
  508. * @return 字段JSON对象
  509. * @throws ClassNotFoundException 当枚举类找不到时抛出
  510. */
  511. public JSONObject createFieldJson(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo, Object fieldValue)
  512. throws ClassNotFoundException {
  513. JSONObject fieldJson = new JSONObject(); // 创建字段JSON对象
  514. String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
  515. String fieldAlias = configInfoEntryFieldInfo.getFieldAlias(); // 获取字段别名
  516. DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型
  517. String thirdField = configInfoEntryFieldInfo.getThirdField(); // 获取第三方字段名
  518. fieldJson.put("fieldName", fieldName); // 添加字段名称
  519. fieldJson.put("fieldAlias", fieldAlias); // 添加字段别名
  520. fieldJson.put("thirdField", thirdField); // 添加第三方字段名
  521. // 添加字段类型信息
  522. JSONObject fieldTypeJson = new JSONObject(); // 创建字段类型JSON对象
  523. fieldTypeJson.put("alias", fieldType.getAlias()); // 添加类型别名
  524. fieldTypeJson.put("name", fieldType.getName()); // 添加类型名称
  525. fieldTypeJson.put("value", fieldType.getValue()); // 添加类型值
  526. fieldJson.put("fieldType", fieldTypeJson); // 添加字段类型信息
  527. // 根据字段类型处理字段值
  528. processFieldValueByType(configInfoEntryFieldInfo, fieldValue, fieldJson);
  529. return fieldJson; // 返回字段JSON对象
  530. }
  531. /**
  532. * 根据字段类型处理字段值
  533. * 针对不同类型的数据采用不同的处理策略,确保数据格式符合预期
  534. *
  535. * @param configInfoEntryFieldInfo 配置信息条目字段信息
  536. * @param fieldValue 字段值
  537. * @param fieldJson 字段JSON对象
  538. * @throws ClassNotFoundException 当枚举类找不到时抛出
  539. */
  540. public void processFieldValueByType(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo,
  541. Object fieldValue, JSONObject fieldJson)
  542. throws ClassNotFoundException {
  543. DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型
  544. String typeAlias = fieldType.getAlias(); // 获取类型别名
  545. if ("Enum".equals(typeAlias)) { // 处理枚举类型
  546. processEnumFieldValue(configInfoEntryFieldInfo, fieldValue, fieldJson);
  547. } else if ("ObjectValue".equals(typeAlias)) { // 处理对象值类型
  548. processObjectValueFieldValue(fieldValue, fieldJson);
  549. } else if ("ObjectCollection".equals(typeAlias)) { // 处理对象集合类型
  550. processObjectCollectionFieldValue(fieldValue, fieldJson);
  551. } else { // 处理其他类型
  552. fieldJson.put("value", fieldValue); // 直接添加字段值
  553. }
  554. }
  555. /**
  556. * 处理枚举类型字段值
  557. * 获取枚举类的所有可能值列表,并将当前字段值转换为对应的枚举别名
  558. *
  559. * @param configInfoEntryFieldInfo 配置信息条目字段信息
  560. * @param fieldValue 字段值
  561. * @param fieldJson 字段JSON对象
  562. * @throws ClassNotFoundException 当枚举类找不到时抛出
  563. */
  564. public void processEnumFieldValue(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo,
  565. Object fieldValue, JSONObject fieldJson)
  566. throws ClassNotFoundException {
  567. String source = configInfoEntryFieldInfo.getSource(); // 获取枚举源
  568. List<?> enumList = EnumUtils.getEnumList(source); // 获取枚举列表
  569. fieldJson.put("source", enumList); // 添加枚举源信息
  570. if (fieldValue != null) { // 检查字段值是否为空
  571. Integer value = (Integer) fieldValue; // 转换字段值为整数
  572. fieldJson.put("value", EnumUtils.getEnum(Class.forName(source), value).getAlias()); // 添加枚举值别名
  573. }
  574. }
  575. /**
  576. * 处理对象值类型字段值
  577. * 提取对象的名称和编号属性,构建简化的对象表示
  578. *
  579. * @param fieldValue 字段值
  580. * @param fieldJson 字段JSON对象
  581. */
  582. public void processObjectValueFieldValue(Object fieldValue, JSONObject fieldJson) {
  583. if (fieldValue instanceof CoreBaseInfo) { // 检查字段值是否为CoreBaseInfo类型
  584. CoreBaseInfo sourceCoreBaseInfo = (CoreBaseInfo) fieldValue; // 转换字段值
  585. JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象
  586. sourceJSONObject.put("name", sourceCoreBaseInfo.get("name")); // 添加名称属性
  587. sourceJSONObject.put("number", sourceCoreBaseInfo.get("number")); // 添加编号属性
  588. fieldJson.put("value", sourceJSONObject); // 添加源对象信息
  589. }
  590. }
  591. /**
  592. * 处理对象集合类型字段值
  593. * 遍历集合中的每个对象,提取名称和编号属性,构建对象数组
  594. *
  595. * @param fieldValue 字段值
  596. * @param fieldJson 字段JSON对象
  597. */
  598. public void processObjectCollectionFieldValue(Object fieldValue, JSONObject fieldJson) {
  599. if (fieldValue instanceof IObjectCollection) { // 检查字段值是否为对象集合类型
  600. IObjectCollection collection = (IObjectCollection) fieldValue; // 转换字段值
  601. JSONArray jsonArray = new JSONArray(); // 创建JSON数组
  602. for (int j = 0; j < collection.size(); j++) { // 遍历集合
  603. Object object = collection.getObject(j); // 获取当前对象
  604. if (object instanceof CoreBaseInfo) { // 检查对象是否为CoreBaseInfo类型
  605. CoreBaseInfo coreBaseInfo = (CoreBaseInfo) object; // 转换对象
  606. JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象
  607. sourceJSONObject.put("name", coreBaseInfo.get("name")); // 添加名称属性
  608. sourceJSONObject.put("number", coreBaseInfo.get("number")); // 添加编号属性
  609. jsonArray.add(sourceJSONObject); // 将源对象添加到数组
  610. }
  611. }
  612. fieldJson.put("value", jsonArray); // 添加对象数组
  613. }
  614. }
  615. /**
  616. * 根据配置的字段集合构建查询选择器,指定查询时需要返回的字段
  617. * 对于对象值类型的字段,额外添加相关字段(名称、编号和所有字段)
  618. *
  619. * @param fields 配置的字段集合
  620. * @return 包含所有需要查询的字段的选择器集合
  621. */
  622. public SelectorItemCollection getSelectorItem(ConfigInfoEntryFieldCollection fields) {
  623. SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合
  624. for (int i = 0; i < fields.size(); i++) { // 遍历字段配置集合
  625. ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fields.get(i); // 获取当前字段配置
  626. String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
  627. DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型
  628. // 添加字段到选择器
  629. selectorItemCollection.add(fieldName); // 添加字段名称
  630. // 对于对象值类型,额外添加相关字段
  631. if ("ObjectValue".equals(fieldType.getAlias())) { // 检查是否为对象值类型
  632. selectorItemCollection.add(fieldName + ".name"); // 添加名称字段
  633. selectorItemCollection.add(fieldName + ".number"); // 添加编号字段
  634. selectorItemCollection.add(fieldName + ".*"); // 添加所有字段
  635. }
  636. }
  637. selectorItemCollection.add("id"); // 添加ID字段
  638. return selectorItemCollection; // 返回选择器集合
  639. }
  640. /**
  641. * 创建实体视图查询条件,用于查询配置信息
  642. * 根据配置编号和实体属性类型过滤配置信息,并指定需要返回的字段
  643. *
  644. * @param configNumber 配置编号,用于精确匹配配置
  645. * @param type 实体属性类型(如HEAD/ENTRY),用于过滤特定类型的配置
  646. * @return 构建好的实体查询视图
  647. */
  648. public EntityViewInfo createEntityViewInfo(String configNumber, String type) {
  649. EntityViewInfo entityViewInfo = new EntityViewInfo(); // 创建实体视图信息
  650. // 创建过滤条件
  651. FilterInfo filterInfo = new FilterInfo(); // 创建过滤器
  652. filterInfo.getFilterItems().add(new FilterItemInfo("parent.number", configNumber, CompareType.EQUALS)); // 添加父级编号过滤条件
  653. filterInfo.getFilterItems().add(new FilterItemInfo("entityAttribute", type, CompareType.EQUALS)); // 添加实体属性过滤条件
  654. entityViewInfo.setFilter(filterInfo); // 设置过滤器
  655. // 构建查询选择器,指定需要返回的字段
  656. SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合
  657. selectorItemCollection.add("parent.*"); // 添加父表所有字段
  658. selectorItemCollection.add("*"); // 添加条目表所有字段
  659. selectorItemCollection.add("Fields.*"); // 添加字段配置表所有字段
  660. entityViewInfo.setSelector(selectorItemCollection); // 设置选择器
  661. return entityViewInfo; // 返回实体视图信息
  662. }
  663. /**
  664. * 处理排序字段字符串,转换为排序器集合
  665. * 支持以下格式:
  666. * 1. "field1 ASC, field2 DESC" - 明确指定排序方向
  667. * 2. "field1, field2" - 默认使用升序
  668. *
  669. * @param sortField 排序字段字符串,格式如 "field1 ASC, field2 DESC"
  670. * @return 排序器集合,如果排序字段为空则返回null
  671. */
  672. public SorterItemCollection sorterProcessing(String sortField) {
  673. if (sortField == null || sortField.trim().isEmpty()) { // 检查排序字段是否为空
  674. return null; // 返回空值
  675. }
  676. SorterItemCollection sorterItemCollection = new SorterItemCollection(); // 创建排序器集合
  677. String[] sortFields = sortField.split(","); // 分割排序字段
  678. for (String field : sortFields) { // 遍历排序字段数组
  679. SorterItemInfo sorterItemInfo = new SorterItemInfo(); // 创建排序器信息
  680. String trimmedField = field.trim().toLowerCase(); // 去除空格并转换为小写
  681. if (trimmedField.contains("asc")) { // 检查是否包含升序关键字
  682. String propertyName = trimmedField.replace("asc", "").trim(); // 移除升序关键字
  683. sorterItemInfo.setPropertyName(propertyName); // 设置属性名称
  684. sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序
  685. } else if (trimmedField.contains("desc")) { // 检查是否包含降序关键字
  686. String propertyName = trimmedField.replace("desc", "").trim(); // 移除降序关键字
  687. sorterItemInfo.setPropertyName(propertyName); // 设置属性名称
  688. sorterItemInfo.setSortType(SortType.DESCEND); // 设置降序排序
  689. } else { // 默认情况
  690. sorterItemInfo.setPropertyName(trimmedField); // 设置属性名称
  691. sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序
  692. }
  693. sorterItemCollection.add(sorterItemInfo); // 添加排序器到集合
  694. }
  695. return sorterItemCollection; // 返回排序器集合
  696. }
  697. /**
  698. * 初始化集合数据
  699. * 通过业务接口获取指定实体的数据集合
  700. *
  701. * @param entityName 实体名称
  702. * @param entityViewInfo 实体视图信息
  703. * @param context 上下文对象
  704. * @return 核心基础集合
  705. * @throws SHRWebException SHR Web异常
  706. * @throws ParserException 解析异常
  707. * @throws BOSException 业务异常
  708. */
  709. public CoreBaseCollection initCollection(String entityName, EntityViewInfo entityViewInfo, Context context)
  710. throws SHRWebException, ParserException, BOSException {
  711. IQueryExecutor queryExecutor = this.getQueryExecutor(context, entityViewInfo, entityName); // 获取查询执行器
  712. Uuid uuid = queryExecutor.openQuery(); // 打开查询
  713. VirtualDataFetcher vdf = VirtualDataFetcher.createInstance(queryExecutor, uuid, 0, 1000); // 创建虚拟数据获取器
  714. List<Map<String, Object>> data = vdf.getData(); // 获取数据
  715. CoreBaseCollection collection = new CoreBaseCollection(); // 创建核心基础集合
  716. for (int i = 0; i < data.size(); i++) { // 遍历数据
  717. Map<String, Object> stringObjectMap = data.get(i); // 获取当前数据项
  718. String string = stringObjectMap.get("id").toString(); // 获取ID字符串
  719. BOSUuid read = BOSUuid.read(string); // 读取BOS UUID
  720. EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(read.getType()); // 获取实体对象信息
  721. String fullName = entityObject.getFullName(); // 获取完整类名
  722. Class<?> targetClass = MetaDataUtil.getObjectValueClass(fullName); // 获取目标类
  723. CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, fullName); // 创建核心基础信息实例
  724. SelectorItemCollection selector = entityViewInfo.getSelector(); // 获取选择器
  725. for (int j = 0; j < selector.size(); j++) { // 遍历选择器
  726. SelectorItemInfo selectorItemInfo = selector.get(j); // 获取当前选择器项
  727. String propertyName = selectorItemInfo.getPropertyName(); // 获取属性名称
  728. coreBaseInfo.put(propertyName, stringObjectMap.get(propertyName)); // 设置属性值
  729. }
  730. collection.add(coreBaseInfo); // 添加到集合
  731. }
  732. return collection; // 返回集合
  733. }
  734. /**
  735. * 获取查询执行器
  736. * 创建并配置查询执行器,用于执行数据查询操作
  737. *
  738. * @param context 上下文对象
  739. * @param entityViewInfo 实体视图信息
  740. * @param query 查询字符串
  741. * @return 查询执行器
  742. * @throws SHRWebException SHR Web异常
  743. * @throws ShrWebBizException 业务异常
  744. * @throws BOSException 业务异常
  745. * @throws ParserException 解析异常
  746. */
  747. public IQueryExecutor getQueryExecutor(Context context,
  748. EntityViewInfo entityViewInfo,
  749. String query) throws SHRWebException, ShrWebBizException, BOSException, ParserException {
  750. IQueryExecutor exec = QueryExecutorFactory.getLocalInstance(context, MetaDataPK.create(query)); // 创建查询执行器
  751. exec.setObjectView(entityViewInfo); // 设置对象视图
  752. exec.option().isIgnoreOrder = true; // 设置忽略排序
  753. exec.option().isAutoIgnoreZero = true; // 设置自动忽略零值
  754. exec.option().isAutoTranslateBoolean = true; // 设置自动转换布尔值
  755. exec.option().isAutoTranslateEnum = true; // 设置自动转换枚举
  756. exec.option().isIgnorePermissionCheck = false; // 设置不忽略权限检查
  757. return exec; // 返回查询执行器
  758. }
  759. /**
  760. * 获取业务接口
  761. * 根据实体名称获取对应的业务接口实例
  762. *
  763. * @param entityName 实体名称
  764. * @return 核心基础接口
  765. * @throws SHRWebException SHR Web异常
  766. */
  767. public ICoreBase getBizInterface(String entityName) throws SHRWebException {
  768. if (entityName == null) { // 检查实体名称是否为空
  769. return null; // 返回空值
  770. }
  771. try {
  772. return MetaDataUtil.getBizInterface(SHRContext.getInstance().getContext(), entityName); // 获取业务接口
  773. } catch (BOSException e) {
  774. e.printStackTrace();
  775. throw new SHRWebException(e); // 抛出SHR Web异常
  776. }
  777. }
  778. /**
  779. * 给CoreBaseInfo类型对象设置属性值,支持级联属性
  780. * 支持"主属性.子属性"格式的属性路径,可以设置嵌套对象的属性值
  781. *
  782. * @param ctx 上下文对象,用于获取元数据信息
  783. * @param coreBaseInfo 要设置属性值的目标对象
  784. * @param name 属性名称,支持"主属性.子属性"格式的级联属性
  785. * @param value 要设置的属性值
  786. * @throws BOSException 当操作过程中发生业务异常时抛出
  787. */
  788. public void setCoreBaseInfo(Context ctx, IObjectValue coreBaseInfo, String name, Object value) throws BOSException {
  789. // 判断是否为级联属性
  790. if (name.contains(".")) { // 检查是否包含点号
  791. String[] split = name.split("\\."); // 分割属性名称
  792. Object parentValue = coreBaseInfo.get(split[0]); // 获取父属性值
  793. // 获取实体元数据信息
  794. EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(coreBaseInfo.getBOSType()); // 获取实体对象信息
  795. PropertyCollection properties = entityObject.getInheritedNoDuplicatedProperties(); // 获取属性集合
  796. PropertyInfo propertyInfo = (PropertyInfo) properties.getObject(split[0]); // 获取属性信息
  797. // 处理关联属性
  798. if (propertyInfo instanceof LinkPropertyInfo) { // 检查是否为链接属性
  799. LinkPropertyInfo linkProperty = (LinkPropertyInfo) propertyInfo; // 转换属性信息
  800. RelationshipInfo relationship = linkProperty.getRelationship(); // 获取关系信息
  801. String targetFullName = relationship.getSupplierObject().getFullName(); // 获取目标完整名称
  802. try {
  803. Class<?> targetClass = MetaDataUtil.getObjectValueClass(targetFullName); // 获取目标类
  804. CoreBaseInfo childObject = getOrCreateChildObject(parentValue, targetClass, targetFullName); // 获取或创建子对象
  805. // 给子对象设置级联属性的子属性值
  806. if (childObject != null) { // 检查子对象是否为空
  807. childObject.put(split[1], value); // 设置子属性值
  808. }
  809. } catch (ShrWebBizException e) {
  810. e.printStackTrace();
  811. throw new BOSException("获取目标类失败: " + e.getMessage(), e); // 抛出业务异常
  812. }
  813. }
  814. } else {
  815. // 非级联属性,直接设置值
  816. coreBaseInfo.put(name, value); // 设置属性值
  817. }
  818. }
  819. /**
  820. * 获取或创建子对象
  821. * 根据父属性值的类型(集合或单个对象),获取现有子对象或创建新的子对象
  822. *
  823. * @param parentValue 父属性值
  824. * @param targetClass 目标类
  825. * @param targetFullName 目标全名
  826. * @return 子对象
  827. */
  828. public CoreBaseInfo getOrCreateChildObject(Object parentValue, Class<?> targetClass, String targetFullName) {
  829. CoreBaseInfo childObject = null; // 初始化子对象
  830. if (parentValue instanceof IObjectCollection) { // 检查父属性值是否为对象集合
  831. IObjectCollection collection = (IObjectCollection) parentValue; // 转换父属性值
  832. if (collection.size() == 0) { // 检查集合是否为空
  833. childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例
  834. collection.addObject(childObject); // 添加到集合
  835. } else {
  836. childObject = (CoreBaseInfo) collection.getObject(0); // 获取第一个对象
  837. }
  838. } else if (parentValue instanceof CoreBaseInfo) { // 检查父属性值是否为CoreBaseInfo
  839. if (parentValue == null) { // 检查是否为空
  840. childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例
  841. } else {
  842. childObject = (CoreBaseInfo) parentValue; // 使用现有对象
  843. }
  844. }
  845. return childObject; // 返回子对象
  846. }
  847. /**
  848. * 主方法,用于本地测试
  849. * 可以在此添加测试代码,验证类的功能
  850. *
  851. * @param args 命令行参数
  852. */
  853. public static void main(String[] args) {
  854. // 测试代码可以在这里添加
  855. System.out.println("AssistSynchronizingFacadeControllerBean main method"); // 输出主方法信息
  856. }
  857. }