1428594221
2023-06-14 931eb15f748f181fbf347508830f21830f09c863
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java
@@ -1,1026 +1,1210 @@
package com.vci.ubcs.code.service.impl;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.entity.CodeClassify;
import com.vci.ubcs.code.entity.CodeClassifyTemplate;
import com.vci.ubcs.code.enumpack.FrameworkDataLCStatus;
import com.vci.ubcs.code.mapper.CodeClassifyMapper;
import com.vci.ubcs.code.mapper.CodeClassifyTemplateMapper;
import com.vci.ubcs.code.entity.CodeClassifyDO;
import com.vci.ubcs.code.entity.CodeClassifyTemplateDO;
import com.vci.ubcs.code.service.CodeClassifyServiceI;
import com.vci.ubcs.code.service.CodeDuckingServiceI;
import com.vci.ubcs.code.service.CodeKeyAttrRepeatRuleServiceI;
import com.vci.ubcs.code.service.CodeRuleServiceI;
import com.vci.frameworkcore.lcstatuspck.FrameworkDataLCStatus;
import com.vci.starter.poi.bo.ReadExcelOption;
import com.vci.starter.poi.bo.WriteExcelData;
import com.vci.starter.poi.bo.WriteExcelOption;
import com.vci.starter.poi.constant.ExcelLangCodeConstant;
import com.vci.starter.poi.util.ExcelUtil;
import com.vci.starter.revision.bo.TreeWrapperOptions;
import com.vci.starter.revision.service.RevisionModelUtil;
import com.vci.starter.web.constant.QueryOptionConstant;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.*;
import com.vci.starter.web.util.*;
import com.vci.starter.web.wrapper.VciParentQueryOption;
import com.vci.starter.web.wrapper.VciQueryWrapperForDO;
import com.vci.web.pageModel.BatchCBO;
import com.vci.web.pageModel.OsAttributeVO;
import com.vci.web.pageModel.OsBtmTypeAttributeVO;
import com.vci.web.pageModel.OsBtmTypeVO;
import com.vci.web.service.OsAttributeServiceI;
import com.vci.web.service.OsBtmServiceI;
import com.vci.web.service.WebBoServiceI;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.dto.CodeClassifyDTO;
import com.vci.ubcs.code.po.CodeClassifyPO;
import com.vci.ubcs.code.service.ICodeClassifyService;
import com.vci.ubcs.code.service.ICodeKeyAttrRepeatService;
import com.vci.ubcs.code.service.ICodeRuleService;
import com.vci.ubcs.code.vo.pagemodel.CodeClassifyVO;
import com.vci.ubcs.code.vo.pagemodel.CodeKeyAttrRepeatRuleVO;
import com.vci.ubcs.code.vo.pagemodel.CodeRuleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import com.vci.ubcs.omd.cache.EnumCache;
import com.vci.ubcs.omd.enums.EnumEnum;
import com.vci.ubcs.omd.feign.IBtmTypeClient;
import com.vci.ubcs.omd.vo.BtmTypeAttributeVO;
import com.vci.ubcs.omd.feign.IBtmTypeClient;
import com.vci.ubcs.omd.vo.BtmTypeVO;
import com.vci.ubcs.starter.bo.WriteExcelData;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.poi.bo.ReadExcelOption;
import com.vci.ubcs.starter.poi.bo.WriteExcelOption;
import com.vci.ubcs.starter.poi.constant.ExcelLangCodeConstant;
import com.vci.ubcs.starter.poi.util.ExcelUtil;
import com.vci.ubcs.starter.revision.model.TreeQueryObject;
import com.vci.ubcs.starter.revision.model.TreeWrapperOptions;
import com.vci.ubcs.starter.revision.service.RevisionModelUtil;
import com.vci.ubcs.starter.util.BladeTreeQueryObject;
import com.vci.ubcs.starter.util.LocalFileUtil;
import com.vci.ubcs.starter.web.pagemodel.BaseQueryObject;
import com.vci.ubcs.starter.web.pagemodel.DataGrid;
import com.vci.ubcs.starter.web.pagemodel.Tree;
import com.vci.ubcs.starter.web.util.BeanUtilForVCI;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import org.apache.poi.hssf.util.HSSFColor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.awt.event.ItemEvent;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.vci.frameworkcore.constant.FrameWorkBusLangCodeConstant.*;
import static com.vci.frameworkcore.constant.FrameWorkDefaultValueConstant.*;
import static com.vci.ubcs.code.constant.FrameWorkDefaultValueConstant.*;
/**
 * 主题库分类服务
 * @author weidy
 * @date 2022-01-20
 */
@Service
public class CodeClassifyServiceImpl implements CodeClassifyServiceI {
public class CodeClassifyServiceImpl extends ServiceImpl<CodeClassifyMapper, CodeClassify> implements ICodeClassifyService {
    /**
    * 日志
    */
    private Logger logger = LoggerFactory.getLogger(getClass());
   @Resource
   private CodeClassifyMapper codeClassifyMapper;
    /**
    * 数据操作层
    */
    @Resource
    private CodeClassifyMapper codeClassifyMapper;
   @Resource
   private CodeClassifyTemplateMapper codeClassifyTemplateMapper;
    /**
    * 业务类型操作的服务
    */
    @Autowired
   @Lazy
   private WebBoServiceI boService;
   @Resource
   private ICodeRuleService codeRuleService;
    /**
    * 对象的操作
    */
    @Autowired
    private RevisionModelUtil revisionModelUtil;
   @Resource
   private IBtmTypeClient btmTypeClient;
    /**
     * 规则的服务
     */
    @Autowired
   @Lazy
    private CodeRuleServiceI codeRuleService;
   /**
    * 日志
    */
   private Logger logger = LoggerFactory.getLogger(getClass());
   /**
    * 对象的操作
    */
   @Resource
   private RevisionModelUtil revisionModelUtil;
    /**
     * 关键属性的服务
     */
    @Autowired
    private CodeKeyAttrRepeatRuleServiceI keyAttrRepeatRuleService;
   @Resource
   private ICodeKeyAttrRepeatService iCodeKeyattrrepeatService;
   /**
    * 上级节点的属性名称
    */
   public static  final String PARENT_FIELD_NAME = "parentCodeClassifyOid";
   /**
    * 使用查询封装器来查询
    * @param wrapper 查询封装器
    * @return 数据对象
    */
   @Override
   public List<CodeClassify> selectByWrapper(Wrapper wrapper) {
      return codeClassifyMapper.selectList(wrapper);
   }
    /**
     * 数据集成
     */
    @Autowired
   @Lazy
    private CodeDuckingServiceI codeDuckingServiceI;
   /**
    * 查询
    * @param wrapper 查询封装器
    * @return
    */
   @Override
   public List<String> select1(Wrapper wrapper) {
    /**
     * 业务类型的服务
     */
    @Autowired
    private OsBtmServiceI btmService;
      return codeClassifyMapper.selectObjs(wrapper);
   }
    /**
     * 属性服务
     */
    @Autowired
    private OsAttributeServiceI attributeService;
    /**
     * 数据操作层
     */
    @Resource
    private CodeClassifyTemplateMapper codeClassifyTemplateMapper;
    /**
    * 上级节点的属性名称
    */
    public static  final String PARENT_FIELD_NAME = "parentCodeClassifyOid";
    /**
     * 查询主题库分类 树
     * @param treeQueryObject 树查询对象
     * @return 主题库分类 显示树
     * @throws VciBaseException 查询条件不符合要求的时候会抛出异常
     */
    @Override
    public List<Tree> treeCodeClassify(TreeQueryObject treeQueryObject) throws VciBaseException {
        List<CodeClassifyDO> doList =selectCodeClassifyDOByTree(treeQueryObject);
        List<CodeClassifyVO> voList = codeClassifyDO2VOs(doList);
        TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions(PARENT_FIELD_NAME.toLowerCase(Locale.ROOT));
        treeWrapperOptions.copyFromTreeQuery(treeQueryObject);
        List<Tree> tree= revisionModelUtil.doList2Trees(voList,treeWrapperOptions,(CodeClassifyVO s) ->{
            //可以在这里处理树节点的显示
            return s.getId() + " " + s.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equalsIgnoreCase(s
                    .getLcStatus()) ? (" 【停用】 ") : "");
        });
        Iterator var6 =  tree.listIterator();
        while(var6.hasNext()){
            Tree trees = (Tree) var6.next();
            boolean checkHasChild=codeClassifyMapper.checkHasChild(trees.getOid());
            if(checkHasChild){
                trees.setLeaf(false);
            }else{
                trees.setLeaf(true);
            }
        }
        return tree;
    }
    /**
     * 主题库的树
     *
     * @param treeQueryObject 树形查询对象
     * @return 主题库显示树
     */
    @Override
    public List<Tree> treeTopCodeClassify(TreeQueryObject treeQueryObject) {
        if(treeQueryObject == null){
            treeQueryObject = new TreeQueryObject();
        }
        if(treeQueryObject.getConditionMap() == null){
            treeQueryObject.setConditionMap(new HashMap<>());
        }
        treeQueryObject.getConditionMap().put(PARENT_FIELD_NAME, QueryOptionConstant.ISNULL);
        return treeCodeClassify(treeQueryObject);
    }
   @Override
   public IPage<CodeClassifyVO> selectPlCodeClassifyPage(IPage<CodeClassifyVO> page, CodeClassifyVO plCodeClassify) {
      return page.setRecords(codeClassifyMapper.selectPlCodeClassifyPage(page, plCodeClassify));
   }
    /**
     * 根据树形查询对象来查询数据对象
     *
     * @param treeQueryObject 树形查询对象
     * @return 查询结果,数据对象
     */
    @Override
    public List<CodeClassifyDO> selectCodeClassifyDOByTree(TreeQueryObject treeQueryObject) {
        VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(null,CodeClassifyDO.class);
        VciParentQueryOption parentQueryOption = new VciParentQueryOption();
        parentQueryOption.setParentFieldName(PARENT_FIELD_NAME);
        queryWrapperForDO.parentQueryChild(treeQueryObject,parentQueryOption);
        if(StringUtils.isBlank(treeQueryObject.getSort())) {
            PageHelper pageHelper = new PageHelper(-1);
            pageHelper.addDefaultAsc("id");
            queryWrapperForDO.setPageHelper(pageHelper);
        }
        return codeClassifyMapper.selectByWrapper(queryWrapperForDO);
    }
   @Override
   public R addSave(CodeClassify codeClassifyEntity) {
    /**
     * 批量数据对象转换为显示对象
     * @param codeClassifyDOs 数据对象列表
     * @return 显示对象
     * @throws VciBaseException 参数为空或者不存在的时候会抛出异常
     */
    @Override
    public List<CodeClassifyVO> codeClassifyDO2VOs(Collection<CodeClassifyDO> codeClassifyDOs) throws VciBaseException{
        List<CodeClassifyVO> voList = new ArrayList<CodeClassifyVO>();
        if(!CollectionUtils.isEmpty(codeClassifyDOs)){
           for(CodeClassifyDO s: codeClassifyDOs){
                CodeClassifyVO vo =  codeClassifyDO2VO(s);
                if(vo != null){
                    voList.add(vo);
                }
            }
        }
        return voList;
    }
      if(StringUtils.isNotBlank(codeClassifyEntity.getParentCodeClassifyOid()) && StringUtils.isNotBlank(codeClassifyEntity.getBtmTypeId())){
         return R.fail("只有在顶层的主题库分类才能设置业务类型");
      }
      codeClassifyEntity.setCreator(AuthUtil.getUser().getUserName());
      codeClassifyEntity.setCreateTime(new Date());
      codeClassifyEntity.setTs(new Date());
      codeClassifyEntity.setOwner(AuthUtil.getUser().getUserName());
      codeClassifyEntity.setLastModifier(AuthUtil.getUser().getUserName());
      codeClassifyEntity.setLastModifyTime(new Date());
      codeClassifyEntity.setRevisionSeq(1);
      codeClassifyEntity.setVersionSeq(1);
      int insertNumber = codeClassifyMapper.insert(codeClassifyEntity);
      return R.status(SqlHelper.retBool(insertNumber));
   }
    /**
     * 数据对象转换为显示对象
     * @param  codeClassifyDO 数据对象
     * @return 显示对象
     * @throws VciBaseException 拷贝属性出错的时候会抛出异常
     */
    @Override
    public  CodeClassifyVO codeClassifyDO2VO(CodeClassifyDO codeClassifyDO) throws VciBaseException{
              CodeClassifyVO vo = new CodeClassifyVO();
        if(codeClassifyDO != null){
            BeanUtilForVCI.copyPropertiesIgnoreCase(codeClassifyDO,vo);
            //如果有lcstatus的类的话
            vo.setLcStatusText(FrameworkDataLCStatus.getTextByValue(vo.getLcStatus()));
        }
        return vo;
    }
   /**
    * 修改主题库分类
    * @param codeClassifyEntity 主题库分类数据传输对象
    * @return 执行结果
    */
   @Override
   public R editSave(CodeClassify codeClassifyEntity) {
      if(codeClassifyEntity == null || codeClassifyEntity.getOid() == null){
         return R.fail("传入数据不能为空!");
      }
      //检查ts
      Map<String,Object> condition = new HashMap<>(2);
      condition.put("oid",codeClassifyEntity.getOid());
      condition.put("ts",codeClassifyEntity.getTs());
      CodeClassify detail = codeClassifyMapper
         .selectOne(Condition.getQueryWrapper(condition,CodeClassify.class));
      if(detail == null){//不是最新的不让改
         return R.fail("当前数据不是最新,请刷新后再修改!");
      }
    /**
     * 增加主题库分类
     * @param codeClassifyDTO 主题库分类数据传输对象
     * @return 执行结果
     * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常
     */
    @Override
    public CodeClassifyVO addSave(CodeClassifyDTO codeClassifyDTO) throws VciBaseException{
        VciBaseUtil.alertNotNull(codeClassifyDTO,"需要添加的数据对象");
        //将DTO转换为DO
        CodeClassifyDO codeClassifyDO = new CodeClassifyDO();
        BeanUtilForVCI.copyPropertiesIgnoreCase(codeClassifyDTO,codeClassifyDO);
        if(StringUtils.isNotBlank(codeClassifyDO.getParentCodeClassifyOid()) && StringUtils.isNotBlank(codeClassifyDO.getBtmTypeId())){
            throw new VciBaseException("只有在顶层的主题库分类才能设置业务类型");
        }
        BatchCBO cbo_insert = codeClassifyMapper.insert(codeClassifyDO);
//        //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理
//        ClientBusinessObject[] clientBusinessObjects = cbo_insert.getCreateCboArray();
//        if(clientBusinessObjects.length!=0);
//        {
//            codeDuckingServiceI.insertCache1(CACHE_TYPE_CLASSIFY_ADD,FRAMEWORK_DATA_ENABLED,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, codeClassifyDO.getOid(), DateUtils.addHours(new Date(),1));
//        }
        return codeClassifyDO2VO(codeClassifyDO);
    }
    /**
     * 修改主题库分类
     * @param codeClassifyDTO 主题库分类数据传输对象
     * @return 执行结果
     * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常
     */
     @Override
     public BaseResult editSave(CodeClassifyDTO codeClassifyDTO) throws VciBaseException{
         VciBaseUtil.alertNotNull(codeClassifyDTO,"数据对象",codeClassifyDTO.getOid(),"主题库分类主键");
         //检查ts
         CodeClassifyDO codeClassifyDOCopyFromDTO = new CodeClassifyDO();
         BeanUtilForVCI.copyPropertiesIgnoreCase(codeClassifyDTO,codeClassifyDOCopyFromDTO);
         boolean tsBoolean = boService.checkTs(codeClassifyDOCopyFromDTO);
         if(!tsBoolean){//不是最新的不让改
             return BaseResult.fail("当前数据不是最新,请刷新后再修改!");
         }
         //将DTO转换为DO
         CodeClassifyDO codeClassifyDO = selectByOid(codeClassifyDTO.getOid());
         revisionModelUtil.copyFromDTOIgnore(codeClassifyDTO,codeClassifyDO);
         if(StringUtils.isNotBlank(codeClassifyDO.getParentCodeClassifyOid()) && StringUtils.isNotBlank(codeClassifyDO.getBtmTypeId())){
             throw new VciBaseException("只有在顶层的主题库分类才能设置业务类型");
         }
         codeClassifyMapper.updateByPrimaryKey(codeClassifyDO);
      if(StringUtils.isNotBlank(codeClassifyEntity.getParentCodeClassifyOid()) && StringUtils.isNotBlank(codeClassifyEntity.getBtmTypeId())){
         return R.fail("只有在顶层的主题库分类才能设置业务类型");
      }
      codeClassifyEntity.setLastModifier(AuthUtil.getUser().getUserName());
      codeClassifyEntity.setLastModifyTime(new Date());
      int insertNumber = codeClassifyMapper.updateById(codeClassifyEntity);
//         //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。只有启用状态的分类才推送
//         if(FRAMEWORK_DATA_ENABLED.equals(codeClassifyDO.getLcStatus()));
//         {
//             codeDuckingServiceI.insertCache1(CACHE_TYPE_CLASSIFY_EDIT,FRAMEWORK_DATA_ENABLED,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, codeClassifyDO.getOid(), codeClassifyDTO.getTs());
//         }
      return R.status(SqlHelper.retBool(insertNumber));
//      return BaseResult.success(codeClassifyDO2VO(codeClassifyDO));
   }
         return BaseResult.success(codeClassifyDO2VO(codeClassifyDO));
     }
   /**
    * 检查 主题库分类是否删除
    * @param codeClassifyEntity 主题库分类数据传输对象,必须要有oid和ts属性
    * @return 执行结果 success为true为可以删除,false表示有数据引用,obj为true表示有下级
    */
   @Override
   public R checkIsCanDelete(CodeClassify codeClassifyEntity) {
      if(codeClassifyEntity == null || codeClassifyEntity.getOid() == null){
         return R.fail("传入数据不能为空!");
      }
      CodeClassify codeClassifyNew = selectByOid(codeClassifyEntity.getOid());
      if(codeClassifyNew == null){
         return R.fail("未查询到相关数据!");
      }
      codeClassifyNew.setTs(codeClassifyEntity.getTs());
      return checkIsCanDeleteForDO(codeClassifyEntity);
   }
/**
 * 检查 主题库分类是否删除
 * @param codeClassifyDTO 主题库分类数据传输对象,必须要有oid和ts属性
 * @return 执行结果 success为true为可以删除,false表示有数据引用,obj为true表示有下级
 * @throws VciBaseException 参数为空,被引用时抛出异常
 */
@Override
public BaseResult checkIsCanDelete(CodeClassifyDTO codeClassifyDTO) throws VciBaseException{
    VciBaseUtil.alertNotNull(codeClassifyDTO,"数据传输对象",codeClassifyDTO.getOid(),"主键");
    CodeClassifyDO codeClassifyDO = selectByOid(codeClassifyDTO.getOid());
    return checkIsCanDeleteForDO(codeClassifyDTO,codeClassifyDO);
}
   /**
    * 主键查询数据对象
    * @param oid 主键
    * @return  数据对象
    */
   private CodeClassify selectByOid(String oid){
    /**
     * 校验是否可以删除,如果存在下级,并且下级有数据引用则不能删除
     * @param codeClassifyDTO 数据传输对象
     * @param codeClassifyDO 数据库中的数据对象
     * @return success为true为可以删除,false表示有数据引用,obj为true表示有下级
     */
    private BaseResult checkIsCanDeleteForDO(CodeClassifyDTO codeClassifyDTO, CodeClassifyDO codeClassifyDO) {
        CodeClassifyDO tsDO = new CodeClassifyDO();
        BeanUtilForVCI.copyPropertiesIgnoreCase(codeClassifyDTO,tsDO);
        boService.checkTs(tsDO);
        //校验下级是否有引用
        if(checkChildIsLinked(codeClassifyDO.getOid())){
            return BaseResult.fail(DATA_CASCADE_LINKED_NOT_DELETE,new String[]{""});
        }
        return BaseResult.success(checkHasChild(codeClassifyDO.getOid()));
    }
    /**
      * 检查是否有下级是否关联了数据
      *
      * @param oid 主键
      * @return true 表示有引用,false表示没有引用
      * @throws VciBaseException 参数为空和有引用的时候会抛出异常
      */
    @Override
    public boolean checkChildIsLinked(String oid) throws VciBaseException {
        VciBaseUtil.alertNotNull(oid,"主键");
        Map<String,String> childOids = codeClassifyMapper.selectAllLevelChildOid(oid.trim());
        if(!CollectionUtils.isEmpty(childOids)){
             for(String childOid: childOids.keySet()){
                 if(!checkIsLinked(childOid)){
                     return false;
                 }
             }
            return true;
        }
        return false;
    }
      CodeClassify codeClassifyEntity = codeClassifyMapper.selectById(oid.trim());
      if(codeClassifyEntity == null || StringUtils.isBlank(codeClassifyEntity.getOid())){
         throw new ServiceException("dataOidNotExist");//根据主键id未查到相关数据
      }
      return codeClassifyEntity;
   }
    /**
    * 校验是否有下级节点,不校验是否关联了数据
    *
    * @param oid 主键
    * @return true表示有下级,false表示没有下级
    * @throws VciBaseException 参数错误,或者数据不存在的时候会抛出异常
    */
    @Override
    public boolean checkHasChild(String oid) throws VciBaseException {
        VciBaseUtil.alertNotNull(oid,"主键");
        return codeClassifyMapper.checkHasChild(oid.trim());
    }
   /**
    * 校验是否可以删除,如果存在下级,并且下级有数据引用则不能删除
    * @param codeClassifyEntity 数据库中的数据对象
    * @return success为true为可以删除,false表示有数据引用,obj为true表示有下级
    */
   private R checkIsCanDeleteForDO(CodeClassify codeClassifyEntity) {
    /**
    * 校验是否被引用
    * @param oid 主键
    * @throws VciBaseException 被引用的时候会抛出异常
    */
    private boolean checkIsLinked(String oid) throws VciBaseException{
        //TODO 添加需要校验引用的地方
        return false;
    }
      //检查ts
//      Map<String,Object> condition = new HashMap<>(2);
//      condition.put("oid",codeClassifyEntity.getOid());
//      condition.put("ts",codeClassifyEntity.getTs());
      CodeClassify detail = codeClassifyMapper.selectOne(Condition.getQueryWrapper(codeClassifyEntity));
//         .selectOne(Condition.getQueryWrapper(condition,CodeClassify.class));
      if(detail == null){//不是最新的不让改
         throw new ServiceException("当前数据不是最新,请刷新后再修改!");
//         return R.fail("当前数据不是最新,请刷新后再修改!");
      }
      //校验下级是否有引用
      if(checkChildIsLinked(detail.getOid())){
         return R.fail("dataCascadeLinkedNotDelete");
      }
      return R.data(checkHasChild(detail.getOid()));
   }
    /**
     * 删除主题库分类
     * @param codeClassifyDTO 主题库分类数据传输对象,oid和ts需要传输
     * @return 删除结果反馈::success:成功,fail:失败
     * @throws VciBaseException 参数为空,被引用时抛出异常
     */
    @Override
    public BaseResult deleteCodeClassify(CodeClassifyDTO codeClassifyDTO) throws VciBaseException{
        VciBaseUtil.alertNotNull(codeClassifyDTO,"主题库分类数据对象",codeClassifyDTO.getOid(),"主题库分类的主键");
        CodeClassifyDO codeClassifyDO = selectByOid(codeClassifyDTO.getOid());
        BaseResult baseResult = checkIsCanDeleteForDO(codeClassifyDTO,codeClassifyDO);
   /**
    * 检查是否有下级是否关联了数据
    *
    * @param oid 主键
    * @return true 表示有引用,false表示没有引用
    */
   @Override
   public boolean checkChildIsLinked(String oid) {
        //先简称是否有关联模板,有模板要先删除
        VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(CodeClassifyTemplateDO.class);
        queryWrapper.addQueryMap("codeClassifyOid",codeClassifyDTO.getOid());
        List<CodeClassifyTemplateDO> codeClassifyTemplateDOListHaveTemplate =  codeClassifyTemplateMapper.selectByWrapper(queryWrapper);
        if(codeClassifyTemplateDOListHaveTemplate.size()>0){
            return BaseResult.fail("分类关联模板,请先删除!");
        }
      Map<String,String> childOids = codeClassifyMapper.selectAllLevelChildOid(oid.trim());
      if(!CollectionUtils.isEmpty(childOids)){
         for(String childOid: childOids.keySet()){
            if(!checkIsLinked(childOid)){
               return false;
            }
         }
         return true;
      }
      return false;
   }
        //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。
        //1、查询要删除的父类数据
        List<CodeClassifyDO> deletes = new ArrayList<CodeClassifyDO>();
        deletes.add(codeClassifyDO);
   /**
    * 校验是否被引用
    * @param oid 主键
    */
   private boolean checkIsLinked(String oid) {
      //TODO 添加需要校验引用的地方
      return false;
   }
        if(baseResult.isSuccess()) {
                        //找下级的,这个是可以删除的时候
            Map<String,String> childrenOids = codeClassifyMapper.selectAllLevelChildOid(codeClassifyDO.getOid().trim());
            if (!CollectionUtils.isEmpty(childrenOids)) {
                Collection<Collection<String>> childrenCollections = VciBaseUtil.switchCollectionForOracleIn(childrenOids.keySet());
                for(Collection<String> s : childrenCollections){
   @Override
   public boolean checkHasChild(String oid) {
      if(StringUtils.isBlank(oid)){
         throw new ServiceException("oid不能为空!");
      }
      return codeClassifyMapper.checkHasChild(oid.trim());
   }
                    //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。
                    //2、查询要删除的子类数据
                    List<CodeClassifyDO>  codeClassifyDOList = codeClassifyMapper.selectByPrimaryKeyCollection(s);
                    deletes.addAll(codeClassifyDOList);
   /**
    * 删除主题库分类
    * @param codeClassify 主题库分类数据传输对象,oid和ts需要传输
    * @return 删除结果反馈::success:成功,fail:失败
    */
   @Override
   public R deleteCodeClassify(CodeClassify codeClassify) {
                    codeClassifyMapper.batchDeleteByOids(s);
                }
      if(codeClassify == null || codeClassify.getOid() == null){
         throw new ServiceException("传入参数不能为空!");
      }
      codeClassify = codeClassifyMapper.selectById(codeClassify.getOid());
            }
                    }else{
            return baseResult;
        }
      R result = checkIsCanDeleteForDO(codeClassify);
        //执行删除操作
        BatchCBO batchCBO = codeClassifyMapper.deleteByPrimaryKey(codeClassifyDO.getOid());
      //先简称是否有关联模板,有模板要先删除
      Map<String,Object> condition = new HashMap<>(2);
      condition.put("codeClassifyOid",codeClassify.getOid());
      List<CodeClassifyTemplate> codeClstemplateEntities = codeClassifyTemplateMapper.selectByMap(condition);
//      VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(CodeClassifyTemplateDO.class);
//      queryWrapper.addQueryMap("codeClassifyOid",codeClassifyDTO.getOid());
//      List<CodeClassifyTemplateDO> codeClassifyTemplateDOListHaveTemplate =  codeClassifyTemplateMapper.selectByWrapper(queryWrapper);
      if(codeClstemplateEntities.size()>0){
         return R.fail("分类关联模板,请先删除!");
      }
        //处理数据集成逻辑,成功后执行集成第一步
        for (CodeClassifyDO codeClassifyDO1:deletes){
            //codeDuckingServiceI.insertCache1(CACHE_TYPE_CLASSIFY_DELETE,FRAMEWORK_DATA_DISABLED,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, codeClassifyDO1.getOid(), DateUtils.addHours(new Date(),1));//这里是当前时间
      //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。
      //1、查询要删除的父类数据
      List<CodeClassify> deletes = new ArrayList<CodeClassify>();
      deletes.add(codeClassify);
            //存储要删除的数据
            codeDuckingServiceI.cacheDeleteData(codeClassifyDO1.getOid(), codeClassifyDO1);
        }
        return (batchCBO!=null && batchCBO.getDeleteCbos() !=null &&batchCBO.getDeleteCbos().size() > 0)?BaseResult.successMsg(DELETE_SUCCESS):BaseResult.fail(DELETE_FAIL);
    }
      if(result.isSuccess()) {
         //找下级的,这个是可以删除的时候
         Map<String,String> childrenOids = codeClassifyMapper.selectAllLevelChildOid(codeClassify.getOid().trim());
         if (!CollectionUtils.isEmpty(childrenOids)) {
            Collection<Collection<String>> childrenCollections = VciBaseUtil.switchCollectionForOracleIn(childrenOids.keySet());
            for(Collection<String> s : childrenCollections){
    /**
    * 主键获取主题库分类
    * @param oid 主键
    * @return 主题库分类显示对象
    * @throws VciBaseException 参数为空,数据不存在时会抛出异常
    */
    @Override
    public  CodeClassifyVO getObjectByOid(String oid) throws VciBaseException{
        return codeClassifyDO2VO(selectByOid(oid));
    }
               //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。
               //2、查询要删除的子类数据
               List<CodeClassify>  codeClassifyDOList = codeClassifyMapper.selectBatchIds(s);
               deletes.addAll(codeClassifyDOList);
//               codeClassifyMapper.deleteBatchIds(s);
               baseMapper.deleteBatchIds(s);
            }
    /**
    * 主键查询数据对象
    * @param oid 主键
    * @return  数据对象
    * @throws VciBaseException 参数为空,并且数据不存在的时候会抛出异常
    */
    private CodeClassifyDO selectByOid(String oid) throws VciBaseException{
        VciBaseUtil.alertNotNull(oid,"主键");
        CodeClassifyDO codeClassifyDO = codeClassifyMapper.selectByPrimaryKey(oid.trim());
        if(codeClassifyDO == null || StringUtils.isBlank(codeClassifyDO.getOid())){
            throw new VciBaseException(DATA_OID_NOT_EXIST);
        }
        return codeClassifyDO;
    }
         }
      }else{
         return result;
      }
    /**
     * 主键批量获取主题库分类
     * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个
     * @return 主题库分类显示对象
     * @throws VciBaseException 查询出现异常时会抛出
     */
    @Override
    public Collection<CodeClassifyVO> listCodeClassifyByOids(Collection<String> oidCollections) throws VciBaseException{
        VciBaseUtil.alertNotNull(oidCollections,"数据对象主键集合");
        List<CodeClassifyDO> codeClassifyDOList = listCodeClassifyDOByOidCollections(oidCollections);
        return codeClassifyDO2VOs(codeClassifyDOList);
    }
      //执行删除操作
      int deleteCount = codeClassifyMapper.deleteById(codeClassify.getOid());
    /**
    * 使用主键集合查询数据对象
    * @param oidCollections 主键的集合
    * @return 数据对象列表
    */
    private List<CodeClassifyDO> listCodeClassifyDOByOidCollections(Collection<String> oidCollections){
        List<CodeClassifyDO> codeClassifyDOList = new ArrayList<CodeClassifyDO>();
        if(!CollectionUtils.isEmpty(oidCollections)){
            Collection<Collection<String>> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections);
            for(Collection<String> oids: oidCollectionsList){
                List<CodeClassifyDO> tempDOList =  codeClassifyMapper.selectByPrimaryKeyCollection(oids);
                if(!CollectionUtils.isEmpty(tempDOList)){
                        codeClassifyDOList.addAll(tempDOList);
                }
            }
        }
        return  codeClassifyDOList;
    }
      //处理数据集成逻辑,成功后执行集成第一步
      for (CodeClassify codeClassifyTemp:deletes){
         //codeDuckingServiceI.insertCache1(CACHE_TYPE_CLASSIFY_DELETE,FRAMEWORK_DATA_DISABLED,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, codeClassifyDO1.getOid(), DateUtils.addHours(new Date(),1));//这里是当前时间
         //存储要删除的数据
//         CacheUtil.put();
         CacheUtil.put("ubcs:code", "bean:id:", codeClassifyTemp.getOid(), codeClassifyTemp);
//         codeDuckingServiceI.cacheDeleteData(codeClassifyTemp.getOid(), codeClassifyTemp);
      }
      return R.data(deleteCount>0);
//      return null;
   }
   /**
    * 启用、停用
    * @param oid 主键
    * @param lcStatus 状态
    * @return 执行结果
    */
   @Override
   public R updateLcStatus(String oid, String lcStatus){
    /**
     * 参照树 主题库分类
     * @param treeQueryObject 树形查询对象
     * @return 主题库分类显示树
     * @throws VciBaseException 查询条件和分页出错的时候会抛出异常
     */
    @Override
    public List<Tree> referTree(TreeQueryObject treeQueryObject)  throws VciBaseException{
        if(treeQueryObject == null){
            treeQueryObject = new TreeQueryObject();
        }
        if(treeQueryObject.getConditionMap() == null){
            treeQueryObject.setConditionMap(new HashMap<>());
        }
        if(treeQueryObject.getConditionMap().containsKey(LC_STATUS)) {
            treeQueryObject.getConditionMap().remove(LC_STATUS);
        }
        if(treeQueryObject.getExtandParamsMap() ==null || !treeQueryObject.getExtandParamsMap().containsKey(REFER_SHOW_DISABLED_QUERY_KEY)) {
        }
        treeQueryObject.getConditionMap().put(LC_STATUS, FRAMEWORK_DATA_ENABLED);
        return treeCodeClassify(treeQueryObject);
    }
    /**
     * 启用、停用
     * @param oid 主键
     * @param lcStatus 状态
     * @return 执行结果
     */
    @Override
    public BaseResult updateLcStatus(String oid, String lcStatus){
        //查询修改前ts
        CodeClassifyDO codeClassifyDO_old = selectByOid(oid);//主要是为了查询ts
        //启用、停用
        int u = codeClassifyMapper.updateLcStatus(oid,lcStatus);
      //查询修改前ts
      CodeClassify codeClassify = codeClassifyMapper.selectById(oid);//主要是为了查询ts
      codeClassify.setLcStatus(lcStatus);
      codeClassify.setTs(new Date());
      codeClassify.setLastModifyTime(new Date());
      codeClassify.setLastModifier(AuthUtil.getUser().getUserName());
      //启用、停用
//      int u = codeClassifyMapper.updateLcStatus(oid,lcStatus);
      int count = codeClassifyMapper.updateById(codeClassify);
//        //处理数据集成逻辑,成功后执行集成第一步,分类数据特殊处理。
//        if(u!=0) {
//            codeDuckingServiceI.insertCache1(lcStatus,lcStatus,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, oid, codeClassifyDO_old.getTs());
//        }
        BaseResult baseResult = u==0?BaseResult.error("修改失败!"):BaseResult.success("修改成功");
        return baseResult;
    }
      return R.data(SqlHelper.retBool(count));
   }
    /**
     * 使用查询封装器来查询
     * @param queryWrapper 查询封装器
     * @return 数据对象
     */
    @Override
    public List<CodeClassifyDO> selectByWrapper(VciQueryWrapperForDO queryWrapper) {
        return codeClassifyMapper.selectByWrapper(queryWrapper);
    }
   /**
    * 主键批量获取主题库分类
    * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个
    * @return 主题库分类显示对象
    */
   @Override
   public Collection<CodeClassifyVO> listCodeClassifyByOids(Collection<String> oidCollections) {
      VciBaseUtil.alertNotNull(oidCollections,"数据对象主键集合");
      List<CodeClassify> codeClassifyDOList = listCodeClassifyDOByOidCollections(oidCollections);
      return codeClassifyDO2VOs(codeClassifyDOList);
   }
    /**
     * 使用分类主键获取分类相关的所有信息
     *
     * @param codeClassifyOid 分类的主键
     * @return 分类上级,下级的信息
     */
    @Override
    public CodeClassifyFullInfoBO getClassifyFullInfo(String codeClassifyOid) {
        VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键");
        CodeClassifyFullInfoBO fullInfo = new CodeClassifyFullInfoBO();
        CodeClassifyDO classifyDO = selectByOid(codeClassifyOid);
        //查询上级
        fullInfo.setCurrentClassifyVO(codeClassifyDO2VO(classifyDO));
        fullInfo.setParentClassifyVOs(codeClassifyDO2VOs(codeClassifyMapper.selectAllLevelParentByOid(codeClassifyOid)));
        if(!CollectionUtils.isEmpty(fullInfo.getParentClassifyVOs())){
            fullInfo.setTopClassifyVO(fullInfo.getParentClassifyVOs().stream().filter(s->StringUtils.isBlank(s.getParentcodeclassifyoid())).findFirst().orElseGet(()->null));
        }
        return fullInfo;
    }
   /**
    * 使用主键集合查询数据对象
    * @param oidCollections 主键的集合
    * @return 数据对象列表
    */
   private List<CodeClassify> listCodeClassifyDOByOidCollections(Collection<String> oidCollections){
      List<CodeClassify> codeClassifyList = new ArrayList<CodeClassify>();
      if(!CollectionUtils.isEmpty(oidCollections)){
         Collection<Collection<String>> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections);
         for(Collection<String> oids: oidCollectionsList){
            List<CodeClassify> tempDOList =  codeClassifyMapper.selectBatchIds(oids);
            if(!CollectionUtils.isEmpty(tempDOList)){
               codeClassifyList.addAll(tempDOList);
            }
         }
      }
      return  codeClassifyList;
   }
    /**
     * 获取当前分类的顶层分类
     *
     * @param codeClassifyOid 分类的主键
     * @return 顶层分类的信息
     */
    @Override
    public CodeClassifyVO getTopClassifyVO(String codeClassifyOid) {
        VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键");
        List<CodeClassifyDO> classifyDOS = codeClassifyMapper.selectAllLevelParentByOid(codeClassifyOid);
        if(!CollectionUtils.isEmpty(classifyDOS)){
            CodeClassifyDO classifyDO = classifyDOS.stream().filter(s -> StringUtils.isBlank(s.getParentCodeClassifyOid())).findFirst().orElseGet(() -> null);
            if(classifyDO!=null){
                return codeClassifyDO2VO(classifyDO);
            }
        }
        return null;
    }
   /**
    * 批量数据对象转换为显示对象
    * @param codeClassifys 数据对象列表
    * @return 显示对象
    */
   @Override
   public List<CodeClassifyVO> codeClassifyDO2VOs(Collection<CodeClassify>  codeClassifys) {
      List<CodeClassifyVO> voList = new ArrayList<CodeClassifyVO>();
      if(!CollectionUtils.isEmpty(codeClassifys)){
         for(CodeClassify s: codeClassifys){
            CodeClassifyVO vo =  codeClassifyDO2VO(s);
            if(vo != null){
               voList.add(vo);
            }
         }
      }
      return voList;
   }
    /**
     * 统计子节点的个数
     *
     * @param codeClassifyOid 分类的主键
     * @return 个数
     */
    @Override
    public int countChildrenByClassifyOid(String codeClassifyOid) {
        Map<String,String> conditionMap = new HashMap<>();
        conditionMap.put("parentCodeClassifyOid",codeClassifyOid);
        return codeClassifyMapper.countByCondition(conditionMap).intValue();
    }
   /**
    * 数据对象转换为显示对象
    * @param  codeClassify 数据对象
    * @return 显示对象
    */
   @Override
   public  CodeClassifyVO codeClassifyDO2VO(CodeClassify codeClassify) {
      CodeClassifyVO vo = new CodeClassifyVO();
      if(codeClassify != null){
         BeanUtilForVCI.copyPropertiesIgnoreCase(codeClassify,vo);
         //如果有lcstatus的类的话
         vo.setLcStatusText(FrameworkDataLCStatus.getTextByValue(vo.getLcStatus()));
      }
      return vo;
   }
    /**
     * 获取子级的主题库分类
     *
     * @param codeClassifyOid 分类的主键
     * @param allLevel        是否所有的层级
     * @param fieldInPath 在路径中的字段
     * @param enable 是否只显示启用
     * @return 分类的显示对象
     */
    @Override
    public List<CodeClassifyVO> listChildrenClassify(String codeClassifyOid, boolean allLevel, String fieldInPath, boolean enable) {
        if(allLevel){
            List<CodeClassifyDO> classifyDOS = codeClassifyMapper.selectAllLevelChildHasPath(codeClassifyOid,fieldInPath,enable);
            if(!CollectionUtils.isEmpty(classifyDOS)){
                classifyDOS = classifyDOS.stream().filter(s->FRAMEWORK_DATA_ENABLED.equalsIgnoreCase(s.getLcStatus())).collect(Collectors.toList());
            }
            return codeClassifyDO2VOs(classifyDOS);
        }else{
            //只查询一条,那path就没必要查询了
            Map<String,String> conditionMap = new HashMap<>();
            conditionMap.put("parentcodeclassifyoid",codeClassifyOid);
            if (enable){
                conditionMap.put(VciQueryWrapperForDO.LC_STATUS_FIELD,FRAMEWORK_DATA_ENABLED);
            }
            return codeClassifyDO2VOs(codeClassifyMapper.selectByCondition(conditionMap,new PageHelper(-1)));
        }
    }
   /**
    * 参照树 主题库分类
    * @param treeQueryObject 树形查询对象
    * @return 主题库分类显示树
    */
   @Override
   public List<Tree> referTree(TreeQueryObject treeQueryObject) {
      if(treeQueryObject == null){
         treeQueryObject = new TreeQueryObject();
      }
      if(treeQueryObject.getConditionMap() == null){
         treeQueryObject.setConditionMap(new HashMap<>());
      }
      if(treeQueryObject.getConditionMap().containsKey(LC_STATUS)) {
         treeQueryObject.getConditionMap().remove(LC_STATUS);
      }
      if(treeQueryObject.getExtandParamsMap() ==null || !treeQueryObject.getExtandParamsMap().containsKey(REFER_SHOW_DISABLED_QUERY_KEY)) {
      }
      treeQueryObject.getConditionMap().put(LC_STATUS, FRAMEWORK_DATA_ENABLED);
      return treeCodeClassify(treeQueryObject);
   }
    /**
     * 反向从子级获取父级的主题库分类
     *
     * @param codeClassifyOid 分类的主键
     * @return 分类的显示对象
     */
    @Override
    public List<CodeClassifyVO> listParentClassify(String codeClassifyOid){
        List<CodeClassifyDO> classifyDOS = codeClassifyMapper.listParentClassify(codeClassifyOid);
        return codeClassifyDO2VOs(classifyDOS);
    }
   /**
    * 主键查询数据对象,关联查询
    * @param oid 主键
    * @return  数据对象
    */
   private CodeClassify selectByOidRel(String oid){
    /**
     * 导出分类
     *
     * @param oid 分类主键
     * @return excel文件路径
     */
    @Override
    public String exportClassify(String oid) {
        VciBaseUtil.alertNotNull(oid,"分类的主键");
        CodeClassifyVO classifyVO = getObjectByOid(oid);
        classifyVO.setDataLevel(0);
        classifyVO.setPath(classifyVO.getId());
        List<CodeClassifyVO> codeClassifyVOS = listChildrenClassify(oid, true, "id", false);
        if(codeClassifyVOS ==null){
            codeClassifyVOS = new ArrayList<>();
        }
        codeClassifyVOS.add(classifyVO);
      List<CodeClassify> codeClassifyList = codeClassifyMapper.selectClassifyByKeyAndReseRel("'"+oid.trim()+"'");
//      CodeClassify codeClassifyEntity = (CodeClassify) codeClassifyList;
      if(codeClassifyList.size() == 0 ){
         throw new ServiceException("dataNotExist");//根据主键id未查到相关数据
      }
//      if(codeClassifyEntity == null || StringUtils.isBlank(codeClassifyEntity.getOid())){
//         throw new ServiceException("dataOidNotExist");//根据主键id未查到相关数据
//      }
      return codeClassifyList.get(0);
   }
        //查询一下规则的编号,和关键属性重复规则
        List<String> codeRuleOids = codeClassifyVOS.stream().filter(s -> StringUtils.isNotBlank(s.getCoderuleoid())).map(CodeClassifyVO::getCoderuleoid).collect(Collectors.toList());
        Map<String, CodeRuleVO> ruleVOMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(codeRuleOids)){
            VciBaseUtil.switchCollectionForOracleIn(codeRuleOids).stream().forEach(ruleOids->{
                Collection<CodeRuleVO> ruleVOS = codeRuleService.listCodeRuleByOids(ruleOids);
                ruleVOMap.putAll( Optional.ofNullable(ruleVOS).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getOid(),t->t)));
            });
        }
        //找关键属性规则
        List<String> keyRuleOids = codeClassifyVOS.stream().filter(s -> StringUtils.isNotBlank(s.getCodekeyattrrepeatoid())).map(CodeClassifyVO::getCodekeyattrrepeatoid).collect(Collectors.toList());
        Map<String, CodeKeyAttrRepeatRuleVO> keyRuleVOMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(keyRuleOids)){
            VciBaseUtil.switchCollectionForOracleIn(keyRuleOids).stream().forEach(ruleOids->{
                Collection<CodeKeyAttrRepeatRuleVO> ruleVOS = keyAttrRepeatRuleService.listCodeKeyAttrRepeatRuleByOids(ruleOids);
                keyRuleVOMap.putAll( Optional.ofNullable(ruleVOS).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getOid(),t->t)));
            });
        }
        //ok,写excel
        String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + "导出分类.xls";
        try {
            new File(excelName).createNewFile();
        } catch (Throwable e) {
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e);
        }
        List<WriteExcelData> excelDataList = new ArrayList<>();
        excelDataList.add(new WriteExcelData(0,0,"分类编号"));
        excelDataList.add(new WriteExcelData(0,1,"分类名称"));
        excelDataList.add(new WriteExcelData(0,2,"业务类型编号"));
        excelDataList.add(new WriteExcelData(0,3,"业务类型名称"));
        excelDataList.add(new WriteExcelData(0,4,"编码规则编号"));
        excelDataList.add(new WriteExcelData(0,5,"编码规则名称"));
        excelDataList.add(new WriteExcelData(0,6,"查重规则编号"));
        excelDataList.add(new WriteExcelData(0,7,"查重规则名称"));
        excelDataList.add(new WriteExcelData(0,8,"分类路径"));
        excelDataList.add(new WriteExcelData(0,9,"状态"));
        excelDataList.add(new WriteExcelData(0,10,"分类层级"));
        excelDataList.add(new WriteExcelData(0,11,"描述"));
        for (int i = 0; i < codeClassifyVOS.size(); i++) {
            CodeClassifyVO vo = codeClassifyVOS.get(i);
            excelDataList.add(new WriteExcelData(i+1,0,vo.getId()));
            excelDataList.add(new WriteExcelData(i+1,1,vo.getName()));
            excelDataList.add(new WriteExcelData(i+1,2,vo.getBtmtypeid()));
            excelDataList.add(new WriteExcelData(i+1,3,vo.getBtmtypename()));
            excelDataList.add(new WriteExcelData(i+1,4,StringUtils.isNotBlank(vo.getCoderuleoid())?ruleVOMap.getOrDefault(vo.getCoderuleoid(),new CodeRuleVO()).getId():""));
            excelDataList.add(new WriteExcelData(i+1,5,StringUtils.isNotBlank(vo.getCoderuleoid())?ruleVOMap.getOrDefault(vo.getCoderuleoid(),new CodeRuleVO()).getName():""));
            excelDataList.add(new WriteExcelData(i+1,6,StringUtils.isNotBlank(vo.getCodekeyattrrepeatoid())?keyRuleVOMap.getOrDefault(vo.getCodekeyattrrepeatoid(),new CodeKeyAttrRepeatRuleVO()).getId():""));
            excelDataList.add(new WriteExcelData(i+1,7,StringUtils.isNotBlank(vo.getCodekeyattrrepeatoid())?keyRuleVOMap.getOrDefault(vo.getCodekeyattrrepeatoid(),new CodeKeyAttrRepeatRuleVO()).getName():""));
            excelDataList.add(new WriteExcelData(i+1,8,vo.getOid().equalsIgnoreCase(classifyVO.getOid())?vo.getPath():classifyVO.getPath() + vo.getPath()));
            excelDataList.add(new WriteExcelData(i+1,9,FrameworkDataLCStatus.getTextByValue(vo.getLcStatus())));
            excelDataList.add(new WriteExcelData(i+1,10,vo.getDataLevel()));
            excelDataList.add(new WriteExcelData(i+1,11,vo.getDescription()));
        }
        WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
        ExcelUtil.writeDataToFile(excelName, excelOption);
        return excelName;
    }
   /**
    * 查询主题库分类 树
    * @param treeQueryObject 树查询对象
    * @return 主题库分类 显示树
    */
   @Override
   public List<Tree> treeCodeClassify(TreeQueryObject treeQueryObject) {
      List<CodeClassify> doList = null;
      String id = null;
      String lcStatus = null;
      if(!Objects.isNull(treeQueryObject.getConditionMap())){
         id = treeQueryObject.getConditionMap().getOrDefault("id",null);
         lcStatus = treeQueryObject.getConditionMap().getOrDefault("lcStatus",null);
      }
      if(StringUtils.isNotBlank(id) || StringUtils.isNotBlank(lcStatus) ){
         doList = codeClassifyMapper
            .selectCodeClassifyDOByTree(treeQueryObject.getConditionMap().get("id"),treeQueryObject.getConditionMap().get("lcStatus"),treeQueryObject.getParentOid());
      }else{
         doList =codeClassifyMapper.selectCodeClassifyVOByTree(treeQueryObject.getParentOid());
      }
      List<CodeClassifyVO> voList = codeClassifyDO2VOs(doList);
      TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions(PARENT_FIELD_NAME.toLowerCase(Locale.ROOT));
      treeWrapperOptions.copyFromTreeQuery(treeQueryObject);
      List<Tree> tree= revisionModelUtil.doList2Trees(voList,treeWrapperOptions,(CodeClassifyVO s) ->{
         //可以在这里处理树节点的显示
         return s.getId() + " " + s.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equalsIgnoreCase(s
            .getLcStatus()) ? (" 【停用】 ") : "");
      });
      Iterator var6 =  tree.listIterator();
      while(var6.hasNext()){
         Tree trees = (Tree) var6.next();
         boolean checkHasChild=codeClassifyMapper.checkHasChild(trees.getOid());
         if(checkHasChild){
            trees.setLeaf(false);
         }else{
            trees.setLeaf(true);
         }
      }
      return tree;
   }
    /**
     * 创建导入模板
     *
     * @return excel文件路径
     */
    @Override
    public String createImportExcel() {
        //ok,写excel
        String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + "分类导入模板.xls";
        try {
            new File(excelName).createNewFile();
        } catch (Throwable e) {
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e);
        }
        List<WriteExcelData> excelDataList = new ArrayList<>();
        WriteExcelData excelData = new WriteExcelData(0, 0, "分类编号");
        excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
        excelDataList.add(excelData);
        WriteExcelData excelData1 = new WriteExcelData(0, 1, "分类名称");
        excelData1.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
        excelDataList.add(excelData1);
        excelDataList.add(new WriteExcelData(0,2,"业务类型编号"));
        excelDataList.add(new WriteExcelData(0,3,"编码规则编号"));
        excelDataList.add(new WriteExcelData(0,4,"查重规则编号"));
        WriteExcelData excelData2 = new WriteExcelData(0, 5, "分类路径");
        excelData2.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
        excelDataList.add(excelData2);
        excelDataList.add(new WriteExcelData(0,6,"状态"));
        WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
        ExcelUtil.writeDataToFile(excelName, excelOption);
        return excelName;
    }
   /**
    * 根据树形查询对象来查询数据对象
    *
    * @param treeQueryObject 树形查询对象
    * @return 查询结果,数据对象
    */
   @Override
   public List<CodeClassifyVO> selectCodeClassifyDOByTree(TreeQueryObject treeQueryObject) {
      List<CodeClassify> doList =codeClassifyMapper.selectCodeClassifyVOByTree(treeQueryObject.getParentOid());
      List<CodeClassifyVO> voList = codeClassifyDO2VOs(doList);
      return voList;
   }
   /**
    * 使用编号的路径获取对象
    *
    * @param fieldPath 编号的路径,一定要从最顶层节点开始,格式为xxx/yyy/zz 这样
    * @return 分类的显示对象
    */
   @Override
   public CodeClassifyVO getObjectByClsfNamePath(String fieldPath){
      CodeClassifyVO codeClassifyVO=new CodeClassifyVO();
      List<CodeClassify> classifyList = codeClassifyMapper.selectByFieldNamePath(fieldPath,"name");
      if(classifyList.size()>0){
         codeClassifyVO=codeClassifyDO2VO(classifyList.get(0));
      }
      return codeClassifyVO;
   }
   /***
    * 根据上级节点获取下级节点代号路径和名称路径
    * @param classifyId
    * @param enable
    * @return
    */
   @Override
   public List<CodeClassifyVO> getIdPathToNamePathByParentId(String classifyId, boolean enable) {
      return null;
   }
    /**
     * 导入分类
     *
     * @param file1 文件的信息
     * @return 错误文件的地址
     */
    @Override
    public void importClassify(File file1) {
        VciBaseUtil.alertNotNull(file1,"excel文件");
        if(!file1.exists()){
            throw new VciBaseException("导入的excel文件不存在,{0}",new String[]{file1.getPath()});
        }
        ReadExcelOption excelOption = new ReadExcelOption();
        List<CodeClassifyPO> poList = null;
        try{
            poList = ExcelUtil.readDataObjectFromExcel(file1,CodeClassifyPO.class,excelOption,(value,po,fieldName)->{
                po.setLcStatus(FrameworkDataLCStatus.getValueByText(po.getLcStatusText()));
                if(StringUtils.isBlank(po.getLcStatusText())){
                    po.setLcStatus(FrameworkDataLCStatus.ENABLED.getValue());
                }
            });
        }catch (Exception e){
            if(logger.isErrorEnabled()){
                logger.error("读取excel内容的时候出现了错误",e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{},e);
        }
        //去除整行都是空的情况
   //   /**
//    * 根据树形查询对象来查询数据对象
//    *
//    * @param treeQueryObject 树形查询对象
//    * @return 查询结果,数据对象
//    */
//   @Override
//   public List<CodeClassifyVO> selectCodeClassifyDOByTree(TreeQueryObject treeQueryObject) {
//      VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(null,CodeClassifyDO.class);
//      VciParentQueryOption parentQueryOption = new VciParentQueryOption();
//      parentQueryOption.setParentFieldName(PARENT_FIELD_NAME);
//      queryWrapperForDO.parentQueryChild(treeQueryObject,parentQueryOption);
//      if(StringUtils.isBlank(treeQueryObject.getSort())) {
//         PageHelper pageHelper = new PageHelper(-1);
//         pageHelper.addDefaultAsc("id");
//         queryWrapperForDO.setPageHelper(pageHelper);
//      }
//      return codeClassifyMapper.selectByWrapper(queryWrapperForDO);
//   }
        if(CollectionUtils.isEmpty(poList)){
            throw new VciBaseException(ExcelLangCodeConstant.IMPORT_CONTENT_NULL,new String[]{});
        }
   /**
    * 导出分类
    *
    * @param oid 分类主键
    * @return excel文件路径
    */
   @Override
   public String exportClassify(String oid) {
      VciBaseUtil.alertNotNull(oid,"分类的主键");
      CodeClassify codeClassify = codeClassifyMapper.selectById(oid);
      codeClassify.setDataLevel(0);
      codeClassify.setPath(codeClassify.getId());
      List<CodeClassifyVO> codeClassifyVOS = listChildrenClassify(oid, true, "id", false);
      if(codeClassifyVOS ==null){
         codeClassifyVOS = new ArrayList<>();
      }
      CodeClassifyVO codeClassifyVO = new CodeClassifyVO();
      BeanUtils.copyProperties(codeClassify,codeClassifyVO);
      codeClassifyVOS.add(codeClassifyVO);
        poList = poList.stream().filter(s->!(StringUtils.isBlank(s.getId()) && StringUtils.isBlank(s.getName()) && StringUtils.isBlank(s.getPath()))).collect(Collectors.toList());
      //查询一下规则的编号,和关键属性重复规则
      List<String> codeRuleOids = codeClassifyVOS.stream().filter(s -> StringUtils.isNotBlank(s.getCoderuleoid())).map(CodeClassifyVO::getCoderuleoid).collect(Collectors.toList());
      Map<String, CodeRuleVO> ruleVOMap = new HashMap<>();
      if(!CollectionUtils.isEmpty(codeRuleOids)){
         VciBaseUtil.switchCollectionForOracleIn(codeRuleOids).stream().forEach(ruleOids->{
//            Collection<CodeRuleVO> ruleVOS = codeRuleService.listCodeRuleByOids(ruleOids);
            Collection<CodeRuleVO> ruleVOS = null;
            ruleVOMap.putAll( Optional.ofNullable(ruleVOS).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getOid(),t->t)));
         });
      }
      //找关键属性规则
      List<String> keyRuleOids = codeClassifyVOS.stream().filter(s -> StringUtils.isNotBlank(s.getCodekeyattrrepeatoid())).map(CodeClassifyVO::getCodekeyattrrepeatoid).collect(Collectors.toList());
      Map<String, CodeKeyAttrRepeatRuleVO> keyRuleVOMap = new HashMap<>();
      if(!CollectionUtils.isEmpty(keyRuleOids)){
         VciBaseUtil.switchCollectionForOracleIn(keyRuleOids).stream().forEach(ruleOids->{
            Collection<CodeKeyAttrRepeatRuleVO> ruleVOS = iCodeKeyattrrepeatService.listCodeKeyAttrRepeatRuleByOids(ruleOids);
            keyRuleVOMap.putAll( Optional.ofNullable(ruleVOS).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.toMap(s->s.getOid(),t->t)));
         });
      }
      //ok,写excel
      String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + "导出分类.xls";
      try {
         new File(excelName).createNewFile();
      } catch (Throwable e) {
         throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e);
      }
      List<WriteExcelData> excelDataList = new ArrayList<>();
      excelDataList.add(new WriteExcelData(0,0,"分类编号"));
      excelDataList.add(new WriteExcelData(0,1,"分类名称"));
      excelDataList.add(new WriteExcelData(0,2,"业务类型编号"));
      excelDataList.add(new WriteExcelData(0,3,"业务类型名称"));
      excelDataList.add(new WriteExcelData(0,4,"编码规则编号"));
      excelDataList.add(new WriteExcelData(0,5,"编码规则名称"));
      excelDataList.add(new WriteExcelData(0,6,"查重规则编号"));
      excelDataList.add(new WriteExcelData(0,7,"查重规则名称"));
      excelDataList.add(new WriteExcelData(0,8,"分类路径"));
      excelDataList.add(new WriteExcelData(0,9,"状态"));
      excelDataList.add(new WriteExcelData(0,10,"分类层级"));
      excelDataList.add(new WriteExcelData(0,11,"描述"));
      for (int i = 0; i < codeClassifyVOS.size(); i++) {
         CodeClassifyVO vo = codeClassifyVOS.get(i);
         excelDataList.add(new WriteExcelData(i+1,0,vo.getId()));
         excelDataList.add(new WriteExcelData(i+1,1,vo.getName()));
         excelDataList.add(new WriteExcelData(i+1,2,vo.getBtmtypeid()));
         excelDataList.add(new WriteExcelData(i+1,3,vo.getBtmtypename()));
         excelDataList.add(new WriteExcelData(i+1,4, StringUtils.isNotBlank(vo.getCoderuleoid())?ruleVOMap.getOrDefault(vo.getCoderuleoid(),new CodeRuleVO()).getId():""));
         excelDataList.add(new WriteExcelData(i+1,5, StringUtils.isNotBlank(vo.getCoderuleoid())?ruleVOMap.getOrDefault(vo.getCoderuleoid(),new CodeRuleVO()).getName():""));
         excelDataList.add(new WriteExcelData(i+1,6, StringUtils.isNotBlank(vo.getCodekeyattrrepeatoid())?keyRuleVOMap.getOrDefault(vo.getCodekeyattrrepeatoid(),new CodeKeyAttrRepeatRuleVO()).getId():""));
         excelDataList.add(new WriteExcelData(i+1,7, StringUtils.isNotBlank(vo.getCodekeyattrrepeatoid())?keyRuleVOMap.getOrDefault(vo.getCodekeyattrrepeatoid(),new CodeKeyAttrRepeatRuleVO()).getName():""));
         excelDataList.add(new WriteExcelData(i+1,8,vo.getOid().equalsIgnoreCase(codeClassify.getOid())?vo.getPath():codeClassify.getPath() + vo.getPath()));
         excelDataList.add(new WriteExcelData(i+1,9,FrameworkDataLCStatus.getTextByValue(vo.getLcStatus())));
         excelDataList.add(new WriteExcelData(i+1,10,vo.getDataLevel()));
         excelDataList.add(new WriteExcelData(i+1,11,vo.getDescription()));
      }
      WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
      ExcelUtil.writeDataToFile(excelName, excelOption);
      return excelName;
   }
        List<CodeClassifyDO> classifyDOList = new ArrayList<>();
        //看看路径是否有重复
        Map<String/**路径**/, Long/**个数**/> pathCountMap = poList.stream().filter(s->StringUtils.isNotBlank(s.getPath())).collect(Collectors.groupingBy(s -> s.getPath(), Collectors.counting()));
        List<String> repeatPaths = Optional.ofNullable(pathCountMap).orElse(new HashMap<>()).entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(repeatPaths)){
            //有重复的内容
            List<String> rowIndexList = new ArrayList<>();
            poList.stream().forEach(po->{
                if(repeatPaths.contains(po.getPath())){
                    rowIndexList.add(po.getRowIndex());
                }
            });
            throw new VciBaseException("路径有重复,{0}",new String[]{rowIndexList.stream().collect(Collectors.joining(","))});
        }
   /**
    * 获取子级的主题库分类
    *
    * @param codeClassifyOid 分类的主键
    * @param allLevel        是否所有的层级
    * @param fieldInPath 在路径中的字段
    * @param enable 是否只显示启用
    * @return 分类的显示对象
    */
   @Override
   public List<CodeClassifyVO> listChildrenClassify(String codeClassifyOid, boolean allLevel, String fieldInPath, boolean enable) {
      if(allLevel){
         List<CodeClassify> classifyDOS = codeClassifyMapper.selectAllLevelChildHasPath(codeClassifyOid);
         if(!CollectionUtils.isEmpty(classifyDOS)){
            classifyDOS = classifyDOS.stream().filter(s->FRAMEWORK_DATA_ENABLED.equalsIgnoreCase(s.getLcStatus())).collect(Collectors.toList());
         }
         return codeClassifyDO2VOs(classifyDOS);
      }else{
         //只查询一条,那path就没必要查询了
         Map<String,Object> conditionMap = new HashMap<>();
         conditionMap.put("parentcodeclassifyoid",codeClassifyOid);
         if (enable){
            conditionMap.put("lcstatus",FRAMEWORK_DATA_ENABLED);
         }
         return codeClassifyDO2VOs(codeClassifyMapper.selectByMap(conditionMap));
      }
   }
        Map<String, CodeRuleVO> ruleVOMap = Optional.ofNullable(codeRuleService.listCodeRuleByIds(
                poList.stream().filter(s->StringUtils.isNotBlank(s.getCodeRuleId())).map(CodeClassifyPO::getCodeRuleId).collect(Collectors.toList()))
        ).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
   /**
    * 创建导入模板
    *
    * @return excel文件路径
    */
   @Override
   public String createImportExcel() {
      //ok,写excel
      String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + "分类导入模板.xls";
      try {
         new File(excelName).createNewFile();
      } catch (Throwable e) {
         throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e);
      }
      List<WriteExcelData> excelDataList = new ArrayList<>();
      WriteExcelData excelData = new WriteExcelData(0, 0, "分类编号");
      excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
      excelDataList.add(excelData);
      WriteExcelData excelData1 = new WriteExcelData(0, 1, "分类名称");
      excelData1.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
      excelDataList.add(excelData1);
      excelDataList.add(new WriteExcelData(0,2,"业务类型编号"));
      excelDataList.add(new WriteExcelData(0,3,"编码规则编号"));
      excelDataList.add(new WriteExcelData(0,4,"查重规则编号"));
      WriteExcelData excelData2 = new WriteExcelData(0, 5, "分类路径");
      excelData2.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
      excelDataList.add(excelData2);
      excelDataList.add(new WriteExcelData(0,6,"状态"));
      WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
      ExcelUtil.writeDataToFile(excelName, excelOption);
      return excelName;
   }
        Map<String,CodeKeyAttrRepeatRuleVO> keyRuleVOMap =Optional.ofNullable(keyAttrRepeatRuleService.listCodeKeyAttrRepeatRuleByIds(
                poList.stream().filter(s->StringUtils.isNotBlank(s.getKeyRepeatRuleId())).map(CodeClassifyPO::getKeyRepeatRuleId).collect(Collectors.toList()))
        ).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
   /**
    * 导入分类
    *
    * @param file1 文件的信息
    * @return 错误文件的地址
    */
   @Override
   public void importClassify(File file1) {
      VciBaseUtil.alertNotNull(file1,"excel文件");
      if(!file1.exists()){
         throw new VciBaseException("导入的excel文件不存在,{0}",new String[]{file1.getPath()});
      }
      ReadExcelOption excelOption = new ReadExcelOption();
      List<CodeClassifyPO> poList = null;
      try{
         poList = ExcelUtil.readDataObjectFromExcel(file1,CodeClassifyPO.class,excelOption,(value,po,fieldName)->{
            po.setLcStatus(FrameworkDataLCStatus.getValueByText(po.getLcStatusText()));
            if(StringUtils.isBlank(po.getLcStatusText())){
               po.setLcStatus(FrameworkDataLCStatus.ENABLED.getValue());
            }
         });
      }catch (Exception e){
         if(logger.isErrorEnabled()){
            logger.error("读取excel内容的时候出现了错误",e);
         }
         throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{},e);
      }
      //去除整行都是空的情况
        Map<String, OsBtmTypeVO> btmVOMap = Optional.ofNullable(btmService.listBtmByIds(
                poList.stream().filter(s -> StringUtils.isNotBlank(s.getBtmTypeId())).map(CodeClassifyPO::getBtmTypeId).collect(Collectors.toList()))
        ).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
      if(CollectionUtils.isEmpty(poList)){
         throw new VciBaseException(ExcelLangCodeConstant.IMPORT_CONTENT_NULL,new String[]{});
      }
        Map<String/**路径**/,String/**主键**/> oidPathMap = new HashMap<>();
      poList = poList.stream().filter(s->!(StringUtils.isBlank(s.getId()) && StringUtils.isBlank(s.getName()) && StringUtils.isBlank(s.getPath()))).collect(Collectors.toList());
        //我们需要查询所有已经存在的分类,主要是路径,用来判断分类的数据
        List<CodeClassifyDO> existClassifyDOs = codeClassifyMapper.selectAllLevelChildHasPath("", "id", false);
        Map<String/**路径**/, CodeClassifyDO/**已经存在的数据**/> pathDOMap = Optional.ofNullable(existClassifyDOs).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> {
            String path = s.getPath();
            if(StringUtils.isNotBlank(path) && path.startsWith("#")){
                return path.substring(1);
            }
            return path;
        }, t -> t));
        poList.stream().forEach(po->{
            CodeClassifyDO classifyDO = new CodeClassifyDO();
            VciBaseUtil.alertNotNull(po.getId(),"分类编号",po.getName(),"分类名称",po.getPath(),"分类路径");
            if(StringUtils.isNotBlank(po.getBtmTypeId()) && !btmVOMap.containsKey(po.getBtmTypeId().toLowerCase(Locale.ROOT))){
                throw new VciBaseException("第{0}行的业务类型{1}在系统中不存在",new String[]{String.valueOf(VciBaseUtil.getInt(po.getRowIndex())+1),po.getBtmTypeId()});
            }
            if(StringUtils.isNotBlank(po.getCodeRuleId()) && !ruleVOMap.containsKey(po.getCodeRuleId().toLowerCase(Locale.ROOT))){
                throw new VciBaseException("第{0}行的编码规则{1}在系统中不存在",new String[]{String.valueOf(po.getRowIndex()+1),po.getCodeRuleId()});
            }
            if(StringUtils.isNotBlank(po.getKeyRepeatRuleId()) && !keyRuleVOMap.containsKey(po.getKeyRepeatRuleId().toLowerCase(Locale.ROOT))){
                throw new VciBaseException("第{0}行的关键属性查重规则{1}在系统中不存在",new String[]{String.valueOf(po.getRowIndex()+1),po.getKeyRepeatRuleId()});
            }
            classifyDO.setOid(VciBaseUtil.getPk());
            classifyDO.setId(po.getId());
            classifyDO.setName(po.getName());
            classifyDO.setDescription(po.getDescription());
            oidPathMap.put(po.getPath(),classifyDO.getOid());
            if(StringUtils.isNotBlank(po.getBtmTypeId())){
                OsBtmTypeVO typeVO = btmVOMap.get(po.getBtmTypeId().toLowerCase(Locale.ROOT));
                classifyDO.setBtmTypeId(typeVO.getId());
                classifyDO.setBtmTypeName(typeVO.getName());
            }
            if(StringUtils.isNotBlank(po.getCodeRuleId())){
                CodeRuleVO codeRuleVO = ruleVOMap.get(po.getCodeRuleId().toLowerCase(Locale.ROOT));
                classifyDO.setCodeRuleOid(codeRuleVO.getOid());
            }
            if(StringUtils.isNotBlank(po.getKeyRepeatRuleId())){
                CodeKeyAttrRepeatRuleVO repeatRuleVO = keyRuleVOMap.get(po.getKeyRepeatRuleId());
                classifyDO.setCodeKeyAttrRepeatOid(repeatRuleVO.getOid());
            }
            classifyDO.setLcStatus(po.getLcStatus());
            classifyDO.setPath(po.getPath());
            classifyDOList.add(classifyDO);
        });
        //要看存在的,修改路径对应的主键
        Map<String/**路径**/,String/**主键**/> catchedOidPathMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(oidPathMap)){
            oidPathMap.forEach((path,oid)->{
                if(pathDOMap.containsKey(path)){
                    //说明存在
                    catchedOidPathMap.put(path,pathDOMap.get(path).getOid());
                }else{
                    catchedOidPathMap.put(path,oid);
                }
            });
        }
        List<CodeClassifyDO> addClassifyDOList = new ArrayList<>();
        List<CodeClassifyDO> editClassifyDOList = new ArrayList<>();
        classifyDOList.stream().forEach(classifyDO->{
      List<CodeClassify> codeClassify = new ArrayList<>();
      //看看路径是否有重复
      Map<String/**路径**/, Long/**个数**/> pathCountMap = poList.stream().filter(s->StringUtils.isNotBlank(s.getPath())).collect(Collectors.groupingBy(s -> s.getPath(), Collectors.counting()));
      List<String> repeatPaths = Optional.ofNullable(pathCountMap).orElse(new HashMap<>()).entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()).collect(Collectors.toList());
      if(!CollectionUtils.isEmpty(repeatPaths)){
         //有重复的内容
         List<String> rowIndexList = new ArrayList<>();
         poList.stream().forEach(po->{
            if(repeatPaths.contains(po.getPath())){
               rowIndexList.add(po.getRowIndex());
            }
         });
         throw new VciBaseException("路径有重复,{0}",new String[]{rowIndexList.stream().collect(Collectors.joining(","))});
      }
      //编号获取业务类型服务
      List<String> ruleOids = poList.stream().filter(
            s -> StringUtils.isNotBlank(s.getCodeRuleId()))
         .map(CodeClassifyPO::getCodeRuleId)
         .collect(Collectors.toList());
      Map<String, CodeRuleVO> ruleVOMap = Optional.ofNullable(ruleOids.size()==0 ? null:codeRuleService.listCodeRuleByOids(ruleOids)
      ).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
            //要看上级是不是存在哦
            String parentPath = classifyDO.getPath();
            if(parentPath.contains("#")) {
                parentPath = parentPath.substring(0, parentPath.lastIndexOf("#"));
            }
            if((!catchedOidPathMap.containsKey(parentPath) && !pathDOMap.containsKey(parentPath) )&& !classifyDO.getPath().equalsIgnoreCase(classifyDO.getId())){
                throw new VciBaseException("分类编号[{0}],分类名称[{1}],路径为[{2}]的上级分类在系统中,在本次导入的数据和系统中均没有找到",new String[]{classifyDO.getId(),classifyDO.getName(),classifyDO.getPath()});
            }
            if (!classifyDO.getPath().equalsIgnoreCase(classifyDO.getId())){
                //不是顶级的时候,要设置上级的主键
      List<String> keyOids = poList.stream().filter(s -> StringUtils.isNotBlank(s.getKeyRepeatRuleId()))
         .map(CodeClassifyPO::getKeyRepeatRuleId).collect(Collectors.toList());
      Map<String,CodeKeyAttrRepeatRuleVO> keyRuleVOMap =Optional.ofNullable(keyOids.size()==0 ? null: iCodeKeyattrrepeatService.listCodeKeyAttrRepeatRuleByOids(keyOids)
      ).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
                classifyDO.setParentCodeClassifyOid(catchedOidPathMap.containsKey(parentPath)?catchedOidPathMap.get(parentPath):pathDOMap.get(parentPath).getOid());
            }
            if(classifyDO.getPath().equalsIgnoreCase(classifyDO.getId()) && StringUtils.isBlank(classifyDO.getBtmTypeId())){
                throw new VciBaseException("分类编号[{0}],分类名称[{1}],是顶层分类,需要设置业务类型编号",new String[]{classifyDO.getId(),classifyDO.getName()});
            }
            if(pathDOMap.containsKey(classifyDO.getPath())){
                //存在,需要修改对象
                classifyDO.setOid(catchedOidPathMap.get(classifyDO.getPath()));
                CodeClassifyDO classifyDOInDB = pathDOMap.get(classifyDO.getPath());
                classifyDOInDB.setId(classifyDO.getId());
                classifyDOInDB.setName(classifyDO.getName());
                classifyDOInDB.setDescription(classifyDO.getDescription());
                classifyDOInDB.setBtmTypeId(classifyDO.getBtmTypeId());
                classifyDOInDB.setBtmTypeName(classifyDO.getBtmTypeName());
                classifyDOInDB.setCodeRuleOid(classifyDO.getCodeRuleOid());
                classifyDOInDB.setCodeRuleOidName(classifyDO.getCodeRuleOidName());
                classifyDOInDB.setParentCodeClassifyOid(classifyDO.getParentCodeClassifyOid());
                classifyDOInDB.setCodeKeyAttrRepeatOid(classifyDO.getCodeKeyAttrRepeatOid());
                classifyDOInDB.setCodeKeyAttrRepeatOidName(classifyDO.getCodeKeyAttrRepeatOidName());
                if(classifyDOInDB.getOrderNum() == null){
                    classifyDOInDB.setOrderNum(0);
                }
                editClassifyDOList.add(classifyDOInDB);
            }else{
                //是新的,直接添加就行了
                //判断号怎么处理?
                classifyDO.setOrderNum(0);
                addClassifyDOList.add(classifyDO);
            }
        });
        if(!CollectionUtils.isEmpty(editClassifyDOList)){
            VciBaseUtil.switchCollectionForOracleIn(editClassifyDOList).stream().forEach(classifyDOs->{
                codeClassifyMapper.batchUpdate(classifyDOs.stream().collect(Collectors.toList()));
            });
        }
        if(!CollectionUtils.isEmpty(addClassifyDOList)){
            revisionModelUtil.wrapperForBatchAdd(addClassifyDOList);
            VciBaseUtil.switchCollectionForOracleIn(addClassifyDOList).stream().forEach(classifyDOs->{
                codeClassifyMapper.batchInsert(classifyDOs.stream().collect(Collectors.toList()));
            });
        }
      List<String> btmOids = poList.stream().filter(s -> StringUtils.isNotBlank(s.getKeyRepeatRuleId()))
         .map(CodeClassifyPO::getBtmTypeId).collect(Collectors.toList());
      Map<String, BtmTypeVO> btmVOMap = Optional
         .ofNullable(btmOids.size()==0 ? null: btmTypeClient.selectByIdCollection(btmOids).getData())
         .orElse(new ArrayList<BtmTypeVO>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t,(o1,o2)->o2));
      //      Map<String, CodeOsbtmtypeVO> btmVOMap = null;
      Map<String/**路径**/,String/**主键**/> oidPathMap = new HashMap<>();
    }
      //我们需要查询所有已经存在的分类,主要是路径,用来判断分类的数据
      List<CodeClassify> existClassifyDOs = codeClassifyMapper.selectAllLevelChildHasPath("");
      Map<String/**路径**/, CodeClassify/**已经存在的数据**/> pathDOMap = Optional.ofNullable(existClassifyDOs).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(s -> {
         String path = s.getPath();
         if(StringUtils.isNotBlank(path) && path.startsWith("#")){
            return path.substring(1);
         }
         return path;
      }, t -> t));
      poList.stream().forEach(po->{
         CodeClassify classify = new CodeClassify();
         VciBaseUtil.alertNotNull(po.getId(),"分类编号",po.getName(),"分类名称",po.getPath(),"分类路径");
         if(StringUtils.isNotBlank(po.getBtmTypeId()) && !btmVOMap.containsKey(po.getBtmTypeId().toLowerCase(Locale.ROOT))){
            throw new VciBaseException("第{0}行的业务类型{1}在系统中不存在",new String[]{String.valueOf(VciBaseUtil.getInt(po.getRowIndex())+1),po.getBtmTypeId()});
         }
         if(StringUtils.isNotBlank(po.getCodeRuleId()) && !ruleVOMap.containsKey(po.getCodeRuleId().toLowerCase(Locale.ROOT))){
            throw new VciBaseException("第{0}行的编码规则{1}在系统中不存在",new String[]{String.valueOf(po.getRowIndex()+1),po.getCodeRuleId()});
         }
         if(StringUtils.isNotBlank(po.getKeyRepeatRuleId()) && !keyRuleVOMap.containsKey(po.getKeyRepeatRuleId().toLowerCase(Locale.ROOT))){
            throw new VciBaseException("第{0}行的关键属性查重规则{1}在系统中不存在",new String[]{String.valueOf(po.getRowIndex()+1),po.getKeyRepeatRuleId()});
         }
         classify.setOid(VciBaseUtil.getPk());
         classify.setId(po.getId());
         classify.setName(po.getName());
         classify.setDescription(po.getDescription());
         oidPathMap.put(po.getPath(),classify.getOid());
         if(StringUtils.isNotBlank(po.getBtmTypeId())){
            BtmTypeVO typeVO = (BtmTypeVO)btmVOMap.get(po.getBtmTypeId().toLowerCase(Locale.ROOT));
            classify.setBtmTypeId(typeVO.getId());
            classify.setBtmTypeName(typeVO.getName());
         }
         if(StringUtils.isNotBlank(po.getCodeRuleId())){
            CodeRuleVO codeRuleVO = ruleVOMap.get(po.getCodeRuleId().toLowerCase(Locale.ROOT));
            classify.setCodeRuleOid(codeRuleVO.getOid());
         }
         if(StringUtils.isNotBlank(po.getKeyRepeatRuleId())){
            CodeKeyAttrRepeatRuleVO repeatRuleVO = keyRuleVOMap.get(po.getKeyRepeatRuleId());
            classify.setCodeKeyAttrRepeatOid(repeatRuleVO.getOid());
         }
         classify.setLcStatus(po.getLcStatus());
         classify.setPath(po.getPath());
         codeClassify.add(classify);
      });
      //要看存在的,修改路径对应的主键
      Map<String/**路径**/,String/**主键**/> catchedOidPathMap = new HashMap<>();
      if(!CollectionUtils.isEmpty(oidPathMap)){
         oidPathMap.forEach((path,oid)->{
            if(pathDOMap.containsKey(path)){
               //说明存在
               catchedOidPathMap.put(path,pathDOMap.get(path).getOid());
            }else{
               catchedOidPathMap.put(path,oid);
            }
         });
      }
      List<CodeClassify> addClassifyDOList = new ArrayList<>();
      List<CodeClassify> editClassifyDOList = new ArrayList<>();
      codeClassify.stream().forEach(classifyDO->{
    /**
     * 获取分类关联的属性
     *
     * @param baseQueryObject 查询对象,必须有codeClassifyOid,支持id和name两种查询条件
     * @return 属性的信息,包含默认的属性
     */
    @Override
    public DataGrid<OsAttributeVO> listClassifyLinkAttr(BaseQueryObject baseQueryObject) {
        if(baseQueryObject == null){
            baseQueryObject = new BaseQueryObject();
        }
        if(baseQueryObject.getConditionMap() == null){
            baseQueryObject.setConditionMap(new HashMap<>());
        }
        String classifyOid = baseQueryObject.getConditionMap().getOrDefault("codeClassifyOid","");
        String id = baseQueryObject.getConditionMap().getOrDefault("id","");
        String name = baseQueryObject.getConditionMap().getOrDefault("name","");
        if(StringUtils.isBlank(classifyOid)){
            return new DataGrid<>();
        }
        CodeClassifyVO topClassifyVO = getTopClassifyVO(classifyOid);
        if(topClassifyVO == null || StringUtils.isBlank(topClassifyVO.getBtmtypeid())){
            return new DataGrid<>();
        }
        List<OsBtmTypeAttributeVO> unDefaultAttributes = btmService.listAttributeByBtmId(topClassifyVO.getBtmtypeid());
        List<OsAttributeVO> attributeVOS = new ArrayList<>();
        if(!CollectionUtils.isEmpty(unDefaultAttributes)){
            unDefaultAttributes.stream().forEach(attr->{
                OsAttributeVO attributeVO = new OsAttributeVO();
                BeanUtil.convert(attr,attributeVO);
                attributeVO.setAttributeDataType(attr.getAttrDataType());
                attributeVO.setAttrLength(attr.getAttributeLength());
                attributeVO.setBtmTypeId(attr.getReferBtmTypeId());
                attributeVO.setBtmTypeName(attr.getReferBtmTypeName());
                boolean add = true;
                if(StringUtils.isNotBlank(id) && !attributeVO.getId().contains(id.replace("*",""))){
                    add = false;
                }
                if(StringUtils.isNotBlank(name) && !attributeVO.getId().contains(name.replace("*",""))){
                    add = false;
                }
                if(add){
                    attributeVOS.add(attributeVO);
                }
            });
        }
        if(!CollectionUtils.isEmpty(attributeService.getDefaultAttributeVOs())){
            attributeService.getDefaultAttributeVOs().stream().forEach(attr->{
                boolean add = true;
                if(StringUtils.isNotBlank(id) && !attr.getId().contains(id.replace("*",""))){
                    add = false;
                }
                if(StringUtils.isNotBlank(name) && !attr.getId().contains(name.replace("*",""))){
                    add = false;
                }
                if(add){
                    attributeVOS.add(attr);
                }
            });
        }
        DataGrid<OsAttributeVO> dataGrid = new DataGrid<>();
        dataGrid.setData(attributeVOS);
        dataGrid.setTotal(attributeVOS.size());
        return dataGrid;
    }
         //要看上级是不是存在哦
         String parentPath = classifyDO.getPath();
         if(parentPath.contains("#")) {
            parentPath = parentPath.substring(0, parentPath.lastIndexOf("#"));
         }
         if((!catchedOidPathMap.containsKey(parentPath) && !pathDOMap.containsKey(parentPath) )&& !classifyDO.getPath().equalsIgnoreCase(classifyDO.getId())){
            throw new VciBaseException("分类编号[{0}],分类名称[{1}],路径为[{2}]的上级分类在系统中,在本次导入的数据和系统中均没有找到",new String[]{classifyDO.getId(),classifyDO.getName(),classifyDO.getPath()});
         }
         if (!classifyDO.getPath().equalsIgnoreCase(classifyDO.getId())){
            //不是顶级的时候,要设置上级的主键
    /**
     * 使用编号的路径获取对象
     *
     * @param idPath 编号的路径,一定要从最顶层节点开始,格式为xxx/yyy/zz 这样
     * @return 分类的显示对象
     */
    @Override
    public CodeClassifyVO getObjectByIdPath(String idPath) {
        CodeClassifyDO classifyDO = codeClassifyMapper.selectByFieldPath(idPath, VciQueryWrapperForDO.ID_FIELD);
        return codeClassifyDO2VO(classifyDO);
    }
    /**
     * 使用编号的路径获取对象
     *
     * @param clsfNamePath 编号的路径,一定要从最顶层节点开始,格式为xxx/yyy/zz 这样
     * @return 分类的显示对象
     */
    @Override
    public CodeClassifyVO getObjectByClsfNamePath(String clsfNamePath){
        CodeClassifyDO classifyDO = codeClassifyMapper.selectByFieldPath(clsfNamePath, "name");
        return codeClassifyDO2VO(classifyDO);
    }
            classifyDO.setParentCodeClassifyOid(catchedOidPathMap.containsKey(parentPath)?catchedOidPathMap.get(parentPath):pathDOMap.get(parentPath).getOid());
         }
         if(classifyDO.getPath().equalsIgnoreCase(classifyDO.getId()) && StringUtils.isBlank(classifyDO.getBtmTypeId())){
            throw new VciBaseException("分类编号[{0}],分类名称[{1}],是顶层分类,需要设置业务类型编号",new String[]{classifyDO.getId(),classifyDO.getName()});
         }
         if(pathDOMap.containsKey(classifyDO.getPath())){
            //存在,需要修改对象
            classifyDO.setOid(catchedOidPathMap.get(classifyDO.getPath()));
            CodeClassify classifyDOInDB = pathDOMap.get(classifyDO.getPath());
            classifyDOInDB.setOid(classifyDO.getOid());
            classifyDOInDB.setId(classifyDO.getId());
            classifyDOInDB.setName(classifyDO.getName());
            classifyDOInDB.setDescription(classifyDO.getDescription());
            classifyDOInDB.setBtmTypeId(classifyDO.getBtmTypeId());
            classifyDOInDB.setBtmTypeName(classifyDO.getBtmTypeName());
            classifyDOInDB.setCodeRuleOid(classifyDO.getCodeRuleOid());
            classifyDOInDB.setCodeRuleOidName(classifyDO.getCodeRuleOidName());
            classifyDOInDB.setParentCodeClassifyOid(classifyDO.getParentCodeClassifyOid());
            classifyDOInDB.setCodeKeyAttrRepeatOid(classifyDO.getCodeKeyAttrRepeatOid());
            classifyDOInDB.setCodeKeyAttrRepeatOidName(classifyDO.getCodeKeyAttrRepeatOidName());
            if(classifyDOInDB.getOrderNum() == null){
               classifyDOInDB.setOrderNum(0);
            }
            editClassifyDOList.add(classifyDOInDB);
         }else{
            //是新的,直接添加就行了
            //判断号怎么处理?
            classifyDO.setOrderNum(0);
            addClassifyDOList.add(classifyDO);
         }
      });
      if(!CollectionUtils.isEmpty(editClassifyDOList)){
         VciBaseUtil.switchCollectionForOracleIn(editClassifyDOList).stream().forEach(
//            classifyDOs->{codeClassifyMapper..updateById(classifyDOs.stream().collect(Collectors.toList()));
            classifyDos->{
               for (CodeClassify classifyDo : classifyDos) {
                  codeClassifyMapper.updateById(classifyDo);
               }
//            }
            });
      }
      if(!CollectionUtils.isEmpty(addClassifyDOList)){
//         revisionModelUtil.wrapperForBatchAdd(addClassifyDOList);
         VciBaseUtil.switchCollectionForOracleIn(addClassifyDOList).stream().forEach(classifyDOs->{
            for (CodeClassify classifyDO : classifyDOs) {
               classifyDO.setCreateTime(new Date());
               classifyDO.setTs(new Date());
               classifyDO.setBtmname("codeclassify");
               classifyDO.setLcStatus("Enabled");
               classifyDO.setOwner(AuthUtil.getUser().getUserName());
               classifyDO.setCreator(AuthUtil.getUser().getUserName());
               classifyDO.setLastModifier(AuthUtil.getUser().getUserName());
               classifyDO.setLastModifyTime(new Date());
               codeClassifyMapper.insert(classifyDO);
            }
//            codeClassifyMapper.batchInsert(classifyDOs.stream().collect(Collectors.toList()));
         });
      }
    /***
     * 根据上级节点获取下级节点代号路径和名称路径
     * @param codeClassifyId
     * @param enable
     * @return
     */
    @Override
   public  List<CodeClassifyVO> getIdPathToNamePathByParentId(String codeClassifyId,boolean enable){
   }
        List<CodeClassifyDO> classifyDOs= codeClassifyMapper.getIdPathToNamePathByParentId(codeClassifyId,enable);
        return codeClassifyDO2VOs(classifyDOs);
   /**
    * 获取分类关联的属性
    *
    * @param baseQueryObject 查询对象,必须有codeClassifyOid,支持id和name两种查询条件
    * @return 属性的信息,包含默认的属性
    */
   @Override
   public DataGrid<BtmTypeAttributeVO> listClassifyLinkAttr(BaseQueryObject baseQueryObject) throws ServiceException{
      if(baseQueryObject == null){
         baseQueryObject = new BaseQueryObject();
      }
      if(baseQueryObject.getConditionMap() == null){
         baseQueryObject.setConditionMap(new HashMap<>());
      }
      String classifyOid = baseQueryObject.getConditionMap().getOrDefault("codeClassifyOid","");
      String btmTypeOid = baseQueryObject.getConditionMap().getOrDefault("btmTypeOid","");
      String id = baseQueryObject.getConditionMap().getOrDefault("id","");
      String name = baseQueryObject.getConditionMap().getOrDefault("name","");
      if(StringUtils.isBlank(classifyOid)){
         return new DataGrid<>();
      }
      if(StringUtils.isBlank(btmTypeOid)){
         return new DataGrid<>();
      }
      CodeClassifyVO topClassifyVO = getTopClassifyVO(classifyOid);
      if(topClassifyVO == null || StringUtils.isBlank(topClassifyVO.getBtmtypeid())){
         return new DataGrid<>();
      }
   }
      Map<String,Object> condition = new HashMap<>(1);
      condition.put("pkbtmtype",topClassifyVO.getBtmtypeid());
      R<BtmTypeVO> btmTypeDetail = btmTypeClient.getDetail(btmTypeOid);
      if(btmTypeDetail.getCode() != 200){
         throw new ServiceException("业务类型feign接口调用出错");
      }
      List<BtmTypeAttributeVO> unDefaultAttributes = btmTypeDetail.getData().getAttributes();
      // List<CodeOsbtmtypeattributeEntity> unDefaultAttributes = codeOsbtmtypeattributeMapper.selectByMap(condition);
      // List<OsBtmTypeAttributeVO> unDefaultAttributes = btmService. (topClassifyVO.getBtmtypeid());
      List<BtmTypeAttributeVO> attributeVOS = new ArrayList<>();
      if(!CollectionUtils.isEmpty(unDefaultAttributes)){
         unDefaultAttributes.stream().forEach(attr->{
            BtmTypeAttributeVO attributeVO = new BtmTypeAttributeVO();
            BeanUtils.copyProperties(attr,attributeVO);
            attributeVO.setAttrDataType(attr.getAttrDataType());
            attributeVO.setAttributeLength(attr.getAttributeLength());
            attributeVO.setBtmTypeId(btmTypeDetail.getData().getId());
            attributeVO.setBtmname(btmTypeDetail.getData().getName());
            attributeVO.setAttrDataTypeText(EnumCache.getValue(EnumEnum.VCI_FIELD_TYPE,attr.getAttrDataType()));
            boolean add = true;
            if(StringUtils.isNotBlank(id) && !attributeVO.getId().contains(id.replace("*",""))){
               add = false;
            }
            if(StringUtils.isNotBlank(name) && !attributeVO.getName().contains(name.replace("*",""))){
               add = false;
            }
            if(add){
               attributeVOS.add(attributeVO);
            }
         });
      }
      R<BtmTypeVO> btmTypeVOR = btmTypeClient.getDefaultAttrByBtmId(topClassifyVO.getBtmtypeid());
      if(btmTypeVOR.getCode() != 200){
         throw new ServiceException("业务类型feign接口调用出错");
      }
      List<BtmTypeAttributeVO> defaultAttrVOS = btmTypeVOR.getData().getAttributes();
      // 取两个集合差集
      List<String> ids = unDefaultAttributes.stream().map(BtmTypeAttributeVO::getId).collect(Collectors.toList());
      defaultAttrVOS.forEach(item->{
         if(!ids.contains(item.getId())){
            BtmTypeAttributeVO attributeVO = new BtmTypeAttributeVO();
            BeanUtils.copyProperties(item,attributeVO);
            attributeVO.setAttrDataType(item.getAttrDataType());
            attributeVO.setAttributeLength(item.getAttributeLength());
            attributeVO.setBtmTypeId(btmTypeDetail.getData().getId());
            attributeVO.setBtmname(btmTypeDetail.getData().getName());
            attributeVO.setAttrDataTypeText(EnumCache.getValue(EnumEnum.VCI_FIELD_TYPE,item.getAttrDataType()));
            boolean add = true;
            if(StringUtils.isNotBlank(id) && !item.getId().contains(id.replace("*",""))){
               add = false;
            }
            if(StringUtils.isNotBlank(name) && !item.getName().contains(name.replace("*",""))){
               add = false;
            }
            if(add){
               attributeVOS.add(attributeVO);
            }
         }
      });
      DataGrid<BtmTypeAttributeVO> dataGrid = new DataGrid<>();
      dataGrid.setData(attributeVOS);
      dataGrid.setTotal(attributeVOS.size());
      return dataGrid;
   }
   /**
    * 获取当前分类的顶层分类
    *
    * @param codeClassifyOid 分类的主键
    * @return 顶层分类的信息
    */
   @Override
   public CodeClassifyVO getTopClassifyVO(String codeClassifyOid) {
      VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键");
//      List<Map<String,Object>> classifyDOS = codeClassifyMapper.selectAllLevelParentByOid(codeClassifyOid);
      List<CodeClassify> classifyDOS = selectAllLevelParentByOid(codeClassifyOid);
      if(!CollectionUtils.isEmpty(classifyDOS)){
         CodeClassify classifyDO = classifyDOS.stream().filter(s -> StringUtils.isBlank(s.getParentCodeClassifyOid())).findFirst().orElseGet(() -> null);
         if(classifyDO!=null){
            return codeClassifyDO2VO(classifyDO);
         }
      }
      return null;
   }
   /**
    * 获取当前分类的所有上级分类(含本次查询层级号)
    * @param oid 主键
    * @return 所有的上级
    */
   @Override
   public List<CodeClassify> selectAllLevelParentByOid(String oid){
      // String sql = "select oid,level from " + VciBaseUtil.getTableName(MdmBtmTypeConstant.CODE_CLASSIFY) + " start with oid= :oid connect by prior PARENTCODECLASSIFYOID = oid ";
      // Map< String,String> conditionMap = new HashMap< String,String>();
      // conditionMap.put("oid",oid);
      List<Map<String,Object>> cbos = codeClassifyMapper.selectAllLevelParentByOid(oid);
      Map<String,String> oidLevelMap = new HashMap<>();
      Optional.ofNullable(cbos).orElseGet(()->new ArrayList<>()).stream().forEach(cbo->{
         oidLevelMap.put(cbo.get("OID").toString(),cbo.get("LEVEL").toString());
      });
      if(CollectionUtils.isEmpty(oidLevelMap)){
         return new ArrayList<>();
      }
      //使用主键查询一下
      String oids = "";
      for (String s : oidLevelMap.keySet()) {
         oids += "'"+s+"',";
      }
      List<CodeClassify> classifyDOS = codeClassifyMapper.selectClassifyByKeyAndReseRel(oids.substring(0,oids.length()-1));
      if(!CollectionUtils.isEmpty(classifyDOS)){
         classifyDOS.stream().forEach(classifyDO->{
            classifyDO.setDataLevel(VciBaseUtil.getInt(oidLevelMap.getOrDefault(classifyDO.getOid(),"0")));
            classifyDO.setLcStatusText(EnumCache.getValue("codeLcstatus",classifyDO.getLcStatus()));
         });
      }
      return classifyDOS;
   }
   /**
    * 主键获取主题库分类
    * @param oid 主键
    * @return 主题库分类显示对象
    * @throws VciBaseException 参数为空,数据不存在时会抛出异常
    */
   @Override
   public CodeClassifyVO getObjectByOid(String oid) throws VciBaseException{
      return codeClassifyDO2VO(selectByOid(oid));
   }
   /**
    * 使用编号的路径获取对象
    *
    * @param idPath 编号的路径,一定要从最顶层节点开始,格式为xxx/yyy/zz 这样
    * @return 分类的显示对象
    */
   @Override
   public CodeClassifyVO getObjectByIdPath(String idPath) {
      List<Map<String, Object>> idPathValues = codeClassifyMapper.selectByFieldPath("/" + idPath);
      CodeClassify classifyDO = null;
      if (idPathValues != null){
         classifyDO = codeClassifyMapper.selectById(idPathValues.get(0).get("oid").toString());
      }
      return codeClassifyDO2VO(classifyDO);
   }
   /**
    * 主题库的树,已联调业务类型查询feign
    * @param treeQueryObject 树形查询对象
    * @return 主题库显示树
    */
   @Override
   public List<Tree> treeTopCodeClassify(TreeQueryObject treeQueryObject) {
      if(treeQueryObject == null){
         treeQueryObject = new TreeQueryObject();
      }
      if(treeQueryObject.getConditionMap() == null){
         treeQueryObject.setConditionMap(new HashMap<String,String>());
      }
      treeQueryObject.getConditionMap().put(PARENT_FIELD_NAME, "=null");
      List<Tree> trees = treeCodeClassify(treeQueryObject);
      treeQueryObject.getConditionMap().put("domain", AppConstant.APPLICATION_NAME_CODE);
      BaseQueryObject baseQueryObject = new BaseQueryObject();
      baseQueryObject.setConditionMap(treeQueryObject.getConditionMap());
      List<BtmTypeVO> btmTypeVOS = btmTypeClient.getRef(baseQueryObject).getData();
      if(Func.isEmpty(btmTypeVOS) || Func.isEmpty(trees)){
         return null;
      }
      List<Tree> treeList = trees.stream().filter(tree -> !CollectionUtils.isEmpty(btmTypeVOS.stream().filter(btmType -> {
               if(Objects.equals(tree.getAttributes().get("id"), btmType.getId())){
                  tree.getAttributes().put("btmTypeOid",btmType.getOid());
                  return true;
               }
               return false;
            }).collect(Collectors.toList())))
         .collect(Collectors.toList());
      return treeList;
   }
   /**
    * 获取这个分类下的业务类型,当前没有就获取上级的第一个业务类型
    * @param oid 当前分类的oid
    * @return oid,id,name,btmtypeid,btmtypename,没有就返回null
    */
   @Override
   public CodeClassify selectBtmOrParentBtm(String oid){
      List<CodeClassify> oidList = selectAllLevelParents(oid);
      return oidList.size()==0?null:oidList.get(0);
   }
   /**
    * 获取所有层级上级关联业务类型数据
    * @param oid 当前分类的oid
    * @return oid,id,name,btmtypeid,btmtypename
    */
   @Override
   public List<CodeClassify> selectAllLevelParents(String oid){
//      String sql = "select oid,id,name,btmtypeid,btmtypename from " + VciBaseUtil.getTableName(MdmBtmTypeConstant.CODE_CLASSIFY) + " where btmtypeid is not null start with oid= :oid connect by prior PARENTCODECLASSIFYOID=oid ";
//      Map< String,String> conditionMap = new HashMap< String,String>();
//      conditionMap.put("oid",oid);
//      List<Map> dataList = boService.queryBySqlForMap(sql,conditionMap);
      List<Map<String, Object>> dataList = codeClassifyMapper.selectAllLevelParents(oid);
      List<CodeClassify> oidList = new ArrayList<CodeClassify>();
      if(!CollectionUtils.isEmpty(dataList)){
         for(Map data:dataList){
            CodeClassify codeClassifyDO = new CodeClassify();
            codeClassifyDO.setOid(VciBaseUtil.getStringValueFromObject(data.get("OID")));
            codeClassifyDO.setId(VciBaseUtil.getStringValueFromObject(data.get("ID")));
            codeClassifyDO.setName(VciBaseUtil.getStringValueFromObject(data.get("NAME")));
            codeClassifyDO.setBtmTypeId(VciBaseUtil.getStringValueFromObject(data.get("BTMTYPEID")));
            codeClassifyDO.setBtmTypeName(VciBaseUtil.getStringValueFromObject(data.get("BTMTYPENAME")));
            oidList.add(codeClassifyDO);
         }
      }
      return oidList;
   }
   /**
    * 使用分类主键获取分类相关的所有信息
    *
    * @param codeClassifyOid 分类的主键
    * @return 分类上级,下级的信息
    */
   @Override
   public CodeClassifyFullInfoBO getClassifyFullInfo(String codeClassifyOid) {
      VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键");
      CodeClassifyFullInfoBO fullInfo = new CodeClassifyFullInfoBO();
      CodeClassify classifyDO = selectByOidRel(codeClassifyOid);
      //查询上级
      fullInfo.setCurrentClassifyVO(codeClassifyDO2VO(classifyDO));
//      List<Map<String, Object>> maps = codeClassifyMapper.selectAllLevelParentByOid(codeClassifyOid);
//      List<Map<String, Object>> maps = selectAllLevelParentByOid(codeClassifyOid);
      List<CodeClassify> codeClassifyList = selectAllLevelParentByOid(codeClassifyOid);
//      for (Map<String, Object> map : maps) {
//         CodeClassify codeClassify = new CodeClassify();
//         codeClassify.setOid(String.valueOf(map.get("OID")));
//         codeClassify.setDataLevel((Integer) map.get("LEVEL"));
//         codeClassifyList.add(codeClassify);
//      }
      fullInfo.setParentClassifyVOs(codeClassifyDO2VOs(codeClassifyList));
      if(!CollectionUtils.isEmpty(fullInfo.getParentClassifyVOs())){
         fullInfo.setTopClassifyVO(fullInfo.getParentClassifyVOs().stream().filter(s->StringUtils.isBlank(s.getParentcodeclassifyoid())).findFirst().orElseGet(()->null));
      }
      return fullInfo;
   }
   /**
    * 统计子节点的个数
    *
    * @param codeClassifyOid 分类的主键
    * @return 个数
    */
   @Override
   public int countChildrenByClassifyOid(String codeClassifyOid) {
//      Map<String,String> conditionMap = new HashMap<>();
//      conditionMap.put("parentCodeClassifyOid",codeClassifyOid);
      QueryWrapper<CodeClassify> wrapper = new QueryWrapper<>();
      wrapper.eq("parentCodeClassifyOid",codeClassifyOid);
      return codeClassifyMapper.selectCount(wrapper).intValue();
   }
}