【仅供内部供应商使用,不提供对外解答和培训】

一、特殊名词介绍

二、背景、场景介绍

帆软的报表是基于制作再发布的过程进行生效的,对于一部分没有购买远程设计(也叫远程工作目录)功能的用户来说,以往就只能在本地设计器制作完模板,然后再把相关资源拷贝到服务器上。对于一些数据连接和服务器数据集,就只每次单独操作。10.0产品决策平台中争对这种问题,专门提供了数据集资源的导入导出,以方便用户快速发布报表。标准产品只针对了标准产品中的数据集的导入导出进行了支持。对于用户自己开发的一些数据集插件,则通过开放的TransferDataSetManagerProvider接口,允许用户自行开发完成扩展数据集资源的导入导出

三、接口介绍

TransferDataSetManagerProvider.java
package com.fr.decision.fun;

import com.fr.base.TableData;
import com.fr.decision.webservice.data.transfer.dataset.TransferDataSetManager;
import com.fr.stable.fun.mark.Mutable;

/**
 * @author lidongy
 * @version 10.0
 * Created by lidongy on 2021/2/25
 */
public interface TransferDataSetManagerProvider<T extends TableData> extends Mutable, TransferDataSetManager<T> {

    String XML_TAG = "TransferDataSetManagerProvider";

    int CURRENT_LEVEL = 1;
}

TransferDataSetManager.java
package com.fr.decision.webservice.data.transfer.dataset;

import com.fr.base.TableData;

/**
 * @author lidongy
 * @version 10.0
 * Created by lidongy on 2021/2/25
 */
public interface TransferDataSetManager<T extends TableData> {

    /**
     * 获取支持的数据集类
     *
     * @return 类对象
     */
    Class<? extends TableData> getDataSetClass();

    /**
     * dataset序列化
     *
     * @param t 数据集本身
     * @return 序列化结果
     */
    String serialize(T t) throws Exception;

    /**
     * dataset反序列化
     *
     * @param str 数据集序列化结果
     * @return 数据集本身
     */
    T deserialize(String str) throws Exception;

    /**
     * 获取依赖的资源路径
     *
     * @param t 数据集本身
     * @return 路径
     */
    String[] getDependencyPaths(T t) throws Exception;
}


四、支持版本

产品线

版本

支持情况

备注

FR10.0支持

五、插件注册

plugin.xml
<extra-decision>
        <TransferDataSetManagerProvider class="your class name"/>
</extra-decision>

六、原理说明

TransferDataSetFactory.java 确认哪些数据集可以导出资源,并匹配对应的管理对象
package com.fr.decision.webservice.bean.data.transfer.builder.dataset;

import com.fr.decision.ExtraDecisionClassManager;
import com.fr.decision.fun.TransferDataSetManagerProvider;
import com.fr.decision.webservice.data.transfer.dataset.TransferDataSetManager;
import com.fr.module.tool.ActivatorToolBox;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author lidongy
 * @version 10.0
 * Created by lidongy on 2021/2/25
 */
public class TransferDataSetFactory {
    private static final Map<String, TransferDataSetManager> dataSetManagerMap = ActivatorToolBox.sandbox(new HashMap<>());

    public static void register(TransferDataSetManager dataSetManager) {
        if (dataSetManagerMap == null) {
            return;
        }
        dataSetManagerMap.put(dataSetManager.getDataSetClass().getName(), dataSetManager);
    }

    public static void reset() {
        dataSetManagerMap.clear();
    }

    public static TransferDataSetManager getDataSetManager(String dataSetClassName) throws Exception {
        TransferDataSetManager dataSetManager = dataSetManagerMap.get(dataSetClassName);
        if (dataSetManager != null) {
            return dataSetManager;
        }
        Set<TransferDataSetManagerProvider> managerProviderSet = ExtraDecisionClassManager.getInstance().getArray(TransferDataSetManagerProvider.XML_TAG);
        if (!CollectionUtils.isEmpty(managerProviderSet)) {
            for (TransferDataSetManagerProvider provider : managerProviderSet) {
                if (StringUtils.equals(provider.getDataSetClass().getName(), dataSetClassName)) {
                    return provider;
                }
            }
        }

        throw new RuntimeException("Transfer is not supported for this data set.");
    }
}

TransferDataSetDataBuilder.java 实际对要导出的资源进行序列化和反序列化并导出相关依赖文件
package com.fr.decision.webservice.bean.data.transfer.builder.impl;

...

/**
 * @author lidongy
 * @version 10.0
 * Created by lidongy on 2021/1/14
 */
public class TransferDataSetDataBuilder extends AbstractTransferDataBuilder {

    private static final String EXPORT_PATH = "dataSet";

    @Override
    public int getEntityType() {
        return DataSetAuthorityControllerImpl.AUTH_TYPE;
    }

    @Override
    public TransferExportEntityDataBean exportEntityData(String entityId) throws Exception {
        TransferExportEntityDataBean result = new TransferExportEntityDataBean();
        result.setId(entityId);
        return result;
    }

    @Override
    public TransferExportEntityDataExtraPropsBean exportDataExtraProps(String entityId) throws Exception {
        TransferDataSetExtraPropsBean result = new TransferDataSetExtraPropsBean();

        TableData tableData = TableDataConfig.getInstance().getTableData(entityId);
        String className = tableData.getClass().getName();
        TransferDataSetManager dataSetManager = TransferDataSetFactory.getDataSetManager(className);
        result.setDataSetClassName(className);
        result.setDataSetInfo(dataSetManager.serialize(tableData));
        return result;
    }

    @Override
    public List<TransferEntityDependencyBean> exportEntityDependencies(String entityId) throws Exception {
        TableData tableData = TableDataConfig.getInstance().getTableData(entityId);
        String className = tableData.getClass().getName();
        TransferDataSetManager dataSetManager = TransferDataSetFactory.getDataSetManager(className);

        List<TransferEntityDependencyBean> dependencyBeanList = new ArrayList<>();
        for (String path : dataSetManager.getDependencyPaths(tableData)) {
            TransferEntityDependencyBean dependencyBean = new TransferEntityDependencyBean();
            dependencyBean.setOriginPath(path);
            dependencyBean.setExportPath(StableUtils.pathJoin(TransferDataFactory.EXPORT_TEMP_DIR, EXPORT_PATH, new File(path).getName()));
            dependencyBeanList.add(dependencyBean);
        }
        return dependencyBeanList;
    }


    @Override
    public TransferImportDisplayDataBean buildImportData(TransferExportDataBean transferExportDataBean) throws Exception {
        TransferExportEntityDataBean entityDataBean = transferExportDataBean.getData();
        TransferImportDisplayDataBean displayDataBean = new TransferImportDisplayDataBean(DataSetAuthorityControllerImpl.AUTH_TYPE);

        //平台路径
        String dataSetName = entityDataBean.getId();
        TransferImportDataValidBean entityFullPath = new TransferImportDataValidBean();
        entityFullPath.setImportDataId(dataSetName);
        entityFullPath.setImportDataAttr(dataSetName);
        entityFullPath.setDataAttrValid(TableDataConfig.getInstance().getTableData(dataSetName) == null);
        displayDataBean.setEntityFullPath(entityFullPath);

        //物理路径
        List<TransferEntityDependencyBean> dependencyBeanList = transferExportDataBean.getDependencies();
        List<TransferImportDataValidBean> originPathList = new ArrayList<>();
        for (TransferEntityDependencyBean dependencyBean : dependencyBeanList) {
            String originPath = dependencyBean.getOriginPath();
            if (StringUtils.isNotEmpty(originPath)) {
                originPathList.add(new TransferImportDataValidBean(originPath, StringUtils.EMPTY, !ResourceIOUtils.exist(originPath)));
            }
        }

        //这里和前台约定,originPathList只能为null不能为空
        if (originPathList.size() != 0) {
            displayDataBean.setDependencyOriginPath(originPathList);
        }
        displayDataBean.setExportData(transferExportDataBean);
        return displayDataBean;
    }

    @Override
    public List<TransferImportResultBean> importData(List<TransferImportEntityBean> importEntities) {
        List<TransferImportResultBean> importResultBeanList = new ArrayList<>();
        for (TransferImportEntityBean importEntityBean : importEntities) {
            TransferDataSetExtraPropsBean dataSetExtraPropsBean = (TransferDataSetExtraPropsBean) importEntityBean.getEntityDataExtraPropsBean();
            String dataSetName = importEntityBean.getEntityId();

            TransferImportResultBean resultBean = new TransferImportResultBean(importEntityBean.getImportId(), DataSetAuthorityControllerImpl.AUTH_TYPE);
            resultBean.setFullPath(dataSetName);
            //物理路径
            List<TransferImportDataValidBean> originPath = importEntityBean.getDependencyOriginPath();
            if (!CollectionUtils.isEmpty(originPath)) {
                List<String> dependencyPath = new ArrayList<>();
                dependencyPath.add(originPath.get(0).getImportDataAttr());
                resultBean.setDependencyPath(dependencyPath);
            }

            try {
                String dataSetInfo = dataSetExtraPropsBean.getDataSetInfo();
                String className = dataSetExtraPropsBean.getDataSetClassName();

                TransferDataSetManager dataSetManager = TransferDataSetFactory.getDataSetManager(className);
                TableData tableData = dataSetManager.deserialize(dataSetInfo);

                if (importEntityBean.getEntityFullPath().isDataAttrValid()) {
                    Configurations.update(new WorkerAdaptor(TableDataConfig.class) {
                        @Override
                        public void run() {
                            TableDataConfig.getInstance().addTableData(dataSetName, tableData);
                        }
                    });
                } else {
                    Configurations.update(new WorkerAdaptor(TableDataConfig.class) {
                        @Override
                        public void run() {
                            TableDataConfig.getInstance().removeTableData(dataSetName);
                            TableDataConfig.getInstance().addTableData(dataSetName, tableData);
                        }
                    });
                }

                //实体文件
                List<TransferEntityDependencyBean> dependencyBeanList = importEntityBean.getEntityDependencyBeans();
                for (TransferEntityDependencyBean dependencyBean : dependencyBeanList) {
                    File exportFile = new File(StableUtils.pathJoin(WorkContext.getCurrent().getPath(), TransferDataFactory.IMPORT_TEMP_DIR, dependencyBean.getExportPath()));
                    TransferDataFactory.importDependencyFile(dependencyBean.getOriginPath(), exportFile);
                }

                resultBean.setImportResult(true);
            } catch (Exception e) {
                FineLoggerFactory.getLogger().error(e, e.getMessage());
                resultBean.setImportMsg(WebServiceUtils.getStackTraceInfo(e));
                resultBean.setImportResult(false);
            }
            importResultBeanList.add(resultBean);
        }
        return importResultBeanList;
    }
}


七、特殊限制说明

绝大多数时候,数据集的序列化或者反序列化,如果开发者本身实现了数据集的readXML和writeXML方法,则可以通过

GeneralXMLTools.writeXMLableAsString(ds);
GeneralXMLTools.readStringAsXMLable(config,ds);

实现序列化和反序列化。

而getDependencyPaths仅仅作为当数据集依赖了某些文件时,使用该依赖接口,将所有要一起导出的文件路径给出。

八、常用链接

demo地址:demo-transfer-data-set-manager-provider


九、开源案例

免责声明:所有文档中的开源示例,均为开发者自行开发并提供。仅用于参考和学习使用,开发者和官方均无义务对开源案例所涉及的所有成果进行教学和指导。禁止用于任何商业用途,若作为商用一切后果责任由使用者自行承担。


  • No labels