ludc
2025-01-16 986aa62ed00bee39363bab41b4eeb8259d446efd
Source/plt-web/plt-web-parent/plt-web/src/main/java/com/vci/web/service/impl/OsBtmServiceImpl.java
@@ -1,12 +1,39 @@
package com.vci.web.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vci.client.common.oq.OQTool;
import com.vci.client.common.providers.ClientServiceProvider;
import com.vci.common.qt.object.Condition;
import com.vci.common.qt.object.QueryTemplate;
import com.vci.constant.FrameWorkLangCodeConstant;
import com.vci.corba.common.PLException;
import com.vci.corba.omd.atm.AttributeDef;
import com.vci.corba.omd.btm.BizType;
import com.vci.corba.omd.data.AttributeValue;
import com.vci.corba.omd.data.BusinessObject;
import com.vci.corba.omd.etm.EnumType;
import com.vci.corba.omd.lcm.Bound;
import com.vci.corba.omd.lcm.LifeCycle;
import com.vci.corba.omd.ltm.LinkType;
import com.vci.corba.omd.qtm.QTD;
import com.vci.corba.omd.stm.StatePool;
import com.vci.corba.omd.tim.TypeIndexDef;
import com.vci.corba.omd.vrm.VersionRule;
import com.vci.dto.OsBtmTypeDTO;
import com.vci.model.IndexObject;
import com.vci.omd.constants.AttributeConstants;
import com.vci.omd.constants.FileObjectType;
import com.vci.omd.objects.OtherInfo;
import com.vci.omd.utils.ObjectTool;
import com.vci.pagemodel.*;
import com.vci.po.OsBtmTypePO;
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.web.annotation.log.VciUnLog;
import com.vci.starter.web.enumpck.BooleanEnum;
import com.vci.starter.web.exception.VciBaseException;
@@ -14,12 +41,12 @@
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.pagemodel.PageHelper;
import com.vci.starter.web.pagemodel.Tree;
import com.vci.starter.web.util.BeanUtil;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import com.vci.starter.web.util.*;
import com.vci.starter.web.util.Lcm.ConcurrentDateFormat;
import com.vci.starter.web.util.Lcm.DateUtil;
import com.vci.starter.web.util.Lcm.Func;
import com.vci.web.other.AllOsEnumVOMapThreadLocal;
import com.vci.web.service.*;
import com.vci.web.util.ConcurrentDateFormat;
import com.vci.web.util.Func;
import com.vci.web.util.PlatformClientUtil;
import com.vci.web.util.WebUtil;
import org.apache.commons.lang3.StringUtils;
@@ -29,7 +56,11 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -87,6 +118,31 @@
    private OsBtmServiceI self;
    /**
     * 一些默认的表
     */
    private final List<String> tableList = Arrays.asList("pl_qtemplate", "PL_QTEMPLATEDEF",
            "pl_typeright", "plcommandparameter", "plpagedefination",
            "pluilayout", "pltabbutton", "pltabpage", "plportalvi",
            "plreleasedobj");
    /**
     * workFlowTables 中的表有主外键关系,当表主键或唯一键被引用为外键时,
     * 就算引用方没有数据, truncate还不是不能删除表中数据, 而 delete可以.
     */
    private final List<String> workFlowTableList = Arrays.asList(
            //流程(自定义表)
            "PLPROCESSTEMPLATE", "PLPROCESSCATEGORY", "PLPROCESSTASK",//"PLRMTEMPLATEPROCESS",
            "PLPROCESSTASKPROPERTY", "PLFLOWAPPROVEOPINION", "PLFLOWOBJECT", "PLFLOWINSTANCE",
            "WORKFLOW_TASK_CC_TABLE", "PLTASKDESC", "PLTASKSASSIGNED", "JBPM_SUBPROCESSTEM",
            "JBPM4_TASKANDUSERCONFIG", "PLREVOKEPOLICY", "JBPM4_TASKANDUSERCONFIGEX",
            //流程(JBPM系统表)
            "JBPM4_DEPLOYPROP", "JBPM4_HIST_DETAIL", "JBPM4_ID_MEMBERSHIP", "JBPM4_JOB",
            "JBPM4_PARTICIPATION", "JBPM4_VARIABLE", "JBPM4_HIST_ACTINST", "JBPM4_HIST_VAR",
            "JBPM4_ID_GROUP", "JBPM4_ID_USER", "JBPM4_LOB", "JBPM4_DEPLOYMENT",
            "JBPM4_HIST_PROCINST", "JBPM4_HIST_TASK", "JBPM4_TASK", "JBPM4_SWIMLANE",
            "JBPM4_EXECUTION", "JBPM4_PROPERTY");
    /**
     * 查询所有的业务类型
     *
     * @return 业务类型对象
@@ -95,8 +151,23 @@
    @VciUnLog
    public List<OsBtmTypeVO> selectAllBtm() {
        try {
            return btmDO2VOs(Arrays.stream(platformClientUtil.getBtmService().getBizTypes("")).collect(Collectors.toList()));
        }  catch (PLException e) {
            return btmDO2VOs(Arrays.stream(platformClientUtil.getBtmService().getBizTypes("")).collect(Collectors.toList()),null);
        } catch (PLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 查询所有的业务类型
     *
     * @return 业务类型对象
     */
    @Override
    @VciUnLog
    public List<OsBtmTypeVO> selectAllBtm(Map<String, OsAttributeVO> attributeVOMap) {
        try {
            return btmDO2VOs(Arrays.stream(platformClientUtil.getBtmService().getBizTypes("")).collect(Collectors.toList()),attributeVOMap);
        } catch (PLException e) {
            throw new RuntimeException(e);
        }
    }
@@ -109,7 +180,17 @@
    @Override
    @VciUnLog
    public Map<String, OsBtmTypeVO> selectAllBtmMap() {
        return Optional.ofNullable(self.selectAllBtm()).orElseGet(()->new ArrayList<OsBtmTypeVO>()).stream().collect(Collectors.toMap(s->s.getId().toLowerCase(), t->t,(o1,o2)->o1));
        return Optional.ofNullable(self.selectAllBtm()).orElseGet(() -> new ArrayList<OsBtmTypeVO>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(), t -> t, (o1, o2) -> o1));
    }
    /**
     * 查询所有的业务类型映射
     *
     * @return key 是业务的英文名称的小写
     */
    @Override
    @VciUnLog
    public Map<String, OsBtmTypeVO> selectAllBtmMap(Map<String, OsAttributeVO> attributeVOMap) {
        return Optional.ofNullable(self.selectAllBtm(attributeVOMap)).orElseGet(() -> new ArrayList<OsBtmTypeVO>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(), t -> t, (o1, o2) -> o1));
    }
    /**
@@ -119,12 +200,16 @@
     * @return 显示对象
     */
    @Override
    public List<OsBtmTypeVO> btmDO2VOs(Collection<BizType> btmItems) {
    public List<OsBtmTypeVO> btmDO2VOs(Collection<BizType> btmItems,Map<String, OsAttributeVO> attributeVOMap) {
        List<OsBtmTypeVO> VOS = new ArrayList<>();
        Optional.ofNullable(btmItems).orElseGet(()->new ArrayList<>()).stream().forEach(btmItem -> {
            OsBtmTypeVO vo = btmDO2VO(btmItem);
//        Optional.ofNullable(btmItems).orElseGet(() -> new ArrayList<>()).parallelStream().forEach(btmItem -> {
//            OsBtmTypeVO vo = btmDO2VO(btmItem,attributeVOMap);
//            VOS.add(vo);
//        });
        for (BizType btmItem : btmItems) {
            OsBtmTypeVO vo = btmDO2VO(btmItem,attributeVOMap);
            VOS.add(vo);
        });
        }
        return VOS;
    }
@@ -135,9 +220,9 @@
     * @return 显示对象
     */
    @Override
    public OsBtmTypeVO btmDO2VO(BizType btmItem) {
    public OsBtmTypeVO btmDO2VO(BizType btmItem, Map<String, OsAttributeVO> attributeVOMap) {
        OsBtmTypeVO vo = new OsBtmTypeVO();
        if(btmItem !=null){
        if (btmItem != null) {
            vo.setOid(btmItem.oid);
            vo.setCreator(btmItem.creator);
            vo.setLastModifier(btmItem.modifier);
@@ -145,49 +230,56 @@
                // btmItem.createTime拿到的是时间戳,但是这儿要的是例如2017-12-27 09:32:20.034这样的格式,所以不调用这个方法,改调用其他方法
                //vo.setCreateTime(VciDateUtil.str2Date(String.valueOf(btmItem.createTime),VciDateUtil.DateTimeFormat));
                vo.setCreateTime(Func.parse(btmItem.createTime, ConcurrentDateFormat.of(VciDateUtil.DateTimeFormat)));
                vo.setLastModifyTime( Func.parse(btmItem.modifyTime, ConcurrentDateFormat.of(VciDateUtil.DateTimeFormat)));
                vo.setTs(Func.parse(btmItem.ts, ConcurrentDateFormat.of(VciDateUtil.DateTimeFormat)));
                vo.setLastModifyTime(Func.parse(btmItem.modifyTime, ConcurrentDateFormat.of(VciDateUtil.DateTimeFormat)));
                vo.setTs(Func.parse(btmItem.ts, ConcurrentDateFormat.of(VciDateUtil.DateTimeMillFormat)));
            } catch (Exception e) {
                e.printStackTrace();
            }
            vo.setDescription(btmItem.description);
            vo.setId(btmItem.name);
             vo.setName(btmItem.label);
            vo.setName(btmItem.label);
            vo.setLifeCycleId(btmItem.lifeCycle);
            vo.setAbstractFlag(btmItem.isAbstract);
            vo.setImplClass(btmItem.implClass);
            vo.setShape(btmItem.shape);
            vo.setRevLevel(btmItem.revLevel);
            vo.setRevisionRuleId(btmItem.revRuleName);
            vo.setTableName(VciBaseUtil.getTableName(vo.getId()));
            vo.setInputRevisionFlag(btmItem.revInput);
            if(StringUtils.isNotBlank(vo.getRevisionRuleId()) || vo.isInputRevisionFlag()){
            vo.setDelimiter(btmItem.delimiter);
            vo.setImageName(btmItem.imageName);
            vo.setfName(btmItem.fName);
            vo.setVersionRule(String.valueOf(btmItem.verRuleName));
            if (StringUtils.isNotBlank(vo.getRevisionRuleId()) || vo.isInputRevisionFlag()) {
                vo.setRevisionFlag(true);
            }
            vo.setVersionRule(String.valueOf(btmItem.verRuleName));
            vo.setSubLifeCycleId(Arrays.stream(btmItem.lifeCycles).collect(Collectors.joining(",")));
            List<OsAttributeVO> attributeVOS = attributeService.listAttrByIds(Arrays.stream(btmItem.apNameArray).collect(Collectors.toList()));
            vo.setLifeCycleIds(Arrays.stream(btmItem.lifeCycles).collect(Collectors.joining(",")));
            vo.setApNameArray(btmItem.apNameArray);
            List<OsAttributeVO> attributeVOS = attributeService.listAttrByIds(Arrays.stream(btmItem.apNameArray).collect(Collectors.toList()),attributeVOMap);
            List<OsBtmTypeAttributeVO> btmTypeAttributeVOS = new ArrayList<>();
            Optional.ofNullable(attributeVOS).orElseGet(()->new ArrayList<>()).stream().forEach(attributeVO->{
//            Optional.ofNullable(attributeVOS).orElseGet(() -> new ArrayList<>()).stream().forEach(attributeVO -> {
            for (OsAttributeVO attributeVO : attributeVOS) {
                OsBtmTypeAttributeVO btmTypeAttributeVO = new OsBtmTypeAttributeVO();
                BeanUtil.convert(attributeVO,btmTypeAttributeVO);
                BeanUtilForVCI.convert(attributeVO, btmTypeAttributeVO);
                btmTypeAttributeVO.setPkBtmType(vo.getOid());
                btmTypeAttributeVO.setBtmTypeId(vo.getId());
                btmTypeAttributeVO.setAttrDataType(attributeVO.getAttributeDataType());
                btmTypeAttributeVO.setAttributeDataType(attributeVO.getAttributeDataType());
                btmTypeAttributeVO.setAttributeLength(attributeVO.getAttrLength());
                btmTypeAttributeVO.setDefaultValue(attributeVO.getDefaultValue());
                if("secretgrade".equalsIgnoreCase(attributeVO.getId())){
                if ("secretgrade".equalsIgnoreCase(attributeVO.getId())) {
                    vo.setSecretFlag(true);
                }
                if(StringUtils.isNotBlank(attributeVO.getBtmTypeId())){
                if (StringUtils.isNotBlank(attributeVO.getBtmTypeId())) {
                    btmTypeAttributeVO.setReferFlag(true);
                    btmTypeAttributeVO.setReferBtmTypeId(attributeVO.getBtmTypeId());
                }
                if(StringUtils.isNotBlank(attributeVO.getEnumId())){
                if (StringUtils.isNotBlank(attributeVO.getEnumId())) {
                    btmTypeAttributeVO.setEnumFlag(true);
                    btmTypeAttributeVO.setEnumItemMap(enumService.getEnumValueMap(btmTypeAttributeVO.getEnumId()));
                }
                btmTypeAttributeVOS.add(btmTypeAttributeVO);
            });
//            });
            }
            vo.setAttributes(btmTypeAttributeVOS);
        }
        return vo;
@@ -201,15 +293,15 @@
     */
    @Override
    public List<OsBtmTypeVO> listBtmByIds(Collection<String> btmIds) {
        if(CollectionUtils.isEmpty(btmIds)){
        if (CollectionUtils.isEmpty(btmIds)) {
            return null;
        }
        Map<String, OsBtmTypeVO> btmTypeVOMap = self.selectAllBtmMap();
        //Map<String, OsBtmTypeVO> btmTypeVOMap = self.selectAllBtmMap();
        BtmDataFetcher btmDataFetcher = new BtmDataFetcher();
        List<OsBtmTypeVO> btmTypeVOS = new ArrayList<>();
        btmIds.stream().forEach(id->{
            if(btmTypeVOMap.containsKey(id.toLowerCase())){
                btmTypeVOS.add(btmTypeVOMap.get(id.toLowerCase()));
            }
        btmIds.stream().forEach(id -> {
            OsBtmTypeVO btmType = btmDataFetcher.getBtmType(id);
            btmTypeVOS.add(btmType);
        });
        return btmTypeVOS;
    }
@@ -221,11 +313,44 @@
     * @return 业务类型
     */
    @Override
    public OsBtmTypeVO getBtmById(String id) {
        if(StringUtils.isBlank(id)){
    public OsBtmTypeVO getBtmById(String id) throws PLException {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        return self.selectAllBtmMap().getOrDefault(id.toLowerCase(),null);
        BizType bizType = platformClientUtil.getBtmService().getBizTypeByName(id);
        return btmDO2VO(bizType,null);
    }
    /**
     * 使用类型名获取业务类型,查不到直接报错
     * @param btmName 类型名
     * @return 业务类型
     * @throws
     */
    @Override
    public OsBtmTypeVO getBtmByName(String btmName) throws PLException{
        if(Func.isBlank(btmName)){
            throw new PLException("500",new String[]{"查询条件类型名不能为空!"});
        }
        BizType bizType = platformClientUtil.getBtmService().getBizTypeByName(btmName);
        if(Func.isEmpty(bizType) || Func.isBlank(bizType.oid)){
            throw new PLException("500",new String[]{"根据【"+btmName+"】未查询到对应业务类型!"});
        }
        return btmDO2VO(bizType,null);
    }
    /**
     * 使用编号获取业务类型
     *
     * @param id 编号
     * @return 业务类型
     */
    @Override
    public OsBtmTypeVO getBtmById(String id,Map<String, OsAttributeVO> attributeVOMap) {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        return self.selectAllBtmMap(attributeVOMap).getOrDefault(id.toLowerCase(), null);
    }
    /**
@@ -236,33 +361,33 @@
     */
    @Override
    public List<OsUsedAttributeVO> listBtmUsedInfo(String btmName) {
        return listBtmUsedInfo(btmName,false);
        return listBtmUsedInfo(btmName, false);
    }
    /**
     * 获取业务类型的在哪个属性中使用
     *
     * @param btmId 业务类型
     * @param btmId   业务类型
     * @param hasLink 是否包含链接类型中
     * @return 引用的信息
     */
    @Override
    public List<OsUsedAttributeVO> listBtmUsedInfo(String btmId, boolean hasLink){
        VciBaseUtil.alertNotNull(btmId,"业务类型的名称");
        List<OsAttributeVO> allReferThisBtmAttributes = Optional.ofNullable(attributeService.selectAllAttribute()).orElseGet(()->new ArrayList<>()).stream().filter(s->btmId.equalsIgnoreCase(s.getBtmTypeId())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(allReferThisBtmAttributes)){
    public List<OsUsedAttributeVO> listBtmUsedInfo(String btmId, boolean hasLink) {
        VciBaseUtil.alertNotNull(btmId, "业务类型的名称");
        List<OsAttributeVO> allReferThisBtmAttributes = Optional.ofNullable(attributeService.selectAllAttribute()).orElseGet(() -> new ArrayList<>()).stream().filter(s -> btmId.equalsIgnoreCase(s.getBtmTypeId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(allReferThisBtmAttributes)) {
            return null;
        }
        //根据这些属性,找它使用的业务类型
        List<OsUsedAttributeVO> usedInfos= new ArrayList<>();
        List<OsUsedAttributeVO> usedInfos = new ArrayList<>();
        List<OsBtmTypeVO> btmTypeVOMap = self.selectAllBtmMap().values().stream().collect(Collectors.toList());
        List<OsLinkTypeVO> linkTypeVOS = linkTypeService.selectAllLinkMap().values().stream().collect(Collectors.toList());
        allReferThisBtmAttributes.stream().forEach(attribute->{
        allReferThisBtmAttributes.stream().forEach(attribute -> {
            //其他的业务类型包含了这个属性的
            List<OsBtmTypeVO> usedBtms = btmTypeVOMap.stream().filter(btmTypeVO -> !CollectionUtils.isEmpty(btmTypeVO.getAttributes()) && btmTypeVO.getAttributes().stream().anyMatch(s -> attribute.getId().equalsIgnoreCase(s.getId()))).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(usedBtms)){
                usedBtms.stream().forEach(btm->{
                    btm.getAttributes().stream().filter(s->attribute.getId().equalsIgnoreCase(s.getId())).forEach(attrInBtm->{
            if (!CollectionUtils.isEmpty(usedBtms)) {
                usedBtms.stream().forEach(btm -> {
                    btm.getAttributes().stream().filter(s -> attribute.getId().equalsIgnoreCase(s.getId())).forEach(attrInBtm -> {
                        OsUsedAttributeVO usedAttributeVO = new OsUsedAttributeVO();
                        usedAttributeVO.setId(attrInBtm.getId());
                        usedAttributeVO.setName(attrInBtm.getName());
@@ -272,11 +397,11 @@
                    });
                });
            }
            if(hasLink){
                List<OsLinkTypeVO> usedLinks = linkTypeVOS.stream().filter(linkTypeVO -> !CollectionUtils.isEmpty(linkTypeVO.getAttributes()) &&linkTypeVO.getAttributes().stream().anyMatch(s->attribute.getId().equalsIgnoreCase(s.getId())) ).collect(Collectors.toList());
                if(!CollectionUtils.isEmpty(usedLinks)){
                    usedLinks.stream().forEach(link->{
                        link.getAttributes().stream().filter(s->attribute.getId().equalsIgnoreCase(s.getId())).forEach(attrInBtm->{
            if (hasLink) {
                List<OsLinkTypeVO> usedLinks = linkTypeVOS.stream().filter(linkTypeVO -> !CollectionUtils.isEmpty(linkTypeVO.getAttributes()) && linkTypeVO.getAttributes().stream().anyMatch(s -> attribute.getId().equalsIgnoreCase(s.getId()))).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(usedLinks)) {
                    usedLinks.stream().forEach(link -> {
                        link.getAttributes().stream().filter(s -> attribute.getId().equalsIgnoreCase(s.getId())).forEach(attrInBtm -> {
                            OsUsedAttributeVO usedAttributeVO = new OsUsedAttributeVO();
                            usedAttributeVO.setId(attrInBtm.getId());
                            usedAttributeVO.setName(attrInBtm.getName());
@@ -298,11 +423,16 @@
     * @return 属性的内容
     */
    @Override
    public List<OsBtmTypeAttributeVO> listAttributeByBtmId(String btmId) {
        VciBaseUtil.alertNotNull(btmId,"业务类型的编号");
        OsBtmTypeVO btmTypeVO = getBtmById(btmId);
    public List<OsBtmTypeAttributeVO> listAttributeByBtmId(String btmId) throws PLException {
        VciBaseUtil.alertNotNull(btmId, "业务类型的编号");
        BizType[] bizTypes = platformClientUtil.getBtmService().getBizTypes(btmId);
        if (Func.isEmpty(bizTypes)) {
            return new ArrayList<>();
        }
        BizType bizType = bizTypes[0];
        OsBtmTypeVO btmTypeVO = btmDO2VO(bizType,null);
        List<OsBtmTypeAttributeVO> attributes = btmTypeVO.getAttributes();
        if(attributes == null){
        if (attributes == null) {
            attributes = new ArrayList<>();
        }
        return attributes.stream().sorted(((o1, o2) -> o1.getId().toLowerCase(Locale.ROOT).compareTo(o2.getId().toLowerCase(Locale.ROOT)))).collect(Collectors.toList());
@@ -315,17 +445,18 @@
     * @return 属性的内容
     */
    @Override
    public List<OsBtmTypeAttributeVO> listAttributeByBtmIdHasDefault(String btmId) {
    public List<OsBtmTypeAttributeVO> listAttributeByBtmIdHasDefault(String btmId) throws PLException {
        List<OsBtmTypeAttributeVO> attrVOs = listAttributeByBtmId(btmId);
        if(attrVOs == null){
        if (attrVOs == null) {
            attrVOs = new ArrayList<>();
        }
        if(!CollectionUtils.isEmpty(attributeService.getDefaultAttributeVOs())) {
        List<OsAttributeVO> defaultAttributeVOs = attributeService.getDefaultAttributeVOs();
        if (!CollectionUtils.isEmpty(defaultAttributeVOs)) {
            List<OsBtmTypeAttributeVO> finalAttrVOs = attrVOs;
            attributeService.getDefaultAttributeVOs().stream().forEach(attr->{
            defaultAttributeVOs.stream().forEach(attr -> {
                OsBtmTypeAttributeVO attributeVO = new OsBtmTypeAttributeVO();
                BeanUtil.convert(attr, attributeVO);
                attributeVO.setAttrDataType(attr.getAttributeDataType());
                BeanUtilForVCI.convert(attr, attributeVO);
                attributeVO.setAttributeDataType(attr.getAttributeDataType());
                attributeVO.setAttributeLength(attr.getAttrLength());
                attributeVO.setReferBtmTypeId(attr.getBtmTypeId());
                attributeVO.setReferBtmTypeName(attr.getBtmTypeName());
@@ -333,7 +464,8 @@
            });
            attrVOs = finalAttrVOs;
        }
        return attrVOs;
        // TODO: 2024/12/2 Ludc 返回值排序
        return attrVOs.stream().sorted(Comparator.comparing(o->o.getId(),String.CASE_INSENSITIVE_ORDER)).collect(Collectors.toList());
    }
    /**
@@ -346,6 +478,7 @@
    /**
     * 修改业务类型中对应属性名的属性
     *
     * @param apName
     * @return
     * @throws PLException
@@ -360,7 +493,7 @@
        } catch (PLException e1) {
            e1.printStackTrace();
        }
        if(abItem == null || abItem.equals("")){
        if (abItem == null || abItem.equals("")) {
            return true;
        }
        try {
@@ -368,24 +501,24 @@
        } catch (PLException e) {
            e.printStackTrace();
        }
        if(btmNames == null || btmNames.length <= 0){
        if (btmNames == null || btmNames.length <= 0) {
            return true;
        }
        btmNameList = Arrays.asList(btmNames);
        for(Iterator<String> i = btmNameList.iterator(); i.hasNext();){
        for (Iterator<String> i = btmNameList.iterator(); i.hasNext(); ) {
            String btmName = i.next();
            try {
                platformClientUtil.getBtmService().modifyBTAttribute(btmName, apName);
            } catch (PLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                String erreMsg = "调整业务类型中【"+apName+"】属性时出现错误,原因:"+e.getMessage();
                String erreMsg = "调整业务类型中【" + apName + "】属性时出现错误,原因:" + e.getMessage();
                logger.error(erreMsg);
                throw new PLException("500",new String[]{erreMsg});
                throw new PLException("500", new String[]{erreMsg});
            }
        }
        return false;
        return true;
    }
    /**
@@ -397,14 +530,14 @@
    @Override
    public boolean hasInstance(String abName) throws PLException {
        String[] btmNames = platformClientUtil.getBtmService().getBTNamesByAPName(abName);
        if(btmNames == null || btmNames.length == 0){
        if (btmNames == null || btmNames.length == 0) {
            return false;
        }
        for(int i = 0; i < btmNames.length; i++){
        for (int i = 0; i < btmNames.length; i++) {
            String btmName = btmNames[i];
            boolean flag;
            flag = platformClientUtil.getBtmService().hasData(btmName);
            if(flag){
            if (flag) {
                return flag;
            }
        }
@@ -414,16 +547,55 @@
    /**
     * 获取名字以filter开始的业务类型(for 查询),主要用于属性池的业务类型选择对话框
     * 获取全部业务类型,传参filter为""
     *
     * @param btmName
     * @return
     * @throws PLException
     */
    @Override
    public BizType[] getBizTypes(String btmName) throws PLException {
        if(null == btmName){
        if (null == btmName) {
            btmName = "";
        }
        return platformClientUtil.getBtmService().getBizTypes(btmName);
    }
    /**
     * 业务类型列表查询,非树结构:用于UI定义左侧业务类型查询,只返回name和lable
     *
     * @param btmName
     * @return
     * @throws PLException
     */
    @Override
    public Tree getBizTree(String btmName) throws PLException {
        if (null == btmName) {
            btmName = "";
        }
        Tree returnTree = new Tree();
        BizType[] bizTypes = platformClientUtil.getBtmService().getBizTypes(btmName);
        if (Func.isEmpty(bizTypes)) {
            return returnTree;
        }
        returnTree.setOid("");
        returnTree.setText("业务类型");
        returnTree.setLeaf(false);
        List<Tree> trees = new ArrayList<>();
        Arrays.stream(bizTypes).forEach(bizType -> {
            Tree tree = new Tree();
            tree.setText(bizType.name + " " + bizType.label);
            tree.setOid(bizType.oid);
            tree.setLeaf(true);
            tree.setParentName(bizType.fName);
            tree.setIcon(bizType.imageName);
            Map<String, String> atrrMap = new HashMap<>();
            atrrMap.put("name", bizType.name);
            atrrMap.put("label", bizType.label);
            tree.setAttributes(atrrMap);
            trees.add(tree);
        });
        returnTree.setChildren(trees);
        return returnTree;
    }
    /**
@@ -435,7 +607,7 @@
     */
    @Override
    public DataGrid<OsBtmTypeVO> referDataGrid(Map<String, String> conditionMap, PageHelper pageHelper) {
        DataGrid<OsBtmTypeVO> dataGrid = queryObjectServiceInfoBySql(conditionMap, pageHelper, "plbtmtype",OsBtmTypeVO.class,((data, obj) -> {
        DataGrid<OsBtmTypeVO> dataGrid = queryObjectServiceInfoBySql(conditionMap, pageHelper, "plbtmtype", OsBtmTypeVO.class, ((data, obj) -> {
            obj.setTableName(VciBaseUtil.getTableName(obj.getId()));
        }));
        return dataGrid;
@@ -450,7 +622,7 @@
    @Override
    public OsBtmTypeVO selectByOid(String oid) {
        List<OsBtmTypeVO> btmTypeVOS = self.selectAllBtmMap().values().stream().collect(Collectors.toList());
        return Optional.ofNullable(btmTypeVOS).orElseGet(()->new ArrayList<>()).stream().filter(s->s.getOid().equalsIgnoreCase(oid)).findFirst().orElseGet(()->null);
        return Optional.ofNullable(btmTypeVOS).orElseGet(() -> new ArrayList<>()).stream().filter(s -> s.getOid().equalsIgnoreCase(oid)).findFirst().orElseGet(() -> null);
    }
    /**
@@ -460,10 +632,10 @@
     * @return 枚举的名称
     */
    @Override
    public String getNameById(String id) {
    public String getNameById(String id) throws PLException {
        OsBtmTypeVO btmTypeVO = getBtmById(id);
        if(btmTypeVO == null){
            throw new VciBaseException("业务类型[{0}]在系统里不存在",new String[]{id});
        if (btmTypeVO == null) {
            throw new VciBaseException("业务类型[{0}]在系统里不存在", new String[]{id});
        }
        return btmTypeVO.getName();
    }
@@ -474,13 +646,13 @@
     * @param btmId 业务类型主键
     */
    @Override
    public OsERVO createERDiagram(String btmId) {
    public OsERVO createERDiagram(String btmId) throws PLException {
        VciBaseUtil.alertNotNull(btmId, "业务类型编号");
        OsBtmTypeVO btmTypeVO = getBtmById(btmId);
        List<OsERNodeVO> nodeVOList = new ArrayList<>();
        List<OsERRelationVO> relationVOList = new ArrayList<>();
        //看当前这个业务类型,参照了其他的哪些业务类型 .我们不显示引用当前业务类型的业务类型
        splicingBtmType2Json(nodeVOList, relationVOList, btmTypeVO,true);
        splicingBtmType2Json(nodeVOList, relationVOList, btmTypeVO, true);
        loadAllLinkTypeByBtmType(nodeVOList, relationVOList, btmTypeVO);
        OsERVO osERVO = new OsERVO();
        osERVO.setTabViewList(nodeVOList);
@@ -495,32 +667,32 @@
     * @return 执行结果
     */
    @Override
    public OsERVO createERUsed(String btmId) {
    public OsERVO createERUsed(String btmId) throws PLException {
        VciBaseUtil.alertNotNull(btmId, "业务类型编号");
        OsBtmTypeVO btmTypeVO = getBtmById(btmId);
        //获取使用当前类型的属性
        List<OsUsedAttributeVO> usedAttributeVOS = listBtmUsedInfo(btmTypeVO.getId());
        List<OsERNodeVO> nodeVOList = new ArrayList<>();
        List<OsERRelationVO> relationVOList = new ArrayList<>();
        splicingBtmType2Json(nodeVOList, relationVOList, btmTypeVO,false);
        if(!CollectionUtils.isEmpty(usedAttributeVOS)){
            usedAttributeVOS.stream().forEach(usedAttr->{
        splicingBtmType2Json(nodeVOList, relationVOList, btmTypeVO, false);
        if (!CollectionUtils.isEmpty(usedAttributeVOS)) {
            usedAttributeVOS.stream().forEach(usedAttr -> {
                //业务类型和链接类型都有可能
                if(BooleanEnum.TRUE.getValue().equalsIgnoreCase(usedAttr.getBusinessType())){
                if (BooleanEnum.TRUE.getValue().equalsIgnoreCase(usedAttr.getBusinessType())) {
                    //业务类型
                    OsBtmTypeVO linkBtmVO = self.selectAllBtmMap().get(usedAttr.getPkBtmType().toLowerCase(Locale.ROOT));
                    splicingBtmType2Json(nodeVOList, relationVOList, linkBtmVO,false);
                    splicingBtmType2Json(nodeVOList, relationVOList, linkBtmVO, false);
                    OsERRelationVO relationVO = new OsERRelationVO();
                    relationVO.setTo(btmTypeVO.getId() + " " + btmTypeVO.getName());
                    relationVO.setFrom(linkBtmVO.getId() + " " + linkBtmVO.getName());
                    relationVO.setToText("引用");
                    relationVOList.add(relationVO);
                }else{
                } else {
                    //是链接类型
                    OsLinkTypeVO linkTypeVO = linkTypeService.selectAllLinkMap().get(usedAttr.getPkBtmType().toLowerCase(Locale.ROOT));
                    List<OsLinkTypeVO> linkTypeVOList = new ArrayList<>();
                    linkTypeVOList.add(linkTypeVO);
                    splicingLinkType2Json(nodeVOList, relationVOList,linkTypeVOList,btmTypeVO,true);
                    splicingLinkType2Json(nodeVOList, relationVOList, linkTypeVOList, btmTypeVO, true);
                }
            });
        }
@@ -529,34 +701,63 @@
        ervo.setTabRelViewList(relationVOList);
        return ervo;
    }
    /**
     * 获取所有业务类型(树形结构)
     *
     * @return 查询结果
     */
    @Override
    public BaseResult<List<Tree>> getTreeBizTypes() throws PLException {
    public List<Tree> getTreeBizTypes() throws PLException {
        List<Tree> rootTreeList = new ArrayList<>();
        BizType[] bizTypes = getBizTypes("");
        BizType btItem = null;
        for(int i = 0; i < bizTypes.length; i++){
            btItem = bizTypes[i];
            if(btItem.fName.equals("")){
        OsBtmTypeVO osBtmTypeVO = null;
        Map<String, OsAttributeVO> attributeVOMap = null;
        if(bizTypes.length > 0){
            //先将所需要的属性、枚举数据全部加载出来,避免后续进行重复加载
            attributeVOMap = attributeService.selectAllAttributeMap();
            AllOsEnumVOMapThreadLocal.set(enumService.selectAllEnumMap());
        }
        List<OsBtmTypeVO> osBtmTypeVOS = btmDO2VOs(Arrays.asList(bizTypes),attributeVOMap);
        for (int i = 0; i < osBtmTypeVOS.size(); i++) {
            osBtmTypeVO = osBtmTypeVOS.get(i);
            if (osBtmTypeVO.getfName().equals("")) {
                Tree tree = new Tree();
                tree.setOid(btItem.oid);
                tree.setOid(osBtmTypeVO.getOid());
                tree.setParentName(null);
                tree.setParentId(null);
                tree.setLeaf(true);
                tree.setText(btItem.description);
                tree.setAttributes(WebUtil.objectToMapString(btItem));
                tree.setChildren(getChildren(bizTypes,btItem));
                tree.setIcon(osBtmTypeVO.getImageName());
                tree.setId(osBtmTypeVO.getId());
                tree.setText(osBtmTypeVO.getDescription());
                tree.setAttributes(WebUtil.objectToMapString(osBtmTypeVO));
                tree.setChildren(getChildren(osBtmTypeVOS, osBtmTypeVO));
                rootTreeList.add(tree);
            }
        }
        return BaseResult.success(rootTreeList);
        AllOsEnumVOMapThreadLocal.remove();
        rootTreeList = rootTreeList.stream().sorted((o1, o2) -> o1.getId().compareTo(o2.getId())).collect(Collectors.toList());
        return rootTreeList;
    }
    /**
     * 获取所有业务类型名称集合
     *
     * @return
     */
    @Override
    public List<String> getAllBtmName() throws PLException {
        BizType[] bizTypes = platformClientUtil.getBtmService().getBizTypes("");
        if (null != bizTypes && bizTypes.length > 0) {
            return Arrays.stream(bizTypes).map(bizType -> bizType.name).collect(Collectors.toList());
        }
        return null;
    }
    /**
     * 获取业务全部属性类型
     *
     * @param btmName 业务类型名称
     * @return 属性的信息
     */
@@ -571,7 +772,7 @@
            AttributeDef sysAttributeDef = collect.get(attrName.toLowerCase());
            OsBtmTypeAttributeVO vo = new OsBtmTypeAttributeVO();
            vo.setOid(sysAttributeDef.oid);
            vo.setAttrDataType(sysAttributeDef.vtDataType);
            vo.setAttributeDataType(sysAttributeDef.vtDataType);
            vo.setPkBtmType(btmName);
            vo.setCreateTime(new Date(sysAttributeDef.createTime));
            vo.setCreator(sysAttributeDef.creator);
@@ -590,7 +791,7 @@
        for (AttributeDef attribute : attributeDefs) {
            OsBtmTypeAttributeVO vo = new OsBtmTypeAttributeVO();
            vo.setOid(attribute.oid);
            vo.setAttrDataType(attribute.vtDataType);
            vo.setAttributeDataType(attribute.vtDataType);
            vo.setPkBtmType(btmName);
            vo.setCreateTime(new Date(attribute.createTime));
            vo.setCreator(attribute.creator);
@@ -604,7 +805,7 @@
            vo.setOwner(attribute.creator);
            vo.setLastModifyTime(new Date(attribute.modifyTime));
            String maxLength = AttributeConstants.getOtherValueByType(attribute.other, AttributeConstants.LENGTH);
            if(StringUtils.isNotBlank(maxLength)){
            if (StringUtils.isNotBlank(maxLength)) {
                vo.setAttributeLength(Integer.valueOf(maxLength));
            }
            osBtms.add(vo);
@@ -612,21 +813,821 @@
        return osBtms;
    }
    private List<Tree> getChildren(BizType[] bizTypes,BizType parentBIzType){
        List<Tree> trees= new ArrayList<>();
        for (BizType bizType : bizTypes) {
            if(StringUtils.isBlank(bizType.fName)){
    /**
     * dto转do对象
     *
     * @return
     */
    private BizType dto2BizType(OsBtmTypeDTO dto) {
        BizType bizType = new BizType();
        bizType.oid = dto.getOid();
        bizType.name = dto.getId();
        bizType.isAbstract = dto.isAbstractFlag();
        bizType.label = dto.getName();
        bizType.fName = dto.getfName();
        bizType.implClass = dto.getImplClass();
        bizType.imageName = dto.getImageName();
        bizType.shape = "";
        bizType.lifeCycle = dto.getLifeCycleId();
        List<String> lcList = Arrays.asList(dto.getSubLifeCycleId().split(","));
        if (lcList != null) {
            bizType.lifeCycles = lcList.toArray(new String[0]);
        } else {
            bizType.lifeCycles = new String[0];
        }
        bizType.description = dto.getDescription();
        bizType.revLevel = dto.getRevLevel();
        bizType.revRuleName = dto.getRevisionRuleId();
        bizType.revInput = dto.isInputRevisionFlag();
        bizType.delimiter = (dto.getDelimiter() == null ? "" : dto.getDelimiter());
        bizType.verRuleName = Func.isBlank(dto.getVersionRule()) ? 0 : Short.parseShort(dto.getVersionRule());
        //List<String> attrIdList = dto.getAttributesDTOList().stream().map(OsBtmTypeLinkAttributesDTO::getId).collect(Collectors.toList());
        bizType.apNameArray = dto.getApNameArray().split(",");//attrIdList.toArray(new String[attrIdList.size()]);
        String userId = WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId();
        long timeMillis = System.currentTimeMillis();
        bizType.creator = Func.isBlank(dto.getCreator()) ? userId : dto.getCreator();
        bizType.createTime = Func.isEmpty(dto.getCreateTime()) ? timeMillis : dto.getCreateTime().getTime();
        bizType.modifier = userId;
        bizType.modifyTime = timeMillis;
        bizType.ts = Func.isEmpty(dto.getTs()) ? timeMillis : dto.getTs().getTime();
        return bizType;
    }
    /**
     * 创建新的业务类型
     *
     * @return
     * @throws PLException
     */
    @Override
    public boolean addBtmType(OsBtmTypeDTO btmTypeDTO) throws PLException {
        VciBaseUtil.alertNotNull(btmTypeDTO, "创建的业务类型对象");
        //业务类型名称检查
        checkName(btmTypeDTO.getId());
        //生命周期检查
        checkLifeCycle(btmTypeDTO);
        //版本规则检查
        checkVersionInfo(btmTypeDTO);
        BizType bizType = this.dto2BizType(btmTypeDTO);
        return platformClientUtil.getBtmService().addBizType(bizType);
    }
    /**
     * 批量新增业务类型
     * @param bizTypes
     * @return
     */
/*    @Override
    public boolean addBtmTypes(List<BizType> bizTypes) {
        VciBaseUtil.alertNotNull(bizTypes,"创建的业务类型对象列表");
        bizTypes.stream().forEach(bizType->{
            try {
                platformClientUtil.getBtmService().addBizType(bizType);
            } catch (PLException e) {
                e.printStackTrace();
                String exceptionMessage = VciBaseUtil.getExceptionMessage(e);
                logger.error(exceptionMessage);
                throw new VciBaseException(exceptionMessage);
            }
        });
        return true;
    }*/
    /**
     * 检查业务类型名称是否合规
     *
     * @param btmName
     * @throws PLException
     */
    private void checkName(String btmName) throws PLException {
        if (Func.isBlank(btmName)) {
            throw new PLException("500", new String[]{"业务类型名不能为空!"});
        }
        if (!btmName.matches("[a-z A-Z]*")) {
            throw new PLException("500", new String[]{"业务类型名只能为英文字母!"});
        }
        int maxLength = platformClientUtil.getBtmService().getBTNameMaxLength();
        if (btmName.length() > maxLength) {
            throw new PLException("500", new String[]{"业务类型名长度不能超过" + maxLength});
        }
        if (platformClientUtil.getBtmService().checkRowIsExists(btmName)) {
            throw new PLException("500", new String[]{"业务类型名已经存在"});
        }
    }
    /**
     * 是否选择生命周期
     *
     * @return
     */
    private void checkLifeCycle(OsBtmTypeDTO btmTypeDTO) throws PLException {
        if (Func.isBlank(btmTypeDTO.getLifeCycleId())) {
            throw new PLException("500", new String[]{"生命周期不能为空"});
        }
    }
    /**
     * 选择一级版本:必须选择或手工输入版本号规则; 选择二级版本:必须选择或手工输入版本号规则, (版次号已经默认选择).
     *
     * @return
     */
    private void checkVersionInfo(OsBtmTypeDTO dto) throws PLException {
        //需要手动输入版本时revisionRuleId不能为空
        if (dto.getRevLevel() == 1 || dto.getRevLevel() == 2) {
            if (Func.isBlank(dto.getRevisionRuleId()) && !dto.isInputRevisionFlag()) {
                throw new PLException("500", new String[]{"版本号规则不能为空"});
            }
        }
    }
    /**
     * 版本机制修改: 仅允许类型从"不可修订"变更至"一级版本管理机制","二级版本管理机制进行调整"; "一级版本管理机制"变更至"二级版本管理机制";
     * 两种方式.
     *
     * @param dbBizType 当前修改前的业务类型(库中存储的)
     * @param dto       当前修改业务类型
     * @throws PLException
     */
    private void checkRevLevel(BizType dbBizType, OsBtmTypeDTO dto) throws PLException {
        if (dbBizType.revLevel == 1 && dto.getRevLevel() == 0) {
            throw new PLException("500", new String[]{"版本变更错误:不能从一级变为不可修订"});
        }
        if (dbBizType.revLevel == 2 && (dto.getRevLevel() == 1 || dto.getRevLevel() == 0)) {
            throw new PLException("500", new String[]{"版本变更错误:不能从二级变为一级或不可修订"});
        }
    }
    /**
     * 修改业务类型
     *
     * @param btmTypeDTO
     * @return
     * @throws PLException
     */
    @Override
    public boolean updateBtmType(OsBtmTypeDTO btmTypeDTO) throws PLException {
        VciBaseUtil.alertNotNull(btmTypeDTO, "修改的业务类型对象");
        //检查生命周期是否合规
        checkLifeCycle(btmTypeDTO);
        //查询数据库中的业务类型
        String id = btmTypeDTO.getId();
        BizType dbBizType = platformClientUtil.getBtmService().getBizTypeByName(id);
        if (Func.isEmpty(dbBizType) || Func.isBlank(dbBizType.oid)) {
            throw new PLException("500", new String[]{"当前修改的业务类型不存在!"});
        }
        //检查版本规则修改是否合规
        checkRevLevel(dbBizType, btmTypeDTO);
        checkVersionInfo(btmTypeDTO);
        //处理业务类型下的属性
        List<String> lastAttrList = new ArrayList<>(Arrays.asList(btmTypeDTO.getApNameArray().split(",")));
        //不能移除的属性
        String[] unRemovableFields = null;
        List<String> unRemovableFields_ = null;
        //需要移除的属性
        List<String> removableFields = new ArrayList<>();
        //修改前业务类型在数据库中已存在的所有属性
        List<String> apNameArray = Func.toStrList(btmTypeDTO.getApNameArray());
        Set<String> dbApNameArray = Arrays.stream(dbBizType.apNameArray)
                .collect(Collectors.toSet());
        //过滤出需要移除的属性
        removableFields = dbApNameArray.stream()
                .filter(ap -> !apNameArray.contains(ap))   // 过滤不在 dbApSet 中的元素
                .collect(Collectors.toList());
        // 当业务类型表中某属性已经有值, 不删除该属性, 将已经移除的属性添加回来
        unRemovableFields = platformClientUtil.getBtmService().getUnRemovableFields(id, removableFields.toArray(new String[0]));
        if (removableFields.size() > 0) {
            //检查业务类型是否具有实例
            if (this.hasInstanceByBtmName(id)) {
                //业务类型已有实例, 只能删除没有数据的列
                if (unRemovableFields != null && unRemovableFields.length > 0) {
                    //移除了不可修改的属性直接报错,就不往下执行了
                    throw new VciBaseException("业务类型已有实例, 只能删除没有数据的列,有数据的列名为:" + removableFields);
                    /*unRemovableFields_ = Arrays.asList(unRemovableFields);
                    for (int i = 0; i < removableFields.size(); i++) {
                        String abName = removableFields.get(i);
                        if (unRemovableFields_.contains(abName)) {
                            if (!lastAttrList.contains(abName)) {
                                lastAttrList.add(abName);
                            }
                        }
                    }*/
                }
            }
        }
        BizType bizType = dto2BizType(btmTypeDTO);
        bizType.apNameArray = lastAttrList.toArray(new String[lastAttrList.size()]);
        return platformClientUtil.getBtmService().updateBizType(bizType);
    }
    /**
     * 删除业务类型
     *
     * @param btmTypeDTO
     * @return
     * @throws PLException
     */
    @Override
    public boolean deleteBtmType(OsBtmTypeDTO btmTypeDTO) throws PLException {
        VciBaseUtil.alertNotNull(btmTypeDTO, "删除的业务类型");
        String btmName = btmTypeDTO.getId();
        //只能删除叶子节点
        if (Func.isNotBlank(btmTypeDTO.getfName())) {
            throw new PLException("500", new String[]{"只能删除叶子节点"});
        }
        // 业务类型被链接类型使用, 不能删除
        List<String> usedNameList = linkTypeService.getUsedBtmLinkList(btmName);
        if (usedNameList != null && usedNameList.size() > 0) {
            throw new PLException("500", new String[]{"该类型已被链接类型使用,禁止删除"});
        }
        // 业务类型已经生成了业务对象, 不能删除
        if (hasInstanceByBtmName(btmName)) {
            throw new PLException("500", new String[]{"该类型已有实例,禁止删除"});
        }
        BizType bizType = new BizType();
        bizType.ts = btmTypeDTO.getTs().getTime();
        bizType.oid = btmTypeDTO.getOid();
        bizType.name = btmTypeDTO.getId();
        return platformClientUtil.getBtmService().deleteBizType(bizType);
    }
    /**
     * 一致性检查
     *
     * @return
     * @throws PLException
     */
    @Override
    public BaseResult checkBtmConsistency() throws PLException {
        String[] result = platformClientUtil.getBtmService().btmConsistencyCheck();
        Map<String, String> dbCheckMap = new HashMap<String, String>();
        for (int i = 0; i < result.length; i++) {
            String info = result[i];
            if (info.equals("")) {
                continue;
            }
            if(bizType.fName.equals(parentBIzType.name)){
            String[] infos = info.split("/DML");
            String typeName = infos[0];
            String dml = infos[1];
            dbCheckMap.put(typeName, dml);
        }
        if (dbCheckMap.size() < 1) {
            return BaseResult.successMsg("数据库中的表结构与类型一致,无需修复!!");
        } else {
            //需要修复时就需要界面唤起对话框进行处理
            List<Map> list = new ArrayList<>();
            list.add(dbCheckMap);
            BaseResult<List<Map>> listBaseResult = BaseResult.dataList(200, list, "需要进行列的修复!!");
            listBaseResult.setSuccess(false);
            return listBaseResult;
        }
    }
    /**
     * 一致性检查修复功能
     *
     * @param repairData
     * @return
     */
    @Override
    public BaseResult executeRepair(String repairData) throws Exception {
        Map<String, String> dbCheckMap = new ObjectMapper().readValue(repairData, new TypeReference<Map<String, String>>() {
        });
        List<String> list = this.getRepairDML(dbCheckMap);
        if (list.size() < 1) {
            return BaseResult.success();
        }
        try {
            String[] result = platformClientUtil.getBtmService().executeRepair(list.toArray(new String[0]));
            return BaseResult.success(result);
        } catch (PLException e) {
            return BaseResult.fail("业务类型修复失败,原因:" + VciBaseUtil.getExceptionMessage(e));
        }
    }
    /**
     * 创建视图
     *
     * @return
     * @throws PLException
     */
    @Override
    public boolean createView() throws PLException {
        return platformClientUtil.getBtmService().createView();
    }
    /**
     * 删除数据界面的查询
     *
     * @return 业务类型,链接类型
     */
    @Override
    public BaseResult getObjectData() throws PLException {
        //获取业务类型名称集合
        List<String> allBtmName = this.getAllBtmName();
        //获取链接类型名称集合
        List<String> allLinkType = linkTypeService.getAllLtName();
        Map<String, List> map = new HashMap<>();
        map.put("btmType", allBtmName);
        map.put("linkType", allLinkType);
        map.put("table", tableList);
        map.put("workFlow", workFlowTableList);
        List<Map> list = new ArrayList<>();
        list.add(map);
        return BaseResult.dataList(list);
    }
    /**
     * 删除数据
     *
     * @param btmNames  业务类型名
     * @param linkNames 链接类型名
     * @return
     * @throws PLException
     */
    @Override
    public List<Map> truncateTable(String[] btmNames, String[] linkNames) throws PLException {
        List<Map> returnMapList = new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();
        map.put("btmSuccess", new ArrayList<>());
        map.put("btmFail", new ArrayList<>());
        map.put("linkSuccess", new ArrayList<>());
        map.put("linkFail", new ArrayList<>());
        if (Func.isNotEmpty(btmNames)) {
            for (int i = 0; i < btmNames.length; i++) {
                String btName = btmNames[i];
                try {
                    if (platformClientUtil.getBtmService().truncateTable(btName)) {
                        //修改成功记录下成功的业务类型名
                        map.get("btmSuccess").add(btName);
                    }
                } catch (PLException e1) {
                    e1.printStackTrace();
                    logger.error(VciBaseUtil.getExceptionMessage(e1));
                    //修改失败记录下失败的业务类型名
                    map.get("btmFail").add(btName);
                }
            }
        }
        if (Func.isNotEmpty(linkNames)) {
            //truncate链接类型数据
            for (int i = 0; i < linkNames.length; i++) {
                String ltName = linkNames[i];
                try {
                    if (platformClientUtil.getLinkTypeService().truncateTable(ltName)) {
                        map.get("linkSuccess").add(ltName);
                    }
                } catch (PLException e1) {
                    e1.printStackTrace();
                    logger.error(VciBaseUtil.getExceptionMessage(e1));
                    map.get("linkFail").add(ltName);
                }
            }
        }
        returnMapList.add(map);
        return returnMapList;
    }
    /**
     * 删除全部类型
     *
     * @return
     * @throws PLException
     */
    @Override
    public BaseResult deleteAllType() throws PLException {
        DeleteType deleteType = new DeleteType();
        //获取待删除的业务类型
        List<BizType> delBtList = deleteType.getDelBtList();
        //获取待删除的链接类型
        List<LinkType> ltNames = deleteType.getDelLtList();
        //获取待删除的属性
        List<String> delAbList = deleteType.getDelAbList();
        //获取待删除的枚举类型
        List<EnumType> delEnumList = deleteType.getDelEnumList();
        //获取待删除的生命周期
        List<LifeCycle> delLCList = deleteType.getDelLCList();
        //获取待删除的状态
        List<StatePool> delStateList = deleteType.getDelSPList();
        //获取待删除的版本规则
        List<VersionRule> delVRList = deleteType.getDelVRList();
        try {
            platformClientUtil.getBtmService().deleteBtsAndTables(delBtList.toArray(new BizType[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除业务类型和对应表格时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            ClientServiceProvider.getOMDService().getLinkTypeService().deleteLtsAndTables(ltNames.toArray(new LinkType[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除链接类型时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            AttributeDef[] abs = platformClientUtil.getAttributeService().getAttributeDefsByNames(delAbList.toArray(new String[0]));
            platformClientUtil.getAttributeService().deleteAttributeDefs(abs);
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除属性池属性时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            platformClientUtil.getEnumService().deleteEnumTypes(delEnumList.toArray(new EnumType[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除枚举类型时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            platformClientUtil.getLifeCycleService().deleteLifeCycles(delLCList.toArray(new LifeCycle[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除生命周期时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            platformClientUtil.getStatePoolService().deleteStatePools(delStateList.toArray(new StatePool[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除状态池状态时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        try {
            platformClientUtil.getVersionService().deleteVersionRules(delVRList.toArray(new VersionRule[0]));
        } catch (PLException e) {
            e.printStackTrace();
            String exceptionMessage = "清除版本规则时出现异常,原因:" + VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            return BaseResult.fail(exceptionMessage);
        }
        return BaseResult.success("清除数据完成!");
    }
    /**
     * 根据业务类型名称和其下的属性名称获取已有的索引
     *
     * @param conditionMap 根据查询条件传参: typename:业务类型名;
     * @return
     */
    @Override
    public List<IndexObject> getIndexByCondition(Map<String, String> conditionMap) throws PLException {
        if (Func.isEmpty(conditionMap)) {
            return new ArrayList<>();
        }
        List<IndexObject> indexObjects = new ArrayList<>();
        TypeIndexDef[] typenames = ClientServiceProvider.getOMDService().getTypeIndexService().getBTIndexDefs(conditionMap.get("typename"));
        for (int i = 0; i < typenames.length; i++) {
            TypeIndexDef typename = typenames[i];
            IndexObject indexObject = new IndexObject();
            indexObject.setOid(typename.oid);
            indexObject.setDescription(typename.description);
            indexObject.setCreateTime(Func.format(new Date(typename.createTime), DateUtil.PATTERN_DATE));
            indexObject.setIndexName(typename.name);
            indexObject.setTypeName(typename.typeName);
            indexObject.setAttrNames(typename.attributes);
            indexObjects.add(indexObject);
        }
        return indexObjects;
    }
    /**
     * 根据业务类型名称和其下的属性名称删除索引
     *
     * @param btmName
     * @param indexName
     * @return
     */
    @Override
    public boolean delIndex(String btmName, String indexName) throws PLException {
        VciBaseUtil.alertNotNull(btmName, "业务类型名", indexName, "索引名");
        TypeIndexDef[] typeIndexDef= ClientServiceProvider.getOMDService().getTypeIndexService().getBTIndexDefs(btmName);
        if( typeIndexDef != null && typeIndexDef.length > 0 ){
            String[] indexAttr = {indexName};
            boolean alterFlag = platformClientUtil.getBtmService().dropIndex(btmName, indexAttr);
            if (!alterFlag) {
                return false;
            }
            for (int i = 0; i < typeIndexDef.length; i++) {
                if(!typeIndexDef[i].name.equals(indexName)) {
                    continue;
                }
                String oid = typeIndexDef[i].oid;
                ClientServiceProvider.getOMDService().getTypeIndexService().delIndexDef(oid);
            }
        }
        return true;
    }
    /**
     * 给业务类型下的指定属性新增索引
     *
     * @param indexObjectList
     * @return
     */
    @Override
    public boolean addIndex(List<IndexObject> indexObjectList) throws PLException {
        VciBaseUtil.alertNotNull(indexObjectList, "新增的索引信息");
        String btmName = indexObjectList.get(0).getTypeName();
        String indexNames = indexObjectList.stream().map(IndexObject::getIndexName).collect(Collectors.joining(","));
        String[] oldindexAttr = {indexNames};
//        BusinessObject bo;
//        List<BusinessObject> boList = new ArrayList<>();
//        //先查询当前添加索引是否已经存在,如果存在就先删除再新增实现替换操作
//        Map<String, String> conditionMap = new HashMap<>();
//        conditionMap.put("typename", btmName);
//        //先这样处理,前端现在只做了单次保存,所以不用in
//        conditionMap.put("indexname", indexNames);
        TypeIndexDef[] typeIndexDefs = platformClientUtil.getTypeIndexService().getBTIndexDefs(btmName);
        if(typeIndexDefs!=null && typeIndexDefs.length>0){
            boolean hasIndex = false;
            for(int i = 0; i < typeIndexDefs.length; i ++){
                if(!typeIndexDefs[i].name.equals(indexNames)) {
                    continue;
                }
                String oid = typeIndexDefs[i].oid;
                platformClientUtil.getTypeIndexService().delIndexDef(oid);
                hasIndex = true;
            }
            //索引不存在时删除就会报错索引不存在,所以这里有索引才去删除
            if(hasIndex) {
                platformClientUtil.getBtmService().dropIndex(btmName, oldindexAttr);
            }
        }
        StringBuilder sb = new StringBuilder();
        List<TypeIndexDef> saveDefs = new ArrayList<>();
        for(int i = 0; i < indexObjectList.size(); i ++){
            TypeIndexDef saveDef = new TypeIndexDef();
            saveDef.typeName = indexObjectList.get(i).getTypeName();
            saveDef.name = indexObjectList.get(i).getIndexName();
            saveDef.description = indexObjectList.get(i).getDescription();
            saveDef.attributes = indexObjectList.get(i).getAttrNames();
            sb.append(indexObjectList.get(i).getAttrNames());
            if(i<indexObjectList.size()-1){
                sb.append(",");
            }
            saveDefs.add(saveDef);
        }
        String[] indexAttr = {indexObjectList.get(0).getIndexName(),sb.toString()};
        boolean alterFlag = platformClientUtil.getBtmService().addIndex(btmName, indexAttr);
        if(!alterFlag) {
            return false;
        }
        ClientServiceProvider.getOMDService().getTypeIndexService().saveIndexDefs(saveDefs.toArray(new TypeIndexDef[saveDefs.size()]));
        return true;
    }
    /**
     * 导出业务类型
     * oid 业务类型名称
     *
     * @return 创建结果
     */
    @Override
    public void expData(String names, HttpServletResponse response) throws PLException, IOException {
        String defaultTempFolder = LocalFileUtil.getDefaultTempFolder();
        //写excel
        String excelPath = defaultTempFolder + File.separator + "btm.xls";
        //设置列名
        List<String> columns = new ArrayList<>(
                Arrays.asList("类型名称", "标签", "继承自", "实现类", "描述", "版本规则", "版本号规则",
                        "是否手工输入", "分隔符", "版次号规则","图标", "生命周期", "备选生命周期列表", "属性列表")
        );
        try {
            new File(excelPath).createNewFile();
            //设置列
            List<WriteExcelData> excelDataList = new ArrayList<>();
            //设置列头
            for (int index = 0; index < columns.size(); index++) {
                excelDataList.add(new WriteExcelData(0, index, columns.get(index)));
            }
            HashSet<String> attributes = new HashSet<>();
            int i = 0;
            for (String name : names.split(",")) {
                BizType bizType = platformClientUtil.getBtmService().getBizTypeByName(name);
                excelDataList.add(new WriteExcelData(i + 1, 0, bizType.name));
                excelDataList.add(new WriteExcelData(i + 1, 1, bizType.label));
                excelDataList.add(new WriteExcelData(i + 1, 2, bizType.fName));
                excelDataList.add(new WriteExcelData(i + 1, 3, bizType.implClass));
                excelDataList.add(new WriteExcelData(i + 1, 4, bizType.description));
                excelDataList.add(new WriteExcelData(i + 1, 5, bizType.revLevel));
                excelDataList.add(new WriteExcelData(i + 1, 6, bizType.revRuleName));
                excelDataList.add(new WriteExcelData(i + 1, 7, bizType.revInput));
                excelDataList.add(new WriteExcelData(i + 1, 8, bizType.delimiter));
                excelDataList.add(new WriteExcelData(i + 1, 9, bizType.verRuleName));
                excelDataList.add(new WriteExcelData(i + 1, 10, bizType.imageName));
                excelDataList.add(new WriteExcelData(i + 1, 11, bizType.lifeCycle));
                excelDataList.add(new WriteExcelData(i + 1, 12, String.join(",", bizType.lifeCycles)));
                excelDataList.add(new WriteExcelData(i + 1, 13, String.join(",", bizType.apNameArray)));
                attributes.addAll(Arrays.asList(bizType.apNameArray));
                i++;
            }
            WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
            ExcelUtil.writeDataToFile(excelPath, excelOption);
            //导出属性
            String attrPath = attributeService.exportAttributes("btmattr",
                    attributes.stream().collect(Collectors.joining(",")), true);
            //移动属性到链接类型文件夹里面去
            FileUtil.move(new File(attrPath), new File(defaultTempFolder), true);
            FileUtil.del(attrPath.substring(0, attrPath.lastIndexOf("\\")));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        File zip = ZipUtil.zip(defaultTempFolder);
        FileUtil.del(defaultTempFolder + File.separator);
        ControllerUtil.writeFileToResponse(response, zip.getAbsoluteFile());
    }
    /**
     * 导入业务类型
     *
     * @param file 上传的文件
     * @return
     */
    @Override
    public BaseResult impData(MultipartFile file) throws Exception {
        String defaultTempFolder = LocalFileUtil.getDefaultTempFolder();
        String fileName = defaultTempFolder + File.separator + LocalFileUtil.getFileNameForIE(file.getOriginalFilename());
        file.transferTo(new File(fileName));
        if (file == null) {
            return BaseResult.fail(FrameWorkLangCodeConstant.IMPORT_FAIL, new String[]{"无导入的文件"});
        }
        if (!fileName.endsWith(".zip") || !fileName.endsWith(".rar")) {
            throw new VciBaseException("仅能上传zip压缩文件,请重新上传!");
        }
        File unzip = ZipUtil.unzip(fileName);
        File btmExcel = new File(unzip.getAbsolutePath() + File.separator + "btm.xls");
        File attrExcel = new File(unzip.getAbsolutePath() + File.separator + "btmattr.xls");
        if (!attrExcel.exists()) {
            //增加解压的路径,看文件还在没有
            attrExcel = new File(unzip.getAbsolutePath() + File.separator + unzip.getName() + File.separator + "btmattr.xls");
            if (!attrExcel.exists()) {
                return BaseResult.fail(FrameWorkLangCodeConstant.IMPORT_FAIL, new String[]{"没有导入的属性文件。导入终止!"});
            }
        }
        //TODO:导入属性,但是这个逻辑实际上存在一些问题,导入的属性只是业务类型的属性不应该去给属性池导入,可能是想的属性不存在的就新增一次
        BaseResult baseResult = attributeService.importAttributes(attrExcel, true);
        if (!baseResult.isSuccess()) {
            //删除上传的文件夹
            FileUtil.del(defaultTempFolder + File.separator);
            return baseResult;
        }
        //入业务类型
        if (!btmExcel.exists()) {
            //增加解压的路径,看文件还在没有
            btmExcel = new File(unzip.getAbsolutePath() + File.separator + unzip.getName() + File.separator + "btm.xls");
            if (!btmExcel.exists()) {
                //删除上传的文件夹
                FileUtil.del(defaultTempFolder + File.separator);
                return BaseResult.fail(FrameWorkLangCodeConstant.IMPORT_FAIL, new String[]{"没有导入的链接文件。导入终止!"});
            }
        }
        try {
            //1、读取excel中的数据,组成对象
            ReadExcelOption excelOption = new ReadExcelOption();
            List<OsBtmTypePO> poList = ExcelUtil.readDataObjectFromExcel(btmExcel, OsBtmTypePO.class, excelOption, (value, po, fieldName) -> {
            });
            //去除都是空的情况
            if (CollectionUtils.isEmpty(poList)) {
                return BaseResult.fail(ExcelLangCodeConstant.IMPORT_CONTENT_NULL, new String[]{});
            }
            //当前excel中是否重复用的判重Map:(key:判重属性,value:行号)
            Map<String, String> excelReapeat = new HashMap<>();
            int maxLength = platformClientUtil.getLinkTypeService().getLTNameMaxLength();
            //判断必填属性是否为空,用户是否已存在,以及部门是否填错等校验逻辑
            poList.stream().forEach(osBtmTypePO -> {
                if (Func.isBlank(osBtmTypePO.getName())) {//属性名判空
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,name");
                } else if (osBtmTypePO.getName().length() > maxLength) {
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,业务类型名长度不能超过" + maxLength);
                } else if (!osBtmTypePO.getName().matches("^[A-Za-z]+$")) {
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,业务类型名称只能为英文字母");
                } else if (osBtmTypePO.getName().length() > maxLength) {
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,业务类型名长度不能超过" + maxLength);
                } else if (excelReapeat.containsKey(osBtmTypePO.getName())) {//业务类型名在表格中判重
                    throw new VciBaseException("第【" + excelReapeat.get(osBtmTypePO.getName()) + "】行和第【" + osBtmTypePO.getRowIndex() + "】行数据,业务类型名重复");
                } else if (Func.isBlank(osBtmTypePO.getLifeCycle())) {
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,生命周期不能为空");
                } else if ("true".equalsIgnoreCase(osBtmTypePO.getRevInput()) && Func.isBlank(osBtmTypePO.getRevRuleName())) {
                    throw new VciBaseException("第【" + osBtmTypePO.getRowIndex() + "】行,版本号规则不能为空");
                }
                try {
                    BizType historyBtm = platformClientUtil.getBtmService().getBizTypeByName(osBtmTypePO.getName());
                    //已有此数据进行删除覆盖
                    if (historyBtm != null && !historyBtm.name.equals("")) {
                        platformClientUtil.getBtmService().deleteBizType(historyBtm);
                    }
                } catch (PLException e) {
                    throw new RuntimeException(e);
                }
                //属性名excel中判重处理
                excelReapeat.put(osBtmTypePO.getName(), osBtmTypePO.getRowIndex());
                BizType bizType = new BizType();
                bizType.name = osBtmTypePO.getName();
                bizType.label = osBtmTypePO.getLabel();
                bizType.description = osBtmTypePO.getDescription();
                bizType.fName = osBtmTypePO.getFName();
                bizType.implClass = osBtmTypePO.getImplClass();
                bizType.revLevel = osBtmTypePO.getRevLevel();
                bizType.revRuleName = osBtmTypePO.getRevRuleName();
                bizType.revInput = Boolean.parseBoolean(osBtmTypePO.getRevInput().toLowerCase(Locale.ROOT));
                bizType.delimiter = osBtmTypePO.getDelimiter();
                bizType.verRuleName = osBtmTypePO.getVerRuleName();
                bizType.imageName = osBtmTypePO.getImageName();
                bizType.lifeCycle = osBtmTypePO.getLifeCycle();
                bizType.lifeCycles = osBtmTypePO.getLifeCycles().split(",");
                bizType.apNameArray = osBtmTypePO.getApNameArray().split(",");
                String userId = WebUtil.getCurrentUserId();
                bizType.modifier = userId;
                bizType.creator = userId;
                try {
                    platformClientUtil.getBtmService().addBizType(bizType);
                } catch (PLException e) {
                    throw new RuntimeException(e);
                }
            });
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                logger.error("读取excel内容时或保存业务类型信息时出现了错误,具体原因:", VciBaseUtil.getExceptionMessage(e));
            }
            e.printStackTrace();
            return BaseResult.fail(VciBaseUtil.getExceptionMessage(e), new String[]{}, e);
        }
        //删除上传的文件夹
        FileUtil.del(defaultTempFolder + File.separator);
        return BaseResult.success("业务类型导入成功!");
    }
    /**
     * 获取需要修复的伪sql
     *
     * @param dbCheckMap
     * @return
     */
    private List<String> getRepairDML(Map<String, String> dbCheckMap) {
        List<String> list = new ArrayList<String>();
        for (Iterator<String> ite = dbCheckMap.keySet().iterator(); ite.hasNext(); ) {
            String type = ite.next();
            String dml = dbCheckMap.get(type);
            list.add(type + "/DML" + dml);
        }
        return list;
    }
    /**
     * 有实例:true 无实例:false
     *
     * @return
     */
    private boolean hasInstanceByBtmName(String btmName) throws PLException {
        //String tableName = OmdTools.getBTMTableName(btmName);
        //boolean flag = DDLToolClient.getService().hasInstanceOralce(tableName);
        boolean flag = false;
        try {
            flag = platformClientUtil.getBtmService().hasData(btmName);
        } catch (PLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            String exceptionMessage = VciBaseUtil.getExceptionMessage(e);
            logger.error(exceptionMessage);
            throw new PLException("500", new String[]{exceptionMessage});
        }
        return flag;
    }
    private List<Tree> getChildren(List<OsBtmTypeVO> osBtmTypeVOS, OsBtmTypeVO parentBIzType) {
        List<Tree> trees = new ArrayList<>();
        for (OsBtmTypeVO bizType : osBtmTypeVOS) {
            if (StringUtils.isBlank(bizType.getfName())) {
                continue;
            }
            if (bizType.getfName().equals(parentBIzType.getId())) {
                Tree tree = new Tree();
                tree.setOid(bizType.oid);
                tree.setParentName(parentBIzType.fName);
                tree.setParentId(parentBIzType.oid);
                tree.setOid(bizType.getOid());
                tree.setParentName(parentBIzType.getfName());
                tree.setParentId(parentBIzType.getOid());
                tree.setLeaf(true);
                tree.setText(bizType.description);
                tree.setIcon(bizType.getImageName());
                tree.setText(bizType.getDescription());
                tree.setAttributes(WebUtil.objectToMapString(bizType));
                tree.setChildren(getChildren(bizTypes,bizType));
                tree.setChildren(getChildren(osBtmTypeVOS, bizType));
                trees.add(tree);
            }
        }
@@ -636,12 +1637,12 @@
    /**
     * 将业务类型拼接json
     *
     * @param nodeVOList  对象节点的信息
     * @param relationVOList  关系的信息
     * @param btmTypeVO 业务类型显示对象
     * @param hasRefer 包含参照
     * @param nodeVOList     对象节点的信息
     * @param relationVOList 关系的信息
     * @param btmTypeVO      业务类型显示对象
     * @param hasRefer       包含参照
     */
    private void splicingBtmType2Json(List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList, OsBtmTypeVO btmTypeVO,boolean hasRefer) {
    private void splicingBtmType2Json(List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList, OsBtmTypeVO btmTypeVO, boolean hasRefer) {
        OsERNodeVO nodeVO = new OsERNodeVO();
        nodeVO.setKey(btmTypeVO.getId() + " " + btmTypeVO.getName());
        List<OsERNodePropertyVO> itemList = new ArrayList<>();
@@ -649,16 +1650,23 @@
            OsERNodePropertyVO nodePropertyVO = new OsERNodePropertyVO();
            nodePropertyVO.setName(attribute.getId() + " " + attribute.getName());
            nodePropertyVO.setKey("oid".equals(attribute.getId().toLowerCase()));
            if(StringUtils.isNotBlank(attribute.getReferBtmTypeId())){
            if (StringUtils.isNotBlank(attribute.getReferBtmTypeId())) {
                //参照的属性,设置为黄色
                nodePropertyVO.setColor("#FEDD32FF");
            }else{
            } else {
                nodePropertyVO.setColor("#000");
            }
            itemList.add(nodePropertyVO);
            //判断参照
            if(hasRefer) {
                selectReferenceBtmType(attribute, btmTypeVO, nodeVOList, relationVOList);
            if (hasRefer) {
                try {
                    selectReferenceBtmType(attribute, btmTypeVO, nodeVOList, relationVOList);
                } catch (PLException e) {
                    e.printStackTrace();
                    String exceptionMessage = "判断业务类型的属性是不是参照类型时出现错误,原因:"+VciBaseUtil.getExceptionMessage(e);
                    logger.error(exceptionMessage);
                    throw new VciBaseException(exceptionMessage);
                }
            }
        });
        nodeVO.setItems(itemList);
@@ -668,13 +1676,13 @@
    /**
     * 判断业务类型的属性是不是参照类型,并将参照添加到ER图中
     *
     * @param attribute     业务类型属性
     * @param nodeVOList  节点信息
     * @param btmTypeVO 业务类型
     * @param attribute      业务类型属性
     * @param nodeVOList     节点信息
     * @param btmTypeVO      业务类型
     * @param relationVOList 关系信息
     */
    private void selectReferenceBtmType(OsBtmTypeAttributeVO attribute, OsBtmTypeVO btmTypeVO,
                                        List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList) {
                                        List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList) throws PLException {
        if (StringUtils.isNotBlank(attribute.getReferBtmTypeId())) {
            //是参照类型的
            OsBtmTypeVO referenceBtmType = getBtmById(attribute.getReferBtmTypeId());
@@ -684,14 +1692,14 @@
            nodeVO.setKey(referenceBtmType.getId() + " " + referenceBtmType.getName());
            List<OsERNodePropertyVO> items = new ArrayList<>();
            if(referenceBtmType.getId().equalsIgnoreCase(btmTypeVO.getId())){
            if (referenceBtmType.getId().equalsIgnoreCase(btmTypeVO.getId())) {
                //参照自己的内容
                OsERRelationVO relationVO = new OsERRelationVO();
                relationVO.setTo(referenceBtmType.getId() + " " + referenceBtmType.getName());
                relationVO.setFrom(btmTypeVO.getId() + " " + btmTypeVO.getName());
                relationVO.setToText("自参照");
                relationVOList.add(relationVO);
            }else {
            } else {
                referenceBtmAttributes.forEach(attr -> {
                    OsERNodePropertyVO nodePropertyVO = new OsERNodePropertyVO();
                    nodePropertyVO.setName(attr.getId() + " " + attr.getName());
@@ -714,23 +1722,23 @@
    /**
     * 加载业务类型所关联的链接类型
     *
     * @param nodeVOList  节点信息
     * @param nodeVOList     节点信息
     * @param relationVOList 关系的信息
     * @param btmTypeVO    业务类型
     * @param btmTypeVO      业务类型
     */
    private void loadAllLinkTypeByBtmType(List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList, OsBtmTypeVO btmTypeVO) {
        Map<String, OsLinkTypeVO> linkTypeVOMap = linkTypeService.selectAllLinkMap();
        Collection<OsLinkTypeVO> linkTypeVOS = linkTypeVOMap.values();
        Set<OsLinkTypeVO> fromLinkTypeVOList = linkTypeVOS.stream().filter(link ->
            Arrays.stream(link.getFromBtmType().split(",")).anyMatch(s->s.equalsIgnoreCase(btmTypeVO.getId()))
                Arrays.stream(link.getFromBtmType().split(",")).anyMatch(s -> s.equalsIgnoreCase(btmTypeVO.getId()))
        ).collect(Collectors.toSet());
        Set<OsLinkTypeVO> toLinkTypeList = linkTypeVOS.stream().filter(link ->
                Arrays.stream(link.getToBtmType().split(",")).anyMatch(s->s.equalsIgnoreCase(btmTypeVO.getId()))).collect(Collectors.toSet());
                Arrays.stream(link.getToBtmType().split(",")).anyMatch(s -> s.equalsIgnoreCase(btmTypeVO.getId()))).collect(Collectors.toSet());
        List<OsLinkTypeVO> linkTypeVOList = new ArrayList<>();
        linkTypeVOList.addAll(fromLinkTypeVOList);
        linkTypeVOList.addAll(toLinkTypeList);
        if (!CollectionUtils.isEmpty(linkTypeVOList)) {
            splicingLinkType2Json(nodeVOList, relationVOList,linkTypeVOList,btmTypeVO,false);
            splicingLinkType2Json(nodeVOList, relationVOList, linkTypeVOList, btmTypeVO, false);
        }
    }
@@ -738,32 +1746,39 @@
    /**
     * 将链接类型拼接成json
     *
     * @param nodeVOList  节点信息
     * @param relationVOList  关系信息
     * @param linkTypeVOs 链接类型
     * @param btmTypeVO 业务类型的显示对象
     * @param used 是否为被使用
     * @param nodeVOList     节点信息
     * @param relationVOList 关系信息
     * @param linkTypeVOs    链接类型
     * @param btmTypeVO      业务类型的显示对象
     * @param used           是否为被使用
     */
    private void splicingLinkType2Json(List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList,
                                       List<OsLinkTypeVO> linkTypeVOs,OsBtmTypeVO btmTypeVO,boolean used) {
                                       List<OsLinkTypeVO> linkTypeVOs, OsBtmTypeVO btmTypeVO, boolean used) {
        linkTypeVOs.forEach(link -> {
            List<OsLinkTypeAttributeVO> attributeList = link.getAttributes();
            OsERNodeVO nodeVO= new OsERNodeVO();
            OsERNodeVO nodeVO = new OsERNodeVO();
            nodeVO.setKey(link.getId() + " " + link.getName());
            List<OsERNodePropertyVO> items = new ArrayList<>();
            attributeList.forEach(attr -> {
                OsERNodePropertyVO nodePropertyVO = new OsERNodePropertyVO();
                nodePropertyVO.setName(attr.getId() + " " + attr.getName());
                nodePropertyVO.setKey("oid".equals(attr.getId().toLowerCase()));
                if(StringUtils.isNotBlank(attr.getReferBtmTypeId())) {
                if (StringUtils.isNotBlank(attr.getReferBtmTypeId())) {
                    nodePropertyVO.setColor("#FEDD32FF");
                }else {
                } else {
                    nodePropertyVO.setColor("#1c446f");
                }
                items.add(nodePropertyVO);
                //判断参照
                if(!used) {
                    selectReferenceLinkType(attr, link, nodeVOList, relationVOList);
                if (!used) {
                    try {
                        selectReferenceLinkType(attr, link, nodeVOList, relationVOList);
                    } catch (PLException e) {
                        e.printStackTrace();
                        String exceptionMessage = "断链接类型的属性是不是参照类型时出现错误,原因:"+VciBaseUtil.getExceptionMessage(e);
                        logger.error(exceptionMessage);
                        throw new VciBaseException(exceptionMessage);
                    }
                }
            });
            nodeVO.setItems(items);
@@ -774,26 +1789,26 @@
            nodeVOList.add(nodeVO);
            if(used){
            if (used) {
                relationVO.setText("被引用");
            }
            //如果当前的from端,那么就显示to端的
            //如果当前的是to端的,那么就显示from端的内容
            if(Arrays.stream(link.getFromBtmType().split(",")).anyMatch(s->s.equalsIgnoreCase(btmTypeVO.getId()))){
            if (Arrays.stream(link.getFromBtmType().split(",")).anyMatch(s -> s.equalsIgnoreCase(btmTypeVO.getId()))) {
                //这个是from端
               if(!used) {
                   relationVO.setToText("from端");
               }
                if (!used) {
                    relationVO.setToText("from端");
                }
                //找这个链接类型的to端的业务类型
               link.getToBtmTypeVOS().stream().forEach(toBtm->{
                    splicingBtmType2JsonForLink(nodeVOList,relationVOList,link,toBtm,true);
               });
            }else{
                if(!used) {
                link.getToBtmTypeVOS().stream().forEach(toBtm -> {
                    splicingBtmType2JsonForLink(nodeVOList, relationVOList, link, toBtm, true);
                });
            } else {
                if (!used) {
                    relationVO.setToText("to端");
                }
                link.getFromBtmTypeVOS().stream().forEach(fromBtm->{
                    splicingBtmType2JsonForLink(nodeVOList,relationVOList,link,fromBtm,false);
                link.getFromBtmTypeVOS().stream().forEach(fromBtm -> {
                    splicingBtmType2JsonForLink(nodeVOList, relationVOList, link, fromBtm, false);
                });
            }
            relationVOList.add(relationVO);
@@ -802,11 +1817,12 @@
    /**
     * 链接类型关键的业务类型
     * @param nodeVOList 对象列表
     *
     * @param nodeVOList     对象列表
     * @param relationVOList 关联关系列表
     * @param link 链接类型
     * @param btmTypeVO 业务类型
     * @param to 是否为to端
     * @param link           链接类型
     * @param btmTypeVO      业务类型
     * @param to             是否为to端
     */
    private void splicingBtmType2JsonForLink(List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList, OsLinkTypeVO link, OsBtmTypeVO btmTypeVO, boolean to) {
        OsERNodeVO nodeVO = new OsERNodeVO();
@@ -824,7 +1840,7 @@
        OsERRelationVO relationVO = new OsERRelationVO();
        relationVO.setFrom(link.getId() + " " + link.getName());
        relationVO.setTo(btmTypeVO.getId() + " " + btmTypeVO.getName());
        relationVO.setToText(to?"to端":"from端");
        relationVO.setToText(to ? "to端" : "from端");
        relationVOList.add(relationVO);
        nodeVOList.add(nodeVO);
    }
@@ -832,12 +1848,12 @@
    /**
     * 判断链接类型的属性是不是参照类型,并将参照添加到ER图中
     *
     * @param attr          链接类型的属性
     * @param linkTypeVO 链接类型的内容
     * @param nodeVOList 节点对象
     * @param attr           链接类型的属性
     * @param linkTypeVO     链接类型的内容
     * @param nodeVOList     节点对象
     * @param relationVOList 关系对象
     */
    private void selectReferenceLinkType(OsLinkTypeAttributeVO attr, OsLinkTypeVO linkTypeVO,List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList) {
    private void selectReferenceLinkType(OsLinkTypeAttributeVO attr, OsLinkTypeVO linkTypeVO, List<OsERNodeVO> nodeVOList, List<OsERRelationVO> relationVOList) throws PLException {
        if (StringUtils.isNotBlank(attr.getReferBtmTypeId())) {
            //是参照类型的
            OsBtmTypeVO referenceBtmType = getBtmById(attr.getReferBtmTypeId());
@@ -864,4 +1880,265 @@
        }
    }
    /**
     * 封装删除全部类型相关的查询方法的内部类
     */
    private class DeleteType {
        private List<String> exceptBts, exceptAbs, exceptEnums, exceptRev, exceptLCs, exceptStates;
        {
            exceptBts.add("workitem");
            exceptBts.add(FileObjectType.FILE_DATA_TABLE);
        }
        /**
         * 获取需要删除的业务类型
         *
         * @return
         */
        public List<BizType> getDelBtList() throws PLException {
            List<BizType> list = new ArrayList<>();
            BizType[] bts = platformClientUtil.getBtmService().getBizTypes("");
            for (BizType bt : bts) {
                boolean exceptFlag = false;
                for (String except : exceptBts) {
                    if (except.equalsIgnoreCase(bt.name)) {
                        exceptFlag = true;
                        break;
                    }
                }
                if (!exceptFlag) {
                    list.add(bt);
                }
            }
            return list;
        }
        /**
         * 获取需要删除的链接类型
         *
         * @return
         */
        public List<LinkType> getDelLtList() throws PLException {
            LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes();
            return Arrays.asList(linkTypes);
        }
        /**
         * 获取待删除的属性
         *
         * @return
         */
        public List<String> getDelAbList() {
            List<String> list = new ArrayList<String>();
            AttributeDef[] attribItems = null;
            try {
                attribItems = platformClientUtil.getAttributeService().getAttributeDefs("", 0, 0);
            } catch (PLException e) {
                e.printStackTrace();
            }
            //依据保留的类型构造保留的属性
            exceptAbs = new ArrayList<String>();
            for (String except : exceptBts) {
                String[] btmApNameArray = null;
                try {
                    btmApNameArray = platformClientUtil.getBtmService().getAttributeNames(except);
                } catch (PLException e) {
                    e.printStackTrace();
                }
                if (btmApNameArray != null) {
                    for (String abName : btmApNameArray) {
                        if (!exceptAbs.contains(abName)) {
                            exceptAbs.add(abName);
                        }
                    }
                }
            }
            //构造可删除的属性
            if (attribItems != null) {
                for (AttributeDef ab : attribItems) {
                    String abName = ab.name;
                    if (!exceptAbs.contains(abName)) {
                        list.add(abName);
                    }
                }
            }
            return list;
        }
        /**
         * 获取待删除的枚举类型
         *
         * @return
         */
        public List<EnumType> getDelEnumList() {
            List<EnumType> list = new ArrayList<EnumType>();
            try {
                //依据保留的类型构造保留的属性
                exceptEnums = new ArrayList<String>();
                EnumType[] emItems = ClientServiceProvider.getOMDService().getEnumService().getEnumTypes("", 0, 0);
                AttributeDef[] abs = platformClientUtil.getAttributeService().getAttributeDefsByNames(exceptAbs.toArray(new String[0]));
                for (AttributeDef ab : abs) {
                    OtherInfo otherInfo = OtherInfo.getOtherInfoByText(ab.other);
                    String enumName = otherInfo.getEnumName();
                    if (enumName != null && !enumName.equals("") && !exceptEnums.contains(enumName)) {
                        exceptEnums.add(enumName);
                    }
                }
                for (EnumType em : emItems) {
                    if (!exceptEnums.contains(em.name)) {
                        list.add(em);
                    }
                }
            } catch (PLException e) {
                e.printStackTrace();
            }
            return list;
        }
        /**
         * 获取待删除的生命周期
         *
         * @return
         */
        public List<LifeCycle> getDelLCList() {
            List<LifeCycle> list = new ArrayList<LifeCycle>();
            exceptLCs = new ArrayList<String>();
            exceptStates = new ArrayList<String>();
            for (String btName : exceptBts) {
                try {
                    BizType bt = platformClientUtil.getBtmService().getBizTypeByName(btName);
                    String lcName = bt.lifeCycle;
                    if (lcName != null && !lcName.equals("") && !exceptLCs.contains(lcName)) {
                        exceptLCs.add(lcName);
                    }
                } catch (PLException e) {
                    e.printStackTrace();
                }
            }
            LifeCycle[] lcs = null;
            try {
                lcs = platformClientUtil.getLifeCycleService().getLifeCycles();
            } catch (PLException e) {
                e.printStackTrace();
            }
            if (lcs != null) {
                for (LifeCycle lc : lcs) {
                    String name = lc.name;
                    if (name != null && !name.equals("") && !exceptLCs.contains(name)) {
                        list.add(lc);
                    } else {
                        //保留的状态池
                        Bound[] bounds = lc.bounds;
                        for (Bound bound : bounds) {
                            String sName = bound.name;
                            exceptStates.add(sName);
                        }
                    }
                }
            }
            return list;
        }
        /**
         * 获取待删除的状态
         *
         * @return
         */
        public List<StatePool> getDelSPList() {
            List<StatePool> list = new ArrayList<StatePool>();
            StatePool[] states = null;
            try {
                states = platformClientUtil.getStatePoolService().getStatePools();
            } catch (PLException e) {
                e.printStackTrace();
            }
            if (states != null) {
                for (StatePool state : states) {
                    String name = state.name;
                    if (name != null && !name.equals("") && !exceptStates.contains(name)) {
                        list.add(state);
                    }
                }
            }
            return list;
        }
        /**
         * 获取待删除的版本规则
         *
         * @return
         */
        public List<VersionRule> getDelVRList() {
            List<VersionRule> list = new ArrayList<VersionRule>();
            exceptRev = new ArrayList<String>();
            for (String btName : exceptBts) {
                try {
                    BizType bt = platformClientUtil.getBtmService().getBizTypeByName(btName);
                    String revName = bt.revRuleName;
                    if (revName != null && !revName.equals("") && !exceptRev.contains(revName)) {
                        exceptRev.add(revName);
                    }
                } catch (PLException e) {
                    e.printStackTrace();
                }
            }
            VersionRule[] revs = null;
            try {
                revs = platformClientUtil.getVersionService().getVersionRules();
            } catch (PLException e) {
                e.printStackTrace();
            }
            if (revs != null) {
                for (VersionRule rev : revs) {
                    String name = rev.name;
                    if (name != null && !name.equals("") && !exceptRev.contains(name)) {
                        list.add(rev);
                    }
                }
            }
            return list;
        }
    }
    private class BtmDataFetcher {
        //业务类型
        private Map<String, BizType> btmTypeVOMap = new HashMap<String, BizType>();
        public BtmDataFetcher() {
            initBtmDataFetcher();
        }
        private void initBtmDataFetcher(){
            try {
                BizType[] bizTypes = platformClientUtil.getBtmService().getBizTypes("");
                //List<OsBtmTypeVO> osBtmTypeVOS = btmDO2VOs(Arrays.asList(bizTypes), null);
                if(Func.isNotEmpty(bizTypes)){
                    btmTypeVOMap = Arrays.stream(bizTypes).collect(Collectors.toMap(btm -> btm.name, btm -> btm));
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        /**
         * 获取业务类型
         * @param id
         * @return
         */
        public OsBtmTypeVO getBtmType(String id) {
            BizType bizType = btmTypeVOMap.get(id);
            if(Func.isEmpty(bizType)){
                return null;
            }
            //获取的时候才赚VO对象,这样避免一次性全部Btm转VO太慢的问题
            return btmDO2VO(bizType,null);
        }
    }
}