package com.vci.web.service.impl; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.vci.corba.common.PLException; import com.vci.corba.omd.atm.AttributeDef; import com.vci.corba.omd.btm.BizType; import com.vci.corba.omd.data.BusinessObject; import com.vci.corba.omd.ltm.LinkType; import com.vci.omd.utils.ObjectTool; import com.vci.pagemodel.*; import com.vci.starter.web.annotation.log.VciUnLog; import com.vci.starter.web.enumpck.VciFieldTypeEnum; import com.vci.starter.web.pagemodel.BaseQueryObject; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.pagemodel.DataGrid; import com.vci.starter.web.util.BeanUtil; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.util.VciDateUtil; import com.vci.model.OsLinkTypeDO; import com.vci.web.service.*; import com.vci.web.util.PlatformClientUtil; import com.vci.web.util.WebUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * 链接类型服务 * @author weidy * @date 2021-2-15 */ @Service public class OsLinkTypeServiceImpl implements OsLinkTypeServiceI { /** * 日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 平台的调用工具类 */ @Autowired private PlatformClientUtil platformClientUtil; /** * 属性的服务 */ @Autowired private OsAttributeServiceI attributeService; /** * 枚举的服务 */ @Autowired private OsEnumServiceI enumService; /** * 业务类型服务 */ @Autowired private OsBtmServiceI btmService; /** * 业务数据查询服务 */ @Autowired private WebBoServiceI boService; /** * 加载自身 */ @Autowired(required = false) @Lazy private OsLinkTypeServiceI self; /** * 查询所有的链接类型 * * @return 链接类型对象 */ @Override @VciUnLog public List selectAllLink() { try { return linkTypeDO2VOs(Arrays.stream(platformClientUtil.getLinkTypeService().getLinkTypes()).collect(Collectors.toList())); } catch (PLException vciError) { throw WebUtil.getVciBaseException(vciError); } } /** * 查询所有的业务类型映射 * * @return key 是业务的英文名称的小写 */ @Override @VciUnLog public Map selectAllLinkMap() { return Optional.ofNullable(self.selectAllLink()).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getId().toLowerCase(),t->t,(o1,o2)->o1)); } /** * 数据对象转换为显示对象 * * @param linkTypes 数据对象 * @return 显示对象 */ @Override public List linkTypeDO2VOs(Collection linkTypes) { List VOS = new ArrayList<>(); Optional.ofNullable(linkTypes).orElseGet(()->new ArrayList<>()).stream().forEach(linkType -> { OsLinkTypeVO vo = linkTypeDO2VO(linkType); VOS.add(vo); }); return VOS; } /** * 数据对象转换为显示对象 * * @param linkType 数据对象 * @return 显示对象 */ @Override public OsLinkTypeVO linkTypeDO2VO(LinkType linkType) { OsLinkTypeVO vo = new OsLinkTypeVO(); if(linkType !=null){ vo.setOid(linkType.oid); vo.setCreator(linkType.creator); vo.setLastModifier(linkType.modifier); try { vo.setCreateTime(VciDateUtil.long2Date(linkType.createTime)); vo.setLastModifyTime(VciDateUtil.long2Date(linkType.modifyTime)); vo.setTs(VciDateUtil.long2Date(linkType.ts)); } catch (Exception e) { e.printStackTrace(); } vo.setDescription(linkType.description); vo.setId(linkType.name); vo.setName(linkType.tag); vo.setFromBtmTypeVOS(btmService.listBtmByIds(Arrays.stream(linkType.btmItemsFrom).collect(Collectors.toSet()))); if(!CollectionUtils.isEmpty(vo.getFromBtmTypeVOS())){ vo.setFromBtmType(Arrays.stream(linkType.btmItemsFrom).collect(Collectors.joining(","))); vo.setFromBtmTypeName(vo.getFromBtmTypeVOS().stream().map(OsBtmTypeVO::getName).collect(Collectors.joining(","))); } vo.setToBtmTypeVOS(btmService.listBtmByIds(Arrays.stream(linkType.btmItemsTo).collect(Collectors.toSet()))); if(!CollectionUtils.isEmpty(vo.getToBtmTypeVOS())){ vo.setToBtmType(Arrays.stream(linkType.btmItemsTo).collect(Collectors.joining(","))); vo.setToBtmTypeName(vo.getToBtmTypeVOS().stream().map(OsBtmTypeVO::getName).collect(Collectors.joining(","))); } vo.setImplClass(linkType.implClass); vo.setShape(linkType.shape); List attributeVOS = attributeService.listAttrByIds(Arrays.stream(linkType.attributes).collect(Collectors.toList())); List linkTypeAttributeVOS = new ArrayList<>(); Optional.ofNullable(attributeVOS).orElseGet(()->new ArrayList<>()).stream().forEach(attributeVO->{ OsLinkTypeAttributeVO linkTypeAttributeVO = new OsLinkTypeAttributeVO(); BeanUtil.convert(attributeVO,linkTypeAttributeVO); linkTypeAttributeVO.setPkLinkType(vo.getOid()); if(StringUtils.isNotBlank(attributeVO.getBtmTypeId())){ linkTypeAttributeVO.setReferFlag(true); linkTypeAttributeVO.setReferBtmTypeId(attributeVO.getBtmTypeId()); } if(StringUtils.isNotBlank(attributeVO.getEnumId())){ linkTypeAttributeVO.setEnumFlag(true); linkTypeAttributeVO.setEnumItemMap(enumService.getEnumValueMap(linkTypeAttributeVO.getEnumId())); } linkTypeAttributeVOS.add(linkTypeAttributeVO); }); vo.setAttributes(linkTypeAttributeVOS); } return vo; } /** * 使用编号获取链接类型 * * @param linkIds 编号 * @return 链接类型 */ @Override public List listLinkTypeIds(Collection linkIds) { if(CollectionUtils.isEmpty(linkIds)){ return null; } Map linkTypeVOMap = self.selectAllLinkMap(); List linkTypeVOS = new ArrayList<>(); linkIds.stream().forEach(id->{ if(linkTypeVOMap.containsKey(id.toLowerCase())){ linkTypeVOS.add(linkTypeVOMap.get(id.toLowerCase())); } }); return linkTypeVOS; } /** * 使用编号获取链接类型 * * @param id 编号 * @return 链接类型 */ @Override public OsLinkTypeVO getLinkTypeById(String id) { if(StringUtils.isBlank(id)){ return null; } return self.selectAllLinkMap().getOrDefault(id.toLowerCase(),null); } /** * 获取链接类型的属性 * * @param linkTypeId 链接类型的编号 * @return 链接类型的属性 */ @Override public List listAttributeByLinkId(String linkTypeId) { OsLinkTypeVO linkTypeVO = getLinkTypeById(linkTypeId); return linkTypeVO.getAttributes(); } /** * 链接类型的列表 * * @param baseQueryObject 查询对象 * @return 链接类型的显示对象 */ @Override public DataGrid gridLinkType(BaseQueryObject baseQueryObject) { return gridObject(baseQueryObject, OsLinkTypeDO.class,self.selectAllLinkMap(),OsLinkTypeVO.class); } /** * 使用主键获取显示对象 * * @param linkTypeOid 链接类型的主键 * @return 链接类型的显示对象 */ @Override public OsLinkTypeVO selectByOid(String linkTypeOid) { List linkTypeVOS = self.selectAllLinkMap().values().stream().collect(Collectors.toList()); return Optional.ofNullable(linkTypeVOS).orElseGet(()->new ArrayList<>()).stream().filter(s->s.getOid().equalsIgnoreCase(linkTypeOid)).findFirst().orElseGet(()->null); } /** * 获取链接类型关联的所有业务类型中属性类型差异的信息 * * @param linkTypeOid 链接类型的主键 * @return 有错误的属性 */ @Override public List checkAttributeTypeDifferent(String linkTypeOid) { if(StringUtils.isBlank(linkTypeOid)){ return new ArrayList<>(); } OsLinkTypeVO linkTypeVO = selectByOid(linkTypeOid); List fromBtmTypeVOS = linkTypeVO.getFromBtmTypeVOS(); List toBtmTypeVOS = linkTypeVO.getToBtmTypeVOS(); List btmTypeVOS = new ArrayList<>(); btmTypeVOS.addAll(fromBtmTypeVOS); btmTypeVOS.addAll(toBtmTypeVOS); List diffList = new ArrayList<>(); btmTypeVOS.stream().forEach(btmTypeVO -> { //查询这个表的信息 String sql = "select t.column_name,t.data_type,t.data_length,t.nullable,t.data_precision,t.data_scale,c.comments from user_tab_columns t " + "inner JOIN user_col_comments c on t.TABLE_NAME = c.table_name and t.COLUMN_NAME = c.column_name where " + "t.table_name = '" + VciBaseUtil.getTableName(btmTypeVO.getId()).toUpperCase(Locale.ROOT) + "' order by t.column_name asc"; Map attributeVOMap = btmTypeVO.getAttributes().stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); List cbosList = boService.queryBySql(sql, new HashMap<>()); if(!CollectionUtils.isEmpty(cbosList)){ cbosList.stream().forEach(cbo->{ String attrId = ObjectTool.getBOAttributeValue(cbo,"column_name"); String dataType = ObjectTool.getBOAttributeValue(cbo,"data_type"); if(StringUtils.isNotBlank(dataType) && dataType.contains("(")){ dataType = dataType.substring(0,dataType.indexOf("(")); } OsBtmTypeAttributeVO attributeVO = attributeVOMap.getOrDefault(attrId.toLowerCase(Locale.ROOT), null); if(attributeVO!=null){ String vtType = attributeVO.getAttrDataType(); String attrType = ""; VciFieldTypeEnum fieldTypeEnum = VciFieldTypeEnum.forValue(vtType); if(fieldTypeEnum == null) { attrType = "VARCHAR2"; }else { switch (fieldTypeEnum) { case VTString: case VTBoolean: attrType = "VARCHAR2"; break; case VTInteger: case VTLong: case VTDouble: attrType = "NUMBER"; break; case VTDate: attrType = "DATE"; break; case VTDateTime: case VTTime: attrType = "TIMESTAMP"; break; default: attrType = "VARCHAR2"; break; } } if(!attrType.equalsIgnoreCase(dataType)) { diffList.add(attributeVO); } } }); } }); return diffList; } /** * 链接类型的列表 * * @return 链接类型的显示对象 */ @Override public BaseResult> gridLink() throws PLException { LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes(); return BaseResult.dataList(Arrays.asList(linkTypes)); } /** * 链接类型保存 * linkType 链接类型的保存对象 * addFlag 是否为新增 true新增,false修改 * @return 保存结果 */ @Override public BaseResult addAndEditLink(LinkType linkType, Boolean addFlag) throws PLException { VciBaseUtil.alertNotNull(linkType.name,"请输入链接类型名称",linkType.btmItemsFrom,"From端业务类型不能为空!", linkType.btmItemsTo,"To端类型均不能为空!"); int maxLength = platformClientUtil.getLinkTypeService().getLTNameMaxLength(); if(linkType.name.length() > maxLength){ throw new PLException("500",new String[] {"链接类型名长度不能超过" + maxLength}); } if(!linkType.name.matches("^[A-Za-z]+$")){ throw new PLException("500",new String[] {"链接类型名称只能为英文字母"}); } LinkType historyLink = platformClientUtil.getLinkTypeService().getLinkType(linkType.name); if(historyLink != null && !historyLink.name.equals("") && addFlag){ throw new PLException("500",new String[] {"该链接类型名称已经存在"}); } linkType.modifier = WebUtil.getCurrentUserId(); if(addFlag){ linkType.creator = WebUtil.getCurrentUserId(); platformClientUtil.getLinkTypeService().addLinkType(linkType); return BaseResult.success(null,"保存成功!"); } ArrayList removeAbList = getRemovedApList(historyLink, linkType); if(removeAbList.size() > 0 && platformClientUtil.getLinkTypeService().hasData(linkType.name)){ linkType.attributes = historyLink.attributes; platformClientUtil.getLinkTypeService().modifyLinkType(linkType); throw new PLException("500",new String[] {"类型已有实例, 不进行移除操作"}); } platformClientUtil.getLinkTypeService().modifyLinkType(linkType); return BaseResult.success(null,"保存成功!"); } /** * 链接类型删除 * linkType 链接类型对象 * @return 删除结果 */ @Override public BaseResult deleteLink(LinkType linkType) throws PLException { if(platformClientUtil.getLinkTypeService().hasData(linkType.name)){ throw new PLException("500",new String[] {"类型已有实例, 不进行删除操作"}); } boolean flag = platformClientUtil.getLinkTypeService().deleteLinkType(linkType); if(!flag){ throw new PLException("500",new String[] {"删除失败"}); }else{ return BaseResult.success(); } } /** * 一致性检查 * @return 删除结果 */ @Override public BaseResult checkLinkType() throws PLException { String[] result = platformClientUtil.getLinkTypeService().linkTypeConsistencyCheck(); Map dbCheckMap = new HashMap(); for(int i = 0; i < result.length; i++){ String info = result[i]; if(info.equals("")){ continue; } String[] infos = info.split("/DML"); String typeName = infos[0]; String dml = infos[1]; dbCheckMap.put(typeName, dml); } Map> btmCheckMap = usedBtmCheck(); if(dbCheckMap.size() < 1 && (btmCheckMap == null || btmCheckMap.size() < 1)){ return BaseResult.successMsg("数据库中的表结构与类型一致, 链接类型引用的业务类型全部正确存在,无需修复!!"); }else{ Map returnData = new HashMap<>(); returnData.put("dbCheckMap",dbCheckMap); returnData.put("btmCheckMap",btmCheckMap); List list = new ArrayList<>(); list.add(returnData); return BaseResult.dataList(500,list,"需要进行列的修复!!"); } } /** * 一致性检查修复数据库表 * repairData 需要修复的数据 * @return 修复结果 */ @Override public BaseResult repairTable(String repairData) throws PLException, IOException { Map map = new ObjectMapper().readValue(repairData, new TypeReference>(){}); HashMap dbCheckMap = (HashMap) map.get("dbCheckMap"); HashMap> btmCheckMap = (HashMap>) map.get("btmCheckMap"); List returnList = new ArrayList<>(); Map returnMap = new HashMap(); if(dbCheckMap.size() > 0){ List list = getRepairDML(dbCheckMap); if(list.size() < 1){ return BaseResult.success(); } String[] result = platformClientUtil.getLinkTypeService().executeRepair(list.toArray(new String[0])); List resultList = Arrays.asList(result); for (String typeName : resultList) { if(dbCheckMap.containsKey(typeName)){ dbCheckMap.remove(typeName); }else if(dbCheckMap.containsKey(typeName + "_ADD")){ String sql = String.valueOf(dbCheckMap.get(typeName)); sql = sql.substring(sql.indexOf(";") + 1, sql.length()); dbCheckMap.put(typeName, sql); }else if(dbCheckMap.containsKey(typeName + "_DROP")){ String sql = String.valueOf(dbCheckMap.get(typeName)); sql = sql.substring(0, sql.indexOf(";")); dbCheckMap.put(typeName, sql); } } if(!dbCheckMap.isEmpty()){ returnMap.put("dbCheckMap",dbCheckMap); } } if(btmCheckMap.size() > 0){ List result = repairXml(btmCheckMap); for(int i = 0; i < result.size(); i++){ String typeName = result.get(i); if(btmCheckMap.containsKey(typeName)){ btmCheckMap.remove(typeName); } } if(!btmCheckMap.isEmpty()){ returnMap.put("btmCheckMap",btmCheckMap); } } returnList.add(returnMap); return BaseResult.success(returnList); } /** * 创建视图 * @return 创建结果 */ @Override public BaseResult createView() throws PLException { boolean f = platformClientUtil.getLinkTypeService().createView(); if(f){ return BaseResult.success("创建视图成功"); }else{ return BaseResult.success("创建视图失败"); } } /** * 修复链接类型的xml文件 * @return */ private List repairXml(HashMap> btmCheckMap){ List result = new ArrayList(); for(Iterator ite = btmCheckMap.keySet().iterator(); ite.hasNext();){ String linkName = ite.next(); List list = btmCheckMap.get(linkName); LinkType link = null; try { link = platformClientUtil.getLinkTypeService().getLinkType(linkName); } catch (PLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); continue; } //将list中包含的F_btm移除, 重新设置btmItemsFrom String[] btms_ = link.btmItemsFrom; List btms = new ArrayList(); for(int i = 0; i < btms_.length; i++){ if(!list.contains("F_" + btms_[i])){ btms.add(btms_[i]); }else{ if(link.primitivesFrom.equals(btms_[i])){ link.primitivesFrom = ""; } } } link.btmItemsFrom = btms.toArray(new String[0]); //将list中包含的T_btm移除, 重新设置btmItemsTo btms_ = link.btmItemsTo; btms = new ArrayList(); for(int i = 0; i < btms_.length; i++){ if(!list.contains("T_" + btms_[i])){ btms.add(btms_[i]); }else{ if(link.primitivesTo.equals(btms_[i])){ link.primitivesTo = ""; } } } link.btmItemsTo = btms.toArray(new String[0]); link.id = link.name; try { if(platformClientUtil.getLinkTypeService().modifyLinkType(link)){ result.add(linkName); } } catch (PLException e) { e.printStackTrace(); } } return result; } /** * 获取需要修复的伪sql * @return */ private List getRepairDML(HashMap dbCheckMap) { List list = new ArrayList(); for(Iterator ite = dbCheckMap.keySet().iterator(); ite.hasNext();){ String type = ite.next(); String dml = String.valueOf(dbCheckMap.get(type)); list.add(type + "/DML" + dml); } return list; } /** * 检查所有的链接类型, 当链接类型中引用的业务类型已经不存在时, 删除该链接类型中对业务类型的引用 * @return */ private Map> usedBtmCheck(){ try { Map> map = new HashMap>(); LinkType[] links = platformClientUtil.getLinkTypeService().getLinkTypes(); for(int i = 0; i < links.length; i++){ LinkType link = links[i]; String[] btms = link.btmItemsFrom; for(int k = 0; k < btms.length; k++){ String btmName = btms[k]; BizType btm = platformClientUtil.getBtmService().getBizTypeByName(btmName); if(btm == null || btm.name.equals("")){ List list = map.get(link.name); if(list == null){ list = new ArrayList(); list.add("F_" + btmName); }else{ list.add("F_" + btmName); } map.put(link.name, list); } } btms = link.btmItemsTo; for(int k = 0; k < btms.length; k++){ String btmName = btms[k]; BizType btm = platformClientUtil.getBtmService().getBizTypeByName(btmName); if(btm == null || btm.name.equals("")){ List list = map.get(link.name); if(list == null){ list = new ArrayList(); list.add("T_" + btmName); }else{ list.add("T_" + btmName); } map.put(link.name, list); } } } return map; } catch (PLException e) { e.printStackTrace(); } return null; } /** * 获取修改链接类型时 减少的属性 * @param oldLt * @param newLt * @return */ private ArrayList getRemovedApList(LinkType oldLt, LinkType newLt) { String[] oldAbInfo = oldLt.attributes; ArrayList oldNameList = new ArrayList(); for(int i = 0; i < oldAbInfo.length; i++){ oldNameList.add(oldAbInfo[i]); } String[] newAbInfo = newLt.attributes; ArrayList newNameList = new ArrayList(); for(int i = 0; i < newAbInfo.length; i++){ newNameList.add(newAbInfo[i]); } ArrayList removedApList = new ArrayList(); for(Iterator iterator = oldNameList.iterator(); iterator.hasNext();){ String oldName = iterator.next(); if(!newNameList.contains(oldName)){ removedApList.add(oldName); } } return removedApList; } /** * 清除缓存 */ @Override public void clearCache() { } /** * 修改链接类型中对应属性名的属性 * @param apName * @return * @throws PLException */ @Override public boolean alterAp(String apName) throws PLException { String[] linkNames = null; List linkNameList = new ArrayList(); AttributeDef abItem = null; try { abItem = platformClientUtil.getAttributeService().getAttributeDefByName(apName); } catch (PLException e1) { e1.printStackTrace(); } if(abItem == null || abItem.equals("")){ return true; } try { linkNames = platformClientUtil.getLinkTypeService().getLTNamesByAPName(apName); } catch (PLException e) { e.printStackTrace(); } if(linkNames == null || linkNames.length <= 0){ return true; } linkNameList = Arrays.asList(linkNames); for(Iterator i = linkNameList.iterator(); i.hasNext();){ String linkName = i.next(); try { platformClientUtil.getLinkTypeService().modifyLTAttribute(linkName, apName); } catch (PLException e) { // TODO Auto-generated catch block e.printStackTrace(); String erreMsg = "调整链接类型中【"+apName+"】属性时出现错误,原因:"+e.getMessage(); logger.error(erreMsg); throw new PLException("500",new String[]{erreMsg}); } } return false; } /** * 判断该属性是否已经在链接类型中产生了数据 * @param abName * @return * @throws PLException */ @Override public boolean hasInstance(String abName) throws PLException { String[] btmNames = platformClientUtil.getLinkTypeService().getLTNamesByAPName(abName); if(btmNames == null || btmNames.length == 0){ return false; } for(int i = 0; i < btmNames.length; i++){ String btmName = btmNames[i]; boolean flag; flag = platformClientUtil.getLinkTypeService().hasData(btmName); if(flag){ return flag; } } return false; } /** * 获取连接类型名称集合 * @return */ @Override public List getAllLtName() throws PLException { LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes(); if(null != linkTypes && linkTypes.length > 0){ return Arrays.stream(linkTypes).map(linkType -> linkType.name).collect(Collectors.toList()); } return null; } }