From fc7396c62efe2a930a4415f1dd05e8ea0902cb5c Mon Sep 17 00:00:00 2001 From: loy Date: Tue, 19 Jan 2021 09:52:30 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-46916=20=E6=96=B0=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E5=86=85=E7=BD=AE=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../java/com/fr/plugin/designer/CptxApp.java | 59 +++++ .../designer/EnginexSupportedFileUIImpl.java | 51 ++++ .../com/fr/plugin/designer/JStreamBook.java | 109 +++++++++ .../com/fr/plugin/designer/StartupAssist.java | 95 ++++++++ .../com/fr/plugin/designer/WritableCptx.java | 29 +++ .../designer/cell/CellTreeAttrPanel.java | 109 +++++++++ .../cell/CellTreeAttrPanelProvider.java | 30 +++ .../designer/clean/CompileCleanManager.java | 133 +++++++++++ .../cptx/io/DesignReadWritableProvider.java | 61 +++++ .../designer/menu/BatchCompileAction.java | 47 ++++ .../designer/menu/BatchCompileMenu.java | 36 +++ .../designer/menu/CalculateAttrAction.java | 76 ++++++ .../designer/menu/CalculateAttrMenu.java | 69 ++++++ .../designer/menu/CalculateAttrPane.java | 200 ++++++++++++++++ .../designer/menu/FeatureFlagsPanel.java | 73 ++++++ .../designer/menu/LocalAnalyzerAction.java | 49 ++++ .../designer/menu/LocalAnalyzerMenu.java | 37 +++ .../designer/menu/bean/FeatureFlagBean.java | 36 +++ .../monitor/DesignerMetricRecorder.java | 176 ++++++++++++++ .../designer/toolbar/CompileAction.java | 116 +++++++++ .../designer/toolbar/TemplateTransformer.java | 221 +++++++++++++++++ .../toolbar/TemplateTransformerUIButton.java | 20 ++ .../designer/toolbar/TransformResult.java | 55 +++++ .../designer/toolbar/TransformResultInfo.java | 64 +++++ .../transform/BatchTransformProgress.java | 25 ++ .../transform/BatchTransformUtil.java | 25 ++ .../designer/transform/BatchTransformer.java | 71 ++++++ .../designer/transform/UpdateCallBack.java | 22 ++ .../transform/ui/BatchTransformDialog.java | 61 +++++ .../transform/ui/BatchTransformPane.java | 223 ++++++++++++++++++ .../ui/PrepareTransformFileList.java | 79 +++++++ .../transform/ui/TransformFileTree.java | 204 ++++++++++++++++ .../transform/ui/TransformPreparePane.java | 130 ++++++++++ .../transform/ui/TransformResultList.java | 70 ++++++ .../transform/ui/TransformResultPane.java | 110 +++++++++ .../ui/UIListControlCellRenderer.java | 86 +++++++ .../transform/ui/UpdateProgressDialog.java | 70 ++++++ .../transform/ui/UpdateProgressPane.java | 72 ++++++ .../designer/utils/CompileTransformUtil.java | 55 +++++ .../designer/utils/DesignerCptxFileUtils.java | 79 +++++++ .../com/fr/plugin/designer/CptxAppTest.java | 55 +++++ .../EnginexSupportedFileUIImplTest.java | 26 ++ .../fr/plugin/designer/JStreamBookTest.java | 121 ++++++++++ .../clean/CompileCleanManagerTest.java | 41 ++++ .../designer/menu/BatchCompileMenuTest.java | 16 ++ .../toolbar/TemplateTransformerTest.java | 85 +++++++ .../toolbar/TransformResultInfoTest.java | 32 +++ .../transform/BatchTransformProgressTest.java | 27 +++ .../transform/BatchTransformUtilTest.java | 35 +++ .../transform/BatchTransformerTest.java | 124 ++++++++++ .../utils/CompileTransformUtilTest.java | 58 +++++ 52 files changed, 3954 insertions(+) create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/CptxApp.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/EnginexSupportedFileUIImpl.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/JStreamBook.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/StartupAssist.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/WritableCptx.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanel.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanelProvider.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/clean/CompileCleanManager.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/cptx/io/DesignReadWritableProvider.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileAction.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileMenu.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrAction.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrMenu.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrPane.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/FeatureFlagsPanel.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerAction.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerMenu.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/menu/bean/FeatureFlagBean.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/monitor/DesignerMetricRecorder.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/toolbar/CompileAction.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformer.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformerUIButton.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResult.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResultInfo.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformProgress.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformUtil.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformer.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/UpdateCallBack.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformDialog.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformPane.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/PrepareTransformFileList.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformFileTree.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformPreparePane.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultList.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultPane.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UIListControlCellRenderer.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressDialog.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressPane.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/utils/CompileTransformUtil.java create mode 100644 designer-realize/src/main/java/com/fr/plugin/designer/utils/DesignerCptxFileUtils.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/CptxAppTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/EnginexSupportedFileUIImplTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/JStreamBookTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/clean/CompileCleanManagerTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/menu/BatchCompileMenuTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TemplateTransformerTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TransformResultInfoTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformProgressTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformUtilTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformerTest.java create mode 100644 designer-realize/src/test/java/com/fr/plugin/designer/utils/CompileTransformUtilTest.java diff --git a/build.gradle b/build.gradle index 617b9d0fa..8399410db 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,7 @@ allprojects { implementation 'com.fr.decision:fine-decision:' + frVersion implementation 'com.fr.schedule:fine-schedule:' + frVersion implementation 'com.fr.report:engine-report:' + frDevVersion + implementation 'com.fr.report:engine-x:' + frDevVersion implementation 'com.fr.report:engine-chart:' + frDevVersion implementation 'com.fr.report:engine-i18n:' + frDevVersion implementation 'com.fr.design:design-i18n:' + frDevVersion diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/CptxApp.java b/designer-realize/src/main/java/com/fr/plugin/designer/CptxApp.java new file mode 100644 index 000000000..cdad02a78 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/CptxApp.java @@ -0,0 +1,59 @@ +package com.fr.plugin.designer; + +import com.fr.base.extension.FileExtension; +import com.fr.design.mainframe.AbstractAppProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.main.impl.WorkBook; +import com.fr.plugin.designer.utils.DesignerCptxFileUtils; + +/** + * 支持设计器打开cptx文件 + */ +public class CptxApp extends AbstractAppProvider { + + static { + // 保证设计器默认 cptx 启动正常 + StartupAssist.init(); + } + + + public CptxApp() { + StartupAssist.initDesignModule(); + } + + @Override + public String[] defaultExtensions() { + return new String[]{FileExtension.CPTX.getExtension()}; + } + + @Override + public void process() { + super.process(); + StartupAssist.reloadTemplate(); + } + + /** + * 该方法只是为了读到cptx中的cpt + * + * @param tplFile file + * @return template + */ + @Override + public JTemplate openTemplate(FILE tplFile) { + WorkBook workBook = DesignerCptxFileUtils.getWorkBook(tplFile); + if (workBook == null) { + workBook = new WorkBook(); + } + return new JStreamBook(workBook, tplFile); + } + + @Override + public WorkBook asIOFile(FILE file) { + WorkBook workBook = DesignerCptxFileUtils.getWorkBook(file); + if (workBook == null) { + workBook = new WorkBook(); + } + return workBook; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/EnginexSupportedFileUIImpl.java b/designer-realize/src/main/java/com/fr/plugin/designer/EnginexSupportedFileUIImpl.java new file mode 100644 index 000000000..ae9ec9796 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/EnginexSupportedFileUIImpl.java @@ -0,0 +1,51 @@ +package com.fr.plugin.designer; + +import com.fr.base.BaseUtils; +import com.fr.base.extension.FileExtension; +import com.fr.design.i18n.Toolkit; +import com.fr.design.fun.impl.AbstractReportSupportedFileUIProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.plugin.designer.toolbar.TemplateTransformer; +import com.fr.stable.ProductConstants; + +import javax.swing.Icon; + + +/** + * Created by kerry on 2019-10-14 + */ +public class EnginexSupportedFileUIImpl extends AbstractReportSupportedFileUIProvider { + public static final Icon CPTX_ICON = BaseUtils.readIcon("/com/fr/plugin/designer/cptx_file_icon.png"); + public static final Icon CPTX_LOCKED_ICON = BaseUtils.readIcon("/com/fr/plugin/designer/cptx_file_icon_locked.png"); + + @Override + public void addChooseFileFilter(FILEChooserPane fileChooser, String suffix) { + String filterDescription = ProductConstants.APP_NAME + Toolkit.i18nText("Fine-Design_Report_Template_File"); + ChooseFileFilter cptxChooserFilter = new ChooseFileFilter(FileExtension.CPTX, filterDescription); + fileChooser.addChooseFILEFilter(cptxChooserFilter); + } + + @Override + public Icon getFileIcon(String path, boolean isShowLock) { + if (!FileExtension.CPTX.matchExtension(path)) { + return null; + } + if (isShowLock) { + return CPTX_LOCKED_ICON; + } + return CPTX_ICON; + } + + + @Override + public boolean saveToNewFile(String targetPath, JTemplate jTemplate) { + if (FileExtension.CPTX.matchExtension(targetPath)) { + TemplateTransformer.TO_CPTX.transform(jTemplate); + return true; + } + return false; + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/JStreamBook.java b/designer-realize/src/main/java/com/fr/plugin/designer/JStreamBook.java new file mode 100644 index 000000000..d52568541 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/JStreamBook.java @@ -0,0 +1,109 @@ +package com.fr.plugin.designer; + +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.file.export.CSVExportAction; +import com.fr.design.actions.file.export.PDFExportAction; +import com.fr.design.actions.file.export.SVGExportAction; +import com.fr.design.actions.file.export.TextExportAction; +import com.fr.design.actions.file.export.WordExportAction; +import com.fr.design.mainframe.JWorkBook; +import com.fr.design.menu.MenuDef; +import com.fr.file.FILE; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.cptx.entry.metadata.CptxMetadata; +import com.fr.plugin.designer.toolbar.TemplateTransformer; +import com.fr.plugin.designer.toolbar.TransformResult; +import com.fr.plugin.designer.toolbar.TransformResultInfo; +import com.fr.plugin.designer.utils.DesignerCptxFileUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; + +public class JStreamBook extends JWorkBook { + + + public JStreamBook(WorkBook workBook, FILE file) { + super(workBook, file); + } + + @Override + protected boolean saveFile() { + boolean saved; + TransformResultInfo resultInfo = TemplateTransformer.compileCPTX(getTarget(), getEditingFILE()); + saved = resultInfo.isSaved(); + this.setSaved(saved); + if (saved) { + this.fireJTemplateSaved(); + } + return saved; + } + + @Override + protected boolean saveToNewFile(String oldName) { + String path = this.getEditingFILE().getPath(); + try { + if (!path.startsWith(ProjectConstants.REPORTLETS_NAME)) { + File file = new File(path); + if (file.getParentFile() != null && !file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + file.createNewFile(); + OutputStream outputStream = new FileOutputStream(file); + this.getTarget().export(outputStream); + return true; + }else { + TransformResult result; + if (FileExtension.CPT.matchExtension(path)) { + result = TemplateTransformer.TO_CPT.transform(this); + } else { + result = TemplateTransformer.TO_CPTX.transform(this); + } + return ComparatorUtils.equals(TransformResult.SUCCESS, result); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return false; + } + + + /** + * 保存文件的后缀名 + * + * @return 后缀的字符串 + */ + @Override + public String suffix() { + return ".cptx"; + } + + @Override + protected void addShortCut(MenuDef exportMenuDef, MenuDef excelExportMenuDef) { + exportMenuDef.addShortCut(excelExportMenuDef, new PDFExportAction(this), new WordExportAction(this), new SVGExportAction(this), + new CSVExportAction(this), new TextExportAction(this)); + } + + + @Override + public String getPath() { + return getEditingFILE().getPath() + getSuffix(); + } + + public String getTemplateName() { + return getEditingFILE().getName() + getSuffix(); + } + + private String getSuffix() { + CptxMetadata metadata = DesignerCptxFileUtils.getMetadata(this.getEditingFILE()); + if (metadata != null && metadata.isForceCpt()) { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Compatibility_Mode"); + } + return StringUtils.EMPTY; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/StartupAssist.java b/designer-realize/src/main/java/com/fr/plugin/designer/StartupAssist.java new file mode 100644 index 000000000..5f2795244 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/StartupAssist.java @@ -0,0 +1,95 @@ +package com.fr.plugin.designer; + +import com.fr.base.Parameter; +import com.fr.base.extension.FileExtension; +import com.fr.common.annotations.Negative; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JTemplateFactory; +import com.fr.design.module.DesignModuleFactory; +import com.fr.design.parameter.AbstractParameterReader; +import com.fr.design.ui.util.UIUtil; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.cptx.CptxIOManager; +import com.fr.nx.cptx.io.handle.CptxTemplateHandle; +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.PluginEventType; + +/** + * 保证设计器默认 cptx 启动正常 + * + * @author yaohwu + * created by yaohwu at 2020/6/5 16:28 + */ +public class StartupAssist { + + public static void init() { + listenInitDesignModule(); + } + + + public static void initDesignModule() { + DesignModuleFactory.registerParameterReader(new AbstractParameterReader() { + @Override + public Parameter[] readParameterFromPath(String tplPath) { + if (accept(tplPath, FileExtension.CPTX.getSuffix())) { + try { + CptxTemplateHandle handle = CptxIOManager.open(tplPath); + WorkBook book = handle.getTemplate().getLegacyWorkBook(); + return book.getParameters(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return new Parameter[0]; + } + } + return null; + } + }); + } + + private static void reload() { + JTemplate old = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + JTemplate template = JTemplateFactory.createJTemplate(old.getEditingFILE()); + DesignerContext.getDesignerFrame().addAndActivateJTemplate(template); + HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(template); + } + + /** + * 主代码修复后就可以删除了 + * + * 主代码任务链接 + */ + @Negative(until = "2021-09-01") + public static void reloadTemplate() { + if (isCptxJTemplate()) { + UIUtil.invokeLaterIfNeeded(() -> { + reload(); + DesignerContext.getDesignerFrame().setVisible(true); + DesignerContext.getDesignerFrame().resizeFrame(); + }); + } + } + + private static boolean isCptxJTemplate() { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path; + return jTemplate != null && + (path = jTemplate.getPath()) != null + && path.endsWith(FileExtension.CPTX.getExtension()); + } + + private static void listenInitDesignModule() { + EventDispatcher.listen(PluginEventType.AfterRun, new Listener() { + @SuppressWarnings("rawtypes") + @Override + public void on(Event event, PluginContext param) { + initDesignModule(); + } + }); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/WritableCptx.java b/designer-realize/src/main/java/com/fr/plugin/designer/WritableCptx.java new file mode 100644 index 000000000..db2249915 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/WritableCptx.java @@ -0,0 +1,29 @@ +package com.fr.plugin.designer; + +import com.fr.file.FILE; +import com.fr.nx.cptx.io.handle.impl.AbstractCptxIOProvider; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * 读写型模板, 用于设计器端增删改模板 + */ +public class WritableCptx extends AbstractCptxIOProvider { + + private FILE file; + + public WritableCptx(FILE file) { + this.file = file; + } + + @Override + public InputStream open() throws Exception { + return file.asInputStream(); + } + + @Override + public OutputStream createTemp() throws Exception { + return file.asOutputStream(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanel.java b/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanel.java new file mode 100644 index 000000000..f6f884306 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanel.java @@ -0,0 +1,109 @@ +package com.fr.plugin.designer.cell; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.event.UIObserverListener; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.MultilineLabel; +import com.fr.design.mainframe.CellWidgetPropertyPane; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.JTemplate; +import com.fr.form.ui.Widget; +import com.fr.locale.InterProviderFactory; +import com.fr.report.cell.TemplateCellElement; +import com.fr.report.web.button.form.TreeNodeToggleButton; + +import java.awt.BorderLayout; +import java.awt.Color; + +/** + * @author yaohwu + * created by yaohwu at 2020/4/26 16:33 + */ +public class CellTreeAttrPanel extends BasicBeanPane { + private static final Color TIP_COLOR = new Color(0x8f8f92); + + private TemplateCellElement cellElement = null; + + private final UICheckBox showAsTreeNodeCheckBox; + + private final UIObserverListener listener = new UIObserverListener() { + @Override + public void doChange() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + if (CellTreeAttrPanel.this.cellElement != null) { + CellTreeAttrPanel.this.updateBean(); + } + template.fireTargetModified(); + CellWidgetPropertyPane.getInstance().populate((ElementCasePane) template.getCurrentElementCasePane()); + } + } + }; + + private static final class Holder { + private static final CellTreeAttrPanel INSTANCE = new CellTreeAttrPanel(); + } + + public static CellTreeAttrPanel getInstance() { + return Holder.INSTANCE; + } + + private CellTreeAttrPanel() { + this.setLayout(new BorderLayout()); + showAsTreeNodeCheckBox = + new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node")); + this.add(showAsTreeNodeCheckBox, BorderLayout.NORTH); + MultilineLabel multilineLabel = + new MultilineLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node_TIP")); + multilineLabel.setForeground(TIP_COLOR); + this.add(multilineLabel, BorderLayout.CENTER); + } + + /** + * 展示数据 + * + * @param ob 待展示的对象 + */ + @Override + public void populateBean(TemplateCellElement ob) { + this.cellElement = ob; + Widget widget = cellElement.getWidget(); + showAsTreeNodeCheckBox.registerChangeListener(null); + showAsTreeNodeCheckBox.setSelected(widget instanceof TreeNodeToggleButton); + showAsTreeNodeCheckBox.registerChangeListener(listener); + } + + /** + * 保存数据 + * + * @return 待保存的对象 + */ + @Override + public TemplateCellElement updateBean() { + if (this.cellElement == null) { + return null; + } + if (showAsTreeNodeCheckBox.isSelected()) { + cellElement.setWidget(createTreeToggleButton()); + } else { + cellElement.setWidget(null); + } + return this.cellElement; + } + + @Override + public void updateBean(TemplateCellElement ob) { + this.cellElement = ob; + updateBean(); + } + + @Override + protected String title4PopupWindow() { + return ""; + } + + private TreeNodeToggleButton createTreeToggleButton() { + return new TreeNodeToggleButton(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanelProvider.java b/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanelProvider.java new file mode 100644 index 000000000..ec4639a8f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/cell/CellTreeAttrPanelProvider.java @@ -0,0 +1,30 @@ +package com.fr.plugin.designer.cell; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.fun.impl.AbstractCellExpandAttrPanelProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.plugin.designer.JStreamBook; +import com.fr.report.cell.TemplateCellElement; + +/** + * @author yaohwu + * created by yaohwu at 2020/4/26 16:32 + */ +public class CellTreeAttrPanelProvider extends AbstractCellExpandAttrPanelProvider { + + @Override + public BasicBeanPane createPanel() { + return CellTreeAttrPanel.getInstance(); + } + + /** + * 只有新引擎 cptx 模版才展示 + * 先注释掉Override,适配老的主jar,保留这个方法是为了在新主jar下支持这个功能 + */ + // @Override + public boolean isDisplayable() { + JTemplate current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return current instanceof JStreamBook; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/clean/CompileCleanManager.java b/designer-realize/src/main/java/com/fr/plugin/designer/clean/CompileCleanManager.java new file mode 100644 index 000000000..abda1f5cf --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/clean/CompileCleanManager.java @@ -0,0 +1,133 @@ +package com.fr.plugin.designer.clean; + +import com.fr.base.extension.FileExtension; +import com.fr.config.ConfigContext; +import com.fr.config.DefaultConfiguration; +import com.fr.config.holder.factory.Holders; +import com.fr.config.holder.impl.MapConf; +import com.fr.general.CommonDateUtils; +import com.fr.nx.cptx.marshal.util.CptxMarshalUtil; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.transaction.Configurations; +import com.fr.transaction.WorkerAdaptor; +import com.fr.workspace.WorkContext; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @author: Maksim + * @Date: Created in 2020/4/23 + * @Description: + */ +public class CompileCleanManager extends DefaultConfiguration { + + private static volatile CompileCleanManager INSTANCE; + private MapConf> mapConf = Holders.map(new HashMap(), String.class, String.class); + + private CompileCleanManager() { + } + + @Override + public String getNameSpace() { + return "CompileCleanManager"; + } + + public static CompileCleanManager getInstance() { + if (INSTANCE == null) { + synchronized (CompileCleanManager.class) { + if (INSTANCE == null) { + INSTANCE = ConfigContext.getConfigInstance(CompileCleanManager.class); + } + } + } + return INSTANCE; + } + + /** + * 增加预览记录 + * + * @param bookPath + */ + public void addRecord(String bookPath) { + String lastPreviewTime = CommonDateUtils.getDate2Str("yyyy-MM-dd", new Date()); + addRecord(bookPath, lastPreviewTime); + } + + public void addRecord(final String bookPath, final String lastPreviewTime) { + Configurations.update(new WorkerAdaptor(CompileCleanManager.class) { + @Override + public void run() { + mapConf.put(bookPath, lastPreviewTime); + } + }); + } + + /** + * 删除预览记录 + * + * @param bookPath + */ + public void deleteRecord(String bookPath) { + this.mapConf.remove(bookPath); + } + + /** + * 获取预览记录 + * + * @return + */ + public Map getRecords() { + return mapConf.get(); + } + + /** + * 执行清理 + */ + public void clear() { + Map cleanMap = getRecords(); + for (Iterator> iterator = cleanMap.entrySet().iterator(); iterator.hasNext(); ) { + Map.Entry item = iterator.next(); + String bookPath = item.getKey(); + String lastPreviewTime = item.getValue(); + if (needClean(lastPreviewTime)) { + String compilePath = getCompilePath(bookPath); + WorkContext.getWorkResource().delete(compilePath); + deleteRecord(bookPath); + } + } + + } + + private String getCompilePath(String bookPath) { + if (bookPath.endsWith(FileExtension.CPTX.getSuffix())) { + bookPath = bookPath.substring(0, bookPath.length() - FileExtension.CPTX.getSuffix().length()); + } + return StableUtils.pathJoin(ProjectConstants.ASSETS_NAME, CptxMarshalUtil.COMPILE_PATH, bookPath); + } + + /** + * 根据时间判断是否需要清理 + * + * @param lastPreviewTime + * @return + */ + private boolean needClean(String lastPreviewTime) { + Date previewTime = CommonDateUtils.transDate(lastPreviewTime, false); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(previewTime); + calendar.add(Calendar.MONTH, 1); + return new Date().after(calendar.getTime()); + } + + @Override + public Object clone() throws CloneNotSupportedException { + CompileCleanManager manager = (CompileCleanManager) super.clone(); + manager.mapConf = (MapConf>) this.mapConf.clone(); + return manager; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/cptx/io/DesignReadWritableProvider.java b/designer-realize/src/main/java/com/fr/plugin/designer/cptx/io/DesignReadWritableProvider.java new file mode 100644 index 000000000..60bcab26f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/cptx/io/DesignReadWritableProvider.java @@ -0,0 +1,61 @@ +package com.fr.plugin.designer.cptx.io; + +import com.fr.common.annotations.Negative; +import com.fr.file.FILE; +import com.fr.nx.cptx.io.handle.impl.AbstractCptxIOProvider; +import com.fr.nx.cptx.pack.util.CompiledReportInputStream; +import com.fr.nx.cptx.pack.util.CompiledReportOutputStream; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.plugin.designer.utils.DesignerCptxFileUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * 用于设计器保存编译后的结果并缓存可web预览模版 + * 没有可观的内存实现,内存实现方式复杂,赶发布,先提供简单的内存实现方式 + * + * @author: Maksim + * @Date: Created in 2020/4/10 + * @Description: 用于cptx写操作的Provider + */ +@Negative(until = "2020-05-10") +public class DesignReadWritableProvider extends AbstractCptxIOProvider { + /** + * 原文件 + */ + private final FILE file; + /** + * 编译文件夹 + */ + private final String compileDir; + + private CompiledReportOutputStream outputStream; + + public DesignReadWritableProvider(FILE file) { + this.file = file; + this.compileDir = DesignerCptxFileUtils.generateCompileDir(file); + } + + @Override + public InputStream open() throws Exception { + if (outputStream == null) { + throw new IOException("can not read cptx template before compile"); + } + return new CompiledReportInputStream(outputStream.toByteArray()); + } + + /** + * 对于写操作,用到的只有这个方法,以流形式来操作 + * + * @return 保存的目标输出流 + * @throws Exception e + */ + @Override + public OutputStream createTemp() throws Exception { + outputStream = new CompiledReportOutputStream(file.asOutputStream(), compileDir); + return outputStream; + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileAction.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileAction.java new file mode 100644 index 000000000..848809089 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileAction.java @@ -0,0 +1,47 @@ +package com.fr.plugin.designer.menu; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.transform.ui.BatchTransformPane; + +import javax.swing.KeyStroke; +import java.awt.Dialog; +import java.awt.event.ActionEvent; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchCompileAction extends UpdateAction { + public BatchCompileAction() { + this.setMenuKeySet(COMPILE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/plugin/designer/transform/batch_transform.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + BatchTransformPane batchTransformPane = new BatchTransformPane(); + Dialog dialog = batchTransformPane.showDialog(); + dialog.setVisible(true); + } + + private static final MenuKeySet COMPILE = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileMenu.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileMenu.java new file mode 100644 index 000000000..6625d247c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/BatchCompileMenu.java @@ -0,0 +1,36 @@ +package com.fr.plugin.designer.menu; + +import com.fr.design.fun.impl.AbstractMenuHandler; +import com.fr.design.menu.ShortCut; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchCompileMenu extends AbstractMenuHandler { + private static final int DEFAULT_INSERT_POSITION = 9; + + @Override + public int insertPosition(int total) { + return DEFAULT_INSERT_POSITION; + } + + @Override + public boolean insertSeparatorBefore() { + return false; + } + + @Override + public boolean insertSeparatorAfter() { + return false; + } + + @Override + public String category() { + return FILE; + } + + @Override + public ShortCut shortcut() { + return new BatchCompileAction(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrAction.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrAction.java new file mode 100644 index 000000000..37667220d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrAction.java @@ -0,0 +1,76 @@ +package com.fr.plugin.designer.menu; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.JTemplateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.UIDialog; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.MenuKeySet; +import com.fr.locale.InterProviderFactory; +import com.fr.main.impl.WorkBook; +import com.fr.plugin.attr.CalculatorAttrMark; +import com.fr.plugin.designer.JStreamBook; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +public class CalculateAttrAction extends JTemplateAction { + + public CalculateAttrAction(JStreamBook jTemplate) { + super(jTemplate); + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(CALCULATE_FIT_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/bbs/center.png")); + } + + /** + * Action触发事件 + * + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + final JStreamBook jwb = getEditingComponent(); + if (jwb == null) { + return; + } + WorkBook workBook = jwb.getTarget(); + CalculatorAttrMark mark = workBook.getAttrMark(CalculatorAttrMark.MARK); + CalculateAttrPane attrPane = new CalculateAttrPane(); + showReportFitDialog(mark, jwb, workBook, attrPane); + } + + private void showReportFitDialog(CalculatorAttrMark mark, final JStreamBook jwb, final WorkBook workBook, final BasicBeanPane attrPane) { + attrPane.populateBean(mark); + UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + workBook.addAttrMark(attrPane.updateBean()); + jwb.fireTargetModified(); + } + }); + dialog.setVisible(true); + } + + private static final MenuKeySet CALCULATE_FIT_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrMenu.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrMenu.java new file mode 100644 index 000000000..06a3f493d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrMenu.java @@ -0,0 +1,69 @@ +package com.fr.plugin.designer.menu; + +import com.fr.design.fun.impl.AbstractMenuHandler; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.menu.ShortCut; +import com.fr.plugin.designer.JStreamBook; + +public class CalculateAttrMenu extends AbstractMenuHandler { + + private static final int DEFAULT_INSERT_POSITION = 7; + + /** + * 插入位置 + * @param total 插入点 + * + * @return 插入位置 + * + */ + public int insertPosition(int total) { + return DEFAULT_INSERT_POSITION; + } + + /** + * 在分隔符前插入 + * + * @return 是否在分隔符前插入 + * + */ + public boolean insertSeparatorBefore() { + return false; + } + + /** + * 在分隔符后插入 + * + * @return 是否在分隔符后插入 + * + */ + public boolean insertSeparatorAfter() { + return false; + } + + /** + * 分类 + * + * @return 菜单分类 + * + */ + public String category() { + return TEMPLATE; + } + + /** + * 获取当前菜单的Action + * + * @param plus 当前操作对象 + * + * @return 菜单Action + * + */ + public ShortCut shortcut(ToolBarMenuDockPlus plus) { + //往ToolBarMenuDockPlus里塞感觉也很糟. + if (!(plus instanceof JStreamBook)){ + return null; + } + + return new CalculateAttrAction((JStreamBook) plus); + } +} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrPane.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrPane.java new file mode 100644 index 000000000..2fe5f793f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/CalculateAttrPane.java @@ -0,0 +1,200 @@ +package com.fr.plugin.designer.menu; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.feature.FeatureFlags; +import com.fr.nx.feature.FeatureManager; +import com.fr.plugin.attr.CalculatorAttrMark; +import com.fr.plugin.designer.menu.bean.FeatureFlagBean; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +public class CalculateAttrPane extends BasicBeanPane { + + private static final Color TIPS_FONT_COLOR = new Color(0x8f8f92); + + // private UICheckBox calculateEnd; + private UICheckBox queryCache; + + private UICheckBox treeAsyncQuery; + + private UICheckBox multiSourceMode; + + private UISpinner treeExpandLayer; + + private JPanel treeConfigPanel; + + /** + * 当前模版从未设置过模版计算属性 + */ + private boolean isEmptyAttr = false; + + public CalculateAttrPane() { + initComponents(); + } + + private void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + JPanel featureFlagPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + ActionLabel featureLabel = new ActionLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature")); + featureLabel.setFont(new Font(null, Font.PLAIN, 10)); + featureLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JDialog wDialog = createJDialog(); + wDialog.setVisible(true); + } + }); + featureFlagPanel.add(featureLabel); + + JPanel calculateAttrPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + calculateAttrPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); + +// JPanel calculatedEndPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); +// calculateEnd = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Calculate-End")); +// calculatedEndPanel.add(calculateEnd); + JPanel queryCachePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + queryCache = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Calculate_Query_Cache")); + queryCachePanel.add(queryCache); + JPanel multiSourcePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + multiSourceMode = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Feature_Multi_Source")); + multiSourcePanel.add(multiSourceMode); + +// calculateAttrPanel.add(calculatedEndPanel); + calculateAttrPanel.add(queryCachePanel); + calculateAttrPanel.add(multiSourcePanel); + + + treeConfigPanel = FRGUIPaneFactory.createTitledBorderPane( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Config") + ); + treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE)); + treeConfigPanel.setLayout(new BoxLayout(treeConfigPanel, BoxLayout.Y_AXIS)); + + JPanel treeAsyncQueryPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + treeAsyncQuery = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Async_Query")); + treeAsyncQueryPanel.add(treeAsyncQuery); + + JPanel treeExpandLayerPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + UILabel treeExpandLayerLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer")); + treeExpandLayer = new UISpinner(1, Integer.MAX_VALUE, 1, 1); + // 功能不支持,设置先禁用 + treeExpandLayer.setEnabled(false); + + treeExpandLayerPanel.add(treeExpandLayerLabel); + treeExpandLayerPanel.add(treeExpandLayer); + + JPanel treeExpandLayerLabelPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + UILabel multilineLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer_Label")); + multilineLabel.setForeground(TIPS_FONT_COLOR); + treeExpandLayerLabelPanel.add(multilineLabel); + + + treeConfigPanel.add(treeAsyncQueryPanel); + treeConfigPanel.add(treeExpandLayerPanel); + treeConfigPanel.add(treeExpandLayerLabelPanel); + + List components = new ArrayList<>(); + components.add(new Component[]{featureFlagPanel}); + components.add(new Component[]{calculateAttrPanel}); + components.add(new Component[]{treeConfigPanel}); + + JPanel content = + TableLayoutHelper.createGapTableLayoutPane( + components.toArray(new Component[0][]), + TableLayoutHelper.FILL_LASTCOLUMN, + 5, + 5 + ); + + this.add(content, BorderLayout.CENTER); + } + + @Override + public void populateBean(CalculatorAttrMark attrMark) { + if (attrMark == null) { + isEmptyAttr = true; + // 默认折叠树配置 + treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC)); + return; + } +// calculateEnd.setSelected(attrMark.isCalculateEnd()); + queryCache.setSelected(attrMark.isQueryCache()); + treeAsyncQuery.setSelected(attrMark.isTreeAsyncQuery()); + treeExpandLayer.setValue(attrMark.getTreeExpandLayer()); + multiSourceMode.setSelected(attrMark.isUseMultiSourceMode()); + isEmptyAttr = false; + } + + + /** + * 提交数据 + * + * @return 界面上的更新数据 + */ + @Override + public CalculatorAttrMark updateBean() { + return new CalculatorAttrMark(false, queryCache.isSelected()) + .treeAsyncQuery(treeAsyncQuery.isSelected()) + .treeExpandLayer((int) treeExpandLayer.getValue()) + .useMultiSourceMode(multiSourceMode.isSelected()); + } + + /** + * 标题 + * + * @return 标题 + */ + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr"); + } + + private void showFeatureConfigPane() { + treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE)); + } + + private void resetTreeAsyncConfigPane() { + if (isEmptyAttr) { + treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC)); + } + } + + + private JDialog createJDialog() { + final FeatureFlagsPanel panel = new FeatureFlagsPanel(); + panel.populateBean(new FeatureFlagBean()); + return panel.showSmallWindow(SwingUtilities.getWindowAncestor(CalculateAttrPane.this), new DialogActionAdapter() { + @Override + public void doOk() { + panel.updateBean().saveModification(); + super.doOk(); + CalculateAttrPane.this.resetTreeAsyncConfigPane(); + CalculateAttrPane.this.showFeatureConfigPane(); + CalculateAttrPane.this.revalidate(); + CalculateAttrPane.this.repaint(); + } + }); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/FeatureFlagsPanel.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/FeatureFlagsPanel.java new file mode 100644 index 000000000..89aad3306 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/FeatureFlagsPanel.java @@ -0,0 +1,73 @@ +package com.fr.plugin.designer.menu; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.feature.FeatureFlag; +import com.fr.plugin.designer.menu.bean.FeatureFlagBean; +import com.fr.stable.collections.combination.Pair; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created by loy on 2020/4/14. + */ +public class FeatureFlagsPanel extends BasicBeanPane { + + private FeatureFlagBean bean; + private JPanel mainPanel; + + public FeatureFlagsPanel() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + mainPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); + JPanel content = + TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{mainPanel}}, + TableLayoutHelper.FILL_LASTCOLUMN, + 5, + 5 + ); + + this.add(content, BorderLayout.CENTER); + } + + @Override + public void populateBean(FeatureFlagBean featureFlagBean) { + this.bean = featureFlagBean; + mainPanel.removeAll(); + for (Pair entry : featureFlagBean.getAllFlags()) { + final FeatureFlag flag = entry.getFirst(); + Boolean selected = entry.getSecond(); + JPanel itemPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + final UICheckBox cb = new UICheckBox(flag.getDisplayName()); + cb.setSelected(selected); + cb.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + bean.modifyFlag(flag, cb.isSelected()); + } + }); + itemPanel.add(cb); + mainPanel.add(itemPanel); + } + } + + @Override + public FeatureFlagBean updateBean() { + return bean; + } + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature"); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerAction.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerAction.java new file mode 100644 index 000000000..20881fa09 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerAction.java @@ -0,0 +1,49 @@ +package com.fr.plugin.designer.menu; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.utils.DesignUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.web.URLConstants; +import com.fr.stable.StableUtils; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +/** + * @author Maksim + * Created in 2020/11/5 11:44 上午 + */ +public class LocalAnalyzerAction extends UpdateAction { + + public LocalAnalyzerAction() { + this.setMenuKeySet(ANALYZER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/plugin/designer/transform/analyzer.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String path = StableUtils.pathJoin("/url", URLConstants.ANALYZE_VIEW); + DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{}); + } + + private static final MenuKeySet ANALYZER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'R'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerMenu.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerMenu.java new file mode 100644 index 000000000..8e270010a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/LocalAnalyzerMenu.java @@ -0,0 +1,37 @@ +package com.fr.plugin.designer.menu; + +import com.fr.design.fun.impl.AbstractMenuHandler; +import com.fr.design.menu.ShortCut; + +/** + * @author Maksim + * Created in 2020/11/5 11:44 上午 + */ +public class LocalAnalyzerMenu extends AbstractMenuHandler { + private static final int DEFAULT_INSERT_POSITION = 13; + + @Override + public int insertPosition(int i) { + return DEFAULT_INSERT_POSITION; + } + + @Override + public boolean insertSeparatorBefore() { + return false; + } + + @Override + public boolean insertSeparatorAfter() { + return false; + } + + @Override + public String category() { + return SERVER; + } + + @Override + public ShortCut shortcut() { + return new LocalAnalyzerAction(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/menu/bean/FeatureFlagBean.java b/designer-realize/src/main/java/com/fr/plugin/designer/menu/bean/FeatureFlagBean.java new file mode 100644 index 000000000..a8de87323 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/menu/bean/FeatureFlagBean.java @@ -0,0 +1,36 @@ +package com.fr.plugin.designer.menu.bean; + +import com.fr.nx.feature.FeatureFlag; +import com.fr.nx.feature.FeatureManager; +import com.fr.stable.collections.combination.Pair; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by loy on 2020/4/14. + */ +public class FeatureFlagBean { + + private Map modifyMap = new HashMap<>(); + + public List> getAllFlags() { + List> flagList = new ArrayList<>(); + for (FeatureFlag flag : FeatureManager.getSupportFlags()) { + flagList.add(new Pair<>(flag, FeatureManager.getInstance().isFlagEnable(flag))); + } + return flagList; + } + + public void modifyFlag(FeatureFlag flag, boolean value) { + modifyMap.put(flag, value); + } + + public void saveModification() { + for (Map.Entry entry : modifyMap.entrySet()) { + FeatureManager.getInstance().setFlagEnable(entry.getKey(), entry.getValue()); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/monitor/DesignerMetricRecorder.java b/designer-realize/src/main/java/com/fr/plugin/designer/monitor/DesignerMetricRecorder.java new file mode 100644 index 000000000..c53fd6bfa --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/monitor/DesignerMetricRecorder.java @@ -0,0 +1,176 @@ +package com.fr.plugin.designer.monitor; + +import com.fr.design.mainframe.errorinfo.ErrorInfo; +import com.fr.general.ComparatorUtils; +import com.fr.intelli.record.ConsumePoint; +import com.fr.intelli.record.FocusPoint; +import com.fr.intelli.record.MetricRegistry; +import com.fr.intelli.record.Original; +import com.fr.json.JSON; +import com.fr.json.JSONArray; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.measure.metric.DBMetric; +import com.fr.message.ErrorMessage; +import com.fr.nx.session.SqlRecorder; +import com.fr.plugin.designer.toolbar.TransformResult; +import com.fr.plugin.monitor.MonitorContentUtils; + +import java.util.Date; + +/** + * Created by loy on 2021/1/18. + * + *

设计器埋点记录相关 + */ +public class DesignerMetricRecorder { + + private static final String LOCAL_IPV6_ADDRESS = "0:0:0:0:0:0:0:1"; + private static final String LOCAL_IPV4_ADDRESS = "127.0.0.1"; + private static final String LOCAL_DOMAIN = "localhost"; + + private static final String ATTR_TEMPLATE_ID = "templateid"; + private static final String ATTR_USERNAME = "username"; + private static final String ATTR_UUID = "uuid"; + private static final String ATTR_ACTIVE_KEY = "activekey"; + private static final String ATTR_TEST_LOG = "testlog"; + private static final String ATTR_REPORT_CONTENT = "reportcontent"; + private static final String ATTR_ERROR_STACK = "errorstack"; + private static final String IDENTIFICATION = "view_plus"; + + private static final String LAYER_TREE_EXEC_LAYER = "FR-P1201"; + private static final String TREE_MODE_CONSUME_ID = "FR-F6006"; + + private static final String TYPE_PAGE_PLUS = "page_plus"; + + private DesignerMetricRecorder() { + } + + public static void submitTreeModeFocusPoint(String ip, String username, String bookPath, String webTitle) { + FocusPoint point = FocusPoint.create(TREE_MODE_CONSUME_ID, bookPath, Original.PLUGIN); + point.setTime(new Date()); + point.setTitle(webTitle); + point.setText(bookPath); + point.setIp(parseIpToLocalhost(ip)); + point.setUsername(username); + try { + MetricRegistry.getMetric().submit(point); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + } + } + + public static void submitLayerTreeExecLayerFocusPoint(long start, String ip, String username, String bookPath, String webTitle, + SqlRecorder sqlRecorder) { + long finish = System.currentTimeMillis(); + long consume = finish - start; + ConsumePoint point = ConsumePoint.create(LAYER_TREE_EXEC_LAYER, consume, Original.PLUGIN); + point.setTime(start); + point.setFinish(finish); + point.setTitle(webTitle); + point.setText(bookPath); + point.setType(TYPE_PAGE_PLUS); + point.setIp(parseIpToLocalhost(ip)); + point.setUsername(username); + if (sqlRecorder != null) { + JSONObject body = JSONObject.create(); + JSONArray sql = JSONArray.create(); + for (String s : sqlRecorder.getSqlList()) { + sql.add(MonitorContentUtils.truncate(s, 150)); + } + JSONArray sqlTime = JSONArray.create(); + JSONArray sqlRowCount = JSONArray.create(); + for (DBMetric dbMetric : sqlRecorder.getDBMetric()) { + if (dbMetric != null) { + sqlTime.add(dbMetric.getSqlTime()); + sqlRowCount.add(dbMetric.getRowCount()); + } + } + body.put("sql", sql); + body.put("sqltime", sqlTime); + body.put("row", sqlRowCount); + point.setBody(body.toString()); + } + try { + MetricRegistry.getMetric().submit(point); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + } + } + + /** + * 模板转换失败的埋点 + */ + public static void submitFailedTransform(TransformResult result, String templateID, String name, Exception e) { + if (isPressureTesting()) { + return; + } + saveAsJSON(result, templateID, name, e); + } + + /** + * 记录在设计器的错误信息收集中 + */ + private static void saveToErrorInfo(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); + jo.put(ATTR_USERNAME, IDENTIFICATION); + jo.put(ATTR_UUID, IDENTIFICATION); + jo.put(ATTR_ACTIVE_KEY, IDENTIFICATION); + jo.put(ATTR_TEMPLATE_ID, templateID); + jo.put(ATTR_REPORT_CONTENT, name); + if (result == TransformResult.FAILED) { + jo.put(ATTR_TEST_LOG, e); + jo.put(ATTR_ERROR_STACK, e.getMessage()); + } else { + jo.put(ATTR_TEST_LOG, unsupportMessage); + } + new ErrorInfo().saveFileToCache(jo); + } + + /** + * 记录在fine_record_error表中 + */ + private static void saveToErrorMessage(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + String errorMessage = unsupportMessage; + if (result == TransformResult.FAILED) { + errorMessage = e.getStackTrace()[0].toString(); + } + ErrorMessage message = ErrorMessage.build(e == null ? errorMessage : e.getMessage(), errorMessage); + message.setTname(name); + message.setDisplayName(name); + MetricRegistry.getMetric().submit(message); + } + + private static void saveAsJSON(TransformResult result, String templateID, String name, Exception e) { + saveToErrorInfo(result, templateID, name, e, null); + saveToErrorMessage(result, templateID, name, e, null); + } + + /** + * 预编译中不支持的功能的埋点 + */ + public static void submitUnSupportTransform(TransformResult result, String templateID, String name, String unsupportMessage) { + if (isPressureTesting()) { + return; + } + saveToErrorInfo(result, templateID, name, null, unsupportMessage); + saveToErrorMessage(result, templateID, name, null, unsupportMessage); + } + + private static String parseIpToLocalhost(String ip) { + if (ComparatorUtils.equals(ip, LOCAL_IPV4_ADDRESS) || ComparatorUtils.equals(ip, LOCAL_IPV6_ADDRESS)) { + return LOCAL_DOMAIN; + } + return ip; + } + + /** + * 埋点对压测性能的影响控制参数 + * + * @return 是否压测 + */ + public static boolean isPressureTesting() { + return Boolean.parseBoolean(System.getProperty("monitorDebug")); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/CompileAction.java b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/CompileAction.java new file mode 100644 index 000000000..6a5b6d2e1 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/CompileAction.java @@ -0,0 +1,116 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.utils.CompileTransformUtil; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.OK_OPTION; +import static javax.swing.JOptionPane.WARNING_MESSAGE; + +/** + * Created by kerry on 2019-10-14 + */ +public class CompileAction extends UpdateAction { + public static final Icon TRANS_ICON = IOUtils.readIcon("/com/fr/plugin/designer/transform.png"); + + private static final MenuKeySet COMPILE_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER); + } + }; + + public CompileAction() { + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(COMPILE_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(TRANS_ICON); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public void actionPerformed(ActionEvent e) { + JTemplate jtemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate(); + if (jtemplate == null || jtemplate.getEditingFILE() == null) { + return; + } + FILE currentTemplate = jtemplate.getEditingFILE(); + if(currentTemplate instanceof FileNodeFILE){ + transformAndDisplay(jtemplate); + }else { + //模板不在报表环境下,提示保存 + int selVal = showConfirmDialog( + DesignerContext.getDesignerFrame(), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Preview_Message"), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Transformer_Tips"), + OK_CANCEL_OPTION, + WARNING_MESSAGE); + + if (OK_OPTION == selVal) { + //保存成功才会执行编译 + if (jtemplate.saveAsTemplate2Env()) { + transformAndDisplay(jtemplate); + } + } + } + + } + + //编译模板并展示 + private void transformAndDisplay(JTemplate jtemplate){ + String path = jtemplate.getEditingFILE().getPath(); + TemplateTransformer transformer = TemplateTransformer.parse(path); + FILE targetFile = CompileTransformUtil.getTargetFile(jtemplate, transformer); + TransformResult result = transformer.transform(jtemplate, targetFile); + jtemplate.fireJTemplateSaved(); + result.display(); + } + + @Override + public boolean isEnabled() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path = jt.getEditingFILE().getPath(); + return FileExtension.CPTX.matchExtension(path) || FileExtension.CPT.matchExtension(path); + } + + @Override + public JComponent createToolBarComponent() { + UIButton transBtn = (UIButton) super.createToolBarComponent(); + transBtn.set4ToolbarButton(); + transBtn.setToolTipText(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip")); + return transBtn; + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformer.java b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformer.java new file mode 100644 index 000000000..9ce7ec272 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformer.java @@ -0,0 +1,221 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.compile.CompileStatus; +import com.fr.nx.compile.ReportCompiler; +import com.fr.nx.compile.adapter.LegacyWorkBookAdapter; +import com.fr.nx.compile.util.ReportCompileUtils; +import com.fr.nx.cptx.CptxIOManager; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.io.handle.CptxTemplateHandle; +import com.fr.plugin.designer.cptx.io.DesignReadWritableProvider; +import com.fr.nx.cptx.monitor.CompileMonitorHandler; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.nx.data.layer.LayerItem; +import com.fr.nx.data.layer.LayerProps; +import com.fr.nx.template.compile.CompiledReport; +import com.fr.plugin.designer.monitor.DesignerMetricRecorder; +import com.fr.stable.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.OutputStream; + +import static com.fr.base.extension.FileExtension.ALL; +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * 模板转换器, 可以把cptx模板转为cpt, 或者cpt模板转为cptx. + * 以后可以扩展支持frm frmx互相转换 + */ + +public enum TemplateTransformer { + + TO_CPTX(CPT) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + TransformResultInfo resultInfo = compileCPTX(workbook, file); + if (needDoAfterTransformed(resultInfo.getResult())) { + doAfterTransformed(file, jtemplate); + } + return resultInfo.getResult(); + } + }, + TO_CPT(CPTX) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + try { + workbook.export(file.asOutputStream()); + doAfterTransformed(file, jtemplate); + return TransformResult.SUCCESS; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResult.FAILED; + } + } + }, + OTHER(ALL); + private FileExtension extension; + + TemplateTransformer(FileExtension extension) { + this.extension = extension; + } + + public TransformResult transform(JTemplate jtemplate) { + return transform(jtemplate, jtemplate.getEditingFILE()); + } + + public TransformResult transform(JTemplate jtemplate, FILE newFile) { + return TransformResult.UNSUPPORT; + } + + public static TemplateTransformer parse(String path) { + for (TemplateTransformer transformer : values()) { + if (transformer.extension.matchExtension(path)) { + return transformer; + } + } + return OTHER; + } + + private static boolean needDoAfterTransformed(TransformResult result) { + return ComparatorUtils.equals(TransformResult.SUCCESS, result) + || ComparatorUtils.equals(TransformResult.UNSUPPORT, result); + } + + private static void doAfterTransformed(FILE file, JTemplate jtemplate) { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (ComparatorUtils.equals(file.getPath(), jt.getPath())) { + HistoryTemplateListCache.getInstance().closeSelectedReport(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + return; + } + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + MutilTempalteTabPane.getInstance().closeFormat(jt); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + } + + + public static FILE createOutputFile(String oldPath, String oldSuffix, String newSuffix) { + String newPath = generateNewPath(oldPath, oldSuffix, newSuffix); + return new FileNodeFILE(new FileNode(newPath, false)); + } + + private static String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + if (StringUtils.isEmpty(oldPath) || StringUtils.isEmpty(oldSuffix) || StringUtils.isEmpty(newSuffix)) { + return oldPath; + } + + if (oldPath.endsWith(oldSuffix)) { + return StringUtils.cutStringEndWith(oldPath, oldSuffix) + newSuffix; + } + return oldPath; + } + + /** + * 编译和保存 + * + * @param workbook work + * @param file file + * @return 编译保存结果 + */ + @NotNull + public static TransformResultInfo compileCPTX(WorkBook workbook, FILE file) { + //对于非工作目录的cptx,修改无需执行编译 + if(!(file instanceof FileNodeFILE)){ + try { + OutputStream outputStream = file.asOutputStream(); + workbook.export(outputStream); + return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true); + }catch (Exception e){ + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false); + } + } + boolean saved; + CompiledReport report = null; + CompileStatus compileStatus = CompileStatus.SUCCEED; + if (workbook == null || file == null) { + return TransformResultInfo + .generateResult(TransformResult.FAILED, "work and file must not be null") + .saved(false); + } + String failMessage = null; + // 编译 + ReportCompiler compiler; + try { + compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook)); + long startTime = System.currentTimeMillis(); + compiler.compile(); + report = compiler.getCompiledReport(); + // 折叠树埋点 + LayerProps props = ReportCompileUtils.getLayerProps(report); + LayerItem[] items; + if (props != null && (items = props.getLayerItems()) != null) { + CompileMonitorHandler.submitTreeCompileFocusPoint( + startTime, file.getPath(), items.length, + props.getExpandLayer(), true + ); + } + compileStatus = compiler.getStatus(); + failMessage = compiler.getFailMessage(); + long endTime = System.currentTimeMillis(); + CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), ""); + if (compileStatus != CompileStatus.SUCCEED) { + DesignerMetricRecorder.submitUnSupportTransform( + TransformResult.UNSUPPORT, + workbook.getTemplateID(), + file.getName(), + compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null + ); + } + } catch (Exception exception) { + String templateID = workbook.getTemplateID(); + String fileName = file.getName(); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception); + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + } + + // 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览 + CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage); + // 保存 + DesignReadWritableProvider cptx = new DesignReadWritableProvider(file); + CptxTemplateHandle handle = CptxIOManager.create(template, cptx); + try { + saved = handle.save(); + } catch (Exception exception) { + // 存储cptx格式报错或者失败 + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception); + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false); + } + // 读取可 web 预览模版并缓存 + try { + // todo 是否考虑异步 + String timestampedPath = CptxFileUtils.getTimestampedPath(file.getPath()); + CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate(); + CptxTemplatePool.getInstance().addCptxTemplate(timestampedPath, previewCptxTemplate); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (report == null) { + // 编译报错或者失败 + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved); + } + return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformerUIButton.java b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformerUIButton.java new file mode 100644 index 000000000..a6b366836 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TemplateTransformerUIButton.java @@ -0,0 +1,20 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.design.fun.impl.AbstractDsinFrameUpButtonProvider; +import com.fr.design.gui.ibutton.UIButton; + + +public class TemplateTransformerUIButton extends AbstractDsinFrameUpButtonProvider { + @Override + public UIButton[] getUpButtons(int menuState) { + CompileAction compileAction = new CompileAction(); + UIButton transBtn = (UIButton) compileAction.createToolBarComponent(); + return new UIButton[]{transBtn}; + } + + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResult.java b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResult.java new file mode 100644 index 000000000..2fc45e703 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResult.java @@ -0,0 +1,55 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.design.file.TemplateTreePane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.compile.CompileStatus; + +import javax.swing.JOptionPane; + +public enum TransformResult { + + SUCCESS(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Success")) { + @Override + public void display() { + // 转换成功后, 刷新下目录树 + TemplateTreePane.getInstance().refresh(); + super.display(); + } + }, + FAILED(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Failed")), + UNSUPPORT(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Unsupport")){ + @Override + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), TransformResult.SUCCESS.toString()); + } + }; + + private String msg; + + private TransformResult(String msg) { + this.msg = msg; + } + + // 展示结果 + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), this.toString()); + } + + @Override + public String toString() { + return this.msg; + } + + public static TransformResult parse(CompileStatus status) { + switch (status) { + case SUCCEED: + return TransformResult.SUCCESS; + case FAILED_UNSUPPORT: + return TransformResult.UNSUPPORT; + default: + return TransformResult.FAILED; + } + + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResultInfo.java b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResultInfo.java new file mode 100644 index 000000000..581f440bd --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/toolbar/TransformResultInfo.java @@ -0,0 +1,64 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import com.fr.stable.StringUtils; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfo { + + private boolean saved; + private TransformResult result; + private final String transformLog; + + public static TransformResultInfo generateResult(TransformResult result, String transformLog) { + return new TransformResultInfo(result, transformLog); + } + + public static TransformResultInfo generateResult(TransformResult result) { + return new TransformResultInfo(result, StringUtils.EMPTY); + } + + + private TransformResultInfo(TransformResult result, String transformLog) { + this.result = result; + this.transformLog = transformLog; + this.saved = false; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public TransformResultInfo saved(boolean saved) { + setSaved(saved); + return this; + } + + public TransformResult getResult() { + return result; + } + + public void setResult(TransformResult result) { + this.result = result; + } + + public String getTransformLog() { + switch (this.result) { + case FAILED: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"); + case SUCCESS: + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"); + case UNSUPPORT: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"); + } + return transformLog; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformProgress.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformProgress.java new file mode 100644 index 000000000..25c089941 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformProgress.java @@ -0,0 +1,25 @@ +package com.fr.plugin.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformProgress { + private double progress = 0.0D; + private int total = 0; + private int complete = 0; + + public BatchTransformProgress(int total) { + this.total = total; + } + + + public double getProgress() { + return this.progress; + } + + + public void updateProgress() { + this.complete++; + this.progress = this.complete * 1D / this.total; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformUtil.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformUtil.java new file mode 100644 index 000000000..4b12a2b02 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformUtil.java @@ -0,0 +1,25 @@ +package com.fr.plugin.designer.transform; + +import com.fr.file.filetree.FileNode; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtil { + private BatchTransformUtil() { + + } + + public static FileNode[] filterTransformedFile(FileNode[] fileNodes, List transformedList){ + List list = new ArrayList(); + for (FileNode fileNode : fileNodes) { + if (!transformedList.contains(fileNode)) { + list.add(fileNode); + } + } + return list.toArray(new FileNode[list.size()]); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformer.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformer.java new file mode 100644 index 000000000..5993dd45c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/BatchTransformer.java @@ -0,0 +1,71 @@ +package com.fr.plugin.designer.transform; + +import com.fr.design.utils.concurrent.ThreadFactoryBuilder; +import com.fr.file.filetree.FileNode; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.designer.toolbar.TransformResultInfo; +import com.fr.plugin.designer.utils.CompileTransformUtil; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformer { + private BatchTransformProgress progress = new BatchTransformProgress(0); + private Map transformResults = new ConcurrentHashMap(); + private UpdateCallBack updateCallBack; + private static final int MAXPOOLSIZE = 5; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + private ExecutorService threadPoolExecutor = + PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + + public BatchTransformer(UpdateCallBack updateCallBack) { + this.updateCallBack = updateCallBack; + } + + + public void batchTransform(List fileNodes) { + //先清理下 + transformResults.clear(); + progress = new BatchTransformProgress(fileNodes.size()); + for (FileNode fileNode : fileNodes) { + transform(fileNode); + } + } + + private void transform(final FileNode fileNode) { + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + TransformResultInfo transformResult = CompileTransformUtil.compileFile(fileNode); + transformResults.put(fileNode, transformResult); + updateTransformProgress(); + } + }); + } + + private synchronized void updateTransformProgress() { + progress.updateProgress(); + updateCallBack.updateProgress(progress.getProgress()); + } + + public void shutDown() { + if (threadPoolExecutor != null) { + threadPoolExecutor.shutdownNow(); + } + threadPoolExecutor = PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + updateCallBack.shutDown(); + } + + public Map getResults() { + return transformResults; + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/UpdateCallBack.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/UpdateCallBack.java new file mode 100644 index 000000000..221abbf0f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/UpdateCallBack.java @@ -0,0 +1,22 @@ +package com.fr.plugin.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public interface UpdateCallBack { + /** + * 更新进度 + * @param progress 进度 + */ + void updateProgress(double progress); + + /** + * 进度中断 + */ + void shutDown(); + + /** + * 进度重置 + */ + void reset(); +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformDialog.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformDialog.java new file mode 100644 index 000000000..e2287a4f4 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformDialog.java @@ -0,0 +1,61 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class BatchTransformDialog extends JDialog implements ActionListener { + private UIButton closeBtn; + + public BatchTransformDialog(Frame parent, JPanel contentPane) { + super(parent, true); + + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + closeBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Close")); + closeBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(closeBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(closeBtn); + + this.setSize(new Dimension(900, 600)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + dialogExit(); + } + + + private void dialogExit() { + this.dispose(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformPane.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformPane.java new file mode 100644 index 000000000..4b77554a1 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/BatchTransformPane.java @@ -0,0 +1,223 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.base.extension.FileExtension; +import com.fr.design.dialog.BasicPane; +import com.fr.design.file.NodeAuthProcessor; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itree.filetree.FileNodeComparator; +import com.fr.design.gui.itree.filetree.FileNodeConstants; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.tree.DefaultTreeModel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformPane extends BasicPane { + private UITextField searchField; + private TransformFileTree tree; + private Dialog showDialog; + private TransformPreparePane preparePane; + private TransformResultPane resultPane; + + + public BatchTransformPane() { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + this.showDialog = new BatchTransformDialog(designerFrame, this); + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initNorthPane(); + initSouthPane(); + } + + private void initNorthPane() { + UILabel northTip = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Tip")); + northTip.setForeground(Color.decode("#8F8F92")); + northTip.setBorder(BorderFactory.createEmptyBorder(0, 550, 10, 10)); + this.add(northTip, BorderLayout.NORTH); + } + + private void initSouthPane() { + preparePane = new TransformPreparePane(this.showDialog, this); + tree = new TransformFileTree(preparePane); + this.add(preparePane, BorderLayout.CENTER); + initLeftPane(); + initRightPane(); + } + + private void initLeftPane() { + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{FileExtension.CPT.getSuffix()}); + tree.setDigIn(true); + tree.setFileNodeFilter(filter); + UIScrollPane scrollPane = new UIScrollPane(tree); + scrollPane.setPreferredSize(new Dimension(320, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(12, 0, 0, 0)); + tree.refreshEnv(); + JPanel selectPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Select_Template")); + JPanel searchPane = initSearchPane(); + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.add(searchPane, BorderLayout.NORTH); + jPanel.add(scrollPane, BorderLayout.WEST); + jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + selectPane.add(jPanel); + selectPane.setPreferredSize(new Dimension(330, 501)); + this.add(selectPane, BorderLayout.WEST); + } + + + private void initRightPane() { + resultPane = new TransformResultPane(); + this.add(resultPane, BorderLayout.EAST); + } + + private JPanel initSearchPane() { + JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + jPanel.setBorder(BorderFactory.createEmptyBorder()); + searchField = new UITextField(); + searchField.requestFocus(); + searchField.addKeyListener(keyFieldKeyListener); + searchField.setPreferredSize(new Dimension(261, 20)); + jPanel.add(searchField); + UIButton searchBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Search")); + searchBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + search(); + } + }); + searchBtn.setPreferredSize(new Dimension(44, 20)); + jPanel.add(searchBtn); + return jPanel; + } + + + private KeyAdapter keyFieldKeyListener = new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + search(); + e.consume(); + } + } + }; + + + + private void search() { + //重新构建TreeModel + filter(searchField.getText()); + ExpandMutableTreeNode rootNode = (ExpandMutableTreeNode) tree.getModel().getRoot(); + ((DefaultTreeModel) tree.getModel()).reload(rootNode); + // 展开所有isExpanded为true的TreeNode + rootNode.expandCurrentTreeNode(tree); + } + + public void filter(String filterString) { + NodeAuthProcessor.getInstance().refresh(); + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + NodeAuthProcessor.getInstance().fixTreeNodeAuth(rootTreeNode); + filter(rootTreeNode, filterString); + defaultTreeModel.reload(rootTreeNode); + } + + private void filter(ExpandMutableTreeNode rootTreeNode, String filterString) { + rootTreeNode.removeAllChildren(); + + FileNode[] fns; + fns = listFileNodes(rootTreeNode); + + ExpandMutableTreeNode[] subTreeNodes = NodeAuthProcessor.getInstance().parser2TreeNodeArray(fns); + + for (ExpandMutableTreeNode node : subTreeNodes) { + filter(node, filterString); + if (node.getChildCount() > 0 || (node.getChildCount() == 0 && node.toString().contains(filterString))) { + node.setExpanded(true); + rootTreeNode.add(node); + } + } + + } + + private FileNode[] listFileNodes(ExpandMutableTreeNode rootTreeNode) { + if (rootTreeNode == null) { + return new FileNode[0]; + } + + Object object = rootTreeNode.getUserObject(); + if (!(object instanceof FileNode)) { + return new FileNode[0]; + } + + FileNode[] fileNodes = null; + try { + fileNodes = tree.listFile(((FileNode) object).getEnvPath()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (fileNodes == null) { + fileNodes = new FileNode[0]; + } + Arrays.sort(fileNodes, new FileNodeComparator(FileNodeConstants.getSupportFileTypes())); + return fileNodes; + } + + public void resetFilePaths(Map resultMap) { + this.tree.resetSelectedPaths(); + Iterator iterator = resultMap.keySet().iterator(); + List list = new ArrayList(); + while (iterator.hasNext()){ + FileNode node = iterator.next(); + list.add(node); + } + this.tree.addTransformedList(list); + this.tree.refresh(); + resultPane.populate(resultMap); + } + + public void removeSelectedNode(FileNode fileNode) { + String path = fileNode.getEnvPath(); + this.tree.removeSelectedPath(path); + } + + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + public Dialog showDialog() { + return this.showDialog; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/PrepareTransformFileList.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/PrepareTransformFileList.java new file mode 100644 index 000000000..30b4960ab --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/PrepareTransformFileList.java @@ -0,0 +1,79 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * Created by kerry on 2020-01-13 + */ +public class PrepareTransformFileList extends UIList { + private TransformPreparePane transformingPane; + private static final int DELETE_RANGE = 20; + + + public PrepareTransformFileList(final TransformPreparePane transformingPane) { + super(); + this.transformingPane = transformingPane; + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + return BaseUtils.readIcon("/com/fr/plugin/designer/transform/tab_close.png"); + } + }); + this.addMouseListener(getListMouseListener()); + } + + + private MouseListener getListMouseListener() { + return new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent evt) { + JList list = (JList) evt.getSource(); + int selectedIndex = list.getSelectedIndex(); + Rectangle rectangle = list.getCellBounds(selectedIndex, selectedIndex); + if (SwingUtilities.isLeftMouseButton(evt) + && pointInSelected(rectangle, evt.getX(), evt.getY())) { + Object value = PrepareTransformFileList.this.getSelectedValue(); + if (value != null) { + transformingPane.removeSelectedNode((FileNode) value); + } + } + } + }; + } + + private boolean pointInSelected(Rectangle rectangle, int x, int y) { + if (rectangle == null) { + return false; + } + return x >= rectangle.x + rectangle.width - DELETE_RANGE && + x <= rectangle.x + rectangle.width && + y >= rectangle.y && y <= rectangle.y + rectangle.height; + } +} + diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformFileTree.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformFileTree.java new file mode 100644 index 000000000..d03f31d10 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformFileTree.java @@ -0,0 +1,204 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.base.FRContext; +import com.fr.base.extension.FileExtension; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTree; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeCellRenderer; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeSelectionModel; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.remote.ui.tree.FileAuthorityTree; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.plugin.designer.transform.BatchTransformUtil; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import java.awt.AlphaComposite; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformFileTree extends FileAuthorityTree { + private TransformPreparePane preparePane; + private static final float CHECKBOX_ENABLE_OPACITY = 0.4f; + + private List transformedList = new ArrayList(); + + public TransformFileTree(TransformPreparePane preparePane) { + this.preparePane = preparePane; + } + + public void addTransformedList(List removeList) { + this.transformedList.addAll(removeList); + } + + @Override + protected CheckBoxTree.Handler createHandler() { + return new CheckBoxTree.Handler(this) { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + TreePath treePath = this.getTreePathForMouseEvent(e); + if (treePath == null) { + return; + } + CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel(); + boolean selected = selectionModel.isPathSelected(treePath, selectionModel.isDigIn()); + ExpandMutableTreeNode lastPathComponent = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + List selectedFileNodes = filterBatchFileNode(lastPathComponent); + preparePane.removeTransformNode(selectedFileNodes); + if (selected) { + preparePane.addTransformNode(selectedFileNodes); + } + + } + }; + } + + + private List filterBatchFileNode(ExpandMutableTreeNode treeNode) { + List fileNodeList = new ArrayList<>(); + int childCount = treeNode.getChildCount(); + if (childCount > 0) { + loadPendingChildTreeNode(treeNode); + int expandChildCount = treeNode.getChildCount(); + for (int i = 0; i < expandChildCount; i++) { + fileNodeList.addAll(filterBatchFileNode((ExpandMutableTreeNode) treeNode.getChildAt(i))); + } + } else { + FileNode fileNode = (FileNode) treeNode.getUserObject(); + boolean locked = fileNodeLocked(treeNode); + if (!fileNode.isDirectory() && !locked) { + fileNodeList.add((FileNode) treeNode.getUserObject()); + } + } + return fileNodeList; + } + + + private boolean fileNodeLocked(ExpandMutableTreeNode treeNode) { + Object userObj = treeNode.getUserObject(); + if (userObj instanceof FileNode) { + FileNode node = (FileNode) userObj; + String lock = node.getLock(); + if (lock != null && !node.getUserID().equals(lock)) { + return true; + } + } + return false; + } + + public void resetSelectedPaths() { + CheckBoxTreeSelectionModel selectionModel = this.getCheckBoxTreeSelectionModel(); + selectionModel.clearSelection(); + } + + @Override + public void selectCheckBoxPaths(String[] paths) { + if (paths == null || paths.length == 0) { + return; + } + + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + List res = new ArrayList<>(); + for (String path : paths) { + TreePath treePath = getSelectedPath(treeNode, path); + if (treePath != null) { + res.add(treePath); + } + } + // 勾选中这些结点 + this.getCheckBoxTreeSelectionModel().setSelectionPaths(res.toArray(new TreePath[0])); + } + + private TreePath getSelectedPath(ExpandMutableTreeNode treeNode, String path) { + //可以只在选中的path中选择 + for (int i = 0, len = treeNode.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); + if (childTreeNode.getChildCount() > 0) { + loadPendingChildTreeNode(childTreeNode); + TreePath treePath = getSelectedPath(childTreeNode, path); + if (treePath != null) { + return treePath; + } + } + if (!(childTreeNode.getUserObject() instanceof FileNode)) { + continue; + } + FileNode fileNode = (FileNode) childTreeNode.getUserObject(); + if (ComparatorUtils.equals(path, fileNode.getEnvPath())) { + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + return new TreePath(model.getPathToRoot(childTreeNode)); + } + } + return null; + } + + public void removeSelectedPath(String path) { + if (path == null) { + return; + } + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + TreePath selectedPath = getSelectedPath(treeNode, path); + if (selectedPath != null) { + this.getCheckBoxTreeSelectionModel().removeSelectionPath(selectedPath); + + } + } + + + @Override + public FileNode[] listFile(String path) { + // 支持插件扩展, 先从env的filter拿, 再从插件拿 + Set supportTypes = new HashSet(); + for (String temp : this.filter.getSupportedTypes()) { + supportTypes.add(FileExtension.parse(temp)); + } + FileNode[] fileNodes = FRContext.getFileNodes().list( + path, + supportTypes.toArray(new FileExtension[supportTypes.size()]) + ); + return BatchTransformUtil.filterTransformedFile(fileNodes, transformedList); + } + + @Override + public boolean isCheckBoxEnabled(TreePath path) { + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) path.getLastPathComponent(); + return !fileNodeLocked(treeNode); + } + + @Override + protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) { + final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer) { + @Override + public void paint(Graphics g) { + if (!_checkBox.isEnabled()) { + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, CHECKBOX_ENABLE_OPACITY); + ((Graphics2D) g).setComposite(composite); + } + super.paint(g); + } + }; + addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue()); + } + }); + return checkBoxTreeCellRenderer; + } + + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformPreparePane.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformPreparePane.java new file mode 100644 index 000000000..db0bf2be8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformPreparePane.java @@ -0,0 +1,130 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.toolbar.TransformResultInfo; +import com.fr.plugin.designer.transform.BatchTransformer; +import com.fr.plugin.designer.transform.UpdateCallBack; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformPreparePane extends JPanel { + private static final String INITIAL_DISPLAY_TEXT = "0"; + private PrepareTransformFileList fileList; + private List selectedFileNodes; + private UpdateProgressDialog dialog; + private BatchTransformer transformer; + private UpdateCallBack updateProgressPane; + private Dialog parentDialog; + private UILabel transCountLabel; + private BatchTransformPane batchTransformPane; + private UIButton startTransform; + + public TransformPreparePane(Dialog parentDialog, BatchTransformPane batchTransformPane) { + this.batchTransformPane = batchTransformPane; + this.parentDialog = parentDialog; + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + updateProgressPane = new UpdateProgressPane(this); + transformer = new BatchTransformer(updateProgressPane); + fileList = new PrepareTransformFileList(this); + selectedFileNodes = new ArrayList<>(); + initPane(); + } + + private void initPane() { + JPanel transformPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Template_To_Transform")); + transformPane.setPreferredSize(new Dimension(270, 501)); + startTransform = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Start")); + startTransform.setEnabled(false); + addStartTransformListener(startTransform); + transCountLabel = new UILabel(INITIAL_DISPLAY_TEXT); + JPanel northPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + northPane.add(startTransform); + northPane.add(Box.createHorizontalStrut(160)); + northPane.add(transCountLabel); + transformPane.add(northPane, BorderLayout.NORTH); + UIScrollPane scrollPane = new UIScrollPane(fileList); + scrollPane.setPreferredSize(new Dimension(260, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + transformPane.add(scrollPane, BorderLayout.CENTER); + this.add(transformPane, BorderLayout.CENTER); + } + + private void addStartTransformListener(UIButton startTransform) { + startTransform.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + //开始转换 + transformer.batchTransform(selectedFileNodes); + displayProgressPane(); + } + + + private void displayProgressPane() { + dialog = new UpdateProgressDialog(transformer, parentDialog, (JPanel) updateProgressPane); + dialog.setVisible(true); + } + }); + } + + public void addTransformNode(List fileNodeList) { + selectedFileNodes.addAll(fileNodeList); + buildFileList(); + + } + + public void removeTransformNode(List fileNodeList) { + selectedFileNodes.removeAll(fileNodeList); + buildFileList(); + } + + public void removeSelectedNode(FileNode fileNode) { + selectedFileNodes.remove(fileNode); + buildFileList(); + this.batchTransformPane.removeSelectedNode(fileNode); + } + + private void buildFileList() { + DefaultListModel listModel = new DefaultListModel(); + int count = selectedFileNodes.size(); + for (int i = count - 1; i >= 0; i--) { + listModel.addElement(selectedFileNodes.get(i)); + } + this.fileList.setModel(listModel); + startTransform.setEnabled(selectedFileNodes.size() > 0); + transCountLabel.setText(String.valueOf(selectedFileNodes.size())); + } + + public void complete() { + dialog.dialogExit(); + updateProgressPane.reset(); + Map resultMap = transformer.getResults(); + resetFileNodeList(); + this.batchTransformPane.resetFilePaths(resultMap); + } + + private void resetFileNodeList(){ + this.selectedFileNodes.clear(); + buildFileList(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultList.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultList.java new file mode 100644 index 000000000..5e53fee86 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultList.java @@ -0,0 +1,70 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; +import com.fr.plugin.designer.toolbar.TransformResultInfo; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ListSelectionModel; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformResultList extends UIList { + private Map resultMap; + private static final Icon FAILED_ICON = BaseUtils.readIcon("/com/fr/plugin/designer/transform/transform_failed.png"); + private static final Icon SUCCESS_ICON = BaseUtils.readIcon("/com/fr/plugin/designer/transform/transform_success.png"); + private static final Icon UNSUPPORT_ICON = BaseUtils.readIcon("/com/fr/plugin/designer/transform/transform_unsupport.png"); + + public TransformResultList() { + super(); + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + if (value != null) { + TransformResultInfo resultInfo = resultMap.get(value); + switch (resultInfo.getResult()) { + case FAILED: + return FAILED_ICON; + case SUCCESS: + return SUCCESS_ICON; + case UNSUPPORT: + return UNSUPPORT_ICON; + } + } + return null; + } + }); + } + + public void populate(Map resultMap) { + this.resultMap = resultMap; + DefaultListModel listModel = new DefaultListModel(); + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + FileNode key = entry.getKey(); + listModel.addElement(key); + } + this.setModel(listModel); + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultPane.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultPane.java new file mode 100644 index 000000000..531ecad02 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/TransformResultPane.java @@ -0,0 +1,110 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.toolbar.TransformResult; +import com.fr.plugin.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-10 + */ +public class TransformResultPane extends JPanel { + private TransformResultList resultList; + private UITextArea resultInfo; + private Map resultMap; + private UILabel successTip; + + public TransformResultPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initPane(); + } + + private void initPane() { + JPanel resultPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Result")); + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultList = new TransformResultList(); + addValueChangeListener(); + UIScrollPane scrollPane = new UIScrollPane(resultList); + scrollPane.setPreferredSize(new Dimension(260, 260)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + successTip = new UILabel(""); + successTip.setBorder(BorderFactory.createEmptyBorder(5, 150, 5, 10)); + northPane.add(successTip, BorderLayout.NORTH); + northPane.add(scrollPane, BorderLayout.CENTER); + resultPane.add(northPane); + + JPanel resultInfoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultInfoPane.setPreferredSize(new Dimension(270, 165)); + resultInfoPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); + UILabel transformLogLabel = new UILabel( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Logs")); + transformLogLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + resultInfoPane.add(transformLogLabel, BorderLayout.NORTH); + resultInfo = new UITextArea(); + resultInfo.setBackground(Color.white); + resultInfo.setLineWrap(true); + resultInfo.setWrapStyleWord(true); + resultInfo.setEditable(false); + UIScrollPane resultScrollPane = new UIScrollPane(resultInfo); + resultInfoPane.add(resultScrollPane, BorderLayout.CENTER); + this.add(resultPane, BorderLayout.NORTH); + this.add(resultInfoPane, BorderLayout.CENTER); + } + + private void addValueChangeListener() { + resultList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + FileNode selectedValue = (FileNode) resultList.getSelectedValue(); + if (resultInfo != null && selectedValue != null) { + TransformResultInfo result = resultMap.get(selectedValue); + resultInfo.setText(result.getTransformLog()); + } + } + }); + } + + public void populate(Map resultMap) { + int count = getSuccessCount(resultMap); + String tip = InterProviderFactory.getProvider().getLocText( + "Fine-Plugin_Engine_Transform_Result_Tip", String.valueOf(count)); + successTip.setText(tip); + this.resultMap = resultMap; + resultList.populate(resultMap); + if (resultList.getModel().getSize() > 0) { + resultList.setSelectedIndex(0); + FileNode firstResult = (FileNode) resultList.getModel().getElementAt(0); + resultInfo.setText(resultMap.get(firstResult).getTransformLog()); + } + } + + private int getSuccessCount(Map resultMap) { + int count = 0; + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + TransformResultInfo resultInfo = entry.getValue(); + if (ComparatorUtils.equals(TransformResult.SUCCESS, resultInfo.getResult())) { + count++; + } + } + return count; + } + +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UIListControlCellRenderer.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UIListControlCellRenderer.java new file mode 100644 index 000000000..796ae62ea --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UIListControlCellRenderer.java @@ -0,0 +1,86 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; +import sun.swing.DefaultLookup; + +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-01-14 + */ +public class UIListControlCellRenderer extends JPanel implements ListCellRenderer { + private UILabel content; + private UILabel controlLabel; + private Color initialLabelForeground; + + public UIListControlCellRenderer() { + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + content = new UILabel(); + initialLabelForeground = content.getForeground(); + controlLabel = new UILabel(); + controlLabel.setPreferredSize(new Dimension(16, 20)); + this.add(content, BorderLayout.CENTER); + this.add(controlLabel, BorderLayout.EAST); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + setComponentOrientation(list.getComponentOrientation()); + Color bg = null; + Color fg = null; + + JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground"); + fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground"); + + isSelected = true; + } + + if (isSelected) { + setBackground(bg == null ? list.getSelectionBackground() : bg); + setForeground(fg == null ? list.getSelectionForeground() : fg); + content.setForeground(Color.WHITE); + + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + content.setForeground(initialLabelForeground); + } + + content.setText((value == null) ? StringUtils.EMPTY : value.toString()); + Icon leftLabelIcon = getLeftLabelIcon(value); + if (leftLabelIcon != null) { + content.setIcon(leftLabelIcon); + } + Icon rightLabelIcon = getRightLabelIcon(value); + if (rightLabelIcon != null) { + controlLabel.setIcon(rightLabelIcon); + } + return this; + } + + protected Icon getLeftLabelIcon(Object value) { + return null; + } + + protected Icon getRightLabelIcon(Object value) { + return null; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressDialog.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressDialog.java new file mode 100644 index 000000000..a980dd822 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressDialog.java @@ -0,0 +1,70 @@ +package com.fr.plugin.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.transform.BatchTransformer; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class UpdateProgressDialog extends JDialog implements ActionListener { + + private UIButton pauseBtn; + private BatchTransformer transformer; + + public UpdateProgressDialog(BatchTransformer transformer, Dialog parent, JPanel contentPane) { + super(parent, true); + this.transformer = transformer; + initPane(contentPane); + } + + private void initPane(JPanel contentPane) { + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Format_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + pauseBtn = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend")); + pauseBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(pauseBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + transformer.shutDown(); + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(pauseBtn); + + this.setSize(new Dimension(262, 122)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + transformer.shutDown(); + dialogExit(); + } + + public void dialogExit() { + this.dispose(); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressPane.java b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressPane.java new file mode 100644 index 000000000..ad5296cc5 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/transform/ui/UpdateProgressPane.java @@ -0,0 +1,72 @@ +package com.fr.plugin.designer.transform.ui; + + +import com.fr.base.BaseUtils; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.designer.transform.UpdateCallBack; +import com.sun.java.swing.plaf.motif.MotifProgressBarUI; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import java.awt.BorderLayout; +import java.awt.Dimension; + + +/** + * Created by kerry on 2019-12-11 + */ +public class UpdateProgressPane extends BasicPane implements UpdateCallBack { + private TransformPreparePane contentPane; + private JProgressBar progressBar; + + public UpdateProgressPane(TransformPreparePane contentPane) { + this.contentPane = contentPane; + initPane(); + } + + private void initPane() { + this.setPreferredSize(new Dimension(262, 60)); + UILabel icon = new UILabel(BaseUtils.readIcon("/com/fr/plugin/designer/transform/transforming.png")); + icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); + this.add(icon, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + UILabel title = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transforming")); + title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); + centerPane.add(title, BorderLayout.NORTH); + progressBar = new JProgressBar(); + progressBar.setUI(new MotifProgressBarUI()); + progressBar.setForeground(UpdateConstants.BAR_COLOR); + centerPane.add(progressBar, BorderLayout.CENTER); + this.add(centerPane, BorderLayout.CENTER); + } + + + @Override + public void updateProgress(double progress) { + progressBar.setValue((int) (progress * 100)); + if (ComparatorUtils.equals(progress, 1D)) { + contentPane.complete(); + } + } + + @Override + public void shutDown() { + contentPane.complete(); + } + + @Override + public void reset() { + progressBar.setValue(0); + } + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend"); + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/utils/CompileTransformUtil.java b/designer-realize/src/main/java/com/fr/plugin/designer/utils/CompileTransformUtil.java new file mode 100644 index 000000000..564adc6c7 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/utils/CompileTransformUtil.java @@ -0,0 +1,55 @@ +package com.fr.plugin.designer.utils; + +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.plugin.designer.toolbar.TemplateTransformer; +import com.fr.plugin.designer.toolbar.TransformResult; +import com.fr.plugin.designer.toolbar.TransformResultInfo; +import com.fr.workspace.WorkContext; + +import java.io.InputStream; + +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * Created by kerry on 2019-12-04 + */ +public class CompileTransformUtil { + + + public static TransformResultInfo compileFile(FileNode fileNode) { + long start = System.currentTimeMillis(); + InputStream in = WorkContext.getWorkResource().openStream(fileNode.getEnvPath()); + WorkBook workBook = new WorkBook(); + TransformResultInfo result = null; + try { + workBook.readStream(in); + FILE file = TemplateTransformer.createOutputFile(fileNode.getEnvPath(), CPT.getSuffix(), CPTX.getSuffix()); + result = TemplateTransformer.compileCPTX(workBook, file); + } catch (Exception ignore) { + result = TransformResultInfo.generateResult(TransformResult.FAILED); + } + long end = System.currentTimeMillis(); + FineLoggerFactory.getLogger().debug(fileNode.getName() + " compile cost : " + (end - start) +" ms "); + return result; + } + + + public static FILE getTargetFile(JTemplate jTemplate, TemplateTransformer transformer) { + FILE file = null; + if (ComparatorUtils.equals(TemplateTransformer.TO_CPTX, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPT.getSuffix(), CPTX.getSuffix()); + + } else if (ComparatorUtils.equals(TemplateTransformer.TO_CPT, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPTX.getSuffix(), CPT.getSuffix()); + } + return file; + } +} diff --git a/designer-realize/src/main/java/com/fr/plugin/designer/utils/DesignerCptxFileUtils.java b/designer-realize/src/main/java/com/fr/plugin/designer/utils/DesignerCptxFileUtils.java new file mode 100644 index 000000000..9578a0491 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/plugin/designer/utils/DesignerCptxFileUtils.java @@ -0,0 +1,79 @@ +package com.fr.plugin.designer.utils; + +import com.fr.file.FILE; +import com.fr.general.CommonIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.marshal.impl.xml.DefaultXMLObjectUnmarshaler; +import com.fr.marshal.util.MarshalUtil; +import com.fr.nx.cptx.entry.metadata.CptxMetadata; +import com.fr.nx.cptx.io.handle.impl.OriginCptProvider; +import com.fr.nx.cptx.marshal.util.CptxMarshalUtil; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.xml.XMLableReader; +import com.fr.workspace.WorkContext; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Created by loy on 2021/1/18. + * + *

用于设计器的cptx的一些工具类 + *

+ */ +public class DesignerCptxFileUtils { + + /** + * 根据file来获取cptx中的cpt + * @param file + * @return + */ + public static WorkBook getWorkBook(final FILE file){ + try (InputStream input = file.asInputStream(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + CommonIOUtils.copyBinaryTo(input, outputStream); + OriginCptProvider provider = new OriginCptProvider(outputStream.toByteArray()); + return CptxFileUtils.getWorkBook(provider); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + /** + * 获取模板的元数据 + * @param file + * @return + */ + public static CptxMetadata getMetadata(FILE file){ + try { + String metadataPath = StableUtils.pathJoin(generateCompileDir(file), CptxMarshalUtil.NAME_METADATA); + if(!WorkContext.getWorkResource().exist(metadataPath)){ + return null; + } + InputStream metadataInput = WorkContext.getWorkResource().openStream(metadataPath); + XMLableReader reader = XMLableReader.createXMLableReader( + new InputStreamReader(metadataInput, EncodeConstants.ENCODING_UTF_8)); + CptxMetadata metadata = (CptxMetadata) new DefaultXMLObjectUnmarshaler().unmarshal( + MarshalUtil.createMarshalableExtra(CptxMetadata.class), reader); + return metadata; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + /** + * 根据文件获取编译后的文件夹绝对路径,比如原文件位于reportlets/test/merge.cptx,转化后为evn://assets/engine/test/merge文件夹 + * @param file + * @return + */ + public static String generateCompileDir(FILE file){ + String filePath = file.getPath(); + return CptxFileUtils.generateCompileDir(filePath); + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/CptxAppTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/CptxAppTest.java new file mode 100644 index 000000000..8fae48cac --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/CptxAppTest.java @@ -0,0 +1,55 @@ +package com.fr.plugin.designer; + +import com.fr.file.AbstractFILE; +import com.fr.file.FILE; +import com.fr.main.impl.WorkBook; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.plugin.designer.utils.DesignerCptxFileUtils; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(JUnit4.class) +@PrepareForTest({ + CptxFileUtils.class +}) +public class CptxAppTest { + + @Test + public void testDefaultExtensions() { + CptxApp app = new CptxApp(); + String[] extendsions = app.defaultExtensions(); + Assert.assertEquals("cptx", extendsions[0]); + } + + @Test + public void testAsIOFile() { + PowerMock.mockStatic(CptxFileUtils.class); + FILE file = new AbstractFILE() { + }; + WorkBook workBook = new WorkBook(); + EasyMock.expect(DesignerCptxFileUtils.getWorkBook(file)) + .andReturn(workBook).once() + .andReturn(null).once(); + + PowerMock.replay(CptxFileUtils.class); + Assert.assertSame(workBook, new CptxApp().asIOFile(file)); + + Assert.assertNotNull(new CptxApp().asIOFile(file)); + + PowerMock.verify(CptxFileUtils.class); + + + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/EnginexSupportedFileUIImplTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/EnginexSupportedFileUIImplTest.java new file mode 100644 index 000000000..cd8e57890 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/EnginexSupportedFileUIImplTest.java @@ -0,0 +1,26 @@ +package com.fr.plugin.designer; + +import org.junit.Assert; +import org.junit.Test; + +import javax.swing.Icon; + +/** + * Created by kerry on 2019-10-15 + */ +public class EnginexSupportedFileUIImplTest { + + @Test + public void testGetFileIcon() { + EnginexSupportedFileUIImpl newFileType = new EnginexSupportedFileUIImpl(); + Icon icon1 = newFileType.getFileIcon("WorkBook.cpt", false); + Assert.assertNull(icon1); + Icon icon2 = newFileType.getFileIcon("WorkBook.cptx", false); + Assert.assertEquals(EnginexSupportedFileUIImpl.CPTX_ICON, icon2); + Icon icon3 = newFileType.getFileIcon("WorkBook.cpt", true); + Assert.assertNull(icon3); + Icon icon4 = newFileType.getFileIcon("WorkBook.cptx", true); + Assert.assertEquals(EnginexSupportedFileUIImpl.CPTX_LOCKED_ICON, icon4); + } + +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/JStreamBookTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/JStreamBookTest.java new file mode 100644 index 000000000..b7fa4a87f --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/JStreamBookTest.java @@ -0,0 +1,121 @@ +package com.fr.plugin.designer; + +import com.fr.file.FILE; +import com.fr.main.impl.WorkBook; +import com.fr.plugin.designer.toolbar.TemplateTransformer; +import com.fr.plugin.designer.toolbar.TransformResult; +import com.fr.plugin.designer.toolbar.TransformResultInfo; +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({TemplateTransformer.class, JStreamBook.class}) +@PowerMockIgnore({"com.fr.license.*"}) +@SuppressStaticInitializationFor({"com.fr.plugin.designer.JStreamBook"}) +public class JStreamBookTest { + + + @Test + public void saveFile() { + + PowerMock.mockStatic(TemplateTransformer.class); + final boolean[] fireSave = {false}; + + + JStreamBook workbook = + EasyMock.partialMockBuilder(VirtualJStreamBook.class) + .addMockedMethod("fireJTemplateSaved") + .addMockedMethod("getTarget") + .addMockedMethod("getEditingFILE") + .createMock(); + // 保存成功 + EasyMock.expect(TemplateTransformer.compileCPTX(null, null)) + .andReturn(TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "fake Unsupported").saved(true)) + .once(); + PowerMock.replay(TemplateTransformer.class); + + workbook.fireJTemplateSaved(); + EasyMock.expectLastCall().andAnswer(new IAnswer() { + @Override + public Void answer() throws Throwable { + fireSave[0] = true; + return null; + } + }).once(); + + EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer() { + @Override + public WorkBook answer() throws Throwable { + return null; + } + }).once(); + + EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer() { + @Override + public FILE answer() throws Throwable { + return null; + } + }).once(); + + EasyMock.replay(workbook); + + boolean saved = workbook.saveFile(); + Assert.assertTrue(saved); + Assert.assertTrue(fireSave[0]); + + PowerMock.verify(TemplateTransformer.class); + EasyMock.verify(workbook); + + fireSave[0] = false; + + // 保存失败 + PowerMock.reset(TemplateTransformer.class); + EasyMock.expect(TemplateTransformer.compileCPTX(null, null)) + .andReturn(TransformResultInfo.generateResult(TransformResult.FAILED, "fake Unsupported").saved(false)) + .once(); + PowerMock.replay(TemplateTransformer.class); + EasyMock.reset(workbook); + + EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer() { + @Override + public WorkBook answer() throws Throwable { + return null; + } + }).once(); + + EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer() { + @Override + public FILE answer() throws Throwable { + return null; + } + }).once(); + EasyMock.replay(workbook); + + saved = workbook.saveFile(); + Assert.assertFalse(saved); + Assert.assertFalse(fireSave[0]); + + PowerMock.verify(TemplateTransformer.class); + EasyMock.verify(workbook); + } + + private static final class VirtualJStreamBook extends JStreamBook { + + public VirtualJStreamBook(WorkBook workBook, FILE file) { + super(workBook, file); + } + + @Override + public String toString() { + return this.getClass().getName() + "fake to string"; + } + } +} \ No newline at end of file diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/clean/CompileCleanManagerTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/clean/CompileCleanManagerTest.java new file mode 100644 index 000000000..3dfa2655a --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/clean/CompileCleanManagerTest.java @@ -0,0 +1,41 @@ +package com.fr.plugin.designer.clean; + +import com.fr.config.dao.DaoContext; +import com.fr.config.dao.impl.LocalClassHelperDao; +import com.fr.config.dao.impl.LocalEntityDao; +import com.fr.config.dao.impl.LocalXmlEntityDao; +import com.fr.transaction.Configurations; +import com.fr.transaction.LocalConfigurationHelper; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * @author: Maksim + * @Date: Created in 2020/4/23 + * @Description: + */ +public class CompileCleanManagerTest { + + @Before + public void before() { + DaoContext.setEntityDao(new LocalEntityDao()); + DaoContext.setClassHelperDao(new LocalClassHelperDao()); + DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); + Configurations.setHelper(new LocalConfigurationHelper()); + } + + @Test + public void clearTest() { + + CompileCleanManager manager = CompileCleanManager.getInstance(); + manager.addRecord("com.cptx"); + manager.addRecord("abc/com.cptx"); + manager.addRecord("merge.cptx", "2020-01-01"); + manager.addRecord("merge.cptx", "2020-02-01"); + Assert.assertEquals(3, manager.getRecords().size()); + + manager.clear(); + Assert.assertEquals(2, manager.getRecords().size()); + } +} \ No newline at end of file diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/menu/BatchCompileMenuTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/menu/BatchCompileMenuTest.java new file mode 100644 index 000000000..99e409ff8 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/menu/BatchCompileMenuTest.java @@ -0,0 +1,16 @@ +package com.fr.plugin.designer.menu; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class BatchCompileMenuTest { + + @Test + public void testBatchCompileMenuIndex(){ + BatchCompileMenu menu = new BatchCompileMenu(); + Assert.assertEquals(9, menu.insertPosition(20)); + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TemplateTransformerTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TemplateTransformerTest.java new file mode 100644 index 000000000..babf65c34 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TemplateTransformerTest.java @@ -0,0 +1,85 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.invoke.Reflect; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static com.fr.plugin.designer.toolbar.TemplateTransformer.OTHER; +import static com.fr.plugin.designer.toolbar.TemplateTransformer.TO_CPT; +import static com.fr.plugin.designer.toolbar.TemplateTransformer.TO_CPTX; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*", "com.fr.license.*"}) +public class TemplateTransformerTest { + + @Test + public void testParse() { + assertEquals(TO_CPTX, TemplateTransformer.parse("/sdf/abc.cpt")); + assertEquals(TO_CPT, TemplateTransformer.parse("/sdf/abc.cptx")); + assertEquals(OTHER, TemplateTransformer.parse("/sdf/abc.frm")); + assertEquals(OTHER, TemplateTransformer.parse(null)); + assertEquals(OTHER, TemplateTransformer.parse("abc")); + } + + @Test + public void testCompileFailed() { + TransformResultInfo result = TemplateTransformer.compileCPTX(null, null); + assertEquals(result.getResult(), TransformResult.FAILED); + } + + @Test + public void testGenerateNewPath() { + assertEquals(generateNewPath("/abc/dd.cpt", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cptx", ".cpt"), "/abc/dd.cpt"); + assertEquals(generateNewPath("/abc/dd.frm", ".cpt", ".cptx"), "/abc/dd.frm"); + assertNull(generateNewPath(null, null, null)); + assertEquals(generateNewPath("abc", null, null), "abc"); + } + + private String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + return Reflect.on(TemplateTransformer.class).call("generateNewPath", oldPath, oldSuffix, newSuffix).get(); + } + + @Test + public void testCreateOutputFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + FILE file1 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cpt", ".cptx"); + FILE file2 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cptx", ".cpt"); + assertEquals("WorkBook1.cptx", file1.getPath()); + assertEquals("WorkBook1.cpt", file2.getPath()); + } + + + @Test + public void testNeedDoAfterTransformed() { + Assert.assertTrue(needDoAfterTransformed(TransformResult.SUCCESS)); + Assert.assertTrue(needDoAfterTransformed(TransformResult.UNSUPPORT)); + Assert.assertFalse(needDoAfterTransformed(TransformResult.FAILED)); + } + + private boolean needDoAfterTransformed(TransformResult result) { + return Reflect.on(TemplateTransformer.class).call("needDoAfterTransformed", result).get(); + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TransformResultInfoTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TransformResultInfoTest.java new file mode 100644 index 000000000..362729278 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/toolbar/TransformResultInfoTest.java @@ -0,0 +1,32 @@ +package com.fr.plugin.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfoTest { + @Test + public void testGetTransformLog() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed"); + Assert.assertEquals("failed\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"), + resultInfo1.getTransformLog()); + TransformResultInfo resultInfo2 = TransformResultInfo.generateResult(TransformResult.SUCCESS); + Assert.assertEquals(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"), + resultInfo2.getTransformLog()); + TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport"); + Assert.assertEquals("unsupport\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"), + resultInfo3.getTransformLog()); + + } + + @Test + public void testSaved() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed").saved(false); + Assert.assertFalse(resultInfo1.isSaved()); + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformProgressTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformProgressTest.java new file mode 100644 index 000000000..43de999ee --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformProgressTest.java @@ -0,0 +1,27 @@ +package com.fr.plugin.designer.transform; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class BatchTransformProgressTest { + @Test + public void testGetProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + Assert.assertEquals(0.0D, batchTransformProgress.getProgress(), 0.0D); + } + + @Test + public void testUpdateProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + for (int i = 0; i < 80; i++) { + batchTransformProgress.updateProgress(); + } + Assert.assertEquals(0.8D, batchTransformProgress.getProgress(), 0.0D); + batchTransformProgress.updateProgress(); + Assert.assertEquals(0.81D, batchTransformProgress.getProgress(), 0.0D); + + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformUtilTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformUtilTest.java new file mode 100644 index 000000000..56e7c5e3a --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformUtilTest.java @@ -0,0 +1,35 @@ +package com.fr.plugin.designer.transform; + +import com.fr.file.filetree.FileNode; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtilTest { + @Test + public void testFilterTransformedFile(){ + FileNode[] fileNodes = new FileNode[]{ + new FileNode("test1", false), new FileNode("test2", false) + }; + List transformedFileNodes = new ArrayList(); + FileNode[] result1 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(2, result1.length); + + transformedFileNodes.add( new FileNode("test1", false)); + FileNode[] result2 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(1, result2.length); + + transformedFileNodes.add( new FileNode("test2", false)); + FileNode[] result3 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result3.length); + + transformedFileNodes.add( new FileNode("test3", false)); + FileNode[] result4 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result4.length); + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformerTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformerTest.java new file mode 100644 index 000000000..ef272b434 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/transform/BatchTransformerTest.java @@ -0,0 +1,124 @@ +package com.fr.plugin.designer.transform; + +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; + +/** + * Created by kerry on 2020-01-15 + */ +// FIXME @kerry 打包失败,暂时先注释 +//@RunWith(value = PowerMockRunner.class) +//@PrepareForTest({CompileTransformUtil.class, PluginContexts.class}) +//@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class BatchTransformerTest { + + private static final int MAXPOOLSIZE = 5; + private static final int COREPOOLSIZE = 3; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + + @Before + public void setUp() { +// FineRuntime.start(); +// ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE, +// 0L, TimeUnit.MILLISECONDS, +// new LinkedBlockingQueue(), +// new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); +// PowerMock.mockStatic(PluginContexts.class); +// PluginContext pluginContext = EasyMock.mock(PluginContext.class); +// EasyMock.expect(pluginContext.newFixedThreadPool( +// EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))) +// .andReturn(threadPoolExecutor).anyTimes(); +// EasyMock.expect(PluginContexts.currentContext()).andReturn(pluginContext).anyTimes(); +// +// PowerMock.mockStatic(CompileTransformUtil.class); +// TransformResultInfo resultInfo = TransformResultInfo.generateResult(TransformResult.SUCCESS); +// EasyMock.expect(CompileTransformUtil.compileFile(EasyMock.anyObject(FileNode.class))) +// .andReturn(resultInfo).anyTimes(); +// EasyMock.replay(pluginContext); +// PowerMock.replayAll(); + } + + @Test + public void testBatchTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(2); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test1 = new FileNode("path1", false); +// FileNode test2 = new FileNode("path2", false); +// nodeList.add(test1); +// nodeList.add(test2); +// transformer.batchTransform(nodeList); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(2, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test1).getResult()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test2).getResult()); + + } + + @Test + public void testTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// FileNode test = new FileNode("path", false); +// Reflect.on(transformer).call("transform", test); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + @Test + public void testShutDown() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test = new FileNode("path", false); +// nodeList.add(test); +// transformer.batchTransform(nodeList); +// transformer.shutDown(); +// try { +// countDownLatch.await(3, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + + private class MockUpdateCallBack implements UpdateCallBack { + private CountDownLatch countDownLatch; + + + public MockUpdateCallBack(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + @Override + public void updateProgress(double progress) { + countDownLatch.countDown(); + } + + @Override + public void shutDown() { + + } + + @Override + public void reset() { + + } + } +} diff --git a/designer-realize/src/test/java/com/fr/plugin/designer/utils/CompileTransformUtilTest.java b/designer-realize/src/test/java/com/fr/plugin/designer/utils/CompileTransformUtilTest.java new file mode 100644 index 000000000..9b67f5532 --- /dev/null +++ b/designer-realize/src/test/java/com/fr/plugin/designer/utils/CompileTransformUtilTest.java @@ -0,0 +1,58 @@ +package com.fr.plugin.designer.utils; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.plugin.designer.toolbar.TemplateTransformer; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by kerry on 2019-12-04 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class CompileTransformUtilTest { + @Test + public void testGetTargetFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + JTemplate jTemplate1 = EasyMock.mock(JTemplate.class); + FILE file1 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate1.getEditingFILE()).andReturn(file1).anyTimes(); + EasyMock.expect(file1.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate1, file1); + FILE targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + + JTemplate jTemplate2 = EasyMock.mock(JTemplate.class); + FILE file2 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate2.getEditingFILE()).andReturn(file2).anyTimes(); + EasyMock.expect(file2.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate2, file2); + targetFile = CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile =CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + } +}