package com.vci.web.service.impl; import com.vci.corba.common.PLException; import com.vci.corba.omd.data.BusinessObject; import com.vci.corba.omd.lcm.Bound; import com.vci.corba.omd.lcm.LifeCycle; import com.vci.corba.omd.lcm.TransitionVO; import com.vci.pagemodel.*; import com.vci.starter.web.annotation.log.VciUnLog; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.pagemodel.BaseQueryObject; import com.vci.starter.web.pagemodel.DataGrid; import com.vci.starter.web.util.VciDateUtil; import com.vci.model.OsLifeCycleDO; import com.vci.web.service.OsLifeCycleServiceI; import com.vci.web.service.OsStatusServiceI; import com.vci.web.service.WebBoServiceI; 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.util.*; import java.util.stream.Collectors; import static com.vci.constant.FrameWorkBusLangCodeConstant.DATA_ID_NOT_EXIST; import static com.vci.constant.WebLangCodeConstant.LIFE_CYCLE_ROUTER_NULL; import static com.vci.constant.WebLangCodeConstant.LIFE_CYCLE_TRANS_ERROR; /** * 生命周期服务 * @author weidy * @date 2021-2-14 */ @Service public class OsLifeCycleServiceImpl implements OsLifeCycleServiceI { /** * 平台客户端 */ @Autowired private PlatformClientUtil platformClientUtil; /** * 状态的服务 */ @Autowired private OsStatusServiceI statusService; /** * 加载自身 */ @Autowired(required = false) @Lazy private OsLifeCycleServiceI self; /** * 业务对象服务 */ @Autowired private WebBoServiceI boService; /** * 日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /*** * 获取生命周期的状态对应的中文值 * @param status 状态 * @return 状态的显示名称 * @throws VciBaseException 不存在生命周期 */ @Override public String getStatusText(String status) throws VciBaseException { return statusService.selectAllStatusMap().getOrDefault(status,new OsStatusVO()).getName(); } /** * 跃迁生命周期状态,注意调用此方法就会被持久化,不受事务控制 * @param bo 业务类型的数据对象 * @param targetStatus 目标的生命周期状态,不区分大小 * @throws VciBaseException 如果目标生命周期和当前生命周期状态没有连接线时抛出异常 */ @Override public void transStatus(com.vci.corba.omd.data.BusinessObject bo, String targetStatus) throws VciBaseException { WebUtil.alertNotNull(bo,"业务数据对象",bo.lctId,"生命周期编码",bo.lcStatus,"当前生命周期状态",targetStatus,"目标生命周期状态"); OsLifeCycleLineVO transVO = getTransVO(bo.lctId, bo.lcStatus, targetStatus); if(transVO!=null) { doTransVO(bo, transVO); }else{ if(!targetStatus.equalsIgnoreCase(bo.lcStatus)){ //状态相同的时候。,不抛出异常 throw new VciBaseException(LIFE_CYCLE_ROUTER_NULL,new String[]{bo.lcStatus,targetStatus}); } } } /** * 批量跃迁生命周期状态,这些数据中的当前状态必须都是一样。或者是当前状态都可以连接到目标状态 * @param boList 业务类型对象数据 * @param targetStatus 目标状态,不区分大小写 * @throws VciBaseException 转换生命周期出错的时候抛出异常 */ @Override public void transStatus(List boList, String targetStatus) throws VciBaseException { WebUtil.alertNotNull(boList,"业务数据对象",targetStatus,"目标对象"); transStatus(boList.toArray(new com.vci.corba.omd.data.BusinessObject[0]), targetStatus); } /** * 批量跃迁生命周期状态,这些数据中的当前状态必须都是一样,或者是当前状态都可以连接到目标状态 * @param bos 业务类型对象数据 * @param targetStatus 目标状态,不区分大小写 * @throws VciBaseException 转换生命周期出错的时候抛出异常 */ @Override public void transStatus(com.vci.corba.omd.data.BusinessObject[] bos, String targetStatus) throws VciBaseException { WebUtil.alertNotNull(bos,"业务数据对象",targetStatus,"目标对象"); List transVOList = new ArrayList<>(); List transBOs = new ArrayList<>(); for(int i = 0 ; i < bos.length ; i ++){ com.vci.corba.omd.data.BusinessObject bo = bos[i]; WebUtil.alertNotNull(bo,"业务数据对象",bo.lctId,"生命周期编码",bo.lcStatus,"当前生命周期状态"); OsLifeCycleLineVO transVO = getTransVO(bo.lctId, bo.lcStatus, targetStatus); if(transVO!=null){ transVOList.add(transVO); transBOs.add(bo); }else{ if(!targetStatus.equalsIgnoreCase(bo.lcStatus)){ throw new VciBaseException("不存在从【{0}】状态到【{1}】状态的生命周期连接线,请联系管理员进行配置",new String[]{bo.lcStatus, targetStatus} ); } } } if(!CollectionUtils.isEmpty(transBOs)) { batchTransVo(transBOs.toArray(new com.vci.corba.omd.data.BusinessObject[0]), transVOList.toArray(new OsLifeCycleLineVO[0])); } } /** * 批量跃迁生命周期状态,这些数据中的当前状态必须都是一样,或者是当前状态都可以连接到目标状态 * @param cboList 业务类型对象数据 * @param targetStatus 目标状态,不区分大小写 * @throws VciBaseException 转换生命周期出错的时候抛出异常 */ @Override public void transCboStatus(List cboList, String targetStatus) throws VciBaseException { WebUtil.alertNotNull(cboList,"业务数据对象",targetStatus,"目标对象"); BusinessObject[] bos = new BusinessObject[cboList.size()]; for(int i = 0 ; i < cboList.size() ; i ++){ bos[i] = cboList.get(i); } transStatus(bos, targetStatus); } /** * 通过编号获取生命周期状态对象, * * @param lctId 生命周期编号 * @return 显示对象 */ @Override public OsLifeCycleVO getLifeCycleById(String lctId) { WebUtil.alertNotNull(lctId,"业务类型编号"); return self.selectAllLifeCycleMap().getOrDefault(lctId,null); } /** * 生命周期的数据对象转换为显示对象 * @param lifeCycles 数据对象 * @return 显示对象 */ @Override public List lifeCycleDO2VOs(Collection lifeCycles){ List lifeCycleVOS = new ArrayList<>(); Optional.ofNullable(lifeCycles).orElseGet(()->new ArrayList<>()).stream().forEach(lifeCyle -> { OsLifeCycleVO lifeCycleVO = lifeCycleDO2VO(lifeCyle); lifeCycleVOS.add(lifeCycleVO); }); return lifeCycleVOS; } /** * 生命周期的数据对象转换为显示对象 * @param lifeCycle 数据对象 * @return 显示对象 */ @Override public OsLifeCycleVO lifeCycleDO2VO(LifeCycle lifeCycle){ OsLifeCycleVO life = new OsLifeCycleVO(); Map statusVOMap = statusService.selectAllStatusMap(); if(lifeCycle !=null) { try { life.setCreateTime(new Date(lifeCycle.createTime)); } catch (Exception e) { e.printStackTrace(); } life.setCreator(lifeCycle.creator); life.setDescription(lifeCycle.description); life.setId(lifeCycle.name); life.setLastModifier(lifeCycle.modifier); try { life.setLastModifyTime(new Date(lifeCycle.modifyTime)); } catch (Exception e) { e.printStackTrace(); } life.setOid(lifeCycle.oid); List lineVOS = new ArrayList<>(); if(lifeCycle.routes!=null&& lifeCycle.routes.length>0){ Arrays.stream(lifeCycle.routes).forEach(route->{ OsLifeCycleLineVO lineVO = new OsLifeCycleLineVO(); lineVO.setSourceLifeStatus(route.source); lineVO.setSourceLifeStatusName(statusVOMap.getOrDefault(route.source,new OsStatusVO()).getName()); lineVO.setTargetLifeStatus(route.destination); lineVO.setTargetLifeStatusName(statusVOMap.getOrDefault(route.destination,new OsStatusVO()).getName()); lineVO.setOid(route.id); lineVO.setName(route.connect); if(route.transitionVOEvents ==null || route.transitionVOEvents.length == 0){ lineVO.setEvents(new OsLifeCycleLineEventVO[0]); }else { OsLifeCycleLineEventVO[] eventVOs = new OsLifeCycleLineEventVO[route.transitionVOEvents.length]; for (int i = 0; i < route.transitionVOEvents.length; i++) { com.vci.corba.omd.lcm.TransitionVOEvent event = route.transitionVOEvents[i]; OsLifeCycleLineEventVO eventVO = new OsLifeCycleLineEventVO(); eventVO.setOid(event.id); eventVO.setEventFullName(event.name); eventVOs[i] = eventVO; } lineVO.setEvents(eventVOs); } lineVOS.add(lineVO); }); } life.setLines(lineVOS); life.setStartStatus(lifeCycle.startState); life.setStartStatusName(statusVOMap.getOrDefault(lifeCycle.startState,new OsStatusVO()).getName()); life.setName(lifeCycle.tag); try { life.setTs(VciDateUtil.str2Date(lifeCycle.ts,VciDateUtil.DateTimeMillFormat)); } catch (Exception e) { e.printStackTrace(); } } return life; } /** * 生命周期显示对象转换为数据对象 * @param lifeCycleVO 显示对象 * @return 数据对象 */ @Override public LifeCycle lifeCycleVO2DO(OsLifeCycleVO lifeCycleVO){ LifeCycle lifeCyle = new LifeCycle(); lifeCyle.name = lifeCycleVO.getId(); lifeCyle.tag = lifeCycleVO.getName(); lifeCyle.oid = lifeCycleVO.getOid(); lifeCyle.creator = lifeCycleVO.getCreator(); lifeCyle.description = lifeCycleVO.getDescription(); lifeCyle.modifier = lifeCycleVO.getLastModifier(); lifeCyle.modifyTime = lifeCycleVO.getLastModifyTime() != null ? lifeCycleVO.getLastModifyTime().getTime():null; lifeCyle.createTime = lifeCycleVO.getCreateTime() != null ? lifeCycleVO.getCreateTime().getTime():null; lifeCyle.startState =lifeCycleVO.getStartStatus(); lifeCyle.ts = VciDateUtil.date2Str(lifeCycleVO.getTs(),VciDateUtil.DateTimeMillFormat); if(lifeCycleVO.getBounds() !=null && lifeCycleVO.getBounds().length>0) { Bound[] bounds = new Bound[lifeCycleVO.getBounds().length]; for (int i = 0; i < lifeCycleVO.getBounds().length; i++) { OsLifeCycleLineBoundVO boundVO = lifeCycleVO.getBounds()[i]; Bound bound = new Bound(); bound.id = StringUtils.isBlank(boundVO.getId()) ? "" : boundVO.getId(); bound.name = boundVO.getName(); bound.cellx = boundVO.getCellx(); bound.celly = boundVO.getCelly(); bound.cellh = boundVO.getCellh(); bound.cellw = boundVO.getCellw(); bound.cellicon = StringUtils.isBlank(boundVO.getCellicon()) ? "" : boundVO.getCellicon(); bounds[i] = bound; } lifeCyle.bounds = bounds; }else{ lifeCyle.bounds = new Bound[0]; } //加链接线 List lines = new ArrayList<>(); for (int i = 0; i < lifeCycleVO.getLines().size(); i++) { OsLifeCycleLineVO lineVO = lifeCycleVO.getLines().get(i); lines.add(lifeCycleLineVO2DO(lineVO)); } lifeCyle.routes = lines.toArray(new TransitionVO[0]); return lifeCyle; } /** * 查询所有生命周期状态 * * @return 生命周期状态的对象 * @throws VciBaseException 查询的时候出错的时候 */ @Override @VciUnLog public List selectAllLifeCycle() throws VciBaseException { try { LifeCycle[] lifeCyles = platformClientUtil.getLifeCycleService().getLifeCycles(); return lifeCycleDO2VOs(Arrays.stream(lifeCyles).collect(Collectors.toList())); } catch (PLException vciError) { if(logger.isErrorEnabled()){ logger.error(vciError.code,vciError); } throw WebUtil.getVciBaseException(vciError); } } /** * 查询生命周期的映射 * @return key是生命周期的编号, value是生命周期的对象 * @throws VciBaseException 查询出错的时候会抛出异常 */ @Override @VciUnLog public Map selectAllLifeCycleMap() throws VciBaseException{ return Optional.ofNullable(self.selectAllLifeCycle()).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getId(),t->t,(o1,o2)->o1)); } /** * 清除缓存 */ @Override public void clearCache() { } /** * 获取连接线 * @param lcid 生命周期的编号 * @param currentStatus 当前的状态 * @param targetStatus 目标的状态 * @return 连接线 * @throws VciBaseException 读取出错的时候会抛出异常 */ @Override public OsLifeCycleLineVO getTransVO(String lcid, String currentStatus, String targetStatus) throws VciBaseException { WebUtil.alertNotNull(lcid,"生命周期编码",currentStatus,"当前状态",targetStatus,"目标状态"); OsLifeCycleVO life = getLifeCycleById(lcid); if(life == null ){ throw new VciBaseException(DATA_ID_NOT_EXIST,new String[]{lcid}); } if(CollectionUtils.isEmpty(life.getLines())){ throw new VciBaseException(LIFE_CYCLE_ROUTER_NULL,new String[]{lcid}); } return Optional.ofNullable(life.getLines()).orElseGet(()->new ArrayList<>()).stream().filter(s->s.getSourceLifeStatus().equalsIgnoreCase(currentStatus) && s.getTargetLifeStatus().equalsIgnoreCase(targetStatus)).findFirst().orElseGet(()->null); } /** * 跃迁业务类型的生命周期状态 * @param obj 业务类型数据对象 * @param lineVO 跃迁路由 * @throws VciBaseException 跃迁出错的是会抛出异常 */ @Override public void doTransVO(com.vci.corba.omd.data.BusinessObject obj,OsLifeCycleLineVO lineVO) throws VciBaseException { if(lineVO!=null){ try { com.vci.corba.omd.lcm.TransitionVO transitionVO = lifeCycleLineVO2DO(lineVO); platformClientUtil.getBOFService().transferBusinessObject(obj, transitionVO.destination); } catch (PLException e) { throw WebUtil.getVciBaseException(e); } }else{ throw new VciBaseException(LIFE_CYCLE_ROUTER_NULL); } } /** * 连接线转换为平台的对象 * @param lineVO 连接线对象 * @return 平台的连接线对象 */ private com.vci.corba.omd.lcm.TransitionVO lifeCycleLineVO2DO(OsLifeCycleLineVO lineVO){ com.vci.corba.omd.lcm.TransitionVO transitionVO = new com.vci.corba.omd.lcm.TransitionVO(); transitionVO.id = lineVO.getOid(); transitionVO.source = lineVO.getSourceLifeStatus(); transitionVO.destination = lineVO.getTargetLifeStatus(); transitionVO.connect = lineVO.getName() == null?"":lineVO.getName(); //加事件 com.vci.corba.omd.lcm.TransitionVOEvent[] events; if(lineVO.getEvents() == null || lineVO.getEvents().length == 0){ events = new com.vci.corba.omd.lcm.TransitionVOEvent[0]; }else{ events = new com.vci.corba.omd.lcm.TransitionVOEvent[lineVO.getEvents().length]; for (int j = 0; j < lineVO.getEvents().length; j++) { OsLifeCycleLineEventVO eventVO = lineVO.getEvents()[j]; com.vci.corba.omd.lcm.TransitionVOEvent event = new com.vci.corba.omd.lcm.TransitionVOEvent(); event.id = eventVO.getOid(); event.name = eventVO.getEventFullName(); events[j] = event; } } transitionVO.transitionVOEvents = events; return transitionVO; } /** * 批量执行跃迁操作 * @param bos 业务类型数据 * @param vos 跃迁对象 * @throws VciBaseException 跃迁出错的是会抛出异常 */ @Override public void batchTransVo(com.vci.corba.omd.data.BusinessObject[] bos,OsLifeCycleLineVO[] vos) throws VciBaseException{ batchTransVo(bos,vos,null); } /** * 使用生命周期的编号回去包含的状态显示对象 * * @param lifeCycleId 生命周期的编号 * @return 状态的显示对象 */ @Override public List listStatusById(String lifeCycleId) { OsLifeCycleVO lifeCycleVO = getLifeCycleById(lifeCycleId); if(lifeCycleVO == null || StringUtils.isBlank(lifeCycleVO.getOid())){ return new ArrayList<>(); } Set hasStatusIdSet = new HashSet<>(); lifeCycleVO.getLines().stream().forEach(lineVO->{ hasStatusIdSet.add(lineVO.getSourceLifeStatus()); hasStatusIdSet.add(lineVO.getTargetLifeStatus()); }); Map statusVOMap = statusService.selectAllStatusMap(); List statusVOList = new ArrayList<>(); hasStatusIdSet.stream().forEach(statusId->{ statusVOList.add(statusVOMap.getOrDefault(statusId,new OsStatusVO())); }); return statusVOList; } /** * 批量添加生命周期 * * @param lifeCyleList 生命周期的内容 */ @Override public void batchAddLifeCycle(List lifeCyleList) { if(!CollectionUtils.isEmpty(lifeCyleList)){ lifeCyleList.stream().forEach(lifeCyle -> { try { platformClientUtil.getLifeCycleService().addLifeCycle(lifeCyle); } catch (PLException e) { throw WebUtil.getVciBaseException(e); } }); } } /** * 批量修改生命周期 * * @param lifeCycleList 生命周期的内容 */ @Override public void batchEditLifeCycle(List lifeCycleList) { if(!CollectionUtils.isEmpty(lifeCycleList)){ lifeCycleList.stream().forEach(lifeCyle -> { try { platformClientUtil.getLifeCycleService().modifyLifeCycle(lifeCyle); } catch (PLException e) { throw WebUtil.getVciBaseException(e); } }); } } /** * 状态在生命周期中使用的勤快 * * @param statusOid 状态的主键 * @return 生命周期的信息 */ @Override public DataGrid listStatusUsed(String statusOid) { if(StringUtils.isBlank(statusOid)){ return new DataGrid<>("没有状态的信息"); } OsStatusVO statusVO = statusService.getObjectByOid(statusOid); List lifeCycleVOS = self.selectAllLifeCycleMap().values().stream().collect(Collectors.toList()); List exitLifeVOList = new ArrayList<>(); Optional.ofNullable(lifeCycleVOS).orElseGet(()->new ArrayList<>()).stream().forEach( lifeCycleVO -> { if(Optional.ofNullable(lifeCycleVO.getLines()).orElseGet(()->new ArrayList<>()).stream().anyMatch( lineVO->statusVO.getId().equalsIgnoreCase(lineVO.getSourceLifeStatus())|| statusVO.getId().equalsIgnoreCase(lineVO.getTargetLifeStatus()))){ exitLifeVOList.add(lifeCycleVO); } }); DataGrid dataGrid = new DataGrid<>(); dataGrid.setData(exitLifeVOList); dataGrid.setTotal(exitLifeVOList.size()); return dataGrid; } /** * 判断状态是否被引用 * * @param statusVO 状态的显示对象 * @return true表示被引用 */ @Override public boolean checkStatusUsed(OsStatusVO statusVO) { List lifeCycleVOS = self.selectAllLifeCycleMap().values().stream().collect(Collectors.toList()); return Optional.ofNullable(lifeCycleVOS).orElseGet(()->new ArrayList<>()).stream().anyMatch( lifeCycleVO -> Optional.ofNullable(lifeCycleVO.getLines()).orElseGet(()->new ArrayList<>()).stream().anyMatch( lineVO->statusVO.getId().equalsIgnoreCase(lineVO.getSourceLifeStatus())|| statusVO.getId().equalsIgnoreCase(lineVO.getTargetLifeStatus())) ); } /** * 生命周期列表 * * @param baseQueryObject 查询对象,分页对象 * @return 生命周期显示对象 */ @Override public DataGrid gridLifeCycle(BaseQueryObject baseQueryObject) { return gridObject(baseQueryObject,OsLifeCycleDO.class,self.selectAllLifeCycleMap(),OsLifeCycleVO.class); } /** * 生命周期的链接线 * * @param id 编号 * @return ER图内容 */ @Override public OsERVO listLinesPic(String id) { if(StringUtils.isBlank(id)){ return null; } OsLifeCycleVO lifeCycleVO = self.selectAllLifeCycleMap().getOrDefault(id,null); if(lifeCycleVO == null){ return null; } List voLines = lifeCycleVO.getLines(); List statusVOS = listStatusById(lifeCycleVO.getId()); List nodeVOList = new ArrayList<>(); List relationVOList = new ArrayList<>(); Map statusVOMap = Optional.ofNullable(statusVOS).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(statusVOS)){ statusVOS.stream().forEach(statusVO -> { OsERNodeVO nodeVO = new OsERNodeVO(); nodeVO.setKey(statusVO.getId() + " " + statusVO.getName()); nodeVOList.add(nodeVO); }); } if(!CollectionUtils.isEmpty(voLines)){ voLines.stream().forEach(line->{ OsERRelationVO relationVO = new OsERRelationVO(); OsStatusVO statusVO = statusVOMap.get(line.getSourceLifeStatus().toLowerCase(Locale.ROOT)); OsStatusVO targetStatusVO = statusVOMap.get(line.getTargetLifeStatus().toLowerCase(Locale.ROOT)); relationVO.setFrom(statusVO.getId() + " " + statusVO.getName()); relationVO.setTo(targetStatusVO.getId() + " " + targetStatusVO.getName()); relationVO.setToText(line.getName()); relationVOList.add(relationVO); }); } OsERVO ervo = new OsERVO(); ervo.setTabViewList(nodeVOList); ervo.setTabRelViewList(relationVOList); return ervo; } /** * 批量执行跃迁操作,要求必须是同一个业务类型下的 * @param bos 业务类型数据对象 * @param lineVOs 跃迁对象 * @param releaseStatus 发布状态,如果目标状态是发布状态时传递这个值 * @throws VciBaseException 跃迁出错的是会抛出异常 */ @Override public void batchTransVo(com.vci.corba.omd.data.BusinessObject[] bos,OsLifeCycleLineVO[] lineVOs,String[] releaseStatus) throws VciBaseException{ if(bos!=null && lineVOs != null && lineVOs.length == bos.length){ try { if(releaseStatus == null){ releaseStatus = new String[lineVOs.length]; for(int i = 0 ; i < lineVOs.length ; i ++ ){ releaseStatus[i] = ""; } } com.vci.corba.omd.lcm.TransitionVO[] vos = new com.vci.corba.omd.lcm.TransitionVO[lineVOs.length]; for(int i = 0 ; i < lineVOs.length; i ++){ vos[i] = lifeCycleLineVO2DO(lineVOs[i]); } platformClientUtil.getBOFService().batchTransferBusinessObjectAndRelease( bos, vos, releaseStatus); } catch (PLException e) { throw WebUtil.getVciBaseException(e); } }else{ if(bos == null){ throw new VciBaseException(LIFE_CYCLE_TRANS_ERROR,new String[]{"业务类型数据为空"}); }else if(lineVOs ==null){ throw new VciBaseException(LIFE_CYCLE_TRANS_ERROR,new String[]{"跃迁路由为空"}); }else{ throw new VciBaseException(LIFE_CYCLE_TRANS_ERROR,new String[]{"跃迁路由和业务类型数据长度不相同"}); } } } }