Source/plt-web/plt-web-parent/plt-web/src/main/java/com/vci/web/service/impl/OsLinkTypeServiceImpl.java
@@ -1,16 +1,34 @@
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.common.qt.object.QTConstants;
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.BusinessObject;
import com.vci.corba.omd.ltm.LinkType;
import com.vci.model.OsLinkTypeDO;
import com.vci.omd.constants.AttributeConstants;
import com.vci.omd.utils.ObjectTool;
import com.vci.pagemodel.*;
import com.vci.po.OsLinkTypePO;
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.VciFieldTypeEnum;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.BaseQueryObject;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.util.BeanUtil;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import com.vci.web.model.OsLinkTypeDO;
import com.vci.web.pageModel.*;
import com.vci.starter.web.util.*;
import com.vci.starter.web.util.Lcm.Func;
import com.vci.web.service.*;
import com.vci.web.util.PlatformClientUtil;
import com.vci.web.util.WebUtil;
@@ -21,23 +39,38 @@
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.*;
import java.util.stream.Collectors;
/**
 * 链接类型服务
 * @author weidy
 * @date 2021-2-15
 * @date 2024-2-15
 */
@Service
public class OsLinkTypeServiceImpl implements OsLinkTypeServiceI {
    private static final String OID = "oid";
    private static final String NAME = "name";
    private static final String LABEL = "label";
    private static final String DESCRIPTION = "description";
    private static final String TS = "ts";
    private static final String CREATOR = "creator";
    private static final String CREATETIME = "createTime";
    private static final String MODIFIER = "modifier";
    private static final String MODIFYTIME = "modifyTime";
    /**
     * 日志
     */
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 平台的调用工具类
@@ -140,7 +173,7 @@
            }
            vo.setDescription(linkType.description);
            vo.setId(linkType.name);
            vo.setName(linkType.tag);
            vo.setName(linkType.label);
            vo.setFromBtmTypeVOS(btmService.listBtmByIds(Arrays.stream(linkType.btmItemsFrom).collect(Collectors.toSet())));
            if(!CollectionUtils.isEmpty(vo.getFromBtmTypeVOS())){
                vo.setFromBtmType(Arrays.stream(linkType.btmItemsFrom).collect(Collectors.joining(",")));
@@ -157,7 +190,7 @@
            List<OsLinkTypeAttributeVO> linkTypeAttributeVOS = new ArrayList<>();
            Optional.ofNullable(attributeVOS).orElseGet(()->new ArrayList<>()).stream().forEach(attributeVO->{
                OsLinkTypeAttributeVO linkTypeAttributeVO = new OsLinkTypeAttributeVO();
                BeanUtil.convert(attributeVO,linkTypeAttributeVO);
                BeanUtilForVCI.convert(attributeVO,linkTypeAttributeVO);
                linkTypeAttributeVO.setPkLinkType(vo.getOid());
                if(StringUtils.isNotBlank(attributeVO.getBtmTypeId())){
                    linkTypeAttributeVO.setReferFlag(true);
@@ -202,11 +235,12 @@
     * @return 链接类型
     */
    @Override
    public OsLinkTypeVO getLinkTypeById(String id) {
    public OsLinkTypeVO getLinkTypeById(String id) throws PLException {
        if(StringUtils.isBlank(id)){
            return null;
        }
        return self.selectAllLinkMap().getOrDefault(id.toLowerCase(),null);
        LinkType linkType = platformClientUtil.getLinkTypeService().getLinkType(id);
        return this.linkTypeDO2VO(linkType);
    }
    /**
@@ -216,7 +250,7 @@
     * @return 链接类型的属性
     */
    @Override
    public List<OsLinkTypeAttributeVO> listAttributeByLinkId(String linkTypeId) {
    public List<OsLinkTypeAttributeVO> listAttributeByLinkId(String linkTypeId) throws PLException {
        OsLinkTypeVO linkTypeVO = getLinkTypeById(linkTypeId);
        return linkTypeVO.getAttributes();
    }
@@ -270,17 +304,17 @@
                    "inner JOIN user_col_comments c on t.TABLE_NAME  = c.table_name and t.COLUMN_NAME = c.column_name where " +
                    "t.table_name = '" + VciBaseUtil.getTableName(btmTypeVO.getId()).toUpperCase(Locale.ROOT) + "' order by t.column_name asc";
            Map<String, OsBtmTypeAttributeVO> attributeVOMap = btmTypeVO.getAttributes().stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
            List<com.vci.client.bof.ClientBusinessObject> cbosList = boService.queryBySql(sql, new HashMap<>());
            List<BusinessObject> cbosList = boService.queryBySql(sql, new HashMap<>());
            if(!CollectionUtils.isEmpty(cbosList)){
                cbosList.stream().forEach(cbo->{
                    String attrId = cbo.getAttributeValue("column_name");
                    String dataType = cbo.getAttributeValue("data_type");
                    String attrId = ObjectTool.getBOAttributeValue(cbo,"column_name");
                    String dataType = ObjectTool.getBOAttributeValue(cbo,"data_type");
                    if(StringUtils.isNotBlank(dataType) && dataType.contains("(")){
                        dataType = dataType.substring(0,dataType.indexOf("("));
                    }
                    OsBtmTypeAttributeVO attributeVO = attributeVOMap.getOrDefault(attrId.toLowerCase(Locale.ROOT), null);
                    if(attributeVO!=null){
                        String vtType = attributeVO.getAttrDataType();
                        String vtType = attributeVO.getAttributeDataType();
                        String attrType = "";
                        VciFieldTypeEnum fieldTypeEnum = VciFieldTypeEnum.forValue(vtType);
                        if(fieldTypeEnum == null) {
@@ -319,10 +353,704 @@
    }
    /**
     * 链接类型的列表
     *
     * @return 链接类型的显示对象
     */
    @Override
    public BaseResult<List<LinkType>> gridLink() throws PLException {
        LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes();
        return BaseResult.dataList(Arrays.asList(linkTypes));
    }
    /**
     * 链接类型保存
     * linkType 链接类型的保存对象
     * addFlag 是否为新增 true新增,false修改
     * @return 保存结果
     */
    @Override
    public BaseResult addAndEditLink(LinkType linkType, Boolean addFlag) throws PLException {
        VciBaseUtil.alertNotNull(linkType.name,"请输入链接类型名称",linkType.btmItemsFrom,"From端业务类型不能为空!",
                linkType.btmItemsTo,"To端类型均不能为空!");
        int maxLength = platformClientUtil.getLinkTypeService().getLTNameMaxLength();
        if(linkType.name.length() > maxLength){
            throw new PLException("500",new String[] {"链接类型名长度不能超过" + maxLength});
        }
        if(!linkType.name.matches("^[A-Za-z]+$")){
            throw new PLException("500",new String[] {"链接类型名称只能为英文字母"});
        }
        LinkType historyLink = platformClientUtil.getLinkTypeService().getLinkType(linkType.name);
        if(historyLink != null && !historyLink.name.equals("") && addFlag){
            throw new PLException("500",new String[] {"该链接类型名称已经存在"});
        }
        linkType.modifier = WebUtil.getCurrentUserId();
        if(addFlag){
            linkType.creator = WebUtil.getCurrentUserId();
            platformClientUtil.getLinkTypeService().addLinkType(linkType);
            return BaseResult.success(null,"保存成功!");
        }
        ArrayList<String> removeAbList = getRemovedApList(historyLink, linkType);
        if(removeAbList.size() > 0 && platformClientUtil.getLinkTypeService().hasData(linkType.name)){
            linkType.attributes = historyLink.attributes;
            platformClientUtil.getLinkTypeService().modifyLinkType(linkType);
            throw new PLException("500",new String[] {"类型已有实例, 不进行移除操作"});
        }
        platformClientUtil.getLinkTypeService().modifyLinkType(linkType);
        return BaseResult.success(null,"保存成功!");
    }
    /**
     * 链接类型删除
     * linkType 链接类型对象
     * @return 删除结果
     */
    @Override
    public BaseResult deleteLink(LinkType linkType) throws PLException {
        if(platformClientUtil.getLinkTypeService().hasData(linkType.name)){
            throw new PLException("500",new String[] {"类型已有实例, 不进行删除操作"});
        }
        boolean flag = platformClientUtil.getLinkTypeService().deleteLinkType(linkType);
        if(!flag){
            throw new PLException("500",new String[] {"删除失败"});
        }else{
            return BaseResult.success();
        }
    }
    /**
     * 一致性检查
     * @return 删除结果
     */
    @Override
    public BaseResult checkLinkType() throws PLException {
        String[] result = platformClientUtil.getLinkTypeService().linkTypeConsistencyCheck();
        Map<String, String> dbCheckMap = new HashMap<String, String>();
        for(int i = 0; i < result.length; i++){
            String info = result[i];
            if(info.equals("")){
                continue;
            }
            String[] infos = info.split("/DML");
            String typeName = infos[0];
            String dml = infos[1];
            dbCheckMap.put(typeName, dml);
        }
        Map<String, List<String>> btmCheckMap = usedBtmCheck();
        if(dbCheckMap.size() < 1 && (btmCheckMap == null || btmCheckMap.size() < 1)){
            return BaseResult.successMsg("数据库中的表结构与类型一致, 链接类型引用的业务类型全部正确存在,无需修复!!");
        }else{
            Map<String,Object> returnData = new HashMap<>();
            returnData.put("dbCheckMap",dbCheckMap);
            returnData.put("btmCheckMap",btmCheckMap);
            List<Map> list = new ArrayList<>();
            list.add(returnData);
            BaseResult<List<Map>> listBaseResult = BaseResult.dataList(200, list, "需要进行列的修复!!");
            listBaseResult.setSuccess(false);
            return listBaseResult;
        }
    }
    /**
     * 一致性检查修复数据库表
     * repairData 需要修复的数据
     * @return 修复结果
     */
    @Override
    public BaseResult repairTable(String repairData) throws PLException, IOException {
        Map<String, Object> map = new ObjectMapper().readValue(repairData, new TypeReference<Map<String,Object>>(){});
        HashMap<String,Object> dbCheckMap = (HashMap<String, Object>) map.get("dbCheckMap");
        HashMap<String,List<String>> btmCheckMap = (HashMap<String, List<String>>) map.get("btmCheckMap");
        List returnList = new ArrayList<>();
        Map returnMap = new HashMap();
        if(dbCheckMap.size() > 0){
            List<String> list = getRepairDML(dbCheckMap);
            if(list.size() < 1){
                return BaseResult.success();
            }
            String[] result = platformClientUtil.getLinkTypeService().executeRepair(list.toArray(new String[0]));
            List<String> resultList = Arrays.asList(result);
            for (String typeName : resultList) {
                if(dbCheckMap.containsKey(typeName)){
                    dbCheckMap.remove(typeName);
                }else if(dbCheckMap.containsKey(typeName + "_ADD")){
                    String sql = String.valueOf(dbCheckMap.get(typeName));
                    sql = sql.substring(sql.indexOf(";") + 1, sql.length());
                    dbCheckMap.put(typeName, sql);
                }else if(dbCheckMap.containsKey(typeName + "_DROP")){
                    String sql = String.valueOf(dbCheckMap.get(typeName));
                    sql = sql.substring(0, sql.indexOf(";"));
                    dbCheckMap.put(typeName, sql);
                }
            }
            if(!dbCheckMap.isEmpty()){
                returnMap.put("dbCheckMap",dbCheckMap);
            }
        }
        if(btmCheckMap.size() > 0){
            List<String> result = repairXml(btmCheckMap);
            for(int i = 0; i < result.size(); i++){
                String typeName = result.get(i);
                if(btmCheckMap.containsKey(typeName)){
                    btmCheckMap.remove(typeName);
                }
            }
            if(!btmCheckMap.isEmpty()){
                returnMap.put("btmCheckMap",btmCheckMap);
            }
        }
        returnList.add(returnMap);
        return BaseResult.success(returnList);
    }
    /**
     * 创建视图
     * @return 创建结果
     */
    @Override
    public BaseResult createView() throws PLException {
        boolean f = platformClientUtil.getLinkTypeService().createView();
        if(f){
            return BaseResult.success("创建视图成功");
        }else{
            return BaseResult.success("创建视图失败");
        }
    }
    /**
     * 导出链接类型
     * name 链接类型名称
     * @return 创建结果
     */
    @Override
    public void expData(String names, HttpServletResponse response) throws PLException, IOException {
        String defaultTempFolder = LocalFileUtil.getDefaultTempFolder();
        //写excel
        String excelPath = defaultTempFolder + File.separator + "lt.xls";
        //设置列名
        List<String> columns = new ArrayList<>(
                Arrays.asList("名称", "标签", "实现类", "形状", "From端类型列表", "From端主类型", "From端对应关系",
                        "To端类型列表", "To端主类型", "To端对应关系", "属性列表", "描述")
        );
        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(",")) {
                LinkType lt = platformClientUtil.getLinkTypeService().getLinkType(name);
                excelDataList.add(new WriteExcelData(i+1,0, lt.name));
                excelDataList.add(new WriteExcelData(i+1,1, lt.label));
                excelDataList.add(new WriteExcelData(i+1,2, lt.implClass));
                excelDataList.add(new WriteExcelData(i+1,3, lt.shape));
                excelDataList.add(new WriteExcelData(i+1,4, String.join(",",lt.btmItemsFrom)));
                excelDataList.add(new WriteExcelData(i+1,5, lt.primitivesFrom));
                excelDataList.add(new WriteExcelData(i+1,6, lt.relationFrom));
                excelDataList.add(new WriteExcelData(i+1,7, String.join(",",lt.btmItemsTo)));
                excelDataList.add(new WriteExcelData(i+1,8, lt.primitivesTo));
                excelDataList.add(new WriteExcelData(i+1,9, lt.relationTo));
                excelDataList.add(new WriteExcelData(i+1,10, String.join(",",lt.attributes)));
                excelDataList.add(new WriteExcelData(i+1,11, lt.description));
                attributes.addAll(Arrays.asList(lt.attributes));
                i++;
            }
            WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
            ExcelUtil.writeDataToFile(excelPath, excelOption);
            //导出属性
            String attrPath = attributeService.exportAttributes("attr",
                    String.valueOf(attributes.stream().collect(Collectors.joining(","))),true);
            //移动属性到链接类型文件夹里面去
            FileUtil.move(new File(attrPath), new File(defaultTempFolder),true);
            FileUtil.del(attrPath.substring(0,attrPath.lastIndexOf("\\")));
            //todo 导出业务类型还没有实现
//            List<BizType> bts = new ArrayList<BizType>();
//            for (String btName : btNameSet) {
//                BizType bt = BtmProvider.getBtmItemByName(btName);
//                bts.add(bt);
//            }
//            boolean btFlag = BtmProvider.expData(rootPath, bts.toArray(new BizType[0]));
        }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")) {
            throw new VciBaseException("仅能上传zip压缩文件,请重新上传!");
        }
        File unzip = ZipUtil.unzip(fileName);
        File ltExcel = new File(unzip.getAbsolutePath() + File.separator + "lt.xls");
        File attrExcel = new File(unzip.getAbsolutePath() + File.separator + "attr.xls");
        if (!attrExcel.exists()) {
            //增加解压的路径,看文件还在没有
            attrExcel = new File(unzip.getAbsolutePath() + File.separator + unzip.getName() + File.separator + "attr.xls");
            if (!attrExcel.exists()) {
                return BaseResult.fail(FrameWorkLangCodeConstant.IMPORT_FAIL, new String[]{"没有导入的属性文件。导入终止!"});
            }
        }
        BaseResult baseResult = attributeService.importAttributes(attrExcel,true);
        if(!baseResult.isSuccess()){
            //删除上传的文件夹
            FileUtil.del(defaultTempFolder + File.separator);
            return baseResult;
        }
        //todo 还需导入业务类型,等待功能实现
        if (!ltExcel.exists()) {
            //增加解压的路径,看文件还在没有
            ltExcel = new File(unzip.getAbsolutePath() + File.separator + unzip.getName() + File.separator + "lt.xls");
            if (!ltExcel.exists()) {
                //删除上传的文件夹
                FileUtil.del(defaultTempFolder + File.separator);
                return BaseResult.fail(FrameWorkLangCodeConstant.IMPORT_FAIL, new String[]{"没有导入的链接文件。导入终止!"});
            }
        }
        try{
            //1、读取excel中的数据,组成对象
            ReadExcelOption excelOption = new ReadExcelOption();
            List<OsLinkTypePO> poList = ExcelUtil.readDataObjectFromExcel(ltExcel, OsLinkTypePO.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(osLinkTypePO -> {
                if(Func.isBlank(osLinkTypePO.getName())){//属性名判空
                    throw new VciBaseException("第【"+osLinkTypePO.getRowIndex()+"】行,name");
                }else if(osLinkTypePO.getName().length() > maxLength){
                    throw new VciBaseException("第【"+osLinkTypePO.getRowIndex()+"】行,链接类型名长度不能超过" + maxLength);
                }else if(!osLinkTypePO.getName().matches("^[A-Za-z]+$")){
                    throw new VciBaseException("第【"+osLinkTypePO.getRowIndex()+"】行,链接类型名称只能为英文字母");
                }else if(excelReapeat.containsKey(osLinkTypePO.getName())){//属性名表格中判重
                    throw new VciBaseException("第【"+excelReapeat.get(osLinkTypePO.getName())+"】行和第【"+osLinkTypePO.getRowIndex()+"】行数据,链接类型名重复");
                }
                try {
                    LinkType historyLink = platformClientUtil.getLinkTypeService().getLinkType(osLinkTypePO.getName());
                    //已有此数据进行删除覆盖
                    if(historyLink != null && !historyLink.name.equals("")){
                        platformClientUtil.getLinkTypeService().deleteLinkType(historyLink);
                    }
                } catch (PLException e) {
                    throw new RuntimeException(e);
                }
                //属性名excel中判重处理
                excelReapeat.put(osLinkTypePO.getName(),osLinkTypePO.getRowIndex());
                LinkType linkType = new LinkType();
                linkType.name = osLinkTypePO.getName();
                linkType.attributes = osLinkTypePO.getAttributes().split(",");
                linkType.btmItemsFrom = osLinkTypePO.getBtmItemsFrom().split(",");
                linkType.primitivesFrom = osLinkTypePO.getPrimitivesFrom();
                linkType.relationFrom = osLinkTypePO.getRelationFrom();
                linkType.btmItemsTo = osLinkTypePO.getBtmItemsTo().split(",");
                linkType.primitivesTo = osLinkTypePO.getPrimitivesTo();
                linkType.relationTo = osLinkTypePO.getRelationTo();
                linkType.relation = osLinkTypePO.getRelationFrom() + ":" + osLinkTypePO.getRelationTo();
                linkType.description = osLinkTypePO.getDescription();
                linkType.label = osLinkTypePO.getTag();
                linkType.shape = osLinkTypePO.getShape();
                linkType.implClass = osLinkTypePO.getImplClass();
                linkType.modifier = WebUtil.getCurrentUserId();
                linkType.creator = WebUtil.getCurrentUserId();
                try {
                    platformClientUtil.getLinkTypeService().addLinkType(linkType);
                } 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("链接类型导入成功!");
    }
    /**
     * 获取链接类型包含的属性
     * @param name 链接类型的编号
     * @return 属性的信息
     */
    @Override
    public List<OsLinkTypeAttributeVO> getAllAttributeByLink(String name) throws PLException, ParseException {
        AttributeDef[] attributes = platformClientUtil.getLinkTypeService().getAttributes(name);
        Map<String, AttributeDef> collect = Arrays.stream(platformClientUtil.getLinkTypeService().getSysAttributeDefs())
                .collect(Collectors.toMap(str -> str.name, str -> str));
        List<OsLinkTypeAttributeVO> links = new ArrayList<>();
        String[] sysAttibutes = { "OID", "Creator", "CreateTime", "LastModifier", "LASTMODIFYTIME", "F_OID",
                "F_REVISIONOID", "F_NAMEOID", "F_BtwName", "T_OID", "T_REVISIONOID", "T_NAMEOID", "T_BtwName", "TS" };
        for (String sysname : sysAttibutes) {
            AttributeDef sysAttributeDef = collect.get(sysname.toLowerCase());
            OsLinkTypeAttributeVO vo = new OsLinkTypeAttributeVO();
            vo.setOid(sysAttributeDef.oid);
            vo.setAttrDataType(sysAttributeDef.vtDataType);
            vo.setPkLinkType(name);
            vo.setCreateTime(new Date(sysAttributeDef.createTime));
            vo.setCreator(sysAttributeDef.creator);
            vo.setDefaultValue(sysAttributeDef.defValue);
            vo.setDescription(sysAttributeDef.description);
            vo.setRange(sysAttributeDef.rage);
            vo.setId(sysname);
            vo.setName(sysAttributeDef.label);
            vo.setLastModifier(sysAttributeDef.modifier);
            vo.setLastModifyTime(new Date(sysAttributeDef.modifyTime));
            links.add(vo);
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (AttributeDef attribute : attributes) {
            OsLinkTypeAttributeVO vo = new OsLinkTypeAttributeVO();
            vo.setOid(attribute.oid);
            vo.setAttrDataType(attribute.vtDataType);
            vo.setPkLinkType(name);
            vo.setCreateTime(new Date(attribute.createTime));
            vo.setCreator(attribute.creator);
            vo.setDefaultValue(attribute.defValue);
            vo.setDescription(attribute.description);
            vo.setRange(attribute.rage);
            vo.setId(attribute.name);
            vo.setName(attribute.label);
            vo.setTs(formatter.parse(attribute.ts));
            vo.setLastModifier(attribute.modifier);
            vo.setOwner(attribute.creator);
            vo.setLastModifyTime(new Date(attribute.modifyTime));
            String maxLength = AttributeConstants.getOtherValueByType(attribute.other, AttributeConstants.LENGTH);
            if(StringUtils.isNotBlank(maxLength)){
                vo.setAttributeLength(Integer.valueOf(maxLength));
            }
            links.add(vo);
        }
        return links;
    }
    /**
     * 获取设置排序字段的排序字段
     * @param linkType 链接类型的编号
     * @param btmType 业务类型的编号
     * @param direction 正/反向
     * @return 属性的信息
     */
    @Override
    public List<String> getAllOrderbyAttributeByLink(String linkType, String btmType, String direction) throws PLException, ParseException {
        List<String> abNames = new ArrayList<>(Arrays.asList("OID", "Creator", "CreateTime", "LastModifier", "LASTMODIFYTIME", "F_OID",
                "F_REVISIONOID", "F_NAMEOID", "F_BtwName", "T_OID", "T_REVISIONOID", "T_NAMEOID", "T_BtwName", "TS" ));
        AttributeDef[] attributes = platformClientUtil.getLinkTypeService().getAttributes(linkType);
        for (AttributeDef attribute : attributes) {
            abNames.add(String.valueOf(attribute.name));
        }
        String wrapper = "T_OID.";
        if(direction.equals(QTConstants.DIRECTION_OPPOSITE)){
            wrapper = "F_OID.";
        }
        List<OsBtmTypeAttributeVO> bizTypeQTDs = btmService.getBizTypeQTDs(btmType);
        for (OsBtmTypeAttributeVO bizTypeQTD : bizTypeQTDs) {
            abNames.add(wrapper + bizTypeQTD.getId());
        }
        return abNames;
    }
    /**
     * 修复链接类型的xml文件
     * @return
     */
    private List<String> repairXml(HashMap<String, List<String>> btmCheckMap){
        List<String> result = new ArrayList<String>();
        for(Iterator<String> ite = btmCheckMap.keySet().iterator(); ite.hasNext();){
            String linkName = ite.next();
            List<String> list = btmCheckMap.get(linkName);
            LinkType link = null;
            try {
                link = platformClientUtil.getLinkTypeService().getLinkType(linkName);
            } catch (PLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                continue;
            }
            //将list中包含的F_btm移除, 重新设置btmItemsFrom
            String[] btms_ = link.btmItemsFrom;
            List<String> btms = new ArrayList<String>();
            for(int i = 0; i < btms_.length; i++){
                if(!list.contains("F_" + btms_[i])){
                    btms.add(btms_[i]);
                }else{
                    if(link.primitivesFrom.equals(btms_[i])){
                        link.primitivesFrom = "";
                    }
                }
            }
            link.btmItemsFrom = btms.toArray(new String[0]);
            //将list中包含的T_btm移除, 重新设置btmItemsTo
            btms_ = link.btmItemsTo;
            btms = new ArrayList<String>();
            for(int i = 0; i < btms_.length; i++){
                if(!list.contains("T_" + btms_[i])){
                    btms.add(btms_[i]);
                }else{
                    if(link.primitivesTo.equals(btms_[i])){
                        link.primitivesTo = "";
                    }
                }
            }
            link.btmItemsTo = btms.toArray(new String[0]);
            link.id = link.name;
            try {
                if(platformClientUtil.getLinkTypeService().modifyLinkType(link)){
                    result.add(linkName);
                }
            } catch (PLException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    /**
     * 获取需要修复的伪sql
     * @return
     */
    private List<String> getRepairDML(HashMap<String, Object> dbCheckMap) {
        List<String> list = new ArrayList<String>();
        for(Iterator<String> ite = dbCheckMap.keySet().iterator(); ite.hasNext();){
            String type = ite.next();
            String dml = String.valueOf(dbCheckMap.get(type));
            list.add(type + "/DML" + dml);
        }
        return list;
    }
    /**
     * 检查所有的链接类型, 当链接类型中引用的业务类型已经不存在时, 删除该链接类型中对业务类型的引用
     * @return
     */
    private Map<String, List<String>> usedBtmCheck(){
        try {
            Map<String, List<String>> map = new HashMap<String, List<String>>();
            LinkType[] links = platformClientUtil.getLinkTypeService().getLinkTypes();
            for(int i = 0; i < links.length; i++){
                LinkType link = links[i];
                String[] btms = link.btmItemsFrom;
                for(int k = 0; k < btms.length; k++){
                    String btmName = btms[k];
                    BizType btm = platformClientUtil.getBtmService().getBizTypeByName(btmName);
                    if(btm == null || btm.name.equals("")){
                        List<String> list = map.get(link.name);
                        if(list == null){
                            list = new ArrayList<String>();
                            list.add("F_" + btmName);
                        }else{
                            list.add("F_" + btmName);
                        }
                        map.put(link.name, list);
                    }
                }
                btms = link.btmItemsTo;
                for(int k = 0; k < btms.length; k++){
                    String btmName = btms[k];
                    BizType btm = platformClientUtil.getBtmService().getBizTypeByName(btmName);
                    if(btm == null || btm.name.equals("")){
                        List<String> list = map.get(link.name);
                        if(list == null){
                            list = new ArrayList<String>();
                            list.add("T_" + btmName);
                        }else{
                            list.add("T_" + btmName);
                        }
                        map.put(link.name, list);
                    }
                }
            }
            return map;
        } catch (PLException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取修改链接类型时 减少的属性
     * @param oldLt
     * @param newLt
     * @return
     */
    private ArrayList<String> getRemovedApList(LinkType oldLt,
                                               LinkType newLt) {
        String[] oldAbInfo = oldLt.attributes;
        ArrayList<String> oldNameList = new ArrayList<String>();
        for(int i = 0; i < oldAbInfo.length; i++){
            oldNameList.add(oldAbInfo[i]);
        }
        String[] newAbInfo = newLt.attributes;
        ArrayList<String> newNameList = new ArrayList<String>();
        for(int i = 0; i < newAbInfo.length; i++){
            newNameList.add(newAbInfo[i]);
        }
        ArrayList<String> removedApList = new ArrayList<String>();
        for(Iterator<String> iterator = oldNameList.iterator(); iterator.hasNext();){
            String oldName = iterator.next();
            if(!newNameList.contains(oldName)){
                removedApList.add(oldName);
            }
        }
        return removedApList;
    }
    /**
     * 清除缓存
     */
    @Override
    public void clearCache() {
    }
    /**
     * 修改链接类型中对应属性名的属性
     * @param apName
     * @return
     * @throws PLException
     */
    @Override
    public boolean alterAp(String apName) throws PLException {
        String[] linkNames = null;
        List<String> linkNameList = new ArrayList<String>();
        AttributeDef abItem = null;
        try {
            abItem = platformClientUtil.getAttributeService().getAttributeDefByName(apName);
        } catch (PLException e1) {
            e1.printStackTrace();
        }
        if(abItem == null || abItem.equals("")){
            return true;
        }
        try {
            linkNames = platformClientUtil.getLinkTypeService().getLTNamesByAPName(apName);
        } catch (PLException e) {
            e.printStackTrace();
        }
        if(linkNames == null || linkNames.length <= 0){
            return true;
        }
        linkNameList = Arrays.asList(linkNames);
        for(Iterator<String> i = linkNameList.iterator(); i.hasNext();){
            String linkName = i.next();
            try {
                platformClientUtil.getLinkTypeService().modifyLTAttribute(linkName, apName);
            } catch (PLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                String erreMsg = "调整链接类型中【"+apName+"】属性时出现错误,原因:"+e.getMessage();
                logger.error(erreMsg);
                throw new PLException("500",new String[]{erreMsg});
            }
        }
        return true;
    }
    /**
     * 判断该属性是否已经在链接类型中产生了数据
     * @param abName
     * @return
     * @throws PLException
     */
    @Override
    public boolean hasInstance(String abName) throws PLException {
        String[] btmNames = platformClientUtil.getLinkTypeService().getLTNamesByAPName(abName);
        if(btmNames == null || btmNames.length == 0){
            return false;
        }
        for(int i = 0; i < btmNames.length; i++){
            String btmName = btmNames[i];
            boolean flag;
            flag = platformClientUtil.getLinkTypeService().hasData(btmName);
            if(flag){
                return flag;
            }
        }
        return false;
    }
    /**
     * 获取连接类型名称集合
     * @return
     */
    @Override
    public List<String> getAllLtName() throws PLException {
        LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes();
        if(null != linkTypes && linkTypes.length > 0){
            return Arrays.stream(linkTypes).map(linkType -> linkType.name).collect(Collectors.toList());
        }
        return null;
    }
    /**
     * 获取使用该业务类型的链接类型名
     * @param btmName 业务类型名称
     * @return
     */
    @Override
    public List<String> getUsedBtmLinkList(String btmName) {
        try {
            List<String> list = new ArrayList<String>();
            LinkType[] linkTypes = platformClientUtil.getLinkTypeService().getLinkTypes();
            for(int i = 0; i < linkTypes.length; i++){
                LinkType linkType = linkTypes[i];
                if(this.containsBtm(linkType, btmName)){
                    list.add(linkType.name);
                }
            }
            return list;
        } catch (PLException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 指定的链接类型是否使用了指定的业务类型
     * @param link
     * @param btmName
     * @return
     */
    private boolean containsBtm(LinkType link, String btmName){
        String[] btms = link.btmItemsFrom;
        for(int i = 0; i < btms.length; i++){
            if(btmName.equalsIgnoreCase(btms[i])){
                return true;
            }
        }
        btms = link.btmItemsTo;
        for(int i = 0; i < btms.length; i++){
            if(btmName.equalsIgnoreCase(btms[i])){
                return true;
            }
        }
        return false;
    }
}