package com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.kingdee.bos.BOSException; import com.kingdee.bos.BOSObjectFactory; import com.kingdee.bos.Context; import com.kingdee.bos.dao.IObjectCollection; import com.kingdee.bos.dao.IObjectValue; import com.kingdee.bos.dao.query.IQueryExecutor; import com.kingdee.bos.dao.query.QueryExecutorFactory; import com.kingdee.bos.metadata.MetaDataPK; import com.kingdee.bos.metadata.data.SortType; import com.kingdee.bos.metadata.entity.*; import com.kingdee.bos.metadata.query.util.CompareType; import com.kingdee.bos.sql.ParserException; import com.kingdee.bos.util.BOSObjectType; import com.kingdee.bos.util.BOSUuid; import com.kingdee.eas.common.EASBizException; import com.kingdee.eas.custom.thirdpartysystemsyn.config.viewconfig.*; import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.DataTypeEnum; import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.EntityAttributeEnum; import com.kingdee.eas.framework.CoreBaseCollection; import com.kingdee.eas.framework.CoreBaseInfo; import com.kingdee.eas.framework.ICoreBase; import com.kingdee.shr.attachment.SHRAttachmentExtCollection; import com.kingdee.shr.attachment.SHRAttachmentExtFactory; import com.kingdee.shr.attachment.SHRAttachmentExtInfo; import com.kingdee.shr.base.syssetting.MSFServiceFacadeFactory; import com.kingdee.shr.base.syssetting.context.SHRContext; import com.kingdee.shr.base.syssetting.exception.SHRWebException; import com.kingdee.shr.base.syssetting.exception.ShrWebBizException; import com.kingdee.shr.base.syssetting.model.VirtualDataFetcher; import com.kingdee.shr.base.syssetting.util.MetaDataUtil; import com.kingdee.util.Uuid; import com.kingdee.util.enums.EnumUtils; import org.apache.log4j.Logger; import java.util.*; public class AssistSynchronizingUtils { // 日志记录器,用于记录系统操作日志 private static final Logger logger = Logger.getLogger("com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils.AssistSynchronizingUtils"); /** * 重写父类方法,根据配置编号和过滤条件获取数据 * 该方法主要执行以下步骤: * 1. 解析过滤条件JSON字符串 * 2. 获取头部配置信息 * 3. 构建查询条件并执行查询 * 4. 处理查询结果并转换为JSON格式 * 5. 处理分录数据(如果存在) * * @param ctx 上下文对象 * @param configNumber 配置编号,用于定位具体的同步配置 * @param filterInfos 过滤条件信息,JSON格式字符串 * @return 处理后的结果数据,JSON格式字符串 * @throws BOSException 当操作过程中发生业务异常时抛出 */ public JSONArray getData(Context ctx, String configNumber, String filterInfos) throws BOSException { // 记录方法调用日志,包含入参信息 logger.info("Starting getData method with configNumber: " + configNumber + ", filterInfos: " + filterInfos); // 用于记录处理统计信息 int totalRecords = 0; int successRecords = 0; int failedRecords = 0; JSONArray errorDetails = new JSONArray(); // 解析过滤条件JSON字符串为JSONObject JSONObject jsonObject = JSONObject.parseObject(filterInfos); JSONArray resultArray = new JSONArray(); // 创建结果数组 try { // 获取头部配置信息 logger.debug("Getting head configuration for configNumber: " + configNumber); EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE); ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry); // 验证条目信息是否唯一 if (entries.size() != 1) { String errorMsg = "头部信息配置异常,期望1条配置但找到" + entries.size() + "条"; logger.error(errorMsg); throw new RuntimeException(errorMsg); // 抛出配置异常 } // 获取唯一的条目信息 ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0); String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称 logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber); // 创建实体查询视图并设置查询条件 EntityViewInfo headEntityViewInfo = new EntityViewInfo(); String filterExpr = jsonObject.getString(entityName); // 获取实体对应的过滤条件 if (filterExpr != null && !filterExpr.trim().isEmpty()) { // 检查过滤条件是否非空 headEntityViewInfo.setFilter(filterExpr); // 设置过滤条件 logger.debug("Set filter for entity " + entityName + ": " + filterExpr); } // 设置查询字段 ConfigInfoEntryFieldCollection fields = configInfoEntryInfo.getFields(); SelectorItemCollection selectorItem = getSelectorItem(fields); // 获取选择器项目 headEntityViewInfo.setSelector(selectorItem); // 设置选择器 logger.debug("Set selector with " + selectorItem.size() + " fields"); // 设置排序 String sortField = configInfoEntryInfo.getSortField(); // 获取排序字段 SorterItemCollection sorterItemCollection = sorterProcessing(sortField); // 处理排序字段 if (sorterItemCollection != null) { headEntityViewInfo.setSorter(sorterItemCollection); // 设置排序器 logger.debug("Set sorter with " + sorterItemCollection.size() + " fields"); } // 执行查询获取数据集合 boolean isQuery = configInfoEntryInfo.isIsQuery(); // 判断是否为查询类型 CoreBaseCollection collection; // 声明数据集合 if (isQuery) { logger.debug("Initializing collection using query for entity: " + entityName); collection = this.initCollection(entityName, headEntityViewInfo, ctx); // 初始化集合 } else { String bosType = configInfoEntryInfo.getBosType(); // 获取BOS类型 BOSObjectType bosObjectType = BOSObjectType.create(bosType); // 创建BOS对象类型 logger.debug("Getting collection using BOS object type: " + bosType); // 根据BOS类型创建对应的业务对象实例 ICoreBase bosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, bosObjectType); collection = bosObject.getCollection(headEntityViewInfo); // 获取数据集合 } totalRecords = collection.size(); logger.info("Retrieved " + totalRecords + " records for processing"); // 处理查询结果 processCollectionData(ctx, configNumber, jsonObject, resultArray, collection, configInfoEntryInfo, fields, errorDetails); successRecords = resultArray.size(); failedRecords = totalRecords - successRecords; logger.info("Data processing completed. Success: " + successRecords + ", Failed: " + failedRecords + ", Total: " + totalRecords); } catch (Exception e) { e.printStackTrace(); String errorMsg = "Error occurred while getting data for configNumber: " + configNumber; logger.error(errorMsg, e); // 创建错误详情记录 JSONObject errorDetail = new JSONObject(); errorDetail.put("configNumber", configNumber); errorDetail.put("errorType", "MAIN_PROCESS_ERROR"); errorDetail.put("errorMessage", e.getMessage()); errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace())); errorDetails.add(errorDetail); failedRecords = totalRecords; // 所有记录都标记为失败 successRecords = 0; throw new BOSException("数据获取失败: " + e.getMessage(), e); // 抛出业务异常 } finally { // 记录最终处理结果统计 JSONObject processSummary = new JSONObject(); processSummary.put("configNumber", configNumber); processSummary.put("totalRecords", totalRecords); processSummary.put("successRecords", successRecords); processSummary.put("failedRecords", failedRecords); processSummary.put("errorDetails", errorDetails); logger.info("Process summary: " + processSummary.toJSONString()); } logger.info("Successfully retrieved data, result size: " + resultArray.size()); return resultArray; } public void saveData(Context ctx, String configNumber, String controllerBeanEx) throws BOSException { EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE); ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry); // 验证条目信息是否唯一 if (entries.size() != 1) { String errorMsg = "头部信息配置异常,期望1条配置但找到" + entries.size() + "条"; logger.error(errorMsg); throw new RuntimeException(errorMsg); // 抛出配置异常 } // 获取唯一的条目信息 ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0); String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称 logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber); ConfigInfoInfo parent = configInfoEntryInfo.getParent(); //osf服务名 String osfName = parent.getOsfName(); String osfParam = parent.getOsfParam(); Object o = null; try { o = MSFServiceFacadeFactory.getLocalInstance(ctx).processService(osfName, this.getOSFParam(osfParam)); } catch (EASBizException e) { throw new RuntimeException(e); } JSONArray osfReturnData = JSONArray.parseArray(o.toString()); for (int i = 0; i < osfReturnData.size(); i++) { JSONObject osfReturnDataEntry = osfReturnData.getJSONObject(i); //处理头部信息 boolean isCreateData = configInfoEntryInfo.isIsCreateData();//是否创建数据 String thirdUniqueValue = configInfoEntryInfo.getThirdUniqueValue();//第三方唯一值 String hrUniqueValue = configInfoEntryInfo.getHrUniqueValue();//hr唯一值 String bosType = configInfoEntryInfo.getBosType(); Class objectValueClass1 = null; try { objectValueClass1 = MetaDataUtil.getObjectValueClass(entityName); // 创建对应的实体对象 CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(objectValueClass1, entityName); if (!isCreateData){ String value = getThirdUniqueValue(osfReturnDataEntry, thirdUniqueValue); if (value!=null){ CoreBaseInfo coreBaseInfo1 = findCoreBaseInfo(ctx, coreBaseInfo.getBOSType(), value, hrUniqueValue); if (coreBaseInfo1!=null){ coreBaseInfo = coreBaseInfo1; } } } } catch (ShrWebBizException e) { throw new RuntimeException(e); } } } public String getThirdUniqueValue(JSONObject jsonObject,String thirdUniqueValue){ String[] split = thirdUniqueValue.split("\\."); Object value = null; for (int i = 0; i < split.length; i++) { String s = split[i]; value = jsonObject.get(s); if (value instanceof JSONArray){ JSONArray jsonArray = jsonObject.getJSONArray(s); value = jsonArray.get(0); } } return value==null?null:value.toString(); } public CoreBaseInfo findCoreBaseInfo(Context ctx,BOSObjectType bosObjectType, String thirdUniqueValue, String hrUniqueValue) throws BOSException { ICoreBase bosObject = (ICoreBase) (BOSObjectFactory.createBOSObject(ctx,bosObjectType)); CoreBaseCollection collection = bosObject.getCollection("where " + hrUniqueValue + " = '" + thirdUniqueValue + "' "); if (collection.size()>1){ throw new RuntimeException(""); } else if (collection.size()==0) { return null; }else { return collection.get(0); } } public Map getOSFParam(String jsonData){ if (jsonData!=null&&!jsonData.equals("")){ JSONObject param = JSONObject.parseObject(jsonData); Set strings = param.keySet(); Iterator iterator = strings.iterator(); Map map = new HashMap(); while (iterator.hasNext()){ String next = iterator.next(); map.put(next,param.get(next)); } return map; }else { return null; } } /** * 处理查询结果集合数据 * 遍历集合中的每个CoreBaseInfo对象,将其转换为JSON格式,并处理相关的分录数据 * * @param ctx 上下文对象 * @param configNumber 配置编号 * @param jsonObject 过滤条件JSON对象 * @param resultArray 结果数组 * @param collection 查询结果集合 * @param configInfoEntryInfo 配置条目信息 * @param fields 字段配置集合 * @param errorDetails 错误详情数组,用于记录处理过程中的错误 * @throws BOSException 业务异常 * @throws ClassNotFoundException 类未找到异常 * @throws ParserException 解析异常 * @throws SHRWebException SHR Web异常 */ public void processCollectionData(Context ctx, String configNumber, JSONObject jsonObject, JSONArray resultArray, CoreBaseCollection collection, ConfigInfoEntryInfo configInfoEntryInfo, ConfigInfoEntryFieldCollection fields, JSONArray errorDetails) throws BOSException, ClassNotFoundException, ParserException, SHRWebException { for (int i = 0; i < collection.size(); i++) { // 遍历集合中的每个元素 String recordId = "unknown"; try { CoreBaseInfo coreBaseInfo = collection.get(i); // 获取当前元素 recordId = coreBaseInfo.getId() != null ? coreBaseInfo.getId().toString() : "unknown"; logger.debug("Processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId); JSONObject resultData = new JSONObject(); // 创建结果数据对象 JSONObject mainData = new JSONObject(); // 创建主数据对象 // 处理单条数据,转换为JSON格式 dataProcessing(mainData, coreBaseInfo, fields, recordId, ctx); String name = configInfoEntryInfo.getName(); // 获取配置名称 resultData.put(name, mainData); // 将主数据添加到结果数据 // 处理分录数据 processEntryData(ctx, configNumber, jsonObject, resultData, coreBaseInfo, recordId, errorDetails); resultArray.add(resultData); // 将结果数据添加到结果数组 logger.debug("Successfully processed record ID: " + recordId); } catch (Exception e) { e.printStackTrace(); String errorMsg = "Error processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId; logger.error(errorMsg, e); // 创建错误详情记录 JSONObject errorDetail = new JSONObject(); errorDetail.put("configNumber", configNumber); errorDetail.put("recordId", recordId); errorDetail.put("recordIndex", i); errorDetail.put("errorType", "RECORD_PROCESSING_ERROR"); errorDetail.put("errorMessage", e.getMessage()); errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace())); errorDetails.add(errorDetail); // 继续处理下一条记录 continue; } } } /** * 处理分录数据 * 获取配置中的分录信息,根据关联字段查询相关的分录数据,并将其转换为JSON格式 * * @param ctx 上下文对象 * @param configNumber 配置编号 * @param jsonObject 过滤条件JSON对象 * @param resultData 结果数据对象 * @param coreBaseInfo 核心基础信息对象 * @param recordId 当前处理的主记录ID * @param errorDetails 错误详情数组,用于记录处理过程中的错误 * @throws BOSException 业务异常 * @throws ClassNotFoundException 类未找到异常 * @throws ParserException 解析异常 * @throws SHRWebException SHR Web异常 */ public void processEntryData(Context ctx, String configNumber, JSONObject jsonObject, JSONObject resultData, CoreBaseInfo coreBaseInfo, String recordId, JSONArray errorDetails) throws BOSException, ClassNotFoundException, ParserException, SHRWebException { try { // 获取分录为 boy类型的配置 EntityViewInfo boyEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.BOY_VALUE); ConfigInfoEntryCollection entryCollection = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(boyEntry); for (int j = 0; j < entryCollection.size(); j++) { // 遍历分录配置集合 ConfigInfoEntryInfo configInfoEntryInfo1 = entryCollection.get(j); // 获取当前分录配置 String boyEntityName = configInfoEntryInfo1.getEntityName(); // 获取分录实体名称 ConfigInfoEntryFieldCollection boyFields = configInfoEntryInfo1.getFields(); // 获取分录字段配置 logger.debug("Processing entry data for entity: " + boyEntityName + ", main record ID: " + recordId); // 创建分录查询视图 EntityViewInfo boyEntityViewInfo = new EntityViewInfo(); String boyFilterExpr = jsonObject.getString(boyEntityName); // 获取分录过滤条件 // 设置关联字段过滤条件 String crelatedField = configInfoEntryInfo1.getCrelatedField(); // 获取关联字段 FilterInfo filter = new FilterInfo(); // 创建过滤器 String id = coreBaseInfo.getId().toString(); // 获取主数据ID filter.getFilterItems().add(new FilterItemInfo(crelatedField, id, CompareType.EQUALS)); // 添加关联字段过滤条件 if (boyFilterExpr != null && !boyFilterExpr.trim().isEmpty()) { // 检查分录过滤条件是否非空 filter.getFilterItems().add(new FilterItemInfo(boyFilterExpr)); // 添加分录过滤条件 } boyEntityViewInfo.setFilter(filter); // 设置过滤器 // 设置查询字段 SelectorItemCollection boySelectorItem = getSelectorItem(boyFields); // 获取分录选择器 boyEntityViewInfo.setSelector(boySelectorItem); // 设置选择器 // 执行查询获取分录数据 boolean isQuery1 = configInfoEntryInfo1.isIsQuery(); // 判断是否为查询类型 CoreBaseCollection boyCollection; // 声明分录数据集合 if (isQuery1) { boyCollection = this.initCollection(boyEntityName, boyEntityViewInfo, ctx); // 初始化分录集合 } else { String boyDosType = configInfoEntryInfo1.getBosType(); // 获取分录BOS类型 BOSObjectType boyBosObjectType = BOSObjectType.create(boyDosType); // 创建BOS对象类型 ICoreBase boyBosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, boyBosObjectType); // 创建业务对象 boyCollection = boyBosObject.getCollection(boyEntityViewInfo); // 获取分录数据集合 } logger.debug("Retrieved " + boyCollection.size() + " entry records for entity: " + boyEntityName + ", main record ID: " + recordId); // 处理分录数据 JSONArray entryDataArray = new JSONArray(); // 创建分录数据数组 for (int k = 0; k < boyCollection.size(); k++) { // 遍历分录数据集合 try { CoreBaseInfo coreBaseInfo1 = boyCollection.get(k); // 获取当前分录数据 String entryRecordId = coreBaseInfo1.getId() != null ? coreBaseInfo1.getId().toString() : "unknown"; JSONObject entryData = new JSONObject(); // 创建分录数据对象 dataProcessing(entryData, coreBaseInfo1, boyFields, entryRecordId, ctx); // 处理分录数据 entryDataArray.add(entryData); // 将分录数据添加到数组 logger.debug("Processed entry record " + (k+1) + "/" + boyCollection.size() + ", ID: " + entryRecordId + " for main record ID: " + recordId); } catch (Exception e) { e.printStackTrace(); String errorMsg = "Error processing entry record " + (k+1) + "/" + boyCollection.size() + " for main record ID: " + recordId; logger.error(errorMsg, e); // 创建错误详情记录 JSONObject errorDetail = new JSONObject(); errorDetail.put("configNumber", configNumber); errorDetail.put("mainRecordId", recordId); errorDetail.put("entryEntity", boyEntityName); errorDetail.put("entryIndex", k); errorDetail.put("errorType", "ENTRY_RECORD_PROCESSING_ERROR"); errorDetail.put("errorMessage", e.getMessage()); errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace())); errorDetails.add(errorDetail); // 继续处理下一条分录记录 continue; } } String name1 = configInfoEntryInfo1.getName(); // 获取分录配置名称 resultData.put(name1, entryDataArray); // 将分录数据添加到结果数据 logger.debug("Completed processing entry data for entity: " + boyEntityName + ", main record ID: " + recordId + ", records: " + entryDataArray.size()); } } catch (Exception e) { e.printStackTrace(); String errorMsg = "Error processing entry data for main record ID: " + recordId; logger.error(errorMsg, e); // 创建错误详情记录 JSONObject errorDetail = new JSONObject(); errorDetail.put("configNumber", configNumber); errorDetail.put("mainRecordId", recordId); errorDetail.put("errorType", "ENTRY_PROCESSING_ERROR"); errorDetail.put("errorMessage", e.getMessage()); errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace())); errorDetails.add(errorDetail); // 抛出异常,由上层处理 throw new RuntimeException(e); } } /** * 处理单条CoreBaseInfo数据,将其字段信息转换为JSONObject * 根据字段类型的不同,采用不同的处理方式: * 1. 枚举类型:获取枚举列表和当前值的别名 * 2. 对象值类型:提取对象的名称和编号 * 3. 对象集合类型:提取集合中每个对象的名称和编号 * 4. 其他类型:直接使用字段值 * 5. 最后处理附件信息 * * @param jsonObject 用于存储处理后数据的JSON对象 * @param coreBaseInfo 待处理的业务数据对象 * @param fieldCollection 配置的字段集合,包含需要处理的字段信息 * @param recordId 当前处理的记录ID,用于日志记录 * @param context 上下文对象,用于获取附件信息 * @throws ClassNotFoundException 当枚举类找不到时抛出 */ public void dataProcessing(JSONObject jsonObject, CoreBaseInfo coreBaseInfo, ConfigInfoEntryFieldCollection fieldCollection, String recordId, Context context) throws ClassNotFoundException { for (int i = 0; i < fieldCollection.size(); i++) { // 遍历字段配置集合 String fieldName = "unknown"; try { ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fieldCollection.get(i); // 获取当前字段配置 ConfigInfoEntryInfo parent = configInfoEntryFieldInfo.getParent1(); // 获取父配置信息 fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称 Object fieldValue = coreBaseInfo.get(fieldName); // 获取字段值 logger.debug("Processing field: " + fieldName + " for record ID: " + recordId); // 封装字段信息为JSON对象 JSONObject fieldJson = createFieldJson(configInfoEntryFieldInfo, fieldValue); // 将字段JSON对象存入结果JSON中 jsonObject.put(fieldName, fieldJson); logger.debug("Successfully processed field: " + fieldName + " for record ID: " + recordId); } catch (Exception e) { e.printStackTrace(); String errorMsg = "Error processing field: " + fieldName + " for record ID: " + recordId; logger.error(errorMsg, e); // 创建错误字段标记 JSONObject errorField = new JSONObject(); errorField.put("fieldName", fieldName); errorField.put("error", true); errorField.put("errorMessage", e.getMessage()); jsonObject.put(fieldName, errorField); // 继续处理下一个字段 continue; } } // 处理附件信息 String id = coreBaseInfo.getId().toString(); fileProcessor(id, jsonObject, context); } /** * 处理业务对象的附件信息 * 根据业务对象ID查询关联的附件信息,并将附件详情添加到结果JSON对象中 * 该方法通常在dataProcessing方法的最后调用,用于补充附件数据 * * 处理流程: * 1. 根据业务ID查询关联的附件信息 * 2. 提取附件名称和ID等关键信息 * 3. 将附件信息组织成JSON格式并添加到结果集中 * 4. 异常情况下记录错误日志并添加错误标记 * * @param id 业务对象ID,用于查询关联的附件 * @param jsonObject 结果数据集,附件信息将添加到该对象的"file"字段中 * @param context 上下文对象,用于获取数据库连接和执行环境 */ public void fileProcessor(String id, JSONObject jsonObject, Context context) { JSONArray jsonArray = new JSONArray(); try { JSONObject file = new JSONObject(); // 查询与业务对象ID关联的所有附件信息 SHRAttachmentExtCollection shrAttachmentExtCollection = SHRAttachmentExtFactory .getLocalInstance(context) .getSHRAttachmentExtCollection("select *,attachment.* where boid = '" + id + "'"); // 遍历所有附件,提取关键信息 for (int i = 0; i < shrAttachmentExtCollection.size(); i++) { SHRAttachmentExtInfo shrAttachmentExtInfo = shrAttachmentExtCollection.get(i); file.put("name", shrAttachmentExtInfo.getName()); // 附件名称 file.put("id", shrAttachmentExtInfo.getAttachment().getId().toString()); // 附件ID jsonArray.add(file); } // 将附件信息数组添加到结果集 jsonObject.put("file", jsonArray); } catch (BOSException e) { e.printStackTrace(); // 记录附件处理错误日志 String errorMsg = "Error processing file for business object ID: " + id; logger.error(errorMsg, e); // 创建错误字段标记,便于前端识别和处理 JSONObject errorField = new JSONObject(); errorField.put("field", "file"); errorField.put("error", true); errorField.put("errorMessage", e.getMessage()); jsonObject.put("file", errorField); } } /** * 创建字段JSON对象 * 包含字段的基本信息(名称、别名、第三方字段名)和类型信息,以及根据类型处理后的字段值 * * @param configInfoEntryFieldInfo 配置信息条目字段信息 * @param fieldValue 字段值 * @return 字段JSON对象 * @throws ClassNotFoundException 当枚举类找不到时抛出 */ public JSONObject createFieldJson(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo, Object fieldValue) throws ClassNotFoundException { JSONObject fieldJson = new JSONObject(); // 创建字段JSON对象 String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称 String fieldAlias = configInfoEntryFieldInfo.getFieldAlias(); // 获取字段别名 DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型 String thirdField = configInfoEntryFieldInfo.getThirdField(); // 获取第三方字段名 fieldJson.put("fieldName", fieldName); // 添加字段名称 fieldJson.put("fieldAlias", fieldAlias); // 添加字段别名 fieldJson.put("thirdField", thirdField); // 添加第三方字段名 // 添加字段类型信息 JSONObject fieldTypeJson = new JSONObject(); // 创建字段类型JSON对象 fieldTypeJson.put("alias", fieldType.getAlias()); // 添加类型别名 fieldTypeJson.put("name", fieldType.getName()); // 添加类型名称 fieldTypeJson.put("value", fieldType.getValue()); // 添加类型值 fieldJson.put("fieldType", fieldTypeJson); // 添加字段类型信息 // 根据字段类型处理字段值 processFieldValueByType(configInfoEntryFieldInfo, fieldValue, fieldJson); return fieldJson; // 返回字段JSON对象 } /** * 根据字段类型处理字段值 * 针对不同类型的数据采用不同的处理策略,确保数据格式符合预期 * * @param configInfoEntryFieldInfo 配置信息条目字段信息 * @param fieldValue 字段值 * @param fieldJson 字段JSON对象 * @throws ClassNotFoundException 当枚举类找不到时抛出 */ public void processFieldValueByType(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo, Object fieldValue, JSONObject fieldJson) throws ClassNotFoundException { DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型 String typeAlias = fieldType.getAlias(); // 获取类型别名 if ("Enum".equals(typeAlias)) { // 处理枚举类型 processEnumFieldValue(configInfoEntryFieldInfo, fieldValue, fieldJson); } else if ("ObjectValue".equals(typeAlias)) { // 处理对象值类型 processObjectValueFieldValue(fieldValue, fieldJson); } else if ("ObjectCollection".equals(typeAlias)) { // 处理对象集合类型 processObjectCollectionFieldValue(fieldValue, fieldJson); } else { // 处理其他类型 fieldJson.put("value", fieldValue); // 直接添加字段值 } } /** * 处理枚举类型字段值 * 获取枚举类的所有可能值列表,并将当前字段值转换为对应的枚举别名 * * @param configInfoEntryFieldInfo 配置信息条目字段信息 * @param fieldValue 字段值 * @param fieldJson 字段JSON对象 * @throws ClassNotFoundException 当枚举类找不到时抛出 */ public void processEnumFieldValue(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo, Object fieldValue, JSONObject fieldJson) throws ClassNotFoundException { String source = configInfoEntryFieldInfo.getSource(); // 获取枚举源 List enumList = EnumUtils.getEnumList(source); // 获取枚举列表 fieldJson.put("source", enumList); // 添加枚举源信息 if (fieldValue != null) { // 检查字段值是否为空 Integer value = (Integer) fieldValue; // 转换字段值为整数 fieldJson.put("value", EnumUtils.getEnum(Class.forName(source), value).getAlias()); // 添加枚举值别名 } } /** * 处理对象值类型字段值 * 提取对象的名称和编号属性,构建简化的对象表示 * * @param fieldValue 字段值 * @param fieldJson 字段JSON对象 */ public void processObjectValueFieldValue(Object fieldValue, JSONObject fieldJson) { if (fieldValue instanceof CoreBaseInfo) { // 检查字段值是否为CoreBaseInfo类型 CoreBaseInfo sourceCoreBaseInfo = (CoreBaseInfo) fieldValue; // 转换字段值 JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象 sourceJSONObject.put("name", sourceCoreBaseInfo.get("name")); // 添加名称属性 sourceJSONObject.put("number", sourceCoreBaseInfo.get("number")); // 添加编号属性 fieldJson.put("value", sourceJSONObject); // 添加源对象信息 } } /** * 处理对象集合类型字段值 * 遍历集合中的每个对象,提取名称和编号属性,构建对象数组 * * @param fieldValue 字段值 * @param fieldJson 字段JSON对象 */ public void processObjectCollectionFieldValue(Object fieldValue, JSONObject fieldJson) { if (fieldValue instanceof IObjectCollection) { // 检查字段值是否为对象集合类型 IObjectCollection collection = (IObjectCollection) fieldValue; // 转换字段值 JSONArray jsonArray = new JSONArray(); // 创建JSON数组 for (int j = 0; j < collection.size(); j++) { // 遍历集合 Object object = collection.getObject(j); // 获取当前对象 if (object instanceof CoreBaseInfo) { // 检查对象是否为CoreBaseInfo类型 CoreBaseInfo coreBaseInfo = (CoreBaseInfo) object; // 转换对象 JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象 sourceJSONObject.put("name", coreBaseInfo.get("name")); // 添加名称属性 sourceJSONObject.put("number", coreBaseInfo.get("number")); // 添加编号属性 jsonArray.add(sourceJSONObject); // 将源对象添加到数组 } } fieldJson.put("value", jsonArray); // 添加对象数组 } } /** * 根据配置的字段集合构建查询选择器,指定查询时需要返回的字段 * 对于对象值类型的字段,额外添加相关字段(名称、编号和所有字段) * * @param fields 配置的字段集合 * @return 包含所有需要查询的字段的选择器集合 */ public SelectorItemCollection getSelectorItem(ConfigInfoEntryFieldCollection fields) { SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合 for (int i = 0; i < fields.size(); i++) { // 遍历字段配置集合 ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fields.get(i); // 获取当前字段配置 String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称 DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型 // 添加字段到选择器 selectorItemCollection.add(fieldName); // 添加字段名称 // 对于对象值类型,额外添加相关字段 if ("ObjectValue".equals(fieldType.getAlias())) { // 检查是否为对象值类型 selectorItemCollection.add(fieldName + ".name"); // 添加名称字段 selectorItemCollection.add(fieldName + ".number"); // 添加编号字段 selectorItemCollection.add(fieldName + ".*"); // 添加所有字段 } } selectorItemCollection.add("id"); // 添加ID字段 return selectorItemCollection; // 返回选择器集合 } /** * 创建实体视图查询条件,用于查询配置信息 * 根据配置编号和实体属性类型过滤配置信息,并指定需要返回的字段 * * @param configNumber 配置编号,用于精确匹配配置 * @param type 实体属性类型(如HEAD/ENTRY),用于过滤特定类型的配置 * @return 构建好的实体查询视图 */ public EntityViewInfo createEntityViewInfo(String configNumber, String type) { EntityViewInfo entityViewInfo = new EntityViewInfo(); // 创建实体视图信息 // 创建过滤条件 FilterInfo filterInfo = new FilterInfo(); // 创建过滤器 filterInfo.getFilterItems().add(new FilterItemInfo("parent.number", configNumber, CompareType.EQUALS)); // 添加父级编号过滤条件 filterInfo.getFilterItems().add(new FilterItemInfo("entityAttribute", type, CompareType.EQUALS)); // 添加实体属性过滤条件 entityViewInfo.setFilter(filterInfo); // 设置过滤器 // 构建查询选择器,指定需要返回的字段 SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合 selectorItemCollection.add("parent.*"); // 添加父表所有字段 selectorItemCollection.add("*"); // 添加条目表所有字段 selectorItemCollection.add("Fields.*"); // 添加字段配置表所有字段 entityViewInfo.setSelector(selectorItemCollection); // 设置选择器 return entityViewInfo; // 返回实体视图信息 } /** * 处理排序字段字符串,转换为排序器集合 * 支持以下格式: * 1. "field1 ASC, field2 DESC" - 明确指定排序方向 * 2. "field1, field2" - 默认使用升序 * * @param sortField 排序字段字符串,格式如 "field1 ASC, field2 DESC" * @return 排序器集合,如果排序字段为空则返回null */ public SorterItemCollection sorterProcessing(String sortField) { if (sortField == null || sortField.trim().isEmpty()) { // 检查排序字段是否为空 return null; // 返回空值 } SorterItemCollection sorterItemCollection = new SorterItemCollection(); // 创建排序器集合 String[] sortFields = sortField.split(","); // 分割排序字段 for (String field : sortFields) { // 遍历排序字段数组 SorterItemInfo sorterItemInfo = new SorterItemInfo(); // 创建排序器信息 String trimmedField = field.trim().toLowerCase(); // 去除空格并转换为小写 if (trimmedField.contains("asc")) { // 检查是否包含升序关键字 String propertyName = trimmedField.replace("asc", "").trim(); // 移除升序关键字 sorterItemInfo.setPropertyName(propertyName); // 设置属性名称 sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序 } else if (trimmedField.contains("desc")) { // 检查是否包含降序关键字 String propertyName = trimmedField.replace("desc", "").trim(); // 移除降序关键字 sorterItemInfo.setPropertyName(propertyName); // 设置属性名称 sorterItemInfo.setSortType(SortType.DESCEND); // 设置降序排序 } else { // 默认情况 sorterItemInfo.setPropertyName(trimmedField); // 设置属性名称 sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序 } sorterItemCollection.add(sorterItemInfo); // 添加排序器到集合 } return sorterItemCollection; // 返回排序器集合 } /** * 初始化集合数据 * 通过业务接口获取指定实体的数据集合 * * @param entityName 实体名称 * @param entityViewInfo 实体视图信息 * @param context 上下文对象 * @return 核心基础集合 * @throws SHRWebException SHR Web异常 * @throws ParserException 解析异常 * @throws BOSException 业务异常 */ public CoreBaseCollection initCollection(String entityName, EntityViewInfo entityViewInfo, Context context) throws SHRWebException, ParserException, BOSException { IQueryExecutor queryExecutor = this.getQueryExecutor(context, entityViewInfo, entityName); // 获取查询执行器 Uuid uuid = queryExecutor.openQuery(); // 打开查询 VirtualDataFetcher vdf = VirtualDataFetcher.createInstance(queryExecutor, uuid, 0, 1000); // 创建虚拟数据获取器 List> data = vdf.getData(); // 获取数据 CoreBaseCollection collection = new CoreBaseCollection(); // 创建核心基础集合 for (int i = 0; i < data.size(); i++) { // 遍历数据 Map stringObjectMap = data.get(i); // 获取当前数据项 String string = stringObjectMap.get("id").toString(); // 获取ID字符串 BOSUuid read = BOSUuid.read(string); // 读取BOS UUID EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(read.getType()); // 获取实体对象信息 String fullName = entityObject.getFullName(); // 获取完整类名 Class targetClass = MetaDataUtil.getObjectValueClass(fullName); // 获取目标类 CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, fullName); // 创建核心基础信息实例 SelectorItemCollection selector = entityViewInfo.getSelector(); // 获取选择器 for (int j = 0; j < selector.size(); j++) { // 遍历选择器 SelectorItemInfo selectorItemInfo = selector.get(j); // 获取当前选择器项 String propertyName = selectorItemInfo.getPropertyName(); // 获取属性名称 coreBaseInfo.put(propertyName, stringObjectMap.get(propertyName)); // 设置属性值 } collection.add(coreBaseInfo); // 添加到集合 } return collection; // 返回集合 } /** * 获取查询执行器 * 创建并配置查询执行器,用于执行数据查询操作 * * @param context 上下文对象 * @param entityViewInfo 实体视图信息 * @param query 查询字符串 * @return 查询执行器 * @throws SHRWebException SHR Web异常 * @throws ShrWebBizException 业务异常 * @throws BOSException 业务异常 * @throws ParserException 解析异常 */ public IQueryExecutor getQueryExecutor(Context context, EntityViewInfo entityViewInfo, String query) throws SHRWebException, ShrWebBizException, BOSException, ParserException { IQueryExecutor exec = QueryExecutorFactory.getLocalInstance(context, MetaDataPK.create(query)); // 创建查询执行器 exec.setObjectView(entityViewInfo); // 设置对象视图 exec.option().isIgnoreOrder = true; // 设置忽略排序 exec.option().isAutoIgnoreZero = true; // 设置自动忽略零值 exec.option().isAutoTranslateBoolean = true; // 设置自动转换布尔值 exec.option().isAutoTranslateEnum = true; // 设置自动转换枚举 exec.option().isIgnorePermissionCheck = false; // 设置不忽略权限检查 return exec; // 返回查询执行器 } /** * 获取业务接口 * 根据实体名称获取对应的业务接口实例 * * @param entityName 实体名称 * @return 核心基础接口 * @throws SHRWebException SHR Web异常 */ public ICoreBase getBizInterface(String entityName) throws SHRWebException { if (entityName == null) { // 检查实体名称是否为空 return null; // 返回空值 } try { return MetaDataUtil.getBizInterface(SHRContext.getInstance().getContext(), entityName); // 获取业务接口 } catch (BOSException e) { e.printStackTrace(); throw new SHRWebException(e); // 抛出SHR Web异常 } } /** * 给CoreBaseInfo类型对象设置属性值,支持级联属性 * 支持"主属性.子属性"格式的属性路径,可以设置嵌套对象的属性值 * * @param ctx 上下文对象,用于获取元数据信息 * @param coreBaseInfo 要设置属性值的目标对象 * @param name 属性名称,支持"主属性.子属性"格式的级联属性 * @param value 要设置的属性值 * @throws BOSException 当操作过程中发生业务异常时抛出 */ public void setCoreBaseInfo(Context ctx, IObjectValue coreBaseInfo, String name, Object value) throws BOSException { // 判断是否为级联属性 if (name.contains(".")) { // 检查是否包含点号 String[] split = name.split("\\."); // 分割属性名称 Object parentValue = coreBaseInfo.get(split[0]); // 获取父属性值 // 获取实体元数据信息 EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(coreBaseInfo.getBOSType()); // 获取实体对象信息 PropertyCollection properties = entityObject.getInheritedNoDuplicatedProperties(); // 获取属性集合 PropertyInfo propertyInfo = (PropertyInfo) properties.getObject(split[0]); // 获取属性信息 // 处理关联属性 if (propertyInfo instanceof LinkPropertyInfo) { // 检查是否为链接属性 LinkPropertyInfo linkProperty = (LinkPropertyInfo) propertyInfo; // 转换属性信息 RelationshipInfo relationship = linkProperty.getRelationship(); // 获取关系信息 String targetFullName = relationship.getSupplierObject().getFullName(); // 获取目标完整名称 try { Class targetClass = MetaDataUtil.getObjectValueClass(targetFullName); // 获取目标类 CoreBaseInfo childObject = getOrCreateChildObject(parentValue, targetClass, targetFullName); // 获取或创建子对象 // 给子对象设置级联属性的子属性值 if (childObject != null) { // 检查子对象是否为空 childObject.put(split[1], value); // 设置子属性值 } } catch (ShrWebBizException e) { e.printStackTrace(); throw new BOSException("获取目标类失败: " + e.getMessage(), e); // 抛出业务异常 } } } else { // 非级联属性,直接设置值 coreBaseInfo.put(name, value); // 设置属性值 } } /** * 获取或创建子对象 * 根据父属性值的类型(集合或单个对象),获取现有子对象或创建新的子对象 * * @param parentValue 父属性值 * @param targetClass 目标类 * @param targetFullName 目标全名 * @return 子对象 */ public CoreBaseInfo getOrCreateChildObject(Object parentValue, Class targetClass, String targetFullName) { CoreBaseInfo childObject = null; // 初始化子对象 if (parentValue instanceof IObjectCollection) { // 检查父属性值是否为对象集合 IObjectCollection collection = (IObjectCollection) parentValue; // 转换父属性值 if (collection.size() == 0) { // 检查集合是否为空 childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例 collection.addObject(childObject); // 添加到集合 } else { childObject = (CoreBaseInfo) collection.getObject(0); // 获取第一个对象 } } else if (parentValue instanceof CoreBaseInfo) { // 检查父属性值是否为CoreBaseInfo if (parentValue == null) { // 检查是否为空 childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例 } else { childObject = (CoreBaseInfo) parentValue; // 使用现有对象 } } return childObject; // 返回子对象 } /** * 主方法,用于本地测试 * 可以在此添加测试代码,验证类的功能 * * @param args 命令行参数 */ public static void main(String[] args) { // 测试代码可以在这里添加 System.out.println("AssistSynchronizingFacadeControllerBean main method"); // 输出主方法信息 } }