diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java index af9850172b..4fe69e08eb 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java @@ -442,64 +442,73 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp if (selectedNO != null) { data = selectedNO.getObject(); } - try { - if (((TableDataWrapper) Objects.requireNonNull(data)).getTableData() instanceof MultiResultTableData) { - ((MultiResultTableData) (((TableDataWrapper) data).getTableData())).resetDataModelList(); - if (data instanceof MultiResultTableDataWrapper) { - MultiResultTableDataWrapper oldSdw = ((MultiResultTableDataWrapper) data); - MultiResultTableDataWrapper newSdw = new MultiResultTableDataWrapper((MultiResultTableData) oldSdw.getTableData(), oldSdw.getMultiResultTableDataName(), oldSdw.getTableDataName()); - newSdw.previewData(MultiResultTableDataWrapper.PREVIEW_ONE); - } else { - MultiResultTableData tableData = (MultiResultTableData) ((TableDataWrapper) data).getTableData(); - MultiResultTableDataWrapper storeProcedureDataWrapper = new MultiResultTableDataWrapper(tableData, StringUtils.EMPTY, StringUtils.EMPTY); - storeProcedureDataWrapper.previewData(MultiResultTableDataWrapper.PREVIEW_ALL); - } - } else { - TableDataWrapper wrapper = ((TableDataWrapper) data); - if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) { - // 先打开一个Loading面板 - TableDataLoadingPane loadingPane = new TableDataLoadingPane(); - BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(BasicTableDataTreePane.this), null); - // 查询权限 - new SwingWorker() { - @Override - protected Boolean doInBackground() throws Exception { - // 获取无权限连接名称集合 - Collection noAuthConnections = TableDataAuthHelper.getNoAuthConnections(); - // 获取当前数据集对应的数据连接名称 - String connectionName = TableDataAuthHelper.getConnectionNameByDBTableData((DBTableData) wrapper.getTableData()); - return !noAuthConnections.contains(connectionName); - } + preview((TableDataWrapper) data, BasicTableDataTreePane.this); + } + } - @Override - protected void done() { - try { - Boolean hasAuth = get(); - if (hasAuth) { - // 有权限时,关闭Loading面板,打开编辑面板 - loadingDialog.setVisible(false); - wrapper.previewData(); - } else { - // 无权限时,给出无权限提示 - loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage()); - // 查询权限失败时,给出报错提示 - loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME); + /** + * 预览数据集 + * + * @param data TableDataWrapper + * @param c 底层面板 + */ + public static void preview(TableDataWrapper data, Component c) { + try { + if (((TableDataWrapper) Objects.requireNonNull(data)).getTableData() instanceof MultiResultTableData) { + ((MultiResultTableData) (((TableDataWrapper) data).getTableData())).resetDataModelList(); + if (data instanceof MultiResultTableDataWrapper) { + MultiResultTableDataWrapper oldSdw = ((MultiResultTableDataWrapper) data); + MultiResultTableDataWrapper newSdw = new MultiResultTableDataWrapper((MultiResultTableData) oldSdw.getTableData(), oldSdw.getMultiResultTableDataName(), oldSdw.getTableDataName()); + newSdw.previewData(MultiResultTableDataWrapper.PREVIEW_ONE); + } else { + MultiResultTableData tableData = (MultiResultTableData) ((TableDataWrapper) data).getTableData(); + MultiResultTableDataWrapper storeProcedureDataWrapper = new MultiResultTableDataWrapper(tableData, StringUtils.EMPTY, StringUtils.EMPTY); + storeProcedureDataWrapper.previewData(MultiResultTableDataWrapper.PREVIEW_ALL); + } + } else { + TableDataWrapper wrapper = ((TableDataWrapper) data); + if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) { + // 先打开一个Loading面板 + TableDataLoadingPane loadingPane = new TableDataLoadingPane(); + BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(c), null); + // 查询权限 + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + // 获取无权限连接名称集合 + Collection noAuthConnections = TableDataAuthHelper.getNoAuthConnections(); + // 获取当前数据集对应的数据连接名称 + String connectionName = TableDataAuthHelper.getConnectionNameByDBTableData((DBTableData) wrapper.getTableData()); + return !noAuthConnections.contains(connectionName); + } + + @Override + protected void done() { + try { + Boolean hasAuth = get(); + if (hasAuth) { + // 有权限时,关闭Loading面板,打开编辑面板 + loadingDialog.setVisible(false); + wrapper.previewData(); + } else { + // 无权限时,给出无权限提示 + loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME); } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage()); + // 查询权限失败时,给出报错提示 + loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME); } - }.execute(); - loadingDialog.setVisible(true); - } else { - wrapper.previewData(); - } + } + }.execute(); + loadingDialog.setVisible(true); + } else { + wrapper.previewData(); } - - } catch (Exception ex) { - FineLoggerFactory.getLogger().error(ex.getMessage(), ex); } + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java index 149fa87dc2..06e9a969d1 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java @@ -98,6 +98,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; public class TableDataTreePane extends BasicTableDataTreePane { + private static Map extraActions = new HashMap<>(); private static final TableDataTreePane singleton = new TableDataTreePane(); public static final int PLUGIN_LISTENER_PRIORITY = 1; @@ -176,14 +177,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { ToolTipManager.sharedInstance().setDismissDelay(3000); ToolTipManager.sharedInstance().setInitialDelay(0); // 右键菜单 - popupMenu = new UIPopupMenu(); - popupMenu.add(editAction.createMenuItem()); - popupMenu.add(previewTableDataAction.createMenuItem()); - popupMenu.addSeparator(); - popupMenu.add(copyAction.createMenuItem()); - popupMenu.add(pasteAction.createMenuItem()); - popupMenu.add(removeAction.createMenuItem()); - popupMenu.addSeparator(); + initPopupMenu(); // 监听 tableDataTree.addMouseListener(new MouseAdapter() { @Override @@ -221,6 +215,25 @@ public class TableDataTreePane extends BasicTableDataTreePane { new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); } + private void initPopupMenu() { + popupMenu = new UIPopupMenu(); + popupMenu.add(editAction.createMenuItem()); + popupMenu.add(previewTableDataAction.createMenuItem()); + popupMenu.addSeparator(); + popupMenu.add(copyAction.createMenuItem()); + popupMenu.add(pasteAction.createMenuItem()); + popupMenu.add(removeAction.createMenuItem()); + popupMenu.addSeparator(); + for (AbstractExtraAction action : extraActions.values()) { + try { + popupMenu.add(action.createMenuItem()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + } + } + /** * 工具栏面板 * @@ -233,7 +246,17 @@ public class TableDataTreePane extends BasicTableDataTreePane { createAddMenuDef(); // 创建插件监听 createPluginListener(); + createToolbarDef(); + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); + toolBar.setBorderPainted(true); + toolbarDef.updateToolBar(toolBar); + TreeSearchToolbarPane searchLayerdPane = new TreeSearchToolbarPane(toolBar); + searchLayerdPane.setPreferredSize(new Dimension(this.getWidth(), 23)); + return searchLayerdPane; + } + private void createToolbarDef() { editAction = new EditAction(); copyAction = new CopyAction(); pasteAction = new PasteAction(); @@ -243,18 +266,38 @@ public class TableDataTreePane extends BasicTableDataTreePane { esdAction = new EsdOnAction(); esdOffAction = new EsdOffAction(); switchAction = new SwitchAction(); - toolbarDef = new ToolBarDef(); - toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction, switchAction); - UIToolbar toolBar = ToolBarDef.createJToolBar(); - toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); - toolBar.setBorderPainted(true); - toolbarDef.updateToolBar(toolBar); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction); + initExtraAction(); + toolbarDef.addShortCut(SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction, switchAction); + } - TreeSearchToolbarPane searchLayerdPane = new TreeSearchToolbarPane(toolBar); - searchLayerdPane.setPreferredSize(new Dimension(this.getWidth(), 23)); + private void initExtraAction() { + for (AbstractExtraAction action: extraActions.values()) { + try { + toolbarDef.addShortCut(action); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } - return searchLayerdPane; + /** + * 注册ExtraAction + * + * @param extraAction TableDataTree工具栏的扩展接口Action + */ + public static void registerExtraAction(AbstractExtraAction extraAction) { + extraActions.put(extraAction.getClass().getSimpleName(), extraAction); + } + + /** + * 移除ExtraAction + * + * @param extraAction TableDataTree工具栏的扩展接口Action + */ + public static void removeExtraAction(AbstractExtraAction extraAction) { + extraActions.remove(extraAction.getClass().getSimpleName()); } /** @@ -331,7 +374,12 @@ public class TableDataTreePane extends BasicTableDataTreePane { public void on(PluginEvent event) { addMenuDef.clearShortCuts(); + toolbarDef.clearShortCuts(); createAddMenuDef(); + createToolbarDef(); + toolbarDef.updateToolBar(toolbarPane.getToolbar()); + initPopupMenu(); + checkEnable(); } }, new PluginFilter() { @@ -679,10 +727,16 @@ public class TableDataTreePane extends BasicTableDataTreePane { pasteAction.setEnabled(false); removeAction.setEnabled(false); previewTableDataAction.setEnabled(false); + for (AbstractExtraAction action : extraActions.values()) { + action.setEnabled(false); + } if (op == null || op.interceptButtonEnabled()) { // 保持false状态 return; } + if(getDataTree() != null) { + checkExtraActionEnable(op.getDataMode(), getDataTree().getSelectedTableDataCounts(), getDataTree().hasSelectedIndependentColumns()); + } // 获取选中的数据集数量 int selectioncount = getDataTree().getSelectedTableDataCounts(); if (op.getDataMode() == SERVER_TABLE_DATA) { @@ -706,6 +760,13 @@ public class TableDataTreePane extends BasicTableDataTreePane { } removeAction.setEnabled(true); copyAction.setEnabled(true); + + } + + private void checkExtraActionEnable(int dataMode, int selectioncount, boolean hasSelectedIndependentColumns) { + for (AbstractExtraAction action : extraActions.values()) { + action.setEnabled(action.checkEnable(dataMode, selectioncount, hasSelectedIndependentColumns)); + } } @@ -1215,6 +1276,45 @@ public class TableDataTreePane extends BasicTableDataTreePane { } } + /** + * TableDataTree工具栏的扩展接口Action + */ + public static abstract class AbstractExtraAction extends UpdateAction { + + public AbstractExtraAction() { + init(); + } + + /** + * 初始化逻辑 + *

一般用于设置名称、快捷键、icon

+ */ + protected abstract void init(); + + @Override + public void actionPerformed(ActionEvent e) { + doActionPerformed(e, singleton.tableDataTree.getSelectedTableDataNameObjects()); + } + + /** + * 点击事件 + * + * @param e actionEvent + * @param selectedTableDataNameObjects 数据集tree选中的对象 + */ + protected abstract void doActionPerformed(ActionEvent e, NameObject[] selectedTableDataNameObjects); + + /** + * 是否可以启用 + * + * @param dataMode 模板数据集还是服务器数据集 + * @param selectioncount 选中的数据集个数 + * @param hasSelectedIndependentColumns 是否存在单独选了数据列节点,但没选其对应数据集的情况 + * @return 返回启用与否 + */ + protected abstract boolean checkEnable(int dataMode, int selectioncount, boolean hasSelectedIndependentColumns); + } + public String getNoRepeatedDsName4Paste(String oldName) { while (isDsNameRepeaded(oldName)) { oldName = oldName + Toolkit.i18nText("Fine-Design_Table_Data_Copy_Of_Table_Data"); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java index f5266c9b6d..5dc751c29e 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java @@ -189,6 +189,10 @@ public class TreeSearchToolbarPane extends JPanel implements TreeSearchStatusCha this.searchTextField.setPlaceholder(placeHolder); } + public UIToolbar getToolbar() { + return toolbar; + } + /** * 根据搜索状态变化,来调整自身面板的显示 * diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaConstants.java b/designer-base/src/main/java/com/fr/design/formula/FormulaConstants.java index 4dfcb4bb47..a020924816 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaConstants.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaConstants.java @@ -13,6 +13,7 @@ public enum FormulaConstants { TOTAL_PAGE_NUMBER("$$totalPage_number", "Total_Page_Number"), FINE_USERNAME("$fine_username", "Fine_Username"), FINE_ROLE("$fine_role", "Fine_Role"), + FINE_ROLE_ID("$fine_role_id", "Fine_Role_Id"), FINE_POSITION("$fine_position", "Fine_Position"), NULL("NULL", "Null"), NOFILTER("NOFILTER", "No_Filter"), diff --git a/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java b/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java index 5fd384be8e..13e69d7f4b 100644 --- a/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java +++ b/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java @@ -31,6 +31,7 @@ public abstract class VariableResolverAdapter implements VariableResolver { // 下面是权限相关的参数 ScriptConstants.DETAIL_TAG + ParameterConstants.FINE_USERNAME, ScriptConstants.DETAIL_TAG + ParameterConstants.FINE_ROLE, + ScriptConstants.DETAIL_TAG + ParameterConstants.FINE_ROLE_ID, ScriptConstants.DETAIL_TAG + ParameterConstants.FINE_POSITION, // 空值参数 "NULL", "NOFILTER", diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java index 66b057d0ca..55877a6892 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java @@ -409,7 +409,7 @@ public class CommitTabbedPane extends JComponent implements MouseListener, Mous selectedIndex = dbManipulationPaneList.size()-1; commit2DBJavaScriptPane.updateCardPane(); } else if (isOverCloseIcon(x)){ - int re = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_CommitTab_Sure_To_Delete")+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_CommitTab_Remove") + int re = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_CommitTab_Sure_To_Delete")+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips") , JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (re == JOptionPane.OK_OPTION) { dbManipulationPaneList.remove(getTabIndex(x)); diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/cell/SearchCellAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/cell/SearchCellAction.java index 2711069847..a717ec9805 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/cell/SearchCellAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/cell/SearchCellAction.java @@ -152,7 +152,10 @@ public class SearchCellAction implements SearchAction { } - private void getCellInfoFromElementCase(ElementCase elementCase, List result, ITContent content) { + /** + * 从ElementCase获取单元格 + */ + public void getCellInfoFromElementCase(ElementCase elementCase, List result, ITContent content) { Iterator cellIterator = elementCase.cellIterator(); while (cellIterator.hasNext()) { ITContent newContent = ITContent.copy(content); diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchCellFormulaAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchCellFormulaAction.java index 45a85d697a..b065842445 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchCellFormulaAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchCellFormulaAction.java @@ -63,30 +63,38 @@ public class SearchCellFormulaAction implements SearchCellFormula { SearchCellAction searchCellAction = SearchCellAction.getInstance(); searchCellAction.search4Infos(jTemplate); if (searchCellAction.isCellInfosExist()) { - for (CellInfo cellInfo : searchCellAction.getCellInfos()) { - //根据单元格类型的不同来进行不同的操作 - searchFormulaFromCellInfo(cellInfo, formulaInfos); - - if (cellInfo.getContent().getReplaceObject() instanceof TemplateCellElement) { - //单元格属性-排序 - searchCellSortAttr4Formula(cellInfo, formulaInfos); - //单元格属性-形态 - searchCellPresent4Formula(cellInfo, formulaInfos); - //单元格属性-其他-内容提示-自定义 - searchCellToolTip4Formula(cellInfo, formulaInfos); - //单元格属性-其他-插入策略 - searchCellInsertPolicy4Formula(cellInfo, formulaInfos); - //单元格条件属性-参数-公式 - searchCellConditionPara4Formula(cellInfo, formulaInfos); - //单元格条件属性-属性-参数 - searchCellHighlightPara4Formula(cellInfo, formulaInfos); - //单元格超链 - searchCellHyperLink4Formula(cellInfo, formulaInfos); - } + searchFormulaFromCellInfos(searchCellAction.getCellInfos(), formulaInfos); + } + + } + + /** + * 从单元格获取公式 + */ + public void searchFormulaFromCellInfos(List cellInfos, List formulaInfos) { + for (CellInfo cellInfo : cellInfos) { + //根据单元格类型的不同来进行不同的操作 + searchFormulaFromCellInfo(cellInfo, formulaInfos); + + if (cellInfo.getContent().getReplaceObject() instanceof TemplateCellElement) { + //单元格属性-排序 + searchCellSortAttr4Formula(cellInfo, formulaInfos); + //单元格属性-形态 + searchCellPresent4Formula(cellInfo, formulaInfos); + //单元格属性-其他-内容提示-自定义 + searchCellToolTip4Formula(cellInfo, formulaInfos); + //单元格属性-其他-插入策略 + searchCellInsertPolicy4Formula(cellInfo, formulaInfos); + //单元格条件属性-参数-公式 + searchCellConditionPara4Formula(cellInfo, formulaInfos); + //单元格条件属性-属性-参数 + searchCellHighlightPara4Formula(cellInfo, formulaInfos); + //单元格超链 + searchCellHyperLink4Formula(cellInfo, formulaInfos); } - } + } } private void searchCellToolTip4Formula(CellInfo cellInfo, List formulaInfos) { diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchDSColumnFormulaAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchDSColumnFormulaAction.java index 5bced089a6..89ccad3b1a 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchDSColumnFormulaAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/cell/SearchDSColumnFormulaAction.java @@ -58,8 +58,7 @@ public class SearchDSColumnFormulaAction implements SearchCellFormula { } private void addFormulaInfos2ArrayFromResult(ITContent content, DSColumn dsColumn, List formulaInfos) { - char formulaLabel = '='; - if (dsColumn.getResult() != null && dsColumn.getResult().length() > 0 && dsColumn.getResult().charAt(0) == formulaLabel) { + if (dsColumn.getResult() != null && dsColumn.getResult().length() > 0) { ITContent newContent = ITContent.copy(content); newContent.setReplaceObject(dsColumn); //高级-显示值 diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java index 69b763248c..d26bf69767 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java @@ -63,29 +63,33 @@ public class SearchChartCollectionFormulaAction { public void searchChartCollectionFormula(List formulaInfos, ITContent content, ChartCollection chartCollection) { for (int i = 0; i < chartCollection.getChartCount(); i++) { ITContent chartContent = ITContent.copy(content); - searchChartPatternFormula(formulaInfos, chartContent, chartCollection.getChart(i)); + Chart chart = chartCollection.getChart(i); + if (chart == null) { + continue; + } + searchChartPatternFormula(formulaInfos, chartContent, chart); if (isChangeConfigAttrValid(chartCollection.getChangeConfigAttr())) { //图表切换属性 - dealChangeConfig(formulaInfos, chartContent, chartCollection.getChart(i)); + dealChangeConfig(formulaInfos, chartContent, chart); } //图表-交互属性-超级链接 - dealChartHyperLink(formulaInfos, chartContent, chartCollection.getChart(i)); + dealChartHyperLink(formulaInfos, chartContent, chart); //数据-单元格数据-分类名&系列名&值 SearchChartDataFormulaManager searchChartDataFormulaManager = SearchChartDataFormulaManager.getInstance(); Map type = searchChartDataFormulaManager.getChartDataType(); - if (isDefinitionValid(chartCollection.getChart(i).getFilterDefinition())) { - String name = chartCollection.getChart(i).getFilterDefinition().getClass().getSimpleName(); + if (isDefinitionValid(chart.getFilterDefinition())) { + String name = chart.getFilterDefinition().getClass().getSimpleName(); SearchChartDataFormula searchChartDataFormula = type.get(name); - TopDefinitionProvider provider = chartCollection.getChart(i).getFilterDefinition(); + TopDefinitionProvider provider = chart.getFilterDefinition(); ITContent dataContent = ITContent.copy(content); - dataContent.addOtherPos(chartCollection.getChart(i).getChartName(), Toolkit.i18nText("Fine-Design_Basic_Data")); + dataContent.addOtherPos(chart.getChartName(), Toolkit.i18nText("Fine-Design_Basic_Data")); searchChartDataFormula.searchChartDataFormula(formulaInfos, dataContent, provider); } //数据-形态 - if (chartCollection.getChart(i).getFilterDefinition() != null) { + if (chart.getFilterDefinition() != null) { ITContent presentContent = ITContent.copy(content); - presentContent.addOtherPos(chartCollection.getChart(i).getChartName(), Toolkit.i18nText("Fine-Design_Basic_Data")); - searchFormulaFromChartPresent(formulaInfos, presentContent, chartCollection.getChart(i).getFilterDefinition()); + presentContent.addOtherPos(chart.getChartName(), Toolkit.i18nText("Fine-Design_Basic_Data")); + searchFormulaFromChartPresent(formulaInfos, presentContent, chart.getFilterDefinition()); } } } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/template/SearchTemplateFormulaAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/template/SearchTemplateFormulaAction.java index 0dab4a7e4b..b95a6f6be6 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/template/SearchTemplateFormulaAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/template/SearchTemplateFormulaAction.java @@ -2,21 +2,17 @@ package com.fr.design.actions.replace.action.content.formula.template; import com.fr.base.Formula; import com.fr.base.Parameter; -import com.fr.base.ParameterConfig; import com.fr.base.io.AttrMark; import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.data.ClassSubmitJob; import com.fr.data.Verifier; import com.fr.data.VerifyItem; import com.fr.design.actions.replace.action.content.formula.highlight.javascript.SearchCommit2DBJSFormulaAction; import com.fr.design.actions.replace.info.FormulaInfo; import com.fr.design.actions.replace.info.base.ITContent; import com.fr.design.actions.replace.info.base.SearchTag; -import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.JTemplate; -import com.fr.design.mainframe.ReportComponentComposite; -import com.fr.design.mainframe.SheetNameTabPane; import com.fr.main.impl.WorkBook; import com.fr.report.core.ReportUtils; import com.fr.report.report.Report; @@ -25,8 +21,10 @@ import com.fr.report.write.BuiltInSQLSubmiter; import com.fr.report.write.ReportWriteAttr; import com.fr.report.write.SubmitVisitor; import com.fr.report.write.ValueVerifier; +import com.fr.report.write.WClassSubmiter; +import com.fr.report.write.WClassVerifier; import com.fr.stable.CommonUtils; - +import com.fr.stable.ListMap; import java.util.List; @@ -109,16 +107,31 @@ public class SearchTemplateFormulaAction implements SearchTemplateFormula { //数据校验 for (int i = 0, len = attr.getVerifierCount(); i < len; i++) { Verifier verifier = attr.getVerifier(i); + ITContent content = ITContent.copy(sheetContent); + content.addOtherPos(Toolkit.i18nText("Fine-Design_Report_Verify_Data_Verify")); if (verifier instanceof ValueVerifier) { - ITContent content = ITContent.copy(sheetContent); - content.addOtherPos(Toolkit.i18nText("Fine-Design_Report_Verify_Data_Verify")); dealValueVerifier4Formula(formulaInfos, content, (ValueVerifier) verifier); + } else if (verifier instanceof WClassVerifier) { + dealWClassVerifier(formulaInfos, content, (WClassVerifier)verifier); } } } } + private void dealWClassVerifier(List formulaInfos, ITContent content, WClassVerifier verifier) { + if (verifier.getClassVerifyJob() != null) { + ListMap map = verifier.getClassVerifyJob().getPropertyMap(); + for (Object value : map.values()) { + if (value instanceof Formula) { + ITContent formulaContent = ITContent.copy(content); + formulaContent.setReplaceObject(value); + formulaInfos.add(new FormulaInfo(formulaContent)); + } + } + } + } + private void dealValueVerifier4Formula(List formulaInfos, ITContent content, ValueVerifier verifier) { ITContent verifyContent = ITContent.copy(content); verifyContent.addOtherPos(verifier.getName()); @@ -133,6 +146,7 @@ public class SearchTemplateFormulaAction implements SearchTemplateFormula { ITContent messageContent = ITContent.copy(verifyContent); messageContent.setReplaceObject(item.getMessage()); messageContent.setHoldObject(item); + messageContent.setTag(SearchTag.WRITE_ATTR_MESSAGE); formulaInfos.add(new FormulaInfo(messageContent)); } } @@ -144,6 +158,25 @@ public class SearchTemplateFormulaAction implements SearchTemplateFormula { ITContent content = ITContent.copy(submitContent); content.addOtherPos(submiter.getName()); SearchCommit2DBJSFormulaAction.getInstance().dealWithDBManipulation(formulaInfos, content, submiter.getDBManipulation()); + } else if (visitor instanceof WClassSubmiter) { + WClassSubmiter submiter = (WClassSubmiter) visitor; + ITContent content = ITContent.copy(submitContent); + content.addOtherPos(submiter.getName()); + if (submiter.getSubmitJob() instanceof ClassSubmitJob) { + ClassSubmitJob job = (ClassSubmitJob) submiter.getSubmitJob(); + dealClassSubmitJob(formulaInfos, job, content); + } + } + } + + private void dealClassSubmitJob(List formulaInfos, ClassSubmitJob job, ITContent content) { + ListMap map = job.getPropertyMap(); + for (Object value : map.values()) { + if (value instanceof Formula) { + ITContent formulaContent = ITContent.copy(content); + formulaContent.setReplaceObject(value); + formulaInfos.add(new FormulaInfo(formulaContent)); + } } } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchCellJSAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchCellJSAction.java index cff74e9e0a..997000d06b 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchCellJSAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchCellJSAction.java @@ -9,6 +9,7 @@ import com.fr.design.actions.replace.info.base.ITContent; import com.fr.design.actions.replace.utils.SearchJSUtils; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.JTemplate; +import com.fr.js.JavaScript; import com.fr.js.JavaScriptImpl; import com.fr.js.NameJavaScriptGroup; @@ -42,6 +43,18 @@ public class SearchCellJSAction implements SearchJS { jsInfos.addAll(CellJSInfos); } + @Override + public List getTemplateJSDependenceTables(JTemplate jTemplate) { + List scripts = new ArrayList<>(); + SearchCellAction searchCellAction = SearchCellAction.getInstance(); + searchCellAction.search4Infos(jTemplate); + for (CellInfo cellInfo : searchCellAction.getCellInfos()) { + CellElement cell = (CellElement) cellInfo.getContent().getReplaceObject(); + scripts.addAll(SearchJSUtils.getJSDependenceTables(cell)); + } + return scripts; + } + private void addJSInfos2ListFromCell(JTemplate jTemplate, List jsInfos) { SearchCellAction searchCellAction = SearchCellAction.getInstance(); searchCellAction.search4Infos(jTemplate); diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java index 1d04ac2ccf..ca550066ac 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java @@ -9,7 +9,6 @@ import com.fr.design.actions.replace.utils.SearchJSUtils; import com.fr.design.i18n.Toolkit; import com.fr.js.JavaScriptImpl; import com.fr.js.NameJavaScript; - import com.fr.js.NameJavaScriptGroup; import com.fr.plugin.chart.attr.axis.VanChartAxis; import com.fr.plugin.chart.attr.plot.VanChartPlot; @@ -21,7 +20,6 @@ import com.fr.plugin.chart.custom.VanChartCustomPlot; import com.fr.plugin.chart.vanchart.VanChart; import com.fr.stable.collections.combination.Pair; -import java.util.ArrayList; import java.util.List; /** diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchFloatJSAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchFloatJSAction.java index 4270d5bbca..96f589d791 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchFloatJSAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchFloatJSAction.java @@ -11,6 +11,7 @@ import com.fr.design.actions.replace.utils.SearchJSUtils; import com.fr.design.mainframe.JTemplate; +import com.fr.js.JavaScript; import com.fr.report.cell.FloatElement; @@ -37,6 +38,17 @@ public class SearchFloatJSAction implements SearchJS { jsInfos.addAll(floatJSInfos); } + @Override + public List getTemplateJSDependenceTables(JTemplate jTemplate) { + List scripts = new ArrayList<>(); + SearchFloatAction searchFloatAction = SearchFloatAction.getInstance(); + searchFloatAction.search4Infos(jTemplate); + for (FloatInfo floatInfo : searchFloatAction.getFloatInfos()) { + FloatElement floatElement = (FloatElement) floatInfo.getContent().getReplaceObject(); + scripts.addAll(SearchJSUtils.getJSDependenceTables(floatElement)); + } + return scripts; + } private void addJSInfos2ListFromFloat(JTemplate jTemplate, List jsInfos) { SearchFloatAction searchFloatAction = SearchFloatAction.getInstance(); diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJS.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJS.java index d543a4c2ea..64d65abfc9 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJS.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJS.java @@ -3,7 +3,9 @@ package com.fr.design.actions.replace.action.content.js; import com.fr.design.actions.replace.action.SearchAction; import com.fr.design.actions.replace.info.JSInfo; import com.fr.design.mainframe.JTemplate; +import com.fr.js.JavaScript; +import java.util.ArrayList; import java.util.List; /** @@ -23,4 +25,14 @@ public interface SearchJS extends SearchAction { */ default void searchJSFromObject(JTemplate jTemplate, List jsInfos) { } + + /** + * 获取模板中的涉及数据集的所有超链 + * + * @param jTemplate 模板 + * @return 超链集合 + */ + default List getTemplateJSDependenceTables(JTemplate jTemplate) { + return new ArrayList<>(); + } } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJSManager.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJSManager.java index 9bd972a1f1..f2a1cc38af 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJSManager.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchJSManager.java @@ -5,6 +5,7 @@ import com.fr.design.actions.replace.action.SearchManager; import com.fr.design.actions.replace.info.JSInfo; import com.fr.design.mainframe.JTemplate; +import com.fr.js.JavaScript; import java.util.ArrayList; import java.util.HashSet; @@ -45,6 +46,21 @@ public class SearchJSManager implements SearchAction, SearchManager { setJsInfos(jsInfos); } + + /** + * 查找超链 + * + * @param jTemplate 模板 + * @return 超链集合 + */ + public List getTemplateJSDependenceTables(JTemplate jTemplate) { + List javaScripts = new ArrayList<>(); + for (SearchJS searchJS : searchJSSet) { + javaScripts.addAll(searchJS.getTemplateJSDependenceTables(jTemplate)); + } + return javaScripts; + } + public List getJsInfos() { return jsInfos; } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaType.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaType.java new file mode 100644 index 0000000000..af1ba2a661 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaType.java @@ -0,0 +1,87 @@ +package com.fr.design.actions.replace.action.content.tabledata; + +import com.fr.stable.StringUtils; + +/** + * 涉及数据集的公式类型枚举 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/11/5 + */ +public enum TableDataFormulaType { + /** + * COLCOUNT公式 + */ + COLCOUNT("COLCOUNT", 0), + /** + * CLONAME公式 + */ + COLNAME("COLNAME", 0), + /** + * MAP公式 + */ + MAP("MAP", 1), + /** + * ROWCOUNT公式 + */ + ROWCOUNT("ROWCOUNT", 0), + /** + * TABLEDATAFILEDS公式 + */ + TABLEDATAFIELDS("TABLEDATAFIELDS", 0), + /** + * VALUE公式或者是ds1.value(xxx)两种情况 + */ + VALUE("VALUE", 0), + /** + * ds1.select(xxx) + */ + SELECT("SELECT", 0), + /** + * ds1.group(xxx) + */ + GROUP("GROUP", 0), + /** + * ds1.find(xxx) + */ + FIND("FIND", 0); + + private int argumentIndex; + private String name; + + TableDataFormulaType(String name, int argumentIndex) { + this.argumentIndex = argumentIndex; + this.name = name; + } + + public int getArgumentIndex() { + return argumentIndex; + } + + /** + * 公式content是否需要替换处理 + */ + public static boolean needReplace(String value) { + for (TableDataFormulaType type : TableDataFormulaType.values()) { + if (value.toUpperCase().contains(type.name().toUpperCase())) { + return true; + } + } + return false; + } + + + /** + * 获取对应的公式类型 + */ + public static TableDataFormulaType get(String functionName) { + for (TableDataFormulaType type : TableDataFormulaType.values()) { + if (StringUtils.equalsIgnoreCase(functionName, type.name())) { + return type; + } + } + return null; + } +} + diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtils.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtils.java new file mode 100644 index 0000000000..ffeabb95a2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtils.java @@ -0,0 +1,316 @@ +package com.fr.design.actions.replace.action.content.tabledata; + +import com.fr.data.TableReplacementEntity; +import com.fr.invoke.Reflect; +import com.fr.log.FineLoggerFactory; +import com.fr.parser.BinaryExpression; +import com.fr.parser.DatasetFunctionCall; +import com.fr.parser.FunctionCall; +import com.fr.parser.StringLiteral; +import com.fr.script.Calculator; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Expression; +import com.fr.stable.script.Node; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 公式工具 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/11/5 + */ +public class TableDataFormulaUtils { + + + private static final String LEFT_BRACKET = "${"; + private static final String RIGHT_BRACKET = "}"; + private static final String FORMULA_MARK = "="; + private static final String STATEMENT = "statement"; + private static final String SOURCE_NAME = "sourceName"; + + /** + * 从公式中寻找数据集名称 + * + * @param formula 公式的content + * @return 返回数据集名称集合 + */ + public static Set search4TableData(String formula) { + Set result = new HashSet<>(); + for (TableDataFormulaType tableDataFormulaType : TableDataFormulaType.values()) { + result.addAll(TableDataFormulaUtils.fetchArgument(formula, tableDataFormulaType.name(), tableDataFormulaType.getArgumentIndex())); + } + return result; + } + + + /** + * 获取替换指定数据集后的公式全文 + * + * @param formula 公式content + * @param entities 替换信息 + * @return 替换后的全文 + */ + public static String replace4TableData(String formula, List entities) { + try { + Expression expression = Calculator.createCalculator().parse(formula); + TableDataFormulaUtils.replace0(expression, entities); + String ans = expression.toString(); + if (formula.startsWith(FORMULA_MARK) && !ans.startsWith(FORMULA_MARK)) { + return FORMULA_MARK + ans; + } else { + if (ans.startsWith(FORMULA_MARK)) { + return ans.substring(1); + } + } + return ans; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return formula; + } + } + + private static void replace0(Expression expression, List entities) { + if (expression != null) { + Node node = expression.getConditionalExpression(); + if (node instanceof BinaryExpression) { + BinaryExpression binaryExpression = (BinaryExpression) node; + Node[] nodes = binaryExpression.getNodes(); + if (nodes != null) { + for (Node subNode : nodes) { + if (subNode instanceof FunctionCall) { + FunctionCall functionCall = (FunctionCall) subNode; + TableDataFormulaUtils.replaceArgument4FunctionCall(functionCall, entities); + } else if (subNode instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) subNode; + TableDataFormulaUtils.replaceArgument4DatasetFunctionCall(datasetFunctionCall, entities); + } + } + } + } else if (node instanceof FunctionCall) { + FunctionCall functionCall = (FunctionCall) node; + TableDataFormulaUtils.replaceArgument4FunctionCall(functionCall, entities); + } else if (node instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) node; + TableDataFormulaUtils.replaceArgument4DatasetFunctionCall(datasetFunctionCall, entities); + } + } + } + + private static void replaceArgument4DatasetFunctionCall(DatasetFunctionCall datasetFunctionCall, List entities) { + Node[] subNodes = datasetFunctionCall.getArguments(); + if (subNodes != null) { + // 数据集名称 + StringBuilder parent = new StringBuilder(datasetFunctionCall.getSourceName()); + for (Node subNode : subNodes) { + // 嵌套普通公式 + if (subNode instanceof FunctionCall) { + replaceArgument4FunctionCall((FunctionCall) subNode, entities); + } else if (subNode instanceof StringLiteral) { + // 无嵌套,可以根据传进来的datasetFunctionCall进行替换 + StringLiteral stringLiteral = (StringLiteral) subNode; + replaceDatasetFunctionCall0(stringLiteral, datasetFunctionCall, entities, parent); + } else if (subNode instanceof DatasetFunctionCall) { + // 嵌套datasetFunctionCall,递归回来该方法继续往下 + DatasetFunctionCall datasetFunctionCall1 = (DatasetFunctionCall) subNode; + replaceArgument4DatasetFunctionCall(datasetFunctionCall1, entities); + } + } + for (TableReplacementEntity entity : entities) { + if (StringUtils.equals(parent.toString(), entity.getOldName())) { + // 子节点都替换完了才换最前面的数据集名称 + Reflect.on(datasetFunctionCall).set(SOURCE_NAME, entity.getNewName()); + break; + } + } + } + } + + private static void replaceDatasetFunctionCall0(StringLiteral stringLiteral, DatasetFunctionCall datasetFunctionCall, List entities, StringBuilder parent) { + try { + TableDataFormulaType type = TableDataFormulaType.get(datasetFunctionCall.getFnName()); + if (type != null) { + String name = stringLiteral.eval(Calculator.createCalculator()).toString(); + for (TableReplacementEntity entity : entities) { + if (StringUtils.equals(parent.toString(), entity.getOldName())) { + // 如果是要替换的数据集 + String field = entity.getTargetField(name); + // 替换成匹配后的字段 + Reflect.on(stringLiteral).set(STATEMENT, field); + break; + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().debug(e, e.getMessage()); + } + } + + + /** + * 从公式(可能存在嵌套)中解析出某类型函数的第几个参数 + * + * @param formula 公式 + * @param functionName 函数名 + * @param argumentIndex 参数位置 + * @return 对应参数位置的值 + */ + public static List fetchArgument(String formula, String functionName, int argumentIndex) { + List result = new ArrayList<>(); + try { + Expression expression = Calculator.createCalculator().parse(formula); + if (expression != null) { + Node node = expression.getConditionalExpression(); + if (node instanceof BinaryExpression) { + BinaryExpression binaryExpression = (BinaryExpression) node; + Node[] nodes = binaryExpression.getNodes(); + if (nodes != null) { + for (Node subNode : nodes) { + if (subNode instanceof FunctionCall) { + FunctionCall functionCall = (FunctionCall) subNode; + result.addAll(TableDataFormulaUtils.fetchArgument(functionCall, functionName, argumentIndex)); + } else if (subNode instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) subNode; + result.addAll(TableDataFormulaUtils.fetchArgument(datasetFunctionCall, functionName)); + } + } + } + } else if (node instanceof FunctionCall) { + FunctionCall functionCall = (FunctionCall) node; + result.addAll(TableDataFormulaUtils.fetchArgument(functionCall, functionName, argumentIndex)); + } else if (node instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) node; + result.addAll(TableDataFormulaUtils.fetchArgument(datasetFunctionCall, functionName)); + } + } + + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + return result; + } + + private static List fetchArgument(DatasetFunctionCall datasetFunctionCall, String functionName) { + List result = new ArrayList<>(); + Node[] subNodes = datasetFunctionCall.getArguments(); + String sourceName = datasetFunctionCall.getSourceName(); + if (StringUtils.isNotEmpty(functionName)) { + result.add(sourceName); + } + if (subNodes != null) { + // 遍历子公式 + for (Object subNode : subNodes) { + if (subNode instanceof FunctionCall) { + for (TableDataFormulaType tableDataFormulaType : TableDataFormulaType.values()) { + result.addAll(TableDataFormulaUtils.fetchArgument((FunctionCall) subNode, tableDataFormulaType.name(), tableDataFormulaType.getArgumentIndex())); + } + } else if (subNode instanceof DatasetFunctionCall) { + result.addAll(fetchArgument((DatasetFunctionCall) subNode, functionName)); + } + } + } + return result; + } + + private static void replaceArgument4FunctionCall(FunctionCall functionCall, List entities) { + Node[] subNodes = functionCall.getArguments(); + if (subNodes != null) { + StringBuilder parent = new StringBuilder(StringUtils.EMPTY); + for (int i = 0; i < subNodes.length; i++) { + Node subNode = subNodes[i]; + if (subNode instanceof FunctionCall) { + replaceArgument4FunctionCall((FunctionCall) subNode, entities); + } + if (subNode instanceof StringLiteral) { + StringLiteral stringLiteral = (StringLiteral) subNode; + replaceFunctionCall0(i, stringLiteral, functionCall, entities, parent); + + } + } + } + } + + private static void replaceFunctionCall0(int i, StringLiteral stringLiteral, FunctionCall functionCall, List entities, StringBuilder parent) { + try { + TableDataFormulaType type = TableDataFormulaType.get(functionCall.getName()); + if (type != null) { + String name = stringLiteral.eval(Calculator.createCalculator()).toString(); + for (TableReplacementEntity entity : entities) { + // 数据集名 + if (i == type.getArgumentIndex()) { + if (StringUtils.equals(name, entity.getOldName())) { + // 替换数据集名 + parent.append(name); + Reflect.on(stringLiteral).set(STATEMENT, entity.getNewName()); + break; + } + } else { + String field = entity.getTargetField(name); + // 如果是需要匹配的字段 + // 要走到字段匹配,就必须先经过数据集名匹配,目前所有公式都是数据集在前,字段在后 + if (StringUtils.isNotEmpty(field) && StringUtils.isNotEmpty(parent.toString())) { + // 替换成匹配后的字段 + Reflect.on(stringLiteral).set(STATEMENT, field); + break; + } + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().debug(e, e.getMessage()); + } + } + + + /** + * 从公式(可能存在嵌套)中解析出某类型函数的第几个参数 + * + * @param functionCall 公式 + * @param functionName 函数名 + * @param argumentIndex 参数位置 + * @return 对应参数位置的值 + */ + public static List fetchArgument(FunctionCall functionCall, String functionName, int argumentIndex) { + List result = new ArrayList<>(); + Node[] subNodes = functionCall.getArguments(); + if (subNodes != null) { + // 遍历子公式 + for (int i = 0; i < subNodes.length; i++) { + Object subNode = subNodes[i]; + if (i == argumentIndex && subNode instanceof StringLiteral && StringUtils.equalsIgnoreCase(functionCall.getName(), functionName)) { + StringLiteral stringLiteral = (StringLiteral) subNode; + try { + result.add(stringLiteral.eval(Calculator.createCalculator()).toString()); + } catch (Exception e) { + FineLoggerFactory.getLogger().debug(e, e.getMessage()); + } + continue; + } + if (subNode instanceof FunctionCall) { + for (TableDataFormulaType tableDataFormulaType : TableDataFormulaType.values()) { + result.addAll(TableDataFormulaUtils.fetchArgument((FunctionCall) subNode, tableDataFormulaType.name(), tableDataFormulaType.getArgumentIndex())); + } + } + } + } + return result; + } + + /** + * 通过${content}格式获取公式内容 + * + * @param formula 原公式值 + * @return 最终公式值 + */ + public static String getFormulaPureContent(String formula) { + if (formula.startsWith(LEFT_BRACKET) && formula.endsWith(RIGHT_BRACKET)) { + return formula.substring(LEFT_BRACKET.length() + 1, formula.length() - 1); + } else { + return formula; + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/widget/SearchWidgetAction.java b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/widget/SearchWidgetAction.java index 63b5df9d8f..afa6c4e4fb 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/widget/SearchWidgetAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/action/content/widget/SearchWidgetAction.java @@ -68,21 +68,29 @@ public class SearchWidgetAction implements SearchAction { } - private void addCellWidget2Array(ArrayList widgetInfos, JTemplate jTemplate) { + private void addCellWidget2Array(List widgetInfos, JTemplate jTemplate) { SearchCellAction searchCellAction = SearchCellAction.getInstance(); searchCellAction.search4Infos(jTemplate); if (searchCellAction.getCellInfos().size() > 0) { - for (CellInfo cellInfo : searchCellAction.getCellInfos()) { - //单元格本身的控件 - addWidget2ArrayFromCell(widgetInfos, cellInfo); - //单元格条件属性中超链内的控件 - addWidget2ArrayFromCellHighlight(widgetInfos, cellInfo); - } + searchCellWidget(widgetInfos, searchCellAction.getCellInfos()); + } + + } + + /** + * 搜索单元格中的控件 + */ + public void searchCellWidget(List widgetInfos, List cellInfos) { + for (CellInfo cellInfo : cellInfos) { + //单元格本身的控件 + addWidget2ArrayFromCell(widgetInfos, cellInfo); + //单元格条件属性中超链内的控件 + addWidget2ArrayFromCellHighlight(widgetInfos, cellInfo); } } - private void addWidget2ArrayFromCellHighlight(ArrayList widgetInfos, CellInfo cellInfo) { + private void addWidget2ArrayFromCellHighlight(List widgetInfos, CellInfo cellInfo) { if (cellInfo.getContent().getReplaceObject() instanceof TemplateCellElement) { TemplateCellElement cell = (TemplateCellElement) cellInfo.getContent().getReplaceObject(); if (cell.getHighlightGroup() != null) { @@ -92,7 +100,7 @@ public class SearchWidgetAction implements SearchAction { } } - private void dealWithHighlightGroup4Widget(HighlightGroup highlightGroup, ArrayList widgetInfos, CellInfo cellInfo) { + private void dealWithHighlightGroup4Widget(HighlightGroup highlightGroup, List widgetInfos, CellInfo cellInfo) { for (int i = 0; i < highlightGroup.size(); i++) { for (int j = 0; j < ((DefaultHighlight) highlightGroup.getHighlight(i)).actionCount(); j++) { HighlightAction highlightAction = ((DefaultHighlight) highlightGroup.getHighlight(i)).getHighlightAction(j); @@ -115,7 +123,7 @@ public class SearchWidgetAction implements SearchAction { return highlightAction instanceof WidgetHighlightAction && ((WidgetHighlightAction) highlightAction).getWidget() != null; } - private void addWidget2ArrayFromCell(ArrayList widgetInfos, CellInfo cellInfo) { + private void addWidget2ArrayFromCell(List widgetInfos, CellInfo cellInfo) { if (cellInfo.getContent().getReplaceObject() instanceof TemplateCellElement && ((TemplateCellElement) cellInfo.getContent().getReplaceObject()).getWidget() != null) { // 单元格内有控件 diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/info/FormulaInfo.java b/designer-realize/src/main/java/com/fr/design/actions/replace/info/FormulaInfo.java index ce2ecd36c6..e0f86fc084 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/info/FormulaInfo.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/info/FormulaInfo.java @@ -20,6 +20,8 @@ import java.util.Map; * created by Destiny.Lin on 2022-08-17 */ public class FormulaInfo implements Info { + + public static final String CONTENT = "content"; private ITContent content; private static final String DISPLAY = Toolkit.i18nText("Fine-Design_Basic_DS_Dictionary") + "-" + Toolkit.i18nText("Fine-Design_Chart_Formula") + "-" + Toolkit.i18nText("Fine-Design_Basic_Display_Value"); private static final String ACTUAL = Toolkit.i18nText("Fine-Design_Basic_DS_Dictionary") + "-" + Toolkit.i18nText("Fine-Design_Chart_Formula") + "-" + Toolkit.i18nText("Fine-Design_Basic_Actual_Value"); @@ -76,4 +78,11 @@ public class FormulaInfo implements Info { return map; } + /** + * 获取公式值 + */ + public String getPureValue() { + return getCommonValue().get(CONTENT); + } + } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java b/designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java index cf9a5ca165..41d24534af 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java @@ -38,7 +38,6 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -import static com.fr.design.actions.replace.ui.ITTableEditorPane.editTable; import static com.fr.design.actions.replace.ui.ITTableEditorPane.getEditTable; /** @@ -126,6 +125,7 @@ public class ITReplaceMainDialog extends UIDialog { setLocation(new Point(point.x, point.y + jTemplate.getHeight() / 2 + jTemplate.getHeight() / 2 - 385)); northPane.fitScreen(0, 0, width); + } @@ -566,7 +566,7 @@ public class ITReplaceMainDialog extends UIDialog { } } } - + private boolean isSupportReplace(Info info) { return info.getContent().isSelected() && !info.getContent().isReplaced(); } diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/utils/ReplaceUtils.java b/designer-realize/src/main/java/com/fr/design/actions/replace/utils/ReplaceUtils.java new file mode 100644 index 0000000000..f7c4946eb6 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/utils/ReplaceUtils.java @@ -0,0 +1,639 @@ +package com.fr.design.actions.replace.utils; + +import com.fr.base.Formula; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.web.ChartHyperPoplink; +import com.fr.data.SimpleDSColumn; +import com.fr.data.TableReplacementEntity; +import com.fr.data.condition.CommonCondition; +import com.fr.data.condition.JoinCondition; +import com.fr.data.condition.ListCondition; +import com.fr.data.core.Compare; +import com.fr.data.impl.NameTableData; +import com.fr.data.impl.TableDataDictionary; +import com.fr.data.impl.TreeNodeAttr; +import com.fr.data.impl.TreeNodeWrapper; +import com.fr.design.actions.replace.action.content.cell.SearchCellAction; +import com.fr.design.actions.replace.action.content.formula.SearchFormulaManager; +import com.fr.design.actions.replace.action.content.formula.cell.SearchCellFormulaAction; +import com.fr.design.actions.replace.action.content.formula.chart.SearchChartCollectionFormulaAction; +import com.fr.design.actions.replace.action.content.formula.widget.SearchWidgetFormulaAction; +import com.fr.design.actions.replace.action.content.js.SearchJSManager; +import com.fr.design.actions.replace.action.content.tabledata.TableDataFormulaType; +import com.fr.design.actions.replace.action.content.tabledata.TableDataFormulaUtils; +import com.fr.design.actions.replace.action.content.widget.SearchWidgetAction; +import com.fr.design.actions.replace.info.CellInfo; +import com.fr.design.actions.replace.info.FormulaInfo; +import com.fr.design.actions.replace.info.WidgetInfo; +import com.fr.design.actions.replace.info.base.ITContent; +import com.fr.design.mainframe.JTemplate; +import com.fr.form.FormElementCaseProvider; +import com.fr.form.data.DataBinding; +import com.fr.form.ui.DataControl; +import com.fr.form.ui.DictionaryContainer; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.ui.TreeEditor; +import com.fr.form.ui.Widget; +import com.fr.form.ui.concept.data.ValueInitializer; +import com.fr.form.ui.tree.LayerConfig; +import com.fr.general.ComparatorUtils; +import com.fr.general.data.Condition; +import com.fr.general.data.TableDataColumn; +import com.fr.js.JavaScript; +import com.fr.js.NameJavaScript; +import com.fr.js.NameJavaScriptGroup; +import com.fr.main.impl.WorkBook; +import com.fr.main.parameter.ReportParameterAttr; +import com.fr.report.cell.CellElement; +import com.fr.report.cell.FloatElement; +import com.fr.report.cell.TemplateCellElement; +import com.fr.report.cell.cellattr.core.group.DSColumn; +import com.fr.report.cell.cellattr.highlight.DefaultHighlight; +import com.fr.report.cell.cellattr.highlight.Highlight; +import com.fr.report.cell.cellattr.highlight.HighlightGroup; +import com.fr.report.cell.cellattr.highlight.HyperlinkHighlightAction; +import com.fr.report.cell.cellattr.highlight.PresentHighlightAction; +import com.fr.report.cell.cellattr.highlight.WidgetHighlightAction; +import com.fr.report.elementcase.ElementCase; +import com.fr.report.report.Report; +import com.fr.report.utils.ElementCaseHelper; +import com.fr.stable.StringUtils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * 数据集查找替换工具 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/11/4 + */ +public class ReplaceUtils { + /** + * ----------------------------------------------查找部分-------------------------------------------------- + */ + + /** + * 获取公式里使用的数据集 + * + * @param formula 公式内容 + * @return 返回公式中使用的数据集名称 + */ + public static Set getFormulaDependenceTables(String formula) { + return TableDataFormulaUtils.search4TableData(formula); + } + + + /** + * 获取图表块里使用的数据集(不包含公式里的) + * + * @param chartCollection 图表对象 + * @return 使用的数据集名称 + */ + public static Set getChartDependenceTables(ChartCollection chartCollection) { + return chartCollection.getDataSetNames(); + } + + /** + * 获取图表里使用的公式 + * + * @param chartCollection 图表对象 + * @return 图表公式集合 + */ + public static Set getChartDependenceFormulas(ChartCollection chartCollection) { + List formulaInfos = new ArrayList<>(); + SearchChartCollectionFormulaAction.getInstance().searchChartCollectionFormula(formulaInfos, new ITContent(), chartCollection); + Set ans = new HashSet<>(); + for (FormulaInfo formulaInfo : formulaInfos) { + ans.add(formulaInfo.getContent().getReplaceObject().toString()); + } + return ans; + } + + /** + * 获取报表块里使用的数据集(不包含公式里的) + * + * @param elementCaseEditor 报表块 + * @return 报表块使用的数据集 + */ + public static Set getElementCaseDependenceTables(ElementCaseEditor elementCaseEditor) { + FormElementCaseProvider elementCase = elementCaseEditor.getElementCase(); + return elementCase.getCellTableDataSet(); + } + + /** + * 获取报表块里使用的公式 + * + * @param elementCase 报表块 + * @return 公式集合 + */ + public static Set getElementCaseDependenceFormulas(ElementCase elementCase) { + List formulaInfos = getElementCaseFormulas(elementCase); + Set ans = new HashSet<>(); + for (FormulaInfo formulaInfo : formulaInfos) { + ans.add(formulaInfo.getContent().getReplaceObject().toString()); + } + return ans; + } + + /** + * 获取CPT里使用的数据集(不包含公式里的) + * + * @param template 模板 + * @return 数据集名字集合 + */ + public static Set getCptDependenceTables(JTemplate template) { + Set ans = new HashSet<>(); + if (template.getTarget() instanceof WorkBook) { + WorkBook workBook = (WorkBook) template.getTarget(); + Iterator iterator = workBook.getTableDataNameIterator(); + while (iterator.hasNext()) { + String tableName = iterator.next(); + ans.add(tableName); + } + } + return ans; + } + + /** + * 获取CPT里使用的公式 + * + * @param template 包含workbook的Jtemplate + * @return 公式集合 + */ + public static Set getCptDependenceFormulas(JTemplate template) { + SearchFormulaManager.getInstance().search4Infos(template); + List formulaInfos = SearchFormulaManager.getInstance().getFormulaInfos(); + Set ans = new HashSet<>(); + for (FormulaInfo formulaInfo : formulaInfos) { + ans.add(formulaInfo.getContent().getReplaceObject().toString()); + } + return ans; + } + + + /** + * ----------------------------------------------替换部分-------------------------------------------------- + */ + + /** + * 替换公式里的数据集 + * + * @param formula 公式 + * @param entity 替换信息 + * @return 替换后的公式内容 + */ + public static String replaceFormula(String formula, List entity) { + return TableDataFormulaUtils.replace4TableData(formula, entity); + } + + /** + * 替换公式里的数据集 + * + * @param formula 公式 + * @param entity 替换信息 + */ + public static void replaceFormula(Formula formula, List entity) { + String content = formula.getContent(); + formula.setContent(TableDataFormulaUtils.replace4TableData(content, entity)); + } + + /** + * 替换图表里使用的数据集(包含公式里的) + * + * @param chartCollection 图表对象 + * @param entities 替换信息 + */ + public static void replaceChart(ChartCollection chartCollection, List entities) { + // 非公式部分 + chartCollection.replaceTableData(entities); + // 公式部分 + List formulaInfos = new ArrayList<>(); + SearchChartCollectionFormulaAction.getInstance().searchChartCollectionFormula(formulaInfos, new ITContent(), chartCollection); + replaceFormulaInfos(formulaInfos, entities); + // 超链部分 + replaceChartJs(chartCollection, entities); + } + + /** + * 替换报表块里使用的数据集(包含公式里的) + * + * @param elementCase 报表块控件 + * @param entities 替换信息 + */ + public static void replaceElementCase(ElementCase elementCase, List entities) { + // 非公式部分 + replaceTableDataWithOutFormula(elementCase, entities); + // 公式部分——理论上就只有单元格和控件(超链那些都包含) + List formulaInfos = getElementCaseFormulas(elementCase); + replaceFormulaInfos(formulaInfos, entities); + // 超链部分 + replaceElementCasJs(elementCase, entities); + + } + + + /** + * 替换CPT使用的数据集(包含公式里的) + * + * @param template cpt对应的JTemplate + * @param entity 替换信息 + */ + public static void replaceCpt(JTemplate template, List entity) { + if (template.getTarget() instanceof WorkBook) { + WorkBook workBook = (WorkBook) template.getTarget(); + // 参数面板 + replaceWorkBookPara(workBook, entity); + // 主体非公式部分替换 + replaceWorkBook(workBook, entity); + // 公式部分 + SearchFormulaManager.getInstance().search4Infos(template); + List formulaInfos = SearchFormulaManager.getInstance().getFormulaInfos(); + replaceFormulaInfos(formulaInfos, entity); + // 超链部分 + replaceTemplateJs(template, entity); + // 触发响应 + template.fireTargetModified(); + } + } + + /** + * ----------------------------------------------private-------------------------------------------------- + */ + private static void replaceWorkBookPara(WorkBook workBook, List entity) { + ReportParameterAttr attr = workBook.getReportParameterAttr(); + if (attr != null && attr.getParameterUI() != null) { + Widget[] widgets = attr.getParameterUI().getAllWidgets(); + for (Widget widget : widgets) { + replaceWidget(widget, entity); + } + } + + } + + private static void replaceTemplateJs(JTemplate template, List entity) { + List javaScripts = SearchJSManager.getInstance().getTemplateJSDependenceTables(template); + replaceJs(javaScripts, entity); + } + + private static void replaceChartJs(ChartCollection chartCollection, List entities) { + List scripts = new ArrayList<>(); + List nameJavaScripts = SearchJSUtils.getChartJavaScript(chartCollection); + for(NameJavaScript javaScript : nameJavaScripts) { + if (javaScript.getJavaScript() instanceof ChartHyperPoplink) { + scripts.add(javaScript.getJavaScript()); + } + } + replaceJs(scripts, entities); + } + + private static void replaceElementCasJs(ElementCase elementCase, List entities) { + if (elementCase == null) { + return; + } + List javaScripts = new ArrayList<>(); + // 替换悬浮元素 + Iterator floatIterator = elementCase.floatIterator(); + while (floatIterator.hasNext()) { + FloatElement floatCell = (FloatElement) floatIterator.next(); + javaScripts.addAll(SearchJSUtils.getJSDependenceTables(floatCell)); + } + // 替换通用元素 + Iterator cellIterator = elementCase.cellIterator(); + while (cellIterator.hasNext()) { + CellElement cell = (CellElement) cellIterator.next(); + javaScripts.addAll(SearchJSUtils.getJSDependenceTables(cell)); + } + replaceJs(javaScripts, entities); + } + + private static void replaceCellHighlight(CellElement cell, List entities) { + if (cell instanceof TemplateCellElement) { + HighlightGroup group = ((TemplateCellElement) cell).getHighlightGroup(); + if (group != null) { + for (int i = 0 ; i < group.size(); i++) { + Highlight highlight = group.getHighlight(i); + replaceHighlight(highlight, entities); + } + } + } + } + + private static void replaceHighlight(Highlight highlight, List entities) { + if (highlight instanceof DefaultHighlight) { + DefaultHighlight defaultHighlight = (DefaultHighlight) highlight; + for (int i = 0 ; i < defaultHighlight.actionCount() ; i++) { + if (defaultHighlight.getHighlightAction(i) instanceof PresentHighlightAction) { + PresentHighlightAction action = (PresentHighlightAction) defaultHighlight.getHighlightAction(i); + ElementCaseHelper.replacePresent(action.getPresent(), entities); + } else if (defaultHighlight.getHighlightAction(i) instanceof WidgetHighlightAction) { + WidgetHighlightAction action = (WidgetHighlightAction) defaultHighlight.getHighlightAction(i); + replaceWidget(action.getWidget(), entities); + } else if (defaultHighlight.getHighlightAction(i) instanceof HyperlinkHighlightAction) { + HyperlinkHighlightAction action = (HyperlinkHighlightAction) defaultHighlight.getHighlightAction(i); + NameJavaScriptGroup group = action.getHperlink(); + dealNameJavaScriptGroup(group, entities); + } + } + } + } + + private static void dealNameJavaScriptGroup(NameJavaScriptGroup group, List entities) { + if (group != null) { + for (int i = 0 ; i < group.size(); i++) { + NameJavaScript javaScript = group.getNameHyperlink(i); + if (javaScript.getJavaScript() instanceof ChartHyperPoplink) { + if (((ChartHyperPoplink) javaScript.getJavaScript()).getChartCollection() instanceof ChartCollection) { + replaceChart((ChartCollection) ((ChartHyperPoplink) javaScript.getJavaScript()).getChartCollection(), entities); + } + + } + } + } + } + + + private static void replaceJs(List javaScripts, List entity) { + for (JavaScript javaScript : javaScripts) { + if (javaScript instanceof ChartHyperPoplink) { + ChartHyperPoplink chartHyperPoplink = (ChartHyperPoplink) javaScript; + if (chartHyperPoplink.getChartCollection() instanceof ChartCollection) { + replaceChart((ChartCollection) chartHyperPoplink.getChartCollection(), entity); + } + } + } + } + + + private static void replaceWorkBook(WorkBook workBook, List entity) { + if (acceptTableReplacement(entity)) { + for (int i = 0; i < workBook.getReportCount(); i++) { + Report report = workBook.getReport(i); + if (report != null) { + Iterator it = report.iteratorOfElementCase(); + while (it.hasNext()) { + ElementCase elementCase = (ElementCase) it.next(); + replaceTableDataWithOutFormula(elementCase, entity); + } + } + } + } + } + + private static boolean acceptTableReplacement(List entities) { + for (TableReplacementEntity entity : entities) { + if (entity == null) { + return false; + } + String newName = entity.getNewName(); + String oldName = entity.getOldName(); + if (StringUtils.isEmpty(newName) || StringUtils.isEmpty(oldName)) { + return false; + } + } + return true; + } + + private static void replaceFormulaInfos(List formulaInfos, List entity) { + for (FormulaInfo formulaInfo : formulaInfos) { + if (TableDataFormulaType.needReplace(formulaInfo.getPureValue())) { + formulaInfo.setValue(formulaInfo, + formulaInfo.getPureValue(), + TableDataFormulaUtils.replace4TableData(formulaInfo.getPureValue(), entity), + new ArrayList<>()); + } + } + } + + private static List getElementCaseFormulas(ElementCase elementCase) { + List cellInfos = new ArrayList<>(); + List formulaInfos = new ArrayList<>(); + List widgetInfos = new ArrayList<>(); + SearchCellAction.getInstance().getCellInfoFromElementCase(elementCase, cellInfos, new ITContent()); + SearchCellFormulaAction.getInstance().searchFormulaFromCellInfos(cellInfos, formulaInfos); + SearchWidgetAction.getInstance().searchCellWidget(widgetInfos, cellInfos); + for (WidgetInfo widgetInfo : widgetInfos) { + SearchWidgetFormulaAction.getInstance().searchFormulaFromWidgetInfos(widgetInfo, formulaInfos); + } + return formulaInfos; + } + + + /** + * 替换数据集 + * + * @param elementCase 可以是报表块、组件、WorkBook... + * @param entity 数据集替换信息 + */ + private static void replaceTableDataWithOutFormula(ElementCase elementCase, List entity) { + if (elementCase == null) { + return; + } + + // -------非公式部分------- + // 替换悬浮元素 + replaceFloatCell(elementCase, entity); + // 替换通用元素 + replaceNormalCell(elementCase, entity); + } + + + /** + * 替换通用元素,主要是单元格的各个地方 + * + *
  • 单元格形态
  • + *
  • 单元格控件
  • + *
  • 单元格数据字典
  • + *
  • 单元格值
  • + * + * @param elementCase + * @param entity + */ + private static void replaceNormalCell(ElementCase elementCase, List entity) { + Iterator cellIterator = elementCase.cellIterator(); + + while (cellIterator.hasNext()) { + CellElement cell = (CellElement) cellIterator.next(); + // 处理【形态、控件、数据字典】 + replacePresentAndDictionary(cell, entity); + // 处理【单元格值】 + replaceCellValue(cell, entity); + // 处理【条件属性】 + replaceCellHighlight(cell, entity); + } + } + + private static void replaceCellValue(CellElement cell, List entity) { + Object value = cell.getValue(); + if (value instanceof DSColumn) { + // 替换【数据列】 + replaceDSColumn( (DSColumn) value, entity); + // 替换【条件属性】 + replaceCondition(((DSColumn) value).getCondition(), entity); + } else if (value instanceof ChartCollection) { + ((ChartCollection) value).replaceTableData(entity); + replaceChartJs((ChartCollection) value, entity); + } + } + + private static void replaceCondition(Condition condition, List entity) { + if (condition != null) { + //公式条件不需要修改,里面不会涉及到,有问题再加 + //普通条件 + //1条条件 + if (condition instanceof CommonCondition) { + dealWithTableDataNameChange((CommonCondition) condition, entity); + } + //N条条件 + if (condition instanceof ListCondition) { + for (int k = 0; k < ((ListCondition) condition).getJoinConditionCount(); k++) { + JoinCondition joinCondition = ((ListCondition) condition).getJoinCondition(k); + Condition obCondition = joinCondition.getCondition(); + if (obCondition != null) { + if (obCondition instanceof CommonCondition) { + dealWithTableDataNameChange((CommonCondition) obCondition, entity); + } + } + } + } + } + } + + private static void dealWithTableDataNameChange(CommonCondition condition, List entities) { + Compare compare = condition.getCompare(); + Object ob = compare.getValue(); + if (ob instanceof SimpleDSColumn) { + for (TableReplacementEntity entity : entities) { + if (ComparatorUtils.equals(((SimpleDSColumn) ob).getDsName(), entity.getOldName())) { + ((SimpleDSColumn) ob).setDsName(entity.getNewName()); + ((SimpleDSColumn) ob).setColumn(TableDataColumn.createColumn(entity.getTargetField(TableDataColumn.getColumnName(((SimpleDSColumn) ob).getColumn())))); + } + } + + } + } + + private static void replaceDSColumn(DSColumn dsColumn, List entities) { + for (TableReplacementEntity entity : entities) { + if (ComparatorUtils.equals(dsColumn.getDSName(), entity.getOldName())) { + // 数据集替换 + dsColumn.setDSName(entity.getNewName()); + // 数据集字段替换 + dsColumn.setColumn(TableDataColumn.createColumn(entity.getTargetField(dsColumn.getColumnName()))); + } + } + } + + private static void replacePresentAndDictionary(CellElement cell, List entities) { + TemplateCellElement cellElement = (TemplateCellElement) cell; + // 处理单元格的控件 + replaceWidget(cellElement.getWidget(), entities); + // 处理形态 + ElementCaseHelper.replacePresent(cellElement.getPresent(), entities); + } + + + /** + * 处理控件 + * + * @param widget 控件 + * @param entities 替换信息 + */ + private static void replaceWidget(Widget widget, List entities) { + if (widget instanceof DictionaryContainer) { + DictionaryContainer db = (DictionaryContainer) widget; + if (widget instanceof TreeEditor) { + Object config = ((TreeEditor) widget).getBuildModelConfig(); + replaceTreeConfig(config, entities); + ((TreeEditor) widget).setBuildModelConfig(config); + } + if (db.getDictionary() instanceof TableDataDictionary) { + TableDataDictionary tdd = (TableDataDictionary) db.getDictionary(); + NameTableData ndd = (NameTableData) tdd.getTableData(); + // 控件持有的数据字典也得处理 + ElementCaseHelper.replaceTableDataDictionary(tdd, ndd, entities); + } + } + if (widget instanceof DataControl) { + ValueInitializer value = ((DataControl) widget).getWidgetValue(); + if (value != null && value.getValue() instanceof DataBinding) { + DataBinding binding = (DataBinding) value.getValue(); + for (TableReplacementEntity entity : entities) { + if (StringUtils.equals(entity.getOldName(), binding.getDataSourceName())) { + value.setValue(new DataBinding(entity.getNewName(), entity.getTargetField(binding.getDataBindingKey()))); + break; + } + } + } + } + } + + + /** + * 处理树结构的config + * + * @param config 树结构配置 + * @param entities 替换信息 + */ + public static void replaceTreeConfig(Object config, List entities) { + if (config instanceof LayerConfig[]) { + LayerConfig[] layerConfigs = (LayerConfig[]) config; + dealWithLayerConfigs(layerConfigs, entities); + } else if (config instanceof TreeNodeWrapper) { + TreeNodeWrapper wrapper = (TreeNodeWrapper) config; + dealWithTreeNodeWrapper(wrapper, entities); + } else if (config instanceof TableDataDictionary) { + TableDataDictionary tableDataDictionary = (TableDataDictionary) config; + ElementCaseHelper.replaceTableDataDictionary(tableDataDictionary, (NameTableData) tableDataDictionary.getTableData(), entities); + } + } + + private static void dealWithTreeNodeWrapper(TreeNodeWrapper wrapper, List entities) { + for (TreeNodeAttr attr : wrapper.getTreeNodeAttrs()) { + if (attr.getDictionary() instanceof TableDataDictionary) { + TableDataDictionary tableDataDictionary = (TableDataDictionary) attr.getDictionary(); + ElementCaseHelper.replaceTableDataDictionary(tableDataDictionary, (NameTableData) tableDataDictionary.getTableData(), entities); + } + } + } + + private static void dealWithLayerConfigs(LayerConfig[] layerConfigs, List entities) { + for (LayerConfig layerConfig : layerConfigs) { + if (layerConfig.getDictionary() != null ) { + for (TableReplacementEntity entity : entities) { + if (layerConfig.getTableData() instanceof NameTableData && StringUtils.equals(layerConfig.getTableData().getName(), entity.getOldName())) { + layerConfig.setTableData(new NameTableData(entity.getNewName())); + layerConfig.setViewColumn(entity.getTargetIndex(layerConfig.getViewColumn())); + layerConfig.setModelColumn(entity.getTargetIndex(layerConfig.getModelColumn())); + } + } + ElementCaseHelper.replaceTableDataDictionary(layerConfig.getDictionary(), (NameTableData) layerConfig.getDictionary().getTableData(), entities); + } + } + } + + /** + * 替换悬浮元素中的数据集 + * + * @param elementCase 组件 + * @param entities 替换信息 + */ + private static void replaceFloatCell(ElementCase elementCase, List entities) { + Iterator floatIterator = elementCase.floatIterator(); + while (floatIterator.hasNext()) { + FloatElement floatCell = (FloatElement) floatIterator.next(); + Object value = floatCell.getValue(); + if (value instanceof ChartCollection) { + ((ChartCollection) value).replaceTableData(entities); + replaceChartJs((ChartCollection) value, entities); + } + } + } + + + +} diff --git a/designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java b/designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java index 2a1a4ef188..8a2d245b54 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java +++ b/designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java @@ -36,7 +36,6 @@ import com.fr.report.cell.Elem; import com.fr.stable.StringUtils; import com.fr.stable.collections.combination.Pair; - import java.util.ArrayList; import java.util.List; @@ -379,6 +378,27 @@ public class SearchJSUtils { } + /** + * 获取图表-特效-交互属性中的JS + */ + public static List getChartJavaScript(ChartCollection chartCollection) { + ArrayList nameJavaScriptArrayList = new ArrayList<>(); + for (int i = 0; i < chartCollection.getChartCount(); i++) { + if (chartCollection.getChart(i) instanceof VanChart) { + VanChart chart = ((VanChart) chartCollection.getChart(i)); + if (chart.getPlot() != null) { + NameJavaScriptGroup nameJavaScriptGroup = chart.getPlot().getHotHyperLink(); + if (isNameJavaScriptGroupExist(nameJavaScriptGroup)) { + for (int j = 0; j < nameJavaScriptGroup.size(); j++) { + nameJavaScriptArrayList.add(nameJavaScriptGroup.getNameHyperlink(j)); + } + } + } + } + } + return nameJavaScriptArrayList; + } + /** * 处理图表的交互属性(可能存在多种地图) * @param content 存储信息的数据结构 @@ -493,6 +513,41 @@ public class SearchJSUtils { } } + + /** + * 获取涉及数据集的超链 + * + * @param elem 单元对象 + * @return 超链集合 + */ + public static List getJSDependenceTables(Elem elem) { + List scripts = new ArrayList<>(); + if (elem.getNameHyperlinkGroup() != null) { + for (int j = 0; j < elem.getNameHyperlinkGroup().size(); j++) { + NameJavaScript nameJavaScript = elem.getNameHyperlinkGroup().getNameHyperlink(j); + JavaScript javaScript = nameJavaScript.getJavaScript(); + if (isChartHyperPopLinkValid(javaScript)) { + ChartHyperPoplink chartHyperPoplink = (ChartHyperPoplink) javaScript; + scripts.add(javaScript); + dealWithChartHyperPoplink(chartHyperPoplink, scripts); + } + } + } + return scripts; + } + + private static void dealWithChartHyperPoplink(ChartHyperPoplink chartHyperPoplink, List scripts) { + if (chartHyperPoplink.getChartCollection() instanceof ChartCollection) { + List nameJavaScripts = getNameJavaScript((ChartCollection) chartHyperPoplink.getChartCollection(), new ITContent(), new ArrayList<>()); + for(NameJavaScript javaScript : nameJavaScripts) { + if (javaScript.getJavaScript() instanceof ChartHyperPoplink) { + scripts.add(javaScript.getJavaScript()); + } + } + } + } + + /** * 是否图表悬浮超链且内部图表是否可用 * diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java index f0ff751f17..e4b0cb1c5d 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java @@ -24,9 +24,11 @@ import java.awt.BorderLayout; public class CellWidgetPropertyPane extends BasicPane { private static CellWidgetPropertyPane singleton; - + //当前控件板对应的单元格 private TemplateCellElement cellElement; + //右侧控件板 private WidgetPane cellEditorDefPane; + //左侧单元格板 private ElementCasePane ePane; public static CellWidgetPropertyPane getInstance() { @@ -79,6 +81,11 @@ public class CellWidgetPropertyPane extends BasicPane { } + /** + * 重初始化。选中单元格会走到这 + * + * @param ePane 单元格板 + */ public void reInit(ElementCasePane ePane) { this.ePane = ePane; cellEditorDefPane = new WidgetPane(ePane); @@ -101,14 +108,43 @@ public class CellWidgetPropertyPane extends BasicPane { editingSelection.populateWidgetPropertyPane(ePane); } + /** + * 将控件板中的内容更新到当前选择的单元格项中 + */ public void update() { + if (ePane == null) { + return; + } + //当前单元格板选中的单元格 + CellSelection finalCS = (CellSelection) ePane.getSelection(); if (cellElement == null || !cellEditorDefPane.isShouldFireSelectedEvent()) { return; } - final CellSelection finalCS = (CellSelection) ePane.getSelection(); + doUpdate(finalCS); + } + + /** + * 将控件板中的内容更新到指定单元格项中 + * (js事件的提交入库事件选择单元格时,ePane.getSelection()是左侧选择的单元格,不是右侧控件板对应的单元格。这时候假如走无参的方法就有问题) + * + * @param selection 当前选中项 + */ + public void update(Selection selection) { + if (cellElement == null || !cellEditorDefPane.isShouldFireSelectedEvent()) { + return; + } + CellSelection finalCS = (CellSelection) selection; + //假如指定单元格项和当前控件板对应的单元格不同,则跳过 + if (finalCS.getColumn() != cellElement.getColumn() || finalCS.getRow() != cellElement.getRow()) { + return; + } + doUpdate(finalCS); + } + + private void doUpdate(CellSelection finalCS) { final TemplateElementCase tplEC = ePane.getEditingElementCase(); final Widget cellWidget = cellEditorDefPane.update(); - if(cellWidget == null){ + if (cellWidget == null) { return; } if (finalCS.isSelectedOneCell(ePane)) { @@ -122,15 +158,13 @@ public class CellWidgetPropertyPane extends BasicPane { } setCellWidget(cellWidget, cellElement); } else { - ReportActionUtils.actionIterateWithCellSelection(finalCS, tplEC, new ReportActionUtils.IterAction() { - public void dealWith(CellElement editCellElement) { - // p:最后把这个cellEditorDef设置到CellGUIAttr. - TemplateCellElement templateCellElement = (TemplateCellElement) editCellElement; - try { - setCellWidget((Widget) cellWidget.clone(), templateCellElement); - } catch (CloneNotSupportedException e) { - FineLoggerFactory.getLogger().error("InternalError: " + e.getMessage()); - } + ReportActionUtils.actionIterateWithCellSelection(finalCS, tplEC, editCellElement -> { + // p:最后把这个cellEditorDef设置到CellGUIAttr. + TemplateCellElement templateCellElement = (TemplateCellElement) editCellElement; + try { + setCellWidget((Widget) cellWidget.clone(), templateCellElement); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error("InternalError: " + e.getMessage()); } }); } @@ -139,42 +173,7 @@ public class CellWidgetPropertyPane extends BasicPane { } } - public void update(Selection selection) { - if (cellElement == null || !cellEditorDefPane.isShouldFireSelectedEvent()) { - return; - } - final CellSelection finalCS = (CellSelection) selection; - final TemplateElementCase tplEC = ePane.getEditingElementCase(); - final Widget cellWidget = cellEditorDefPane.update(); - if(cellWidget == null){ - return; - } - if(finalCS.isSelectedOneCell(ePane)){ - if(tplEC.getTemplateCellElement(cellElement.getColumn(), cellElement.getRow())== null){//cellElement未加入到report中时要添加进去 - tplEC.addCellElement(cellElement); - } else { - cellElement = tplEC.getTemplateCellElement(finalCS.getColumn(), finalCS.getRow()); - } - setCellWidget(cellWidget, cellElement); - }else{ - ReportActionUtils.actionIterateWithCellSelection(finalCS, tplEC, new ReportActionUtils.IterAction() { - public void dealWith(CellElement editCellElement) { - // p:最后把这个cellEditorDef设置到CellGUIAttr. - TemplateCellElement templateCellElement = (TemplateCellElement) editCellElement; - try { - setCellWidget((Widget)cellWidget.clone(), templateCellElement); - } catch (CloneNotSupportedException e) { - FineLoggerFactory.getLogger().error("InternalError: " + e.getMessage()); - } - } - }); - } - if(DesignerContext.getDesignerFrame().getSelectedJTemplate() != null){ - DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); - } - } - - private void setCellWidget(Widget cellWidget, TemplateCellElement cellElement){ + private void setCellWidget(Widget cellWidget, TemplateCellElement cellElement) { if (cellWidget instanceof NoneWidget) { cellElement.setWidget(null); } else { @@ -185,7 +184,10 @@ public class CellWidgetPropertyPane extends BasicPane { } } - public void reInitAllListener(){ + /** + * 刷新所有监听器 + */ + public void reInitAllListener() { cellEditorDefPane.registerListener(); } diff --git a/designer-realize/src/test/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtilsTest.java b/designer-realize/src/test/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtilsTest.java new file mode 100644 index 0000000000..bf9dca188b --- /dev/null +++ b/designer-realize/src/test/java/com/fr/design/actions/replace/action/content/tabledata/TableDataFormulaUtilsTest.java @@ -0,0 +1,114 @@ +package com.fr.design.actions.replace.action.content.tabledata; + +import com.fr.data.TableReplacementEntity; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 公式工具类的单测 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/11/5 + */ +public class TableDataFormulaUtilsTest extends TestCase { + + public void testSearch() { + String rowcount = "=ROWCOUNT(\"123\")"; + Set strings = new HashSet<>(); + strings.add("123"); + Assert.assertEquals(TableDataFormulaUtils.search4TableData(rowcount), strings); + Set errorSet = new HashSet<>(); + errorSet.add("1223"); + Assert.assertNotEquals(TableDataFormulaUtils.search4TableData(rowcount), errorSet); + String str = "=COLNAME(\"test-测试\",COLCOUNT(\"列数嵌套123\"))"; + Set qiantao = new HashSet<>(); + qiantao.add("test-测试"); + qiantao.add("列数嵌套123"); + Assert.assertEquals(TableDataFormulaUtils.search4TableData(str), qiantao); + String str2 = "=sum(len(MAP(value(\"test-测试1\",COLNAME(\"test-测试2\",2),COLCOUNT(\"test-测试3\")),\"test-测试4\",COLNAME(\"test-测试5\",2),COLNAME(\"test-测试6\",4))),ROWCOUNT(\"test-测试7\"),len(TABLEDATAFIELDS(\"test-测试8\")))"; + Set qiantao2 = TableDataFormulaUtils.search4TableData(str2); + Assert.assertTrue(qiantao2.contains("test-测试1")); + Assert.assertTrue(qiantao2.contains("test-测试2")); + Assert.assertTrue(qiantao2.contains("test-测试3")); + Assert.assertTrue(qiantao2.contains("test-测试4")); + Assert.assertTrue(qiantao2.contains("test-测试5")); + Assert.assertTrue(qiantao2.contains("test-测试6")); + Assert.assertTrue(qiantao2.contains("test-测试7")); + Assert.assertTrue(qiantao2.contains("test-测试8")); + + String str3 = "TEST_TABLE.select(INNER.select(glbName,\"6\"),\"6\")"; + Set result = TableDataFormulaUtils.search4TableData(str3); + Assert.assertTrue(result.contains("TEST_TABLE")); + Assert.assertTrue(result.contains("INNER")); + } + + public void testReplace() { + String rowcount = "=ROWCOUNT(\"123\")"; + TableReplacementEntity entity = new TableReplacementEntity(); + entity.setOldName("123"); + entity.setNewName("222"); + List entities = new ArrayList<>(); + entities.add(entity); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(rowcount, entities), "=ROWCOUNT(\"222\")"); + + String colcount = "=COLCOUNT(\"test测试\")"; + TableReplacementEntity entity1 = new TableReplacementEntity(); + entity1.setOldName("test测试"); + entity1.setNewName("替换"); + List entities1 = new ArrayList<>(); + entities1.add(entity1); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(colcount, entities1), "=COLCOUNT(\"替换\")"); + + String colname = "=COLNAME(\"test测试\")"; + TableReplacementEntity entity2 = new TableReplacementEntity(); + entity2.setOldName("test测试"); + entity2.setNewName("替换123"); + List entities2 = new ArrayList<>(); + entities2.add(entity2); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(colname, entities2), "=COLNAME(\"替换123\")"); + + String TABLEDATAFIELDS = "=TABLEDATAFIELDS(\"test测试\")"; + TableReplacementEntity entity3 = new TableReplacementEntity(); + entity3.setOldName("test测试"); + entity3.setNewName("替换111"); + List entities3 = new ArrayList<>(); + entities3.add(entity3); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(TABLEDATAFIELDS, entities3), "=TABLEDATAFIELDS(\"替换111\")"); + + String test = "=sum(len(MAP(value(\"test-测试\",COLNAME(\"test-测试\",len(MAP(value(\"test-测试\",COLNAME(\"test-测试\",len(MAP(value(\"test-测试\",COLNAME(\"test-测试\",2),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4)))),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4)))),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4))),ROWCOUNT(\"test-测试\"),len(TABLEDATAFIELDS(\"test-测试\")))"; + TableReplacementEntity entity4 = new TableReplacementEntity(); + entity4.setOldName("test-测试"); + entity4.setNewName("test-测试的副本"); + List entities4 = new ArrayList<>(); + entities4.add(entity4); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(test, entities4), "=sum(len(MAP(value(\"test-测试的副本\",COLNAME(\"test-测试的副本\",len(MAP(value(\"test-测试的副本\",COLNAME(\"test-测试的副本\",len(MAP(value(\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4)))),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4)))),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4))),ROWCOUNT(\"test-测试的副本\"),len(TABLEDATAFIELDS(\"test-测试的副本\")))"); + + + String testCircle = "=sum(len(MAP(value(\"test-测试1\",COLNAME(\"test-测试2\",len(MAP(value(\"test-测试3\",COLNAME(\"test-测试4\",len(MAP(value(\"test-测试\",COLNAME(\"test-测试\",2),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4)))),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4)))),COLCOUNT(\"test-测试\")),\"test-测试\",COLNAME(\"test-测试\",2),COLNAME(\"test-测试\",4))),ROWCOUNT(\"test-测试\"),len(TABLEDATAFIELDS(\"test-测试\")))"; + TableReplacementEntity entity5 = new TableReplacementEntity(); + entity5.setOldName("test-测试"); + entity5.setNewName("test-测试的副本"); + TableReplacementEntity entity6 = new TableReplacementEntity(); + entity6.setOldName("test-测试1"); + entity6.setNewName("test-测试2"); + TableReplacementEntity entity7 = new TableReplacementEntity(); + entity7.setOldName("test-测试2"); + entity7.setNewName("test-测试3"); + TableReplacementEntity entity8 = new TableReplacementEntity(); + entity8.setOldName("test-测试3"); + entity8.setNewName("test-测试4"); + List entities5 = new ArrayList<>(); + entities5.add(entity5); + entities5.add(entity6); + entities5.add(entity7); + entities5.add(entity8); + Assert.assertEquals(TableDataFormulaUtils.replace4TableData(testCircle, entities5), "=sum(len(MAP(value(\"test-测试2\",COLNAME(\"test-测试3\",len(MAP(value(\"test-测试4\",COLNAME(\"test-测试4\",len(MAP(value(\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4)))),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4)))),COLCOUNT(\"test-测试的副本\")),\"test-测试的副本\",COLNAME(\"test-测试的副本\",2),COLNAME(\"test-测试的副本\",4))),ROWCOUNT(\"test-测试的副本\"),len(TABLEDATAFIELDS(\"test-测试的副本\")))"); + + } +} \ No newline at end of file