package com.vci.web.service.impl; import com.vci.corba.common.PLException; import com.vci.corba.volume.VolumeServicePrx; import com.vci.dto.VciFileObjectDTO; import com.vci.lcstatuspck.FileLCStatus; import com.vci.pagemodel.VciFileObjectVO; import com.vci.starter.revision.service.RevisionModelUtil; import com.vci.starter.web.annotation.bus.VciChangeDocument; import com.vci.starter.web.enumpck.VciChangeDocumentTypeEnum; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.pagemodel.DataGrid; import com.vci.starter.web.pagemodel.PageHelper; import com.vci.starter.web.util.BeanUtil; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.wrapper.VciQueryWrapperForDO; import com.vci.web.dao.VciFileObjectDaoI; import com.vci.model.VciFileObjectDO; import com.vci.model.VciFileVolumeDO; import com.vci.web.service.VciFileObjectServiceI; import com.vci.web.service.VciFileVolumeServiceI; 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.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import static com.vci.constant.VciFileLangCodeConstant.FILE_RELEASED; import static com.vci.constant.FrameWorkLangCodeConstant.*; /** * 文件对象服务 * * @author weidy * @date 2020-08-04 */ @Service @VciChangeDocument(btmType = "fileObject") public class VciFileObjectServiceImpl implements VciFileObjectServiceI { /** * 日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 文件信息共享集合 */ private volatile Map threadFileObjectMap = new ConcurrentHashMap(); /** * 数据操作层 */ @Resource private VciFileObjectDaoI vciFileObjectMapper; /** * 版本和数据对象工具类 */ @Resource private RevisionModelUtil revisionModelUtil; /** * 文件的卷服务 */ @Resource private VciFileVolumeServiceI vciFileVolumeServiceI; /** * 平台的客户端 */ @Resource private PlatformClientUtil platformClientUtil; /** * 查询所有的文件对象 * @param conditionMap 查询条件 * @param pageHelper 分页和排序 * @return 执行结果 * @throws VciBaseException 查询条件和分页出错的时候会抛出异常 */ @Override public DataGrid gridVciFileObject(Map conditionMap, PageHelper pageHelper) throws VciBaseException { if (pageHelper == null) { pageHelper = new PageHelper(-1); } VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(conditionMap,VciFileObjectDO.class,pageHelper); List doList = vciFileObjectMapper.selectByWrapper(queryWrapper); DataGrid dataGrid=new DataGrid<>(); if (!CollectionUtils.isEmpty(doList)) { dataGrid.setData(vciFileObjectDO2VOs(doList)); queryWrapper.clearPage(); dataGrid.setTotal(vciFileObjectMapper.countByWrapper(queryWrapper)); } return dataGrid; } /** * 批量数据对象转换为显示对象 * @param vciFileObjectDOs 数据对象列表 * @return 显示对象 * @throws VciBaseException 参数为空或者不存在的时候会抛出异常 */ @Override public List vciFileObjectDO2VOs(Collection vciFileObjectDOs) throws VciBaseException { List voList = new ArrayList<>(); if(!CollectionUtils.isEmpty(vciFileObjectDOs)){ vciFileObjectDOs.stream().forEach(s ->{ VciFileObjectVO vo = vciFileObjectDO2VO(s); if(vo != null){ voList.add(vo); } }); } return voList; } /** * 数据对象转换为显示对象 * @param vciFileObjectDO 数据对象 * @return 显示对象 * @throws VciBaseException 拷贝属性出错的时候会抛出异常 */ @Override public VciFileObjectVO vciFileObjectDO2VO(VciFileObjectDO vciFileObjectDO) throws VciBaseException { VciFileObjectVO vo = new VciFileObjectVO(); if(vciFileObjectDO != null){ BeanUtil.convert(vciFileObjectDO,vo); //还需要处理枚举等其他的内容 } return vo; } /** * 增加文件对象 * @param vciFileObjectDTO 文件对象数据传输对象 * @return 执行结果 * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常 */ @Override @VciChangeDocument(changeType = VciChangeDocumentTypeEnum.ADD) public VciFileObjectVO addSave(VciFileObjectDTO vciFileObjectDTO) throws VciBaseException { VciBaseUtil.alertNotNull(vciFileObjectDTO,"需要添加的数据对象"); //将DTO转换为DO VciFileObjectDO vciFileObjectDO = new VciFileObjectDO(); BeanUtil.convert(vciFileObjectDTO,vciFileObjectDO); revisionModelUtil.wrapperForAdd(vciFileObjectDO); int insert = vciFileObjectMapper.insert(vciFileObjectDO); if(insert>0){ return vciFileObjectDO2VO(vciFileObjectDO); }else{ throw new VciBaseException(ADD_FAIL); } } /** * 修改文件对象 * @param vciFileObjectDTO 文件对象数据传输对象 * @return 执行结果 * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常 */ @Override @VciChangeDocument(changeType = VciChangeDocumentTypeEnum.EDIT) public VciFileObjectVO editSave(VciFileObjectDTO vciFileObjectDTO) throws VciBaseException { VciBaseUtil.alertNotNull(vciFileObjectDTO,"数据对象",vciFileObjectDTO.getOid(),"文件对象主键"); //将DTO转换为DO VciFileObjectDO vciFileObjectDO = selectByOid(vciFileObjectDTO.getOid()); revisionModelUtil.copyFromDTO(vciFileObjectDTO,vciFileObjectDO); revisionModelUtil.wrapperForEdit(vciFileObjectDO); int update = vciFileObjectMapper.updateByPrimaryKey(vciFileObjectDO); if(update>0){ return vciFileObjectDO2VO(vciFileObjectDO); }else{ throw new VciBaseException(EDIT_FAIL); } } /** * 校验是否可以删除,如果存在下级,并且下级有数据引用则不能删除 * @param vciFileObjectDTO 数据传输对象 * @param vciFileObjectDO 数据库中的数据对象 * @return success为true为可以删除,false表示有数据引用,obj为true表示有下级 */ private BaseResult checkIsCanDeleteForDO(VciFileObjectDTO vciFileObjectDTO, VciFileObjectDO vciFileObjectDO) { revisionModelUtil.checkTs(vciFileObjectDTO.getTs(),vciFileObjectDO.getTs()); if(!checkIsLinked(vciFileObjectDO.getOid())) { return BaseResult.success(); }else{ return BaseResult.fail(DATA_LINKED_NOT_DELETE,new String[]{""}); } } /** * 校验是否被引用 * @param oid 主键 * @throws VciBaseException 被引用的时候会抛出异常 */ private boolean checkIsLinked(String oid) throws VciBaseException { //TODO 添加需要校验引用的地方 return false; } /** * 删除文件对象 * @param vciFileObjectDTO 文件对象数据传输对象,oid和ts需要传输 * @return 删除结果反馈::success:成功,fail:失败 * @throws VciBaseException 参数为空,被引用时抛出异常 */ @Override @VciChangeDocument(changeType = VciChangeDocumentTypeEnum.DELETE) public BaseResult deleteVciFileObject(VciFileObjectDTO vciFileObjectDTO) throws VciBaseException { VciBaseUtil.alertNotNull(vciFileObjectDTO,"文件对象数据对象",vciFileObjectDTO.getOid(),"文件对象的主键"); VciFileObjectDO vciFileObjectDO = selectByOid(vciFileObjectDTO.getOid()); BaseResult baseResult = checkIsCanDeleteForDO(vciFileObjectDTO,vciFileObjectDO); if(baseResult.isSuccess()) { }else{ return baseResult; } //执行删除操作 return (vciFileObjectMapper.deleteByPrimaryKey(vciFileObjectDO.getOid()) > 0)? BaseResult.successMsg(DELETE_SUCCESS): BaseResult.fail(DELETE_FAIL); } /** * 主键获取文件对象 * @param oid 主键 * @return 文件对象显示对象 * @throws VciBaseException 参数为空,数据不存在时会抛出异常 */ @Override public VciFileObjectVO getObjectByOid(String oid) throws VciBaseException { return vciFileObjectDO2VO(selectByOid(oid)); } /** * 主键查询数据对象 * @param oid 主键 * @return 数据对象 * @throws VciBaseException 参数为空,并且数据不存在的时候会抛出异常 */ private VciFileObjectDO selectByOid(String oid) throws VciBaseException { VciBaseUtil.alertNotNull(oid,"主键"); VciFileObjectDO vciFileObjectDO = vciFileObjectMapper.selectByPrimaryKey(oid.trim()); if(vciFileObjectDO == null || StringUtils.isBlank(vciFileObjectDO.getOid())){ throw new VciBaseException(DATA_OID_NOT_EXIST); } return vciFileObjectDO; } /** * 主键批量获取文件对象 * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个 * @return 文件对象显示对象 * @throws VciBaseException 查询出现异常时会抛出 */ @Override public Collection listVciFileObjectByOids(Collection oidCollections) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("数据对象主键集合",oidCollections); List vciFileObjectDOList = listVciFileObjectDOByOidCollections(oidCollections); return vciFileObjectDO2VOs(vciFileObjectDOList); } /** * 使用主键集合查询数据对象 * @param oidCollections 主键的集合 * @return 数据对象列表 */ private List listVciFileObjectDOByOidCollections(Collection oidCollections){ List vciFileObjectDOList = new ArrayList<>(); if(!CollectionUtils.isEmpty(oidCollections)){ Collection> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections); oidCollectionsList.stream().forEach(oids ->{ List tempDOList = vciFileObjectMapper.selectByPrimaryKeyCollection(oids); if(!CollectionUtils.isEmpty(tempDOList)){ vciFileObjectDOList.addAll(tempDOList); } }); } return vciFileObjectDOList; } /** * 参照文件对象列表 * @param conditionMap 查询条件 * @param pageHelper 分页和排序 * @return 文件对象显示对象列表,生效的内容 * @throws VciBaseException 查询条件和分页出错的时候会抛出异常 */ @Override public DataGrid refDataGridVciFileObject(Map conditionMap, PageHelper pageHelper) throws VciBaseException { if(conditionMap == null){ conditionMap = new HashMap<>(); } return gridVciFileObject(conditionMap,pageHelper); } /** * 文件生效 * @param fileOidCollection 文件主键集合 * @return 执行结果 * @throws VciBaseException 保存出错的时候会抛出异常 */ @Override public BaseResult releasedFile(Collection fileOidCollection) throws VciBaseException { List updateList =listVciFileObjectDOByOidCollections(fileOidCollection); if(!CollectionUtils.isEmpty(updateList)){ updateList.stream().forEach(fileDO->{ fileDO.setLcStatus(FileLCStatus.FILE_RELEASE.getValue()); vciFileObjectMapper.updateByPrimaryKey(fileDO); }); } BaseResult baseResult = new BaseResult(); baseResult.setSuccess(true); baseResult.setData(vciFileObjectDO2VOs(updateList)); baseResult.setMsg(FILE_RELEASED); return baseResult; } /** * 文件生效 * * @param btmName 业务类型的名字 * @param businessOid 业务数据的主键 * @param fileOidCollection 文件的主键 * @return 执行的结果 * @throws VciBaseException 发布的时候出现错误会抛出异常 */ @Override public BaseResult releasedFile(String btmName, String businessOid, Collection fileOidCollection) throws VciBaseException { List updateList =listVciFileObjectDOByOidCollections(fileOidCollection); if(!CollectionUtils.isEmpty(updateList)){ updateList.stream().forEach(fileDO->{ fileDO.setLcStatus(FileLCStatus.FILE_RELEASE.getValue()); fileDO.setOwnBtmname(btmName); fileDO.setOwnbizOid(businessOid); }); vciFileObjectMapper.batchUpdateByPrimaryKey(updateList); } BaseResult baseResult = new BaseResult(); baseResult.setSuccess(true); baseResult.setData(vciFileObjectDO2VOs(updateList)); baseResult.setMsg(FILE_RELEASED); return baseResult; } /** * 查询业务类型的文件 * * @param conditionMap 查询条件 * @param pageHelper 分页和排序对象 * @param ownbizOid 业务类型的主键 * @param ownbizBtm 业务类型名称 * @return 文件显示对象的列表 * @throws VciBaseException 参数为空和查询出错的时候会抛出异常 */ @Override public DataGrid gridFilesByOwnbiz(Map conditionMap, PageHelper pageHelper, String ownbizOid, String ownbizBtm) throws VciBaseException { return gridFilesByOwnbiz(conditionMap,pageHelper,ownbizOid,ownbizBtm,null); } /** * 查询业务类型的文件 * * @param conditionMap 查询条件 * @param pageHelper 分页和排序对象 * @param ownbizOid 业务类型的主键 * @param ownbizBtm 业务类型名称 * @param docClassifyId 文档的类型 * @return 文件显示对象的列表 * @throws VciBaseException 参数为空和查询出错的时候会抛出异常 */ @Override public DataGrid gridFilesByOwnbiz(Map conditionMap, PageHelper pageHelper, String ownbizOid, String ownbizBtm, String docClassifyId) throws VciBaseException { if(StringUtils.isBlank(ownbizBtm) || StringUtils.isBlank(ownbizOid)){ return new DataGrid<>("业务类型主键或者名称不能为空"); } if(conditionMap == null){ conditionMap = new HashMap<>(); } conditionMap.put("ownbizOid",ownbizOid.trim()); conditionMap.put("ownBtmname",ownbizBtm.trim()); if(StringUtils.isNotBlank(docClassifyId)){ conditionMap.put("filetype",docClassifyId); } return gridVciFileObject(conditionMap,pageHelper); } /** * 读取业务数据的文件 * * @param ownbizOid 业务类型主键 * @param ownbizBtm 业务类型名称 * @param docClassifyId 文档类型编号 * @return 文件显示对象的列表 * @throws VciBaseException 参数为空和查询出错的时候会抛出异常 */ @Override public List listFilesByOwnbiz(String ownbizOid, String ownbizBtm, String docClassifyId) throws VciBaseException { VciBaseUtil.alertNotNull(ownbizOid,"业务数据的主键",ownbizBtm,"业务类型名称"); VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(null,VciFileObjectDO.class); queryWrapperForDO.eq("ownbizOid",ownbizOid.trim()); queryWrapperForDO.eq("ownBtmname",ownbizBtm.trim()); if(StringUtils.isNotBlank(docClassifyId)){ queryWrapperForDO.eq("filetype",docClassifyId.trim()); } return vciFileObjectDO2VOs(vciFileObjectMapper.selectByWrapper(queryWrapperForDO)); } /** * 批量读取业务类数据的文件 * @param ownbizOidCollection 业务类型主键集合 * @param ownbizBtm 业务类型名称 * @param docClassifyId 文档类型编号 * @return 文件显示对象的列表 * @throws VciBaseException 参数为空和查询出错的时候会抛出异常 */ @Override public List batchListFilesByOwnbizs(Collection ownbizOidCollection,String ownbizBtm,String docClassifyId) throws VciBaseException { VciBaseUtil.alertNotNull(ownbizBtm,"业务类型名称"); VciBaseUtil.alertCollectionNotNull("业务数据的主键",ownbizOidCollection); List fileObjectDOList = new ArrayList<>(); Collection> ownbizOidCollections = VciBaseUtil.switchCollectionForOracleIn(ownbizOidCollection); ownbizOidCollections.stream().forEach(ownbizOids-> { VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(null,VciFileObjectDO.class); queryWrapperForDO.in("ownbizOid", VciBaseUtil.toInSql(ownbizOids.toArray(new String[0]))); queryWrapperForDO.eq("ownBtmname",ownbizBtm.trim()); if(StringUtils.isNotBlank(docClassifyId)){ queryWrapperForDO.eq("filetype",docClassifyId.trim()); } List tempFileObjectDOs = vciFileObjectMapper.selectByWrapper(queryWrapperForDO); if(!CollectionUtils.isEmpty(tempFileObjectDOs)){ fileObjectDOList.addAll(tempFileObjectDOs); } }); return vciFileObjectDO2VOs(fileObjectDOList); } /** * 根据关键信息获取文件信息 * @param keyInfoCollection 关键信息 * @param docClassifyId 文件分类的编号 * @return 文件显示对象,取data属性 * @throws VciBaseException 参数为空和查询出错的时候会抛出异常 */ @Override public BaseResult listFileObjectByKeyInfo(Collection keyInfoCollection, String docClassifyId) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("关键信息",keyInfoCollection); BaseResult baseResult = new BaseResult(); Collection> keyInfoCollections = VciBaseUtil.switchCollectionForOracleIn(keyInfoCollection); List fileObjectDOList = new ArrayList<>(); VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(VciFileObjectDO.class); keyInfoCollections.stream().forEach(keyInfos->{ queryWrapperForDO.setWhereSql(""); queryWrapperForDO.in("keyInfos", VciBaseUtil.toInSql(keyInfos.toArray(new String[0]))); if(StringUtils.isNotBlank(docClassifyId)){ queryWrapperForDO.eq("filetype",docClassifyId); } List tempFileDOList = vciFileObjectMapper.selectByWrapper(queryWrapperForDO); if(!CollectionUtils.isEmpty(tempFileDOList)){ fileObjectDOList.addAll(tempFileDOList); } }); baseResult.setData(vciFileObjectDO2VOs(fileObjectDOList)); baseResult.setSuccess(true); return baseResult; } /** * 使用关键信息统计个数 * * @param keyInfoCollection 关键信息,多个以逗号分隔, * @param docClassifyId 文档分类编号 * @return 个数 */ @Override public Long countByKeyInfo(Collection keyInfoCollection, String docClassifyId) throws VciBaseException { if(CollectionUtils.isEmpty(keyInfoCollection)){ return 0L; } Collection> keyInfoCollections = VciBaseUtil.switchCollectionForOracleIn(keyInfoCollection); VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(VciFileObjectDO.class); final Long[] total = {0L}; keyInfoCollections.stream().forEach(keyInfos->{ queryWrapperForDO.setWhereSql(""); queryWrapperForDO.in("keyInfos", VciBaseUtil.toInSql(keyInfos.toArray(new String[0]))); if(StringUtils.isNotBlank(docClassifyId)){ queryWrapperForDO.eq("filetype",docClassifyId); } Long thisTotal = vciFileObjectMapper.countByWrapper(queryWrapperForDO); if(thisTotal!=null){ total[0] += thisTotal; } }); return total[0]; } /** * 删除文件 * * @param fileOids 文件的主键 * @return 执行结果 */ @Override public BaseResult deleteFiles(Collection fileOids) throws VciBaseException { Collection fileObjectVOS = listVciFileObjectByOids(fileOids); if(!CollectionUtils.isEmpty(fileObjectVOS)){ VciBaseUtil.switchCollectionForOracleIn(fileObjectVOS).stream().forEach(fileObjectVOList->{ vciFileObjectMapper.batchDeleteByOids(fileObjectVOList.stream().map(VciFileObjectVO::getOid).collect(Collectors.toList())); }); //删除仓库中的文件 //获取文件仓位置 VciFileVolumeDO vciFileVolumeDO = vciFileVolumeServiceI.getUploadVolume(); String volumeName = vciFileVolumeDO.getName(); VolumeServicePrx volumnCorbaService = platformClientUtil.getVolumeService(volumeName); if(volumnCorbaService == null){ throw new VciBaseException("没有获取到卷服务"); } Set filePathSet = fileObjectVOS.stream().map(VciFileObjectVO::getFilePath).collect(Collectors.toSet()); String[] filePathArr = new String[filePathSet.size()]; filePathSet.toArray(filePathArr); try { volumnCorbaService.deleteAllFiles(filePathArr); } catch (PLException e) { logger.error("卷服务删除仓库中的文件失败:", e); logger.error("卷服务删除失败的文件:"+ WebUtil.getJSONStringWithDateFormat(filePathSet)); } } return BaseResult.success(); } /** * 使用文件的路径获取对象 * * @param filePathList 文件路径 * @param docClassifyId 文档的类型编号 * @return 文件的显示对象 */ @Override public List listFileObjectByPath(Collection filePathList, String docClassifyId) { if(CollectionUtils.isEmpty(filePathList)){ return new ArrayList<>(); } Collection> filePathCollections = VciBaseUtil.switchCollectionForOracleIn(filePathList); VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(VciFileObjectDO.class); List fileObjectDOList = new ArrayList<>(); filePathCollections.stream().forEach(filePath->{ queryWrapperForDO.setWhereSql(""); queryWrapperForDO.in("filePath", VciBaseUtil.toInSql(filePath.toArray(new String[0]))); if(StringUtils.isNotBlank(docClassifyId)){ queryWrapperForDO.eq("filetype",docClassifyId); } List fileObjectDOS = vciFileObjectMapper.selectByWrapper(queryWrapperForDO); if(!CollectionUtils.isEmpty(fileObjectDOS)){ fileObjectDOList.addAll(fileObjectDOS); } }); return vciFileObjectDO2VOs(fileObjectDOList); } }