* commit '3e01391dbc2bb45bf23e25105469f67a013e690c': (63 commits) REPORT-80693 数据脱敏二期 圈复杂度问题 REPORT-80693 数据脱敏二期 【问题原因】一期和二期一起剩余了比较多的bug,处理有风险,跟Lipei、Harrison、Alicia透明讨论后,确定先延期迭代,已修改的代码屏蔽功能入口与关键位置 【改动方案】具体屏蔽的内容,详见https://kms.fineres.com/pages/viewpage.action?pageId=568269880 【review建议】 REPORT-83876 单元格替换了3次但撤回变成了2次 REPORT-80695 模板全局级别查找替换二期 修改钻取地图的获取逻辑 REPORT-80695 模板全局级别查找替换二期 修改钻取地图的获取逻辑 REPORT-80695 模板全局级别查找替换二期 为了通过插件校验,增加一下注释 REPORT-80695 模板全局级别查找替换二期 校验 REPORT-80690 增加注释 REPORT-83313 数据脱敏-点击“数据脱敏设置”后预览页面没有消失 【问题原因】原本做的是"数据脱敏设置"面板是预览面板为parent的另一个dialog,没按照产品文档里做 【改动方案】修改下,打开脱敏设置面板的同时,预览页面消失 【review建议】 REPORT-83624 模板查找替换提示语句key合并 REPORT-80690 修改传入格式数据 REPORT-80690 修改传入格式数据 REPORT-80690 添加适配适配埋点 REPORT-83083 FR图表全量覆盖-部分位置内容查不到相应位置信息,需要补充一下 REPORT-83604 模板内容所有类型的替换:单条替换会替换所有 REPORT-83302 设置项弹窗打开后再次编辑的内容无法实时显示在可选项里 REPORT-83571 数据列设置从分组-普通替换为列表不生效 REPORT-83305 修复修改后界面出现异常 REPORT-83498 单元格-格式-常规选中替换会提示查找内容不符 REPORT-83501 多次替换时,下一次会覆盖上一次替换的记录 ...new-design
@ -0,0 +1,189 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.data.desensitize.base.DesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||||
|
import com.fr.data.desensitize.manage.DesensitizationManager; |
||||||
|
import com.fr.data.desensitize.util.DesentizationUtils; |
||||||
|
import com.fr.decision.webservice.bean.user.DepartmentPostBean; |
||||||
|
import com.fr.decision.webservice.bean.user.RoleBean; |
||||||
|
import com.fr.decision.webservice.utils.DecisionServiceConstants; |
||||||
|
import com.fr.decision.webservice.v10.user.CustomRoleService; |
||||||
|
import com.fr.decision.webservice.v10.user.PositionService; |
||||||
|
import com.fr.design.data.DesignTableDataManager; |
||||||
|
import com.fr.design.data.datapane.preview.PreviewTableModel; |
||||||
|
import com.fr.design.data.datapane.preview.desensitization.model.DesensitizedPreviewTableModel; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Comparator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 管理所有数据集预览过程中的脱敏计算 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/14 |
||||||
|
*/ |
||||||
|
public class TableDataPreviewDesensitizeManager implements DesensitizationManager { |
||||||
|
|
||||||
|
private static final String CONNECTOR = "_"; |
||||||
|
|
||||||
|
private TableDataPreviewDesensitizeManager() { |
||||||
|
} |
||||||
|
|
||||||
|
private static class Holder { |
||||||
|
private static final TableDataPreviewDesensitizeManager INSTANCE = new TableDataPreviewDesensitizeManager(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取TableDataPreviewDesensitizeManager单例 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static TableDataPreviewDesensitizeManager getInstance() { |
||||||
|
return TableDataPreviewDesensitizeManager.Holder.INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断数据集预览时是否需要脱敏,这里不需要判断roleIds,因为默认有权限编辑的人一定有权限看脱敏前后字段值 |
||||||
|
* 只需要保证此数据集存在脱敏配置就行 |
||||||
|
* |
||||||
|
* @param tableData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean needDesensitize(TableData tableData) { |
||||||
|
return tableData instanceof DesensitizationTableData && |
||||||
|
DesentizationUtils.isCollectionNotEmpty(((DesensitizationTableData) tableData).getDesensitizationConfig().getDesensitizationItems()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据集预览脱敏,使用DesensitizedPreviewTableModel对当前的预览TableModel做包装 |
||||||
|
* |
||||||
|
* @param model |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public PreviewTableModel desensitizeTableModel(TableData tableData, PreviewTableModel model) { |
||||||
|
|
||||||
|
Map<Integer, TableDataDesensitizationItem> desensitizationItemMap = new LinkedHashMap<>(); |
||||||
|
// 获取此数据集的所有脱敏信息
|
||||||
|
Collection<TableDataDesensitizationItem> desensitizationItems = ((DesensitizationTableData) tableData).getDesensitizationConfig().getDesensitizationItems(); |
||||||
|
if (DesentizationUtils.isCollectionNotEmpty(desensitizationItems)) { |
||||||
|
// 先对脱敏配置项集合做过滤和排序处理
|
||||||
|
List<TableDataDesensitizationItem> items = desensitizationItems.stream() |
||||||
|
.filter(item -> item.getRule().isEnable() && |
||||||
|
matchColumnIndex(item, model) >= 0) |
||||||
|
.sorted(Comparator.comparingInt(item -> matchColumnIndex(item, model))) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
// 然后转换成Map
|
||||||
|
for (int i = 0; i < items.size(); i++) { |
||||||
|
desensitizationItemMap.put(i, items.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
// 包装TableModel
|
||||||
|
return new DesensitizedPreviewTableModel(model, desensitizationItemMap); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过TableData获取其列名 |
||||||
|
* 实现逻辑有点绕,TableData本身并不能返回列名集合,只能先去获取当前模板所有数据集,然后匹配名称拿到TableDataWrapper再获取列名 |
||||||
|
* |
||||||
|
* @param tableData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<String> getColumnNamesByTableData(TableData tableData) { |
||||||
|
return DesignTableDataManager.getColumnNamesByTableData(tableData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 这个api会返回 部门职位 + 自定义角色 的Map |
||||||
|
* 其中 key为 "pid" + "_" + "id",value为 "ptext" + "text" |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Map<String, String> getAllRoles() { |
||||||
|
Map<String, String> rolesMap = new LinkedHashMap<>(); |
||||||
|
// 处理部门职位相关的用户组
|
||||||
|
addDepartmentAndPositionRoles2Map(rolesMap); |
||||||
|
// 处理自定义角色相关的用户组
|
||||||
|
addCustomRoles2Map(rolesMap); |
||||||
|
return rolesMap; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有的部门职位,按照 key为 "pid" + "_" + "id",value为 "ptext" + "text"的格式添加到参数Map中 |
||||||
|
* |
||||||
|
* @param rolesMap |
||||||
|
*/ |
||||||
|
private void addDepartmentAndPositionRoles2Map(Map<String, String> rolesMap) { |
||||||
|
try { |
||||||
|
List<DepartmentPostBean> postBeans = PositionService.getInstance().getDepartmentPostNameList(); |
||||||
|
for (DepartmentPostBean postBean : postBeans) { |
||||||
|
String department = postBean.getpText(); |
||||||
|
String position = postBean.getText(); |
||||||
|
String departmentId = postBean.getpId(); |
||||||
|
String positionId = postBean.getId(); |
||||||
|
if (!ComparatorUtils.equals(DecisionServiceConstants.DECISION_DEP_ROOT, postBean.getId()) && StringUtils.isNotEmpty(position)) { |
||||||
|
// 只添加部门和职位同时存在的
|
||||||
|
rolesMap.put(mergeRoleId(departmentId, positionId), mergeRoleText(department, position)); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, "[Desensitization] failed to add department and position roles to map for {}", e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有的自定义角色,按照 id - name添加到参数map里 |
||||||
|
* |
||||||
|
* @param rolesMap |
||||||
|
*/ |
||||||
|
private void addCustomRoles2Map(Map<String, String> rolesMap) { |
||||||
|
try { |
||||||
|
List<RoleBean> allCustomRole = CustomRoleService.getInstance().getAllCustomRoleNameList(null); |
||||||
|
allCustomRole.forEach(roleBean -> rolesMap.put(roleBean.getId(), roleBean.getText())); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, "[Desensitization] failed to add custom role to map for {}", e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 合并部门 + 职位的名称 |
||||||
|
* |
||||||
|
* @param departmentName |
||||||
|
* @param positionName |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String mergeRoleText(String departmentName, String positionName) { |
||||||
|
return departmentName + positionName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 合并部门 + 职位的id |
||||||
|
* |
||||||
|
* @param departmentId |
||||||
|
* @param positionId |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String mergeRoleId(String departmentId, String positionId) { |
||||||
|
return departmentId + CONNECTOR + positionId; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据列名,从PreviewTableModel中匹配列序号,如果返回-1代表未匹配到 |
||||||
|
* @param desensitizationItem |
||||||
|
* @param previewModel |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public int matchColumnIndex(TableDataDesensitizationItem desensitizationItem, PreviewTableModel previewModel) { |
||||||
|
return previewModel.getColumnIndexWithExceptionIngore(desensitizationItem.getColumnName()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,114 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.model; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||||
|
import com.fr.data.desensitize.calculate.DesensitizationCalculator; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.design.data.datapane.preview.PreviewTableModel; |
||||||
|
import com.fr.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据集预览TableModel的脱敏实现 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/14 |
||||||
|
*/ |
||||||
|
public class DesensitizedPreviewTableModel extends PreviewTableModel { |
||||||
|
|
||||||
|
/** |
||||||
|
* 原始数据Model |
||||||
|
*/ |
||||||
|
private PreviewTableModel previewTableModel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏后新组装的TableModel中,列序号 - 脱敏信息 对应的Map |
||||||
|
*/ |
||||||
|
private Map<Integer, TableDataDesensitizationItem> desensitizationItemMap; |
||||||
|
|
||||||
|
private boolean needDesensitize = false; |
||||||
|
|
||||||
|
public DesensitizedPreviewTableModel(PreviewTableModel previewTableModel, Map<Integer, TableDataDesensitizationItem> desensitizationItemMap) { |
||||||
|
this.previewTableModel = previewTableModel; |
||||||
|
this.desensitizationItemMap = desensitizationItemMap; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getColumnName(int column) { |
||||||
|
return needDesensitize ? |
||||||
|
desensitizationItemMap.get(column).getColumnName() : |
||||||
|
previewTableModel.getColumnName(column); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getRowCount() { |
||||||
|
return previewTableModel.getRowCount(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getColumnCount() { |
||||||
|
return needDesensitize ? |
||||||
|
getDesensitizeColumnsCount() : |
||||||
|
previewTableModel.getColumnCount(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
return needDesensitize && Objects.nonNull(desensitizationItemMap.get(columnIndex)) ? |
||||||
|
getDesensitizedValue(rowIndex, columnIndex) : |
||||||
|
previewTableModel.getValueAt(rowIndex, columnIndex); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 返回脱敏后的数据值 |
||||||
|
* |
||||||
|
* @param rowIndex |
||||||
|
* @param columnIndex |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Object getDesensitizedValue(int rowIndex, int columnIndex) { |
||||||
|
// 先通过columnIndex找到对应原TableModel的列序号
|
||||||
|
int originColumnIndex = TableDataPreviewDesensitizeManager.getInstance().matchColumnIndex(desensitizationItemMap.get(columnIndex), previewTableModel); |
||||||
|
// 获取原值
|
||||||
|
Object value = previewTableModel.getValueAt(rowIndex, originColumnIndex); |
||||||
|
// 判空
|
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
// 脱敏
|
||||||
|
String strValue = String.valueOf(value); |
||||||
|
value = desensitizeValue(strValue, columnIndex); |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算脱敏后的value,此时columnIndex对应的脱敏信息一定不为空 |
||||||
|
* |
||||||
|
* @param strValue |
||||||
|
* @param columnIndex |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private String desensitizeValue(String strValue, int columnIndex) { |
||||||
|
DesensitizationRule rule = desensitizationItemMap.get(columnIndex).getRule(); |
||||||
|
return DesensitizationCalculator.getInstance().desensitize(strValue, rule); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前有效的脱敏字段个数 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public int getDesensitizeColumnsCount() { |
||||||
|
return desensitizationItemMap.size(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 切换脱敏状态 |
||||||
|
*/ |
||||||
|
public void toggleNeedDesensite() { |
||||||
|
this.needDesensitize = !needDesensitize; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.common; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.design.border.UITitledBorder; |
||||||
|
import com.fr.design.constants.UIConstants; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.VerticalFlowLayout; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Desktop; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.net.URL; |
||||||
|
|
||||||
|
/** |
||||||
|
* 启用数据脱敏的面板 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/10/12 |
||||||
|
*/ |
||||||
|
public class DesensitizationOpenPane extends JPanel { |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据脱敏启用框 |
||||||
|
*/ |
||||||
|
private UICheckBox desensitizeOpenCheckBox; |
||||||
|
|
||||||
|
/** |
||||||
|
* 跳转帮助文档Label |
||||||
|
*/ |
||||||
|
private UILabel hyperlinkLabel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 启用提示Label |
||||||
|
*/ |
||||||
|
private UILabel tipsLabel; |
||||||
|
|
||||||
|
|
||||||
|
public DesensitizationOpenPane() { |
||||||
|
VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP); |
||||||
|
layout.setAlignLeft(true); |
||||||
|
this.setLayout(layout); |
||||||
|
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Report_Desensitization_Config"))); |
||||||
|
|
||||||
|
JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||||
|
// 启用数据脱敏的勾选框
|
||||||
|
desensitizeOpenCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Desensitization_Opened")); |
||||||
|
// 跳转帮助文档Label
|
||||||
|
hyperlinkLabel = new UILabel(IconUtils.readIcon("/com/fr/design/standard/tip/tips")); |
||||||
|
hyperlinkLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Open_Tips")); |
||||||
|
hyperlinkLabel.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent event) { |
||||||
|
try { |
||||||
|
URL url = new URL(Toolkit.i18nText("Fine-Design_Report_Desensitization_Help_Document_Url")); |
||||||
|
Desktop.getDesktop().browse(url.toURI()); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, "open browse of table data desensitization help document failed for {}", e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
panel.add(desensitizeOpenCheckBox); |
||||||
|
panel.add(hyperlinkLabel); |
||||||
|
|
||||||
|
// 提示Label
|
||||||
|
tipsLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Opened_Tooltips")); |
||||||
|
tipsLabel.setForeground(UIConstants.CHECK_BOX_TIP_FONT_COLOR); |
||||||
|
|
||||||
|
this.add(panel); |
||||||
|
this.add(tipsLabel); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据脱敏启用状态 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean isDesensitizationOpened() { |
||||||
|
return desensitizeOpenCheckBox.isSelected(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置数据脱敏启用状态 |
||||||
|
* @param opened |
||||||
|
*/ |
||||||
|
public void setDesensitizationOpened(boolean opened) { |
||||||
|
desensitizeOpenCheckBox.setSelected(opened); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,319 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.rule; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.data.desensitize.rule.DesensitizationRuleManager; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; |
||||||
|
import com.fr.design.dialog.BasicDialog; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.gui.ibutton.UIRadioButton; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableModelAdapter; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.collections.CollectionUtils; |
||||||
|
|
||||||
|
import javax.swing.AbstractCellEditor; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.JTable; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import javax.swing.table.TableCellEditor; |
||||||
|
import javax.swing.table.TableCellRenderer; |
||||||
|
import java.awt.CardLayout; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.util.LinkedHashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则选择页面 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/26 |
||||||
|
*/ |
||||||
|
public class DesensitizationRuleChoosePane extends JPanel { |
||||||
|
|
||||||
|
private CardLayout cardLayout; |
||||||
|
|
||||||
|
private UITableEditorPane<DesensitizationRule> serverRuleEditPane; |
||||||
|
|
||||||
|
private UITableEditorPane<DesensitizationRule> customRuleEditPane; |
||||||
|
|
||||||
|
private DesensitizationRuleSource currentRuleSource; |
||||||
|
|
||||||
|
public DesensitizationRuleChoosePane() { |
||||||
|
this.cardLayout = new CardLayout(); |
||||||
|
this.setLayout(cardLayout); |
||||||
|
serverRuleEditPane = new UITableEditorPane<>(new DesensitizationRuleChooseTableModel(this, true)); |
||||||
|
customRuleEditPane = new UITableEditorPane<>(new DesensitizationRuleChooseTableModel(this, false)); |
||||||
|
serverRuleEditPane.setHeaderResizing(false); |
||||||
|
customRuleEditPane.setHeaderResizing(false); |
||||||
|
populateDesensitizationRules(); |
||||||
|
this.add(serverRuleEditPane, DesensitizationRuleSource.SERVER.name()); |
||||||
|
this.add(customRuleEditPane, DesensitizationRuleSource.CUSTOM.name()); |
||||||
|
// 默认显示平台规则
|
||||||
|
switchPaneByRuleSource(DesensitizationRuleSource.SERVER); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过脱敏规则来源,切换显示不同的脱敏规则Table面板 |
||||||
|
* |
||||||
|
* @param ruleSource |
||||||
|
*/ |
||||||
|
public void switchPaneByRuleSource(DesensitizationRuleSource ruleSource) { |
||||||
|
this.currentRuleSource = ruleSource; |
||||||
|
this.cardLayout.show(this, ruleSource.name()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 展示当前规则 |
||||||
|
*/ |
||||||
|
private void populateDesensitizationRules() { |
||||||
|
serverRuleEditPane.populate(DesensitizationRuleManager.getInstance().getRules(DesensitizationRuleSource.SERVER)); |
||||||
|
customRuleEditPane.populate(DesensitizationRuleManager.getInstance().getRules(DesensitizationRuleSource.CUSTOM)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前选中的规则 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public DesensitizationRule getSelectedDesensitizationRule() { |
||||||
|
switch (currentRuleSource) { |
||||||
|
case SERVER: |
||||||
|
return serverRuleEditPane.getTableModel().getSelectedValue(); |
||||||
|
case CUSTOM: |
||||||
|
return customRuleEditPane.getTableModel().getSelectedValue(); |
||||||
|
default: |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 规则选择Table的TableModel |
||||||
|
*/ |
||||||
|
private class DesensitizationRuleChooseTableModel extends UITableModelAdapter<DesensitizationRule> { |
||||||
|
|
||||||
|
private Component parent; |
||||||
|
|
||||||
|
private boolean debugActionOnly; |
||||||
|
|
||||||
|
protected DesensitizationRuleChooseTableModel(Component parent, boolean debugActionOnly) { |
||||||
|
super(new String[]{ |
||||||
|
StringUtils.EMPTY, |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Name"), |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description") |
||||||
|
}); |
||||||
|
this.parent = parent; |
||||||
|
this.debugActionOnly = debugActionOnly; |
||||||
|
this.setColumnClass(new Class[]{ |
||||||
|
RuleChoosePane.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class |
||||||
|
}); |
||||||
|
this.setDefaultEditor(RuleChoosePane.class, new RuleChoosePane()); |
||||||
|
this.setDefaultRenderer(RuleChoosePane.class, new RuleChoosePane()); |
||||||
|
this.createTable().getColumnModel().getColumn(0).setMaxWidth(20); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
DesensitizationRule rule = getList().get(rowIndex); |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
// 选中状态
|
||||||
|
return rule.equals(getSelectedValue()); |
||||||
|
case 1: |
||||||
|
// 脱敏规则名称
|
||||||
|
return rule.getRuleName(); |
||||||
|
case 2: |
||||||
|
// 脱敏规则描述
|
||||||
|
return DesensitizationRule.getDescription(rule); |
||||||
|
default: |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isCellEditable(int row, int col) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UITableEditAction[] createAction() { |
||||||
|
return debugActionOnly ? |
||||||
|
new UITableEditAction[]{new DebugRuleAction(parent)} : |
||||||
|
new UITableEditAction[]{new AddRuleAction(), new EditRuleAction(), new DeleteRuleAction(parent), new DebugRuleAction(parent)}; |
||||||
|
} |
||||||
|
|
||||||
|
private Set<String> getCurrentExistRuleNames(String excludeName) { |
||||||
|
List<DesensitizationRule> rules = getList(); |
||||||
|
return CollectionUtils.isEmpty(rules) ? |
||||||
|
new LinkedHashSet<>() : |
||||||
|
rules.stream() |
||||||
|
.map(DesensitizationRule::getRuleName) |
||||||
|
.filter(name -> !StringUtils.equals(name, excludeName)) |
||||||
|
.collect(Collectors.toSet()); |
||||||
|
} |
||||||
|
|
||||||
|
private class RuleChoosePane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||||
|
|
||||||
|
private UIRadioButton selectedButton; |
||||||
|
|
||||||
|
public RuleChoosePane() { |
||||||
|
this.selectedButton = new UIRadioButton(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
selectedButton.setSelected(isSelected); |
||||||
|
return selectedButton; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getCellEditorValue() { |
||||||
|
return selectedButton.isSelected(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||||
|
selectedButton.setSelected(isSelected); |
||||||
|
return selectedButton; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加规则 |
||||||
|
*/ |
||||||
|
private class AddRuleAction extends AddTableRowAction { |
||||||
|
|
||||||
|
public AddRuleAction() { |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Report_Desensitization_Add")); |
||||||
|
this.setSmallIcon("/com/fr/design/standard/add/add_black", false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
// 新增一条规则
|
||||||
|
DesensitizationRuleEditPane editPane = new DesensitizationRuleEditPane(getCurrentExistRuleNames(StringUtils.EMPTY)); |
||||||
|
BasicDialog basicDialog = editPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
DesensitizationRule rule = editPane.updateBean(); |
||||||
|
// 添加到Rule Manager中
|
||||||
|
if (DesensitizationRule.valid(rule)) { |
||||||
|
DesensitizationRuleManager.getInstance().addRule(rule); |
||||||
|
} |
||||||
|
// 添加到Table中
|
||||||
|
addRow(rule); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doCancel() { |
||||||
|
super.doCancel(); |
||||||
|
} |
||||||
|
}, BasicDialog.DEFAULT); |
||||||
|
basicDialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class EditRuleAction extends UITableEditAction { |
||||||
|
|
||||||
|
public EditRuleAction() { |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); |
||||||
|
this.setSmallIcon(IconUtils.readIcon("/com/fr/design/standard/edit/edit")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkEnabled() { |
||||||
|
setEnabled(table.getSelectedRow() != -1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
// 获取当前选中规则
|
||||||
|
DesensitizationRule selectedValue = getSelectedValue(); |
||||||
|
DesensitizationRuleEditPane editPane = new DesensitizationRuleEditPane(getCurrentExistRuleNames(selectedValue.getRuleName())); |
||||||
|
editPane.populateBean(selectedValue); |
||||||
|
BasicDialog basicDialog = editPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
DesensitizationRule rule = editPane.updateBean(); |
||||||
|
// 修改同步到RuleManager中
|
||||||
|
if (DesensitizationRule.valid(rule)) { |
||||||
|
DesensitizationRuleManager.getInstance().updateRule(rule); |
||||||
|
} |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doCancel() { |
||||||
|
super.doCancel(); |
||||||
|
} |
||||||
|
}, BasicDialog.DEFAULT); |
||||||
|
basicDialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class DeleteRuleAction extends DeleteAction { |
||||||
|
|
||||||
|
public DeleteRuleAction(Component parent) { |
||||||
|
super(parent); |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Base_Remove")); |
||||||
|
this.setSmallIcon("/com/fr/design/images/control/remove"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkEnabled() { |
||||||
|
setEnabled(table.getSelectedRow() != -1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
// 获取当前选中规则
|
||||||
|
DesensitizationRule selectedRule = getSelectedValue(); |
||||||
|
// 删除同步到RuleManager中
|
||||||
|
if (DesensitizationRule.valid(selectedRule)) { |
||||||
|
DesensitizationRuleManager.getInstance().removeRule(selectedRule); |
||||||
|
} |
||||||
|
super.actionPerformed(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class DebugRuleAction extends UITableEditAction { |
||||||
|
|
||||||
|
private Component parent; |
||||||
|
|
||||||
|
public DebugRuleAction(Component parent) { |
||||||
|
this.parent = parent; |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Debug")); |
||||||
|
this.setSmallIcon("/com/fr/design/standard/debug/debug"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkEnabled() { |
||||||
|
setEnabled(table.getSelectedRow() != -1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
// 获取当前选中规则
|
||||||
|
DesensitizationRule selectedRule = getSelectedValue(); |
||||||
|
if (selectedRule == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
DesensitizationRuleDebugPane ruleDebugPane = new DesensitizationRuleDebugPane(selectedRule); |
||||||
|
BasicDialog ruleDebugDialog = ruleDebugPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), null, BasicDialog.DEFAULT); |
||||||
|
ruleDebugDialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,128 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.rule; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.calculate.DesensitizationCalculator; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.dialog.FineJOptionPane; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.awt.event.FocusEvent; |
||||||
|
import java.awt.event.FocusListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则调试页 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/8 |
||||||
|
*/ |
||||||
|
public class DesensitizationRuleDebugPane extends BasicPane { |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则 |
||||||
|
*/ |
||||||
|
private DesensitizationRule rule; |
||||||
|
|
||||||
|
public DesensitizationRuleDebugPane(DesensitizationRule rule) { |
||||||
|
this.rule = rule; |
||||||
|
initComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponent() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.add(initNorthPane(), BorderLayout.NORTH); |
||||||
|
this.add(initCenterPane(), BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel initNorthPane() { |
||||||
|
JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description")); |
||||||
|
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 0)); |
||||||
|
UILabel desensitizationRule = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Algorithm")); |
||||||
|
UILabel characterReplace = new UILabel(rule.getRuleType().getRuleTypeName()); |
||||||
|
UILabel description = new UILabel(DesensitizationRule.getDescription(rule)); |
||||||
|
JComponent[][] components = new JComponent[][]{ |
||||||
|
{desensitizationRule, characterReplace}, |
||||||
|
{new UILabel(), description} |
||||||
|
}; |
||||||
|
panel.add( |
||||||
|
TableLayoutHelper.createCommonTableLayoutPane( |
||||||
|
components, |
||||||
|
new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED}, |
||||||
|
new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED}, |
||||||
|
20), |
||||||
|
BorderLayout.CENTER); |
||||||
|
northPane.add(panel); |
||||||
|
return northPane; |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel initCenterPane() { |
||||||
|
JPanel centerPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Debug")); |
||||||
|
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 0)); |
||||||
|
|
||||||
|
UILabel beforeDesensitize = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Before")); |
||||||
|
UITextField beforeDesensitizeText = new UITextField(20); |
||||||
|
beforeDesensitizeText.setPlaceholder(Toolkit.i18nText("Fine-Design_Report_Desensitization_Enter_Content")); |
||||||
|
UILabel afterDesensitize = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_After")); |
||||||
|
UITextField afterDesensitizeText = new UITextField(20); |
||||||
|
afterDesensitizeText.setEditable(false); |
||||||
|
UIButton desensitizeButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_Desensitization_Debug")); |
||||||
|
beforeDesensitizeText.addFocusListener(new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
afterDesensitizeText.setText(StringUtils.EMPTY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
desensitizeButton.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
String text = beforeDesensitizeText.getText(); |
||||||
|
if (StringUtils.isEmpty(text)) { |
||||||
|
FineJOptionPane.showMessageDialog(DesensitizationRuleDebugPane.this, |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Please_Enter_Valid_Content")); |
||||||
|
} |
||||||
|
String desensitizedText = DesensitizationCalculator.getInstance().desensitize(text, rule); |
||||||
|
afterDesensitizeText.setText(desensitizedText); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
JComponent[][] components = new JComponent[][]{ |
||||||
|
{beforeDesensitize, beforeDesensitizeText, desensitizeButton}, |
||||||
|
{afterDesensitize, afterDesensitizeText, new UILabel()} |
||||||
|
}; |
||||||
|
panel.add( |
||||||
|
TableLayoutHelper.createCommonTableLayoutPane( |
||||||
|
components, |
||||||
|
new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED}, |
||||||
|
new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}, |
||||||
|
20), |
||||||
|
BorderLayout.CENTER); |
||||||
|
|
||||||
|
centerPane.add(panel); |
||||||
|
return centerPane; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Debug"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,299 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.rule; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationCondition; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRuleType; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.constants.UIConstants; |
||||||
|
import com.fr.design.event.UIObserverListener; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itextfield.UINumberField; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.CardLayout; |
||||||
|
import java.awt.Insets; |
||||||
|
import java.awt.event.FocusEvent; |
||||||
|
import java.awt.event.FocusListener; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则编辑页 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/8 |
||||||
|
*/ |
||||||
|
public class DesensitizationRuleEditPane extends BasicBeanPane<DesensitizationRule> { |
||||||
|
/** |
||||||
|
* 已经存在的规则名称,用于检测重名 |
||||||
|
*/ |
||||||
|
private Set<String> existRuleNames; |
||||||
|
|
||||||
|
private UITextField ruleNameTextField; |
||||||
|
private UIComboBox ruleTypeComboBox; |
||||||
|
private UINumberField retainFrontTextField; |
||||||
|
private UINumberField retainBackTextField; |
||||||
|
private UITextField firstSymbolTextField; |
||||||
|
private UITextField secondSymbolTextField; |
||||||
|
private CardLayout cardLayout; |
||||||
|
private JPanel ruleConditionPane; |
||||||
|
|
||||||
|
|
||||||
|
private DesensitizationRule rule = DesensitizationRule.createDefaultEmptyRule(); |
||||||
|
|
||||||
|
private final FocusListener retainFrontListener = new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
rule.getCondition().setRetainFront((int) retainFrontTextField.getValue()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final FocusListener retainBackListener = new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
rule.getCondition().setRetainBack((int) retainBackTextField.getValue()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final FocusListener firstSymbolListener = new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
rule.getCondition().setSymbol(firstSymbolTextField.getText()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final FocusListener secondSymbolListener = new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
rule.getCondition().setRetainFront(0); |
||||||
|
rule.getCondition().setRetainBack(0); |
||||||
|
rule.getCondition().setSymbol(secondSymbolTextField.getText()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public DesensitizationRuleEditPane(Set<String> existRuleNames) { |
||||||
|
this.existRuleNames = existRuleNames; |
||||||
|
initComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化面板 |
||||||
|
*/ |
||||||
|
private void initComponent() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); |
||||||
|
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 0)); |
||||||
|
UILabel ruleNameLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Name")); |
||||||
|
// 规则名称输入框
|
||||||
|
initRuleNameTextField(); |
||||||
|
UILabel ruleTypeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Algorithm")); |
||||||
|
// 脱敏算法Type设置
|
||||||
|
JPanel ruleTypePane = initRuleTypePane(); |
||||||
|
// 脱敏算法Condition设置
|
||||||
|
JPanel ruleConditionPane = initRuleConditionPane(); |
||||||
|
JComponent[][] components = { |
||||||
|
{ruleNameLabel, ruleNameTextField}, |
||||||
|
{ruleTypeLabel, ruleTypePane}, |
||||||
|
{new UILabel(), ruleConditionPane} |
||||||
|
}; |
||||||
|
panel.add( |
||||||
|
TableLayoutHelper.createGapTableLayoutPane( |
||||||
|
components, |
||||||
|
new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL}, |
||||||
|
new double[]{TableLayout.FILL, TableLayout.PREFERRED}, |
||||||
|
20, |
||||||
|
20), |
||||||
|
BorderLayout.CENTER); |
||||||
|
this.add(panel); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化规则类型面板 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private JPanel initRuleTypePane() { |
||||||
|
JPanel ruleTypePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
// 脱敏算法类型下拉框
|
||||||
|
initRuleTypeComboBox(); |
||||||
|
ruleTypePane.add(ruleTypeComboBox, BorderLayout.CENTER); |
||||||
|
return ruleTypePane; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化规则条件面板 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private JPanel initRuleConditionPane() { |
||||||
|
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
cardLayout = new CardLayout(); |
||||||
|
ruleConditionPane = new JPanel(cardLayout); |
||||||
|
// 字符替换
|
||||||
|
JPanel characterReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||||
|
UILabel retainFrontLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Retain_Front") + StringUtils.BLANK); |
||||||
|
retainFrontTextField = new UINumberField(5); |
||||||
|
retainFrontTextField.addFocusListener(retainFrontListener); |
||||||
|
|
||||||
|
UILabel retainBackLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Count_And_Back") + StringUtils.BLANK); |
||||||
|
retainBackTextField = new UINumberField(5); |
||||||
|
retainBackTextField.addFocusListener(retainBackListener); |
||||||
|
|
||||||
|
UILabel replaceLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Count_And_Other_Character_Replace_By") + StringUtils.BLANK); |
||||||
|
firstSymbolTextField = new UITextField(10); |
||||||
|
firstSymbolTextField.addFocusListener(firstSymbolListener); |
||||||
|
|
||||||
|
characterReplacePane.add(retainFrontLabel); |
||||||
|
characterReplacePane.add(retainFrontTextField); |
||||||
|
characterReplacePane.add(retainBackLabel); |
||||||
|
characterReplacePane.add(retainBackTextField); |
||||||
|
characterReplacePane.add(replaceLabel); |
||||||
|
characterReplacePane.add(firstSymbolTextField); |
||||||
|
// 整体替换
|
||||||
|
JPanel characterAllReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||||
|
UILabel allReplaceLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_All_Character_Replace_By") + StringUtils.BLANK); |
||||||
|
secondSymbolTextField = new UITextField(10); |
||||||
|
secondSymbolTextField.addFocusListener(secondSymbolListener); |
||||||
|
|
||||||
|
characterAllReplacePane.add(allReplaceLabel); |
||||||
|
characterAllReplacePane.add(secondSymbolTextField); |
||||||
|
|
||||||
|
ruleConditionPane.add(characterReplacePane, DesensitizationRuleType.CHARACTER_REPLACE.getRuleTypeName()); |
||||||
|
ruleConditionPane.add(characterAllReplacePane, DesensitizationRuleType.ALL_CHARACTERS_REPLACE.getRuleTypeName()); |
||||||
|
// 初始化状态为字符替换
|
||||||
|
switchRuleConditionPane(DesensitizationRuleType.CHARACTER_REPLACE); |
||||||
|
|
||||||
|
panel.add(ruleConditionPane, BorderLayout.CENTER); |
||||||
|
return panel; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 切换规则类型面板 |
||||||
|
* |
||||||
|
* @param ruleType |
||||||
|
*/ |
||||||
|
private void switchRuleConditionPane(DesensitizationRuleType ruleType) { |
||||||
|
this.cardLayout.show(ruleConditionPane, ruleType.getRuleTypeName()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化规则类型下拉框 |
||||||
|
*/ |
||||||
|
private void initRuleTypeComboBox() { |
||||||
|
ruleTypeComboBox = new UIComboBox(Arrays.stream(DesensitizationRuleType.values()).map(DesensitizationRuleType::getRuleTypeName).toArray()); |
||||||
|
ruleTypeComboBox.setSelectedIndex(0); |
||||||
|
ruleTypeComboBox.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
DesensitizationRuleType ruleType = DesensitizationRuleType.matchByTypeName((String) ruleTypeComboBox.getSelectedItem()); |
||||||
|
rule.setRuleType(ruleType); |
||||||
|
// 修改底下的conditionPane
|
||||||
|
switchRuleConditionPane(ruleType); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化规则名称输入框 |
||||||
|
*/ |
||||||
|
private void initRuleNameTextField() { |
||||||
|
ruleNameTextField = new UITextField(20) { |
||||||
|
@Override |
||||||
|
public Insets getInsets() { |
||||||
|
return new Insets(2, 4, 0, 4); |
||||||
|
} |
||||||
|
}; |
||||||
|
ruleNameTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Report_Desensitization_Please_Enter_Rule_Name")); |
||||||
|
ruleNameTextField.setBorderPainted(true); |
||||||
|
ruleNameTextField.addFocusListener(new FocusListener() { |
||||||
|
@Override |
||||||
|
public void focusGained(FocusEvent e) { |
||||||
|
ruleNameTextField.setBorder(BorderFactory.createLineBorder(UIConstants.NORMAL_BLUE)); |
||||||
|
ruleNameTextField.repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void focusLost(FocusEvent e) { |
||||||
|
ruleNameTextField.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); |
||||||
|
rule.setRuleName(ruleNameTextField.getText()); |
||||||
|
ruleNameTextField.repaint(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(DesensitizationRule ob) { |
||||||
|
this.rule = ob; |
||||||
|
this.ruleNameTextField.setText(rule.getRuleName()); |
||||||
|
String typeName = rule.getRuleType().getRuleTypeName(); |
||||||
|
this.ruleTypeComboBox.setSelectedItem(typeName); |
||||||
|
switch (DesensitizationRuleType.matchByTypeName(typeName)) { |
||||||
|
case CHARACTER_REPLACE: |
||||||
|
this.retainFrontTextField.setValue(rule.getCondition().getRetainFront()); |
||||||
|
this.retainBackTextField.setValue(rule.getCondition().getRetainBack()); |
||||||
|
this.firstSymbolTextField.setText(rule.getCondition().getSymbol()); |
||||||
|
break; |
||||||
|
case ALL_CHARACTERS_REPLACE: |
||||||
|
this.secondSymbolTextField.setText(rule.getCondition().getSymbol()); |
||||||
|
break; |
||||||
|
default: |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public DesensitizationRule updateBean() { |
||||||
|
rule.setEnable(true); |
||||||
|
return rule; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Desensitization_Custom_Config_Rules"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkValid() throws Exception { |
||||||
|
// 保存rule前检查下
|
||||||
|
String checkMessage = StringUtils.EMPTY; |
||||||
|
if (StringUtils.isEmpty(rule.getRuleName())) { |
||||||
|
checkMessage = Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Name_Cannot_Be_Empty"); |
||||||
|
} else if (existRuleNames.contains(rule.getRuleName())) { |
||||||
|
checkMessage = Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Name_Cannot_Repeat"); |
||||||
|
} else if (DesensitizationCondition.invalid(rule.getCondition())) { |
||||||
|
checkMessage = Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Wrong_Condition"); |
||||||
|
} |
||||||
|
if (StringUtils.isNotEmpty(checkMessage)) { |
||||||
|
throw new Exception(checkMessage); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.rule; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.border.UITitledBorder; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则展示页 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/8 |
||||||
|
*/ |
||||||
|
public class DesensitizationRulePane extends BasicBeanPane<DesensitizationRule> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 规则来源选择面板 |
||||||
|
*/ |
||||||
|
private DesensitizationRuleSourceChoosePane ruleSourceChoosePane; |
||||||
|
|
||||||
|
/** |
||||||
|
* 规则选择面板 |
||||||
|
*/ |
||||||
|
private DesensitizationRuleChoosePane ruleChoosePane; |
||||||
|
|
||||||
|
/** |
||||||
|
* 内容面板 |
||||||
|
*/ |
||||||
|
private JPanel contentPane; |
||||||
|
|
||||||
|
public DesensitizationRulePane() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
initPane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initPane() { |
||||||
|
// 内容面板
|
||||||
|
contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
contentPane.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Choose"))); |
||||||
|
this.add(contentPane, BorderLayout.CENTER); |
||||||
|
// 规则来源选择Pane
|
||||||
|
ruleSourceChoosePane = new DesensitizationRuleSourceChoosePane(this); |
||||||
|
// 规则选择Pane
|
||||||
|
ruleChoosePane = new DesensitizationRuleChoosePane(); |
||||||
|
contentPane.add(ruleSourceChoosePane, BorderLayout.NORTH); |
||||||
|
contentPane.add(ruleChoosePane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 处理规则来源选择面板中改动来源的事件 |
||||||
|
* |
||||||
|
* @param newRuleSource |
||||||
|
*/ |
||||||
|
public void dealWithRuleSourceChanged(DesensitizationRuleSource newRuleSource) { |
||||||
|
ruleChoosePane.switchPaneByRuleSource(newRuleSource); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(DesensitizationRule ob) { |
||||||
|
// 这边展示当前所有规则时,不依靠外界传值,初始化的时候,从规则管理中心去获取
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public DesensitizationRule updateBean() { |
||||||
|
DesensitizationRule desensitizationRule = ruleChoosePane.getSelectedDesensitizationRule(); |
||||||
|
return DesensitizationRule.valid(desensitizationRule) ? |
||||||
|
desensitizationRule : |
||||||
|
DesensitizationRule.createDefaultEmptyRule(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.rule; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; |
||||||
|
import com.fr.design.gui.ibutton.UIRadioButton; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.ButtonGroup; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.FlowLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏规则来源选择页面 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/26 |
||||||
|
*/ |
||||||
|
public class DesensitizationRuleSourceChoosePane extends JPanel { |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源平台的按钮 |
||||||
|
*/ |
||||||
|
private UIRadioButton serverSource; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源本地的按钮 |
||||||
|
*/ |
||||||
|
private UIRadioButton customSource; |
||||||
|
|
||||||
|
public DesensitizationRuleSourceChoosePane(DesensitizationRulePane desensitizationRulePane) { |
||||||
|
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||||
|
this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); |
||||||
|
|
||||||
|
serverSource = new UIRadioButton(Toolkit.i18nText("Fine-Design_Report_Desensitization_Server_Config_Rules")); |
||||||
|
customSource = new UIRadioButton(Toolkit.i18nText("Fine-Design_Report_Desensitization_Custom_Config_Rules")); |
||||||
|
|
||||||
|
ButtonGroup buttonGroup = new ButtonGroup(); |
||||||
|
buttonGroup.add(serverSource); |
||||||
|
buttonGroup.add(customSource); |
||||||
|
serverSource.setSelected(true); |
||||||
|
|
||||||
|
serverSource.registerChangeListener(() -> desensitizationRulePane.dealWithRuleSourceChanged(DesensitizationRuleSource.SERVER)); |
||||||
|
customSource.registerChangeListener(() -> desensitizationRulePane.dealWithRuleSourceChanged(DesensitizationRuleSource.CUSTOM)); |
||||||
|
|
||||||
|
this.add(serverSource); |
||||||
|
this.add(customSource); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.DesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.data.datapane.preview.desensitization.view.common.DesensitizationOpenPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
|
||||||
|
import javax.swing.JComponent; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据集脱敏字段设置页面 |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/8 |
||||||
|
*/ |
||||||
|
public class TableDataDesensitizationSettingPane extends BasicBeanPane<DesensitizationTableData> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置针对的数据集 |
||||||
|
*/ |
||||||
|
private DesensitizationTableData tableData; |
||||||
|
|
||||||
|
private DesensitizationOpenPane desensitizationOpenPane; |
||||||
|
|
||||||
|
private TableDataDesensitizationTablePane tableDataDesensitizationTablePane; |
||||||
|
|
||||||
|
|
||||||
|
public TableDataDesensitizationSettingPane(DesensitizationTableData tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.add(initNorthPane(), BorderLayout.NORTH); |
||||||
|
this.add(initCenterPane(), BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化启用数据脱敏面板 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private JComponent initNorthPane() { |
||||||
|
this.desensitizationOpenPane = new DesensitizationOpenPane(); |
||||||
|
return desensitizationOpenPane; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化数据脱敏规则表面板 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private JComponent initCenterPane() { |
||||||
|
this.tableDataDesensitizationTablePane = new TableDataDesensitizationTablePane(tableData, this); |
||||||
|
return tableDataDesensitizationTablePane; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Desensitization_Config"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(DesensitizationTableData tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
this.desensitizationOpenPane.setDesensitizationOpened(tableData.getDesensitizationConfig().isDesensitizeOpened()); |
||||||
|
tableDataDesensitizationTablePane.populateDesensitizationSetting(tableData); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public DesensitizationTableData updateBean() { |
||||||
|
saveDesensitizeOpened(); |
||||||
|
saveDesensitizationBeans(tableDataDesensitizationTablePane.updateDesensitizationSetting()); |
||||||
|
return tableData; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存脱敏启用状态 |
||||||
|
*/ |
||||||
|
public void saveDesensitizeOpened() { |
||||||
|
tableData.getDesensitizationConfig().setDesensitizeOpened(this.desensitizationOpenPane.isDesensitizationOpened()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存脱敏规则配置信息 |
||||||
|
* |
||||||
|
* @param desensitizationItems |
||||||
|
*/ |
||||||
|
public void saveDesensitizationBeans(List<TableDataDesensitizationItem> desensitizationItems) { |
||||||
|
tableData.getDesensitizationConfig().setDesensitizationItems(desensitizationItems); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,442 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.DesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager; |
||||||
|
import com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRulePane; |
||||||
|
import com.fr.design.dialog.BasicDialog; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.gui.icombocheckbox.UIComboCheckBox; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableModelAdapter; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import javax.swing.AbstractCellEditor; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.JTable; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import javax.swing.event.CellEditorListener; |
||||||
|
import javax.swing.event.ChangeEvent; |
||||||
|
import javax.swing.table.TableCellEditor; |
||||||
|
import javax.swing.table.TableCellRenderer; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.LinkedHashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 处理TableDataDesensitizationTablePane中TableEditPane的Model |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/23 |
||||||
|
*/ |
||||||
|
public class TableDataDesensitizationTableModel extends UITableModelAdapter<TableDataDesensitizationItem> { |
||||||
|
|
||||||
|
private static final String APOSTROPHE = "..."; |
||||||
|
|
||||||
|
private DesensitizationTableData tableData; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前数据集的所有列名 |
||||||
|
*/ |
||||||
|
private List<String> columnNames; |
||||||
|
|
||||||
|
/** |
||||||
|
* key为用户组唯一标识(id拼接),value为用户组名称 |
||||||
|
*/ |
||||||
|
private Map<String, String> roleMap; |
||||||
|
|
||||||
|
private Component parent; |
||||||
|
|
||||||
|
private DesensitizationRuleChooser ruleChooser; |
||||||
|
|
||||||
|
private DesensitizationRuleDescriptionPane descriptionPane; |
||||||
|
|
||||||
|
public TableDataDesensitizationTableModel(DesensitizationTableData tableData, Component parent) { |
||||||
|
// table相关
|
||||||
|
super(new String[]{ |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Column"), |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule"), |
||||||
|
StringUtils.EMPTY, |
||||||
|
Toolkit.i18nText("Fine-Design_Report_Desensitization_Effected_Roles") |
||||||
|
}); |
||||||
|
// 一些数据相关
|
||||||
|
this.tableData = tableData; |
||||||
|
// 获取当前数据集的所有列名
|
||||||
|
this.columnNames = TableDataPreviewDesensitizeManager.getInstance().getColumnNamesByTableData(tableData); |
||||||
|
// 获取当前所有用户组
|
||||||
|
this.roleMap = TableDataPreviewDesensitizeManager.getInstance().getAllRoles(); |
||||||
|
this.parent = parent; |
||||||
|
this.setColumnClass(new Class[]{ |
||||||
|
// 列名选择
|
||||||
|
ColumnNamesComboBox.class, |
||||||
|
// 规则选择
|
||||||
|
DesensitizationRuleChooser.class, |
||||||
|
// 规则详情展示
|
||||||
|
DesensitizationRuleDescriptionPane.class, |
||||||
|
// 生效用户组选择
|
||||||
|
EffectedRolesChooser.class |
||||||
|
}); |
||||||
|
this.setDefaultEditor(ColumnNamesComboBox.class, new ColumnNamesComboBox()); |
||||||
|
this.ruleChooser = new DesensitizationRuleChooser(); |
||||||
|
this.setDefaultEditor(DesensitizationRuleChooser.class, ruleChooser); |
||||||
|
this.setDefaultRenderer(DesensitizationRuleChooser.class, ruleChooser); |
||||||
|
this.descriptionPane = new DesensitizationRuleDescriptionPane(); |
||||||
|
this.setDefaultEditor(DesensitizationRuleDescriptionPane.class, new DesensitizationRuleDescriptionPane()); |
||||||
|
this.setDefaultEditor(EffectedRolesChooser.class, new EffectedRolesChooser()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
TableDataDesensitizationItem desensitizationItem = this.getList().get(rowIndex); |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
// 选中的数据集字段名称
|
||||||
|
return desensitizationItem.getColumnName(); |
||||||
|
case 1: |
||||||
|
// 脱敏规则名称
|
||||||
|
return desensitizationItem.getRule().getRuleName(); |
||||||
|
case 2: |
||||||
|
// 脱敏规则详情
|
||||||
|
return DesensitizationRule.getDescription(desensitizationItem.getRule()); |
||||||
|
case 3: |
||||||
|
// 生效用户组
|
||||||
|
return matchRoleNamesByIds(desensitizationItem.getRoleIds()); |
||||||
|
default: |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过id匹配此用户组对应的部门职位名称(或者说自定义角色名称) |
||||||
|
* |
||||||
|
* @param roleIds |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private List<String> matchRoleNamesByIds(Collection<String> roleIds) { |
||||||
|
List<String> result = new ArrayList<>(); |
||||||
|
for (String roleId : roleIds) { |
||||||
|
if (roleMap != null && roleMap.containsKey(roleId)) { |
||||||
|
result.add(roleMap.get(roleId)); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isCellEditable(int row, int col) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UITableEditAction[] createAction() { |
||||||
|
return new UITableEditAction[]{new AddDesensitizationAction(), new RemoveDesensitizationAction(parent)}; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前选中的item,可能为null |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
private TableDataDesensitizationItem getCurrentSelectBean() { |
||||||
|
return table.getSelectedRow() == -1 ? |
||||||
|
null : |
||||||
|
getList().get(table.getSelectedRow()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 列名选择下拉框 |
||||||
|
*/ |
||||||
|
private class ColumnNamesComboBox extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||||
|
|
||||||
|
private UIComboBox columnNameComboBox; |
||||||
|
|
||||||
|
ColumnNamesComboBox() { |
||||||
|
columnNameComboBox = new UIComboBox(columnNames.toArray(new String[0])); |
||||||
|
this.addCellEditorListener(new CellEditorListener() { |
||||||
|
@Override |
||||||
|
public void editingStopped(ChangeEvent e) { |
||||||
|
|
||||||
|
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationItem)) { |
||||||
|
desensitizationItem.setColumnName(columnNames.get(columnNameComboBox.getSelectedIndex())); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void editingCanceled(ChangeEvent e) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
columnNameComboBox.setSelectedItem(getList().get(row).getColumnName()); |
||||||
|
return columnNameComboBox; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getCellEditorValue() { |
||||||
|
Object selectedItem = columnNameComboBox.getSelectedItem(); |
||||||
|
return Objects.isNull(selectedItem) ? StringUtils.EMPTY : selectedItem.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||||
|
columnNameComboBox.setSelectedItem(getList().get(row).getColumnName()); |
||||||
|
return columnNameComboBox; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class DesensitizationRuleChooser extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||||
|
/** |
||||||
|
* 规则选择页面 |
||||||
|
*/ |
||||||
|
private JPanel choosePane; |
||||||
|
/** |
||||||
|
* 规则名称 |
||||||
|
*/ |
||||||
|
private UITextField ruleNameTextField; |
||||||
|
/** |
||||||
|
* 规则选择按钮 |
||||||
|
*/ |
||||||
|
private UIButton chooseButton; |
||||||
|
/** |
||||||
|
* 规则 |
||||||
|
*/ |
||||||
|
private DesensitizationRule rule; |
||||||
|
|
||||||
|
private ActionListener chooseRuleListener = new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
DesensitizationRulePane rulePane = new DesensitizationRulePane(); |
||||||
|
BasicDialog ruleDialog = rulePane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
rule = rulePane.updateBean(); |
||||||
|
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationItem) && Objects.nonNull(rule)) { |
||||||
|
desensitizationItem.setRule(rule); |
||||||
|
desensitizationItem.setRuleName(rule.getRuleName()); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
rule = null; |
||||||
|
} |
||||||
|
}, BasicDialog.DEFAULT); |
||||||
|
ruleDialog.setVisible(true); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
DesensitizationRuleChooser() { |
||||||
|
// 规则名称展示
|
||||||
|
ruleNameTextField = new UITextField(); |
||||||
|
ruleNameTextField.setEnabled(false); |
||||||
|
// 规则选择按钮
|
||||||
|
chooseButton = new UIButton(APOSTROPHE); |
||||||
|
chooseButton.addActionListener(chooseRuleListener); |
||||||
|
// 规则选择页面
|
||||||
|
Component[][] templateChooserComponent = {{ruleNameTextField, chooseButton}}; |
||||||
|
double[] rowSize = {TableLayout.PREFERRED}; |
||||||
|
double[] columnSize = {TableLayout.FILL, 22}; |
||||||
|
choosePane = TableLayoutHelper.createCommonTableLayoutPane(templateChooserComponent, rowSize, columnSize, 0); |
||||||
|
this.addCellEditorListener(new CellEditorListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void editingCanceled(ChangeEvent e) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void editingStopped(ChangeEvent e) { |
||||||
|
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationItem) && Objects.nonNull(rule)) { |
||||||
|
desensitizationItem.setRule(rule); |
||||||
|
desensitizationItem.setRuleName(rule.getRuleName()); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
ruleNameTextField.setText(getList().get(row).getRule().getRuleName()); |
||||||
|
return choosePane; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getCellEditorValue() { |
||||||
|
return ruleNameTextField.getText(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||||
|
ruleNameTextField.setText((String) value); |
||||||
|
return choosePane; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class DesensitizationRuleDescriptionPane extends AbstractCellEditor implements TableCellEditor { |
||||||
|
|
||||||
|
private UILabel descriptionLabel; |
||||||
|
|
||||||
|
DesensitizationRuleDescriptionPane() { |
||||||
|
// 规则描述
|
||||||
|
this.descriptionLabel = new UILabel(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据脱敏规则信息,刷新下规则描述文字,主要用于与规则选择器的联动 |
||||||
|
* |
||||||
|
* @param desensitizationRule |
||||||
|
*/ |
||||||
|
public void refreshDescription(DesensitizationRule desensitizationRule) { |
||||||
|
this.descriptionLabel.setText(DesensitizationRule.getDescription(desensitizationRule)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
refreshDescription(getList().get(row).getRule()); |
||||||
|
return descriptionLabel; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getCellEditorValue() { |
||||||
|
return this.descriptionLabel.getText(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class EffectedRolesChooser extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||||
|
|
||||||
|
private UIComboCheckBox rolesCheckBox; |
||||||
|
|
||||||
|
EffectedRolesChooser() { |
||||||
|
this.rolesCheckBox = new UIComboCheckBox(roleMap.values().toArray(), true); |
||||||
|
this.addCellEditorListener(new CellEditorListener() { |
||||||
|
@Override |
||||||
|
public void editingStopped(ChangeEvent e) { |
||||||
|
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationItem)) { |
||||||
|
desensitizationItem.setRoleIds(generateRolesIdsBySelectedValues()); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void editingCanceled(ChangeEvent e) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
rolesCheckBox.setSelectedValues(generateRolesCheckBoxSelectedValues(getList().get(row))); |
||||||
|
return rolesCheckBox; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据当前的规则配置信息,生成选中的rolesMap用来展示 |
||||||
|
* |
||||||
|
* @param desensitizationItem |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Map<Object, Boolean> generateRolesCheckBoxSelectedValues(TableDataDesensitizationItem desensitizationItem) { |
||||||
|
Map<Object, Boolean> result = new HashMap<>(roleMap.size()); |
||||||
|
for (Map.Entry<String, String> roleEntry : roleMap.entrySet()) { |
||||||
|
String roleId = roleEntry.getKey(); |
||||||
|
String roleName = roleEntry.getValue(); |
||||||
|
if (desensitizationItem.getRoleIds().contains(roleId)) { |
||||||
|
result.put(roleName, true); |
||||||
|
} else { |
||||||
|
result.put(roleName, false); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据当前的RoleName选择项,生成其对应的RoleId的set存入规则配置信息 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Set<String> generateRolesIdsBySelectedValues() { |
||||||
|
Set<String> result = new LinkedHashSet<>(); |
||||||
|
Object[] selectedValues = rolesCheckBox.getSelectedValues(); |
||||||
|
for (Object selectedValue : selectedValues) { |
||||||
|
String selectedRoleName = (String) selectedValue; |
||||||
|
if (roleMap.containsValue(selectedRoleName)) { |
||||||
|
Optional<Map.Entry<String, String>> matchedEntry = roleMap.entrySet().stream().filter(entry -> StringUtils.equals(entry.getValue(), selectedRoleName)).findFirst(); |
||||||
|
matchedEntry.ifPresent(stringStringEntry -> result.add(stringStringEntry.getKey())); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getCellEditorValue() { |
||||||
|
return rolesCheckBox.getSelectedValues(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||||
|
rolesCheckBox.setSelectedValues(generateRolesCheckBoxSelectedValues(getList().get(row))); |
||||||
|
return rolesCheckBox; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private class AddDesensitizationAction extends AddTableRowAction { |
||||||
|
|
||||||
|
public AddDesensitizationAction() { |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Report_Desensitization_Add")); |
||||||
|
this.setSmallIcon("/com/fr/design/standard/add/add_black", false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
super.actionPerformed(e); |
||||||
|
// 添加一条空白数据
|
||||||
|
addRow(TableDataDesensitizationItem.createDefault()); |
||||||
|
fireTableDataChanged(); |
||||||
|
table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class RemoveDesensitizationAction extends DeleteAction { |
||||||
|
|
||||||
|
public RemoveDesensitizationAction(Component component) { |
||||||
|
super(component); |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Base_Remove")); |
||||||
|
this.setSmallIcon("/com/fr/design/standard/remove/remove_red", false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
super.actionPerformed(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.DesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Component; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏字段设置页面中的Table |
||||||
|
* |
||||||
|
* @author Yvan |
||||||
|
* @version 11.0 |
||||||
|
* Created by Yvan on 2022/9/14 |
||||||
|
*/ |
||||||
|
public class TableDataDesensitizationTablePane extends JPanel { |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏数据集 |
||||||
|
*/ |
||||||
|
private DesensitizationTableData tableData; |
||||||
|
|
||||||
|
/** |
||||||
|
* 父页面 |
||||||
|
*/ |
||||||
|
private Component parent; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏信息Table |
||||||
|
*/ |
||||||
|
private UITableEditorPane<TableDataDesensitizationItem> editorPane; |
||||||
|
|
||||||
|
public TableDataDesensitizationTablePane(DesensitizationTableData tableData, Component parent) { |
||||||
|
this.tableData = tableData; |
||||||
|
this.parent = parent; |
||||||
|
initComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponent() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.editorPane = new UITableEditorPane<>(new TableDataDesensitizationTableModel(tableData, parent)); |
||||||
|
this.editorPane.setHeaderResizing(false); |
||||||
|
this.add(editorPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 展示此TableData中已配置的脱敏规则信息 |
||||||
|
* |
||||||
|
* @param tableData |
||||||
|
*/ |
||||||
|
public void populateDesensitizationSetting(DesensitizationTableData tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0])); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前对TableData的配置脱敏规则信息 |
||||||
|
*/ |
||||||
|
public List<TableDataDesensitizationItem> updateDesensitizationSetting() { |
||||||
|
return editorPane.update(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; |
||||||
|
import com.fr.design.gui.frpane.AttributeChangeListener; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Dimension; |
||||||
|
|
||||||
|
/** |
||||||
|
* 封装格式panel,管理 AttributeChangeListener |
||||||
|
* |
||||||
|
* @author Leo.Qin |
||||||
|
* @version 11.0 |
||||||
|
* Created by Leo.Qin on 2022/10/31 |
||||||
|
*/ |
||||||
|
public class TextFormatPaneContainer extends AbstractAttrNoScrollPane { |
||||||
|
private TextFormatPane formatPane; |
||||||
|
private AttributeChangeListener oldListner; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected JPanel createContentPane() { |
||||||
|
formatPane = new TextFormatPane(); |
||||||
|
return formatPane; |
||||||
|
} |
||||||
|
|
||||||
|
protected void initContentPane() { |
||||||
|
leftContentPane = createContentPane(); |
||||||
|
if (leftContentPane != null) { |
||||||
|
leftContentPane.setBorder(BorderFactory.createEmptyBorder()); |
||||||
|
this.add(leftContentPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Dimension getPreferredSize() { |
||||||
|
if (formatPane == null) { |
||||||
|
return super.getPreferredSize(); |
||||||
|
} |
||||||
|
return formatPane.getPreferredSize(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据单元格样式填充面板设置 |
||||||
|
* |
||||||
|
* @param style 单元格样式 |
||||||
|
*/ |
||||||
|
public void populateBean(Style style) { |
||||||
|
formatPane.populateBean(style); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据面板设置获取修改后的单元格样式 |
||||||
|
* |
||||||
|
* @param style 单元格当前样式 |
||||||
|
* @return 更新后的单元格样式 |
||||||
|
*/ |
||||||
|
public Style update(Style style) { |
||||||
|
return formatPane.update(style); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void removeAttributeChangeListener() { |
||||||
|
super.removeAttributeChangeListener(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addAttributeChangeListener(AttributeChangeListener listener) { |
||||||
|
oldListner = listener; |
||||||
|
super.addAttributeChangeListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 恢复使用AttributeChangeListener |
||||||
|
*/ |
||||||
|
public void restoreAttributeChangeListener() { |
||||||
|
super.addAttributeChangeListener(oldListner); |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 430 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 473 B |
After Width: | Height: | Size: 450 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,135 @@ |
|||||||
|
package com.fr.design.actions.replace.action; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 校验JS、公式、控件、组件 |
||||||
|
* 比较用户的所有对应类别的改动,不论是否选中要替换,只要整体类别改动过就算模板内容改动过 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-11-03 |
||||||
|
*/ |
||||||
|
public enum ITChecker { |
||||||
|
/** |
||||||
|
* 控件 |
||||||
|
*/ |
||||||
|
WIDGET_CHECK_TAG(Toolkit.i18nText("Fine-Design_Basic_Widget")), |
||||||
|
/** |
||||||
|
* 公式 |
||||||
|
*/ |
||||||
|
FORMULA_CHECK_TAG(Toolkit.i18nText("Fine-Design_Basic_Formula")), |
||||||
|
/** |
||||||
|
* JS |
||||||
|
*/ |
||||||
|
JS_CHECK_TAG(Toolkit.i18nText("Fine-Design_Replace_JS")), |
||||||
|
/** |
||||||
|
* 组件 |
||||||
|
*/ |
||||||
|
COMPONENT_CHECK_TAG(Toolkit.i18nText("Fine-Design_Replace_Component")) |
||||||
|
; |
||||||
|
|
||||||
|
|
||||||
|
String name; |
||||||
|
|
||||||
|
ITChecker(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配 |
||||||
|
* |
||||||
|
* @param name 对应的检查类型 |
||||||
|
* @return 对应的检查checker |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
public static ITChecker match(String name) { |
||||||
|
ITChecker[] values = ITChecker.values(); |
||||||
|
for (ITChecker value : values) { |
||||||
|
if (value.name.equals(name)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<? extends Info> checkList = new ArrayList<>(); |
||||||
|
public static Map<String, Integer> appearTimesMap = new HashMap<>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 更新对应的check列表 |
||||||
|
* |
||||||
|
* @param list 查找后的searchList |
||||||
|
*/ |
||||||
|
public static void updateCheckInfo(List<? extends Info> list) { |
||||||
|
checkList = list; |
||||||
|
updateCheckMapFromList(list); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据列表来更新对应元素的匹配Map |
||||||
|
* |
||||||
|
* @param list 更新后的checkList |
||||||
|
*/ |
||||||
|
private static void updateCheckMapFromList(List<? extends Info> list) { |
||||||
|
appearTimesMap.clear(); |
||||||
|
for (Info info : list) { |
||||||
|
String showStr = info.getContent().getOldShowStr(); |
||||||
|
if (appearTimesMap.containsKey(showStr)) { |
||||||
|
//如果已经存过了就个数+1
|
||||||
|
appearTimesMap.put(showStr, appearTimesMap.get(showStr) + 1); |
||||||
|
} else { |
||||||
|
//没有的话就把个数初始化为1个
|
||||||
|
appearTimesMap.put(showStr, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 判断是否修改过 |
||||||
|
* |
||||||
|
* @param list 重新获取的当前模板最新的list |
||||||
|
* @return 修改过返回true |
||||||
|
*/ |
||||||
|
public boolean isChanged(List<? extends Info> list) { |
||||||
|
if (list.size() != checkList.size()) { |
||||||
|
//如果总的数据的数量变了,就说明肯定修改过,没必要再进行下一步
|
||||||
|
return true; |
||||||
|
} |
||||||
|
return isChangedCheckByMap(list); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过检查Map来比较是否修改过 |
||||||
|
* |
||||||
|
* @param list 传入的用于比较的list |
||||||
|
* @return 修改过则返回true |
||||||
|
*/ |
||||||
|
private boolean isChangedCheckByMap(List<? extends Info> list) { |
||||||
|
for (Info info : list) { |
||||||
|
String showStr = info.getContent().getOldShowStr(); |
||||||
|
if (appearTimesMap.containsKey(showStr)) { |
||||||
|
//如果map中存在对应的值,就抵消,个数-1
|
||||||
|
appearTimesMap.put(showStr, appearTimesMap.get(showStr) - 1); |
||||||
|
if (appearTimesMap.get(showStr) < 0) { |
||||||
|
//如果map中的值小于0了,就说明数量对不上,修改过
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} else { |
||||||
|
//如果存在map中没存的值就没必要继续下去了,肯定改过
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.fr.design.actions.replace.action.content.js; |
||||||
|
|
||||||
|
/** |
||||||
|
* 检查JS的标签 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public class JSCheckTag { |
||||||
|
/** |
||||||
|
* 单元格-超级链接 |
||||||
|
*/ |
||||||
|
public static final int CELL_HYPERLINK = 0; |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
package com.fr.design.actions.replace.action.content.js; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.js.NameJavaScript; |
||||||
|
import com.fr.js.NameJavaScriptGroup; |
||||||
|
import com.fr.report.cell.Elem; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
/** |
||||||
|
* 检查JS是否修改过 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public enum JSCheckType { |
||||||
|
/** |
||||||
|
* 单元格-超级链接 |
||||||
|
*/ |
||||||
|
CELL_HYPERLINK(JSCheckTag.CELL_HYPERLINK) { |
||||||
|
@Override |
||||||
|
public boolean check(Info info) { |
||||||
|
Elem elem = (Elem) info.getContent().getHoldObject(); |
||||||
|
NameJavaScriptGroup group = elem.getNameHyperlinkGroup(); |
||||||
|
int len = group.size(); |
||||||
|
if (len == 0) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
NameJavaScript javaScript = (NameJavaScript) info.getContent().getReplaceObject(); |
||||||
|
for (int i = 0; i < len; i++) { |
||||||
|
if (group.getNameHyperlink(i).equals(javaScript)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
int index; |
||||||
|
|
||||||
|
JSCheckType(int index) { |
||||||
|
this.index = index; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配 |
||||||
|
* |
||||||
|
* @param index |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
public static JSCheckType match(int index) { |
||||||
|
JSCheckType[] values = JSCheckType.values(); |
||||||
|
for (JSCheckType value : values) { |
||||||
|
if (value.index == index) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 校验是否修改 |
||||||
|
* @param info 存储信息的数据结构 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public abstract boolean check(Info info); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,314 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting; |
||||||
|
|
||||||
|
import com.fr.base.CoreDecimalFormat; |
||||||
|
import com.fr.base.NameStyle; |
||||||
|
import com.fr.base.TextFormat; |
||||||
|
import com.fr.data.core.FormatField; |
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.general.date.FineDateFormat; |
||||||
|
import com.fr.report.cell.CellElement; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import java.text.Format; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-格式 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-25 |
||||||
|
*/ |
||||||
|
public enum CellFormatType { |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-格式-数字 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_NUMBER(SettingContent.FORMAT_NUMBER) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_NUMBER), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof CoreDecimalFormat && StringUtils.equals(((CoreDecimalFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-常规 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_COMMON(SettingContent.FORMAT_COMMON) { |
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return super.getItems(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
return cellElement.getStyle().getFormat() == null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
return !(cellElement.getStyle() != null && cellElement.getStyle().getFormat() == null); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-货币 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_MONEY(SettingContent.FORMAT_MONEY) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_MONEY), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof CoreDecimalFormat && StringUtils.equals(((CoreDecimalFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-日期 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_DATE(SettingContent.FORMAT_DATE) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_DATE), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof FineDateFormat && StringUtils.equals(((FineDateFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
return isEverChanged4FineDataFormat(info, extraStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-时间 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_TIME(SettingContent.FORMAT_TIME) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_TIME), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof FineDateFormat && StringUtils.equals(((FineDateFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
return isEverChanged4FineDataFormat(info, extraStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-科学计数 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_SCIENCE(SettingContent.FORMAT_SCIENCE) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_SCIENCE), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof CoreDecimalFormat && StringUtils.equals(((CoreDecimalFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-百分比 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_PERCENT(SettingContent.FORMAT_PERCENT) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_PERCENT), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof CoreDecimalFormat && StringUtils.equals(((CoreDecimalFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-千分比 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_PERMILLAGE(SettingContent.FORMAT_PERMILLAGE) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return Arrays.asList(FormatField.getInstance().getFormatArray(FormatField.getInstance().getContents(SettingContent.FORMAT_PERMILLAGE), false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof CoreDecimalFormat && StringUtils.equals(((CoreDecimalFormat) format).toPattern(), secondStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-格式-文本 |
||||||
|
*/ |
||||||
|
CELL_FORMAT_TEXT(SettingContent.FORMAT_TEXT) { |
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
Format format = cellElement.getStyle().getFormat(); |
||||||
|
return format instanceof TextFormat; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
return !(cellElement.getStyle() != null |
||||||
|
&& cellElement.getStyle().getFormat() != null |
||||||
|
&& cellElement.getStyle().getFormat() instanceof TextFormat); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
CellFormatType(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配 |
||||||
|
* |
||||||
|
* @param name |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
public static CellFormatType match(String name) { |
||||||
|
CellFormatType[] values = CellFormatType.values(); |
||||||
|
for (CellFormatType value : values) { |
||||||
|
if (StringUtils.equals(value.name, name)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否能扩展选项 |
||||||
|
* |
||||||
|
* @return 能扩展则返回true |
||||||
|
*/ |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取界面数据 |
||||||
|
*/ |
||||||
|
public List<String> getItems() { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否是要查找的内容 |
||||||
|
* |
||||||
|
* @param cellElement |
||||||
|
* @param firstStr |
||||||
|
* @param secondStr |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 替换 |
||||||
|
* |
||||||
|
* @param info 存储信息的数据结构 |
||||||
|
* @param firstStr 用户输入的第一级下拉框内容 |
||||||
|
* @param secondStr 用户输入的第二级下拉框内容 |
||||||
|
*/ |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
cellElement.setStyle(cellElement.getStyle().deriveFormat(FormatField.getInstance().getFormat(FormatField.getInstance().getContents(firstStr), secondStr))); |
||||||
|
if (cellElement.getStyle() instanceof NameStyle) { |
||||||
|
((NameStyle) cellElement.getStyle()).refreshStyle(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否修改过 |
||||||
|
* |
||||||
|
* @param info 存储单元格信息的数据结构 |
||||||
|
* @param inputStr 用户输入的第一级下拉框内容 |
||||||
|
* @param extraStr 用户输入的第二级下拉框内容 |
||||||
|
* @return 修改过返回true |
||||||
|
*/ |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
return !(cellElement.getStyle() != null |
||||||
|
&& cellElement.getStyle().getFormat() != null |
||||||
|
&& cellElement.getStyle().getFormat() instanceof CoreDecimalFormat |
||||||
|
&& StringUtils.equals(((CoreDecimalFormat) cellElement.getStyle().getFormat()).toPattern(), extraStr)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 针对日期和时间类型的修改判定 |
||||||
|
* |
||||||
|
* @param info 存储单元格信息的数据结构 |
||||||
|
* @param extraStr 用户输入的第二级下拉框内容 |
||||||
|
* @return 修改过返回true |
||||||
|
*/ |
||||||
|
public boolean isEverChanged4FineDataFormat(Info info, String extraStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
return !(cellElement.getStyle() != null |
||||||
|
&& cellElement.getStyle().getFormat() != null |
||||||
|
&& cellElement.getStyle().getFormat() instanceof FineDateFormat |
||||||
|
&& StringUtils.equals(((FineDateFormat) cellElement.getStyle().getFormat()).toPattern(), extraStr)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,249 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.data.util.function.AverageFunction; |
||||||
|
import com.fr.data.util.function.CountFunction; |
||||||
|
import com.fr.data.util.function.DataFunction; |
||||||
|
import com.fr.data.util.function.MaxFunction; |
||||||
|
import com.fr.data.util.function.MinFunction; |
||||||
|
import com.fr.data.util.function.NoneFunction; |
||||||
|
import com.fr.data.util.function.SumFunction; |
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.report.cell.CellElement; |
||||||
|
import com.fr.report.cell.cellattr.core.group.DSColumn; |
||||||
|
import com.fr.report.cell.cellattr.core.group.FunctionGrouper; |
||||||
|
import com.fr.report.cell.cellattr.core.group.RecordGrouper; |
||||||
|
import com.fr.report.cell.cellattr.core.group.SummaryGrouper; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 处理单元格的格式(对于高级,由于需要自定义,不加入处理范围) |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public enum CellGroupType { |
||||||
|
|
||||||
|
/** |
||||||
|
* 分组 |
||||||
|
*/ |
||||||
|
GROUP(SettingContent.DIGIT_SETTING_GROUP) { |
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
List<String> items = new ArrayList<String>() { |
||||||
|
{ |
||||||
|
add(SettingContent.GROUP_COMMON); |
||||||
|
add(SettingContent.GROUP_CONTINUUM); |
||||||
|
} |
||||||
|
}; |
||||||
|
return items; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
RecordGrouper grouper = column.getGrouper(); |
||||||
|
return grouper instanceof FunctionGrouper && grouper.getDivideMode() == getGroupType(secondStr); |
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
/** |
||||||
|
* 列表 |
||||||
|
*/ |
||||||
|
LIST(SettingContent.DIGIT_SETTING_LIST) { |
||||||
|
@Override |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
RecordGrouper grouper = column.getGrouper(); |
||||||
|
return grouper instanceof FunctionGrouper && grouper.getDivideMode() == getGroupType(firstStr); |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 汇总 |
||||||
|
*/ |
||||||
|
SUM(SettingContent.DIGIT_SETTING_SUM) { |
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
List<String> items = new ArrayList<String>() { |
||||||
|
{ |
||||||
|
add(SettingContent.SUMMARY_SUM); |
||||||
|
add(SettingContent.SUMMARY_AVERAGE); |
||||||
|
add(SettingContent.SUMMARY_MAX); |
||||||
|
add(SettingContent.SUMMARY_MIN); |
||||||
|
add(SettingContent.SUMMARY_COUNT); |
||||||
|
add(SettingContent.SUMMARY_NONE); |
||||||
|
} |
||||||
|
}; |
||||||
|
return items; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
RecordGrouper grouper = column.getGrouper(); |
||||||
|
return grouper instanceof SummaryGrouper && ((SummaryGrouper) grouper).getFunction() != null && StringUtils.equals(((SummaryGrouper) grouper).getFunction().getClass().getSimpleName(), getSummaryType(secondStr)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
SummaryGrouper grouper = new SummaryGrouper(); |
||||||
|
grouper.setFunction(createDataFunction(secondStr)); |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
column.setGrouper(grouper); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
private Map<String, Integer> groupMap = new HashMap<String, Integer>() { |
||||||
|
{ |
||||||
|
put(SettingContent.GROUP_COMMON, FunctionGrouper.GROUPING_MODE); |
||||||
|
put(SettingContent.GROUP_CONTINUUM, FunctionGrouper.CONTINUUM_MODE); |
||||||
|
put(SettingContent.DIGIT_LIST, FunctionGrouper.LIST_MODE); |
||||||
|
} |
||||||
|
}; |
||||||
|
private Map<String, String> summaryMap = new HashMap<String, String>() { |
||||||
|
{ |
||||||
|
put(SettingContent.SUMMARY_SUM, SUM_FUNCTION); |
||||||
|
put(SettingContent.SUMMARY_AVERAGE, AVERAGE_FUNCTION); |
||||||
|
put(SettingContent.SUMMARY_MAX, MAX_FUNCTION); |
||||||
|
put(SettingContent.SUMMARY_MIN, MIN_FUNCTION); |
||||||
|
put(SettingContent.SUMMARY_COUNT, COUNT_FUNCTION); |
||||||
|
put(SettingContent.SUMMARY_NONE, NONE_FUNCTION); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public static final String SUM_FUNCTION = "SumFunction"; |
||||||
|
public static final String AVERAGE_FUNCTION = "AverageFunction"; |
||||||
|
public static final String MAX_FUNCTION = "MaxFunction"; |
||||||
|
public static final String MIN_FUNCTION = "MinFunction"; |
||||||
|
public static final String COUNT_FUNCTION = "CountFunction"; |
||||||
|
public static final String NONE_FUNCTION = "NoneFunction"; |
||||||
|
|
||||||
|
|
||||||
|
CellGroupType(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配 |
||||||
|
* |
||||||
|
* @param name |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
public static CellGroupType match(String name) { |
||||||
|
CellGroupType[] values = CellGroupType.values(); |
||||||
|
for (CellGroupType value : values) { |
||||||
|
if (StringUtils.equals(value.name, name)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否是要查找的内容 |
||||||
|
* |
||||||
|
* @param cellElement |
||||||
|
* @param firstStr |
||||||
|
* @param secondStr |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean isNeed(CellElement cellElement, String firstStr, String secondStr) { |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
RecordGrouper recordGrouper = column.getGrouper(); |
||||||
|
return recordGrouper instanceof FunctionGrouper && recordGrouper.getDivideMode() == getGroupType(secondStr); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配分组 |
||||||
|
* |
||||||
|
* @param str |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Integer getGroupType(String str) { |
||||||
|
return groupMap.getOrDefault(str, -1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配汇总 |
||||||
|
*/ |
||||||
|
public String getSummaryType(String str) { |
||||||
|
return summaryMap.getOrDefault(str, StringUtils.EMPTY); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建对应汇总的DataFunction |
||||||
|
* |
||||||
|
* @param str 汇总子级下拉框的内容 |
||||||
|
* @return 指定类型的DataFunction |
||||||
|
*/ |
||||||
|
public DataFunction createDataFunction(String str) { |
||||||
|
switch (getSummaryType(str)) { |
||||||
|
case SUM_FUNCTION: |
||||||
|
return new SumFunction(); |
||||||
|
case AVERAGE_FUNCTION: |
||||||
|
return new AverageFunction(); |
||||||
|
case MAX_FUNCTION: |
||||||
|
return new MaxFunction(); |
||||||
|
case MIN_FUNCTION: |
||||||
|
return new MinFunction(); |
||||||
|
case COUNT_FUNCTION: |
||||||
|
return new CountFunction(); |
||||||
|
default: |
||||||
|
return new NoneFunction(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否能扩展选项 |
||||||
|
* |
||||||
|
* @return 能扩展则返回true |
||||||
|
*/ |
||||||
|
public boolean hasExpand(String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取界面数据 |
||||||
|
*/ |
||||||
|
public List<String> getItems() { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 替换 |
||||||
|
* |
||||||
|
* @param info 存储信息的数据结构 |
||||||
|
* @param firstStr 用户输入的第一级下拉框 |
||||||
|
* @param secondStr 用户输入的第二级下拉框 |
||||||
|
*/ |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
FunctionGrouper grouper = new FunctionGrouper(); |
||||||
|
if (StringUtils.equals(firstStr, SettingContent.DIGIT_SETTING_LIST)) { |
||||||
|
grouper.setDivideMode(getGroupType(firstStr)); |
||||||
|
} else { |
||||||
|
grouper.setDivideMode(getGroupType(secondStr)); |
||||||
|
} |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
DSColumn column = (DSColumn) cellElement.getValue(); |
||||||
|
column.setGrouper(grouper); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.utils.ShowValueUtils; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置项的一些常用常量 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-24 |
||||||
|
*/ |
||||||
|
public class SettingContent { |
||||||
|
|
||||||
|
public static final String CELL_FORMAT_NAME = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Basic_Cell"), Toolkit.i18nText("Fine-Design_Report_Base_Format")); |
||||||
|
public static final String CELL_DATA_SETTING_NAME = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Basic_Cell"), Toolkit.i18nText("Fine-Design_Chart_Data_Setting")); |
||||||
|
public static final String CELL_DS_COLUMN_NAME = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Basic_Cell"), Toolkit.i18nText("Fine-Design_Basic_DS_Column")); |
||||||
|
public static final String DATASOURCE_CONNECTION_NAME = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Replace_Data_Source"), Toolkit.i18nText("Fine-Design_Replace_Data_Connection")); |
||||||
|
public static final String DATASOURCE_COLLECT_NAME = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Replace_Data_Source"), Toolkit.i18nText("Fine-Design_Replace_Data_Collect")); |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-格式 |
||||||
|
*/ |
||||||
|
public static final String FORMAT_COMMON = Toolkit.i18nText("Fine-Design_Replace_Common"); |
||||||
|
public static final String FORMAT_NUMBER = Toolkit.i18nText("Fine-Design_Replace_Number"); |
||||||
|
public static final String FORMAT_MONEY = Toolkit.i18nText("Fine-Design_Replace_Money"); |
||||||
|
public static final String FORMAT_PERCENT = Toolkit.i18nText("Fine-Design_Replace_Percent"); |
||||||
|
public static final String FORMAT_PERMILLAGE = Toolkit.i18nText("Fine-Design_Replace_Permillage"); |
||||||
|
public static final String FORMAT_SCIENCE = Toolkit.i18nText("Fine-Design_Replace_Science"); |
||||||
|
public static final String FORMAT_DATE = Toolkit.i18nText("Fine-Design_Replace_Date"); |
||||||
|
public static final String FORMAT_TIME = Toolkit.i18nText("Fine-Design_Replace_Time"); |
||||||
|
public static final String FORMAT_TEXT = Toolkit.i18nText("Fine-Design_Replace_Text"); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-数据设置 |
||||||
|
*/ |
||||||
|
public static final String DIGIT_SETTING_GROUP = Toolkit.i18nText("Fine-Design_Replace_Group"); |
||||||
|
public static final String DIGIT_SETTING_LIST = Toolkit.i18nText("Fine-Design_Replace_List"); |
||||||
|
public static final String DIGIT_SETTING_SUM = Toolkit.i18nText("Fine-Design_Replace_Sum"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-数据设置-分组 |
||||||
|
*/ |
||||||
|
public static final String GROUP_COMMON = Toolkit.i18nText("Fine-Design_Report_Common"); |
||||||
|
public static final String GROUP_CONTINUUM = Toolkit.i18nText("Fine-Design_Report_Continuum"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-数据设置-列表 |
||||||
|
*/ |
||||||
|
public static final String DIGIT_LIST = Toolkit.i18nText("Fine-Design_Report_Bind_Column_Select"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-数据设置-汇总 |
||||||
|
*/ |
||||||
|
public static final String SUMMARY_SUM = Toolkit.i18nText("Fine-Design_DataFunction_Sum"); |
||||||
|
public static final String SUMMARY_AVERAGE = Toolkit.i18nText("Fine-Design_DataFunction_Average"); |
||||||
|
public static final String SUMMARY_MAX = Toolkit.i18nText("Fine-Design_DataFunction_Max"); |
||||||
|
public static final String SUMMARY_MIN = Toolkit.i18nText("Fine-Design_DataFunction_Min"); |
||||||
|
public static final String SUMMARY_COUNT = Toolkit.i18nText("Fine-Design_DataFunction_Count"); |
||||||
|
public static final String SUMMARY_NONE = Toolkit.i18nText("Fine-Design_DataFunction_None"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据连接 |
||||||
|
*/ |
||||||
|
public static final String CONNECTION_TEMPLATE = Toolkit.i18nText("Fine-Design_Basic_DS_Report_TableData"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 扩展出来的可能的选项 |
||||||
|
*/ |
||||||
|
public static final String DS_COLUMN_EXPEND = "DS_COLUMN_EXPEND"; |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,387 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.data.TableDataSource; |
||||||
|
import com.fr.design.actions.replace.action.ShowValue; |
||||||
|
import com.fr.design.actions.replace.action.setting.action.SearchCellDSColumnAction; |
||||||
|
import com.fr.design.actions.replace.action.setting.action.SearchCellFormatAction; |
||||||
|
import com.fr.design.actions.replace.action.setting.action.SearchConnectionAction; |
||||||
|
import com.fr.design.actions.replace.action.setting.action.SearchDSColumnAction; |
||||||
|
import com.fr.design.actions.replace.info.CellInfo; |
||||||
|
import com.fr.design.actions.replace.info.DataSourceInfo; |
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.design.actions.replace.info.ReplaceObject; |
||||||
|
import com.fr.design.actions.replace.ui.ITReplaceNorthPanel; |
||||||
|
import com.fr.design.data.DesignTableDataManager; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.file.ConnectionConfig; |
||||||
|
import com.fr.general.data.TableDataColumn; |
||||||
|
import com.fr.report.cell.CellElement; |
||||||
|
import com.fr.report.cell.cellattr.core.group.DSColumn; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置项的查找内容 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-24 |
||||||
|
*/ |
||||||
|
public enum SettingController implements ShowValue { |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格-格式 |
||||||
|
*/ |
||||||
|
CELL_FORMAT(SettingContent.CELL_FORMAT_NAME) { |
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return ITReplaceNorthPanel.formatItems; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> showSearchValue(JTemplate jTemplate) { |
||||||
|
SearchCellFormatAction.getInstance().search4Infos(jTemplate); |
||||||
|
return SearchCellFormatAction.getInstance().getCellInfos(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> addMatchResult(List<? extends Info> list, String settingStr, String extraStr) { |
||||||
|
List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
for (Info info : list) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
CellFormatType type = CellFormatType.match(settingStr); |
||||||
|
if (type != null && type.isNeed(cellElement, settingStr, extraStr)) { |
||||||
|
cellInfos.add((CellInfo) info); |
||||||
|
} |
||||||
|
} |
||||||
|
return cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasExpand(String str, String parentStr) { |
||||||
|
CellFormatType type = CellFormatType.match(parentStr); |
||||||
|
if (type != null) { |
||||||
|
return type.hasExpand(parentStr); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getExtraItems(String str) { |
||||||
|
CellFormatType type = CellFormatType.match(str); |
||||||
|
if (type != null) { |
||||||
|
return type.getItems(); |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
CellFormatType type = CellFormatType.match(firstStr); |
||||||
|
if (type != null) { |
||||||
|
type.replace(info, firstStr, secondStr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
if (cellElement.getStyle() != null) { |
||||||
|
CellFormatType type = CellFormatType.match(inputStr); |
||||||
|
if (type != null) { |
||||||
|
return type.isEverChanged(info, inputStr, extraStr); |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-数据设置 |
||||||
|
*/ |
||||||
|
CELL_DATA_SETTING(SettingContent.CELL_DATA_SETTING_NAME) { |
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return ITReplaceNorthPanel.digitItems; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> showSearchValue(JTemplate jTemplate) { |
||||||
|
SearchCellDSColumnAction.getInstance().search4Infos(jTemplate); |
||||||
|
return SearchCellDSColumnAction.getInstance().getCellInfos(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> addMatchResult(List<? extends Info> list, String settingStr, String extraStr) { |
||||||
|
List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
for (Info info : list) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
//能到这步说明单元格里是数据列
|
||||||
|
CellGroupType cellGroupType = CellGroupType.match(settingStr); |
||||||
|
if (cellGroupType != null && cellGroupType.isNeed(cellElement, settingStr, extraStr)) { |
||||||
|
cellInfos.add((CellInfo) info); |
||||||
|
} |
||||||
|
} |
||||||
|
return cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getExtraItems(String str) { |
||||||
|
CellGroupType type = CellGroupType.match(str); |
||||||
|
if (type != null) { |
||||||
|
return type.getItems(); |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasExpand(String str, String parentStr) { |
||||||
|
CellGroupType type = CellGroupType.match(parentStr); |
||||||
|
if (type != null) { |
||||||
|
return type.hasExpand(parentStr); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
CellGroupType type = CellGroupType.match(firstStr); |
||||||
|
if (type != null) { |
||||||
|
type.replace(info, firstStr, secondStr); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 单元格-数据列 |
||||||
|
*/ |
||||||
|
CELL_DS_COLUMN(SettingContent.CELL_DS_COLUMN_NAME) { |
||||||
|
@Override |
||||||
|
public List<? extends Info> showSearchValue(JTemplate jTemplate) { |
||||||
|
SearchCellDSColumnAction.getInstance().search4Infos(jTemplate); |
||||||
|
return SearchCellDSColumnAction.getInstance().getCellInfos(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> addMatchResult(List<? extends Info> list, String settingStr, String extraStr) { |
||||||
|
List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
for (Info info : list) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
//能到这步说明单元格里是数据列
|
||||||
|
DSColumn dsColumn = (DSColumn) cellElement.getValue(); |
||||||
|
if (isNeed(dsColumn, settingStr, extraStr)) { |
||||||
|
cellInfos.add((CellInfo) info); |
||||||
|
} |
||||||
|
} |
||||||
|
return cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isNeed(DSColumn dsColumn, String settingStr, String extraStr) { |
||||||
|
return dsColumn != null && StringUtils.equals(settingStr, dsColumn.getDSName()) && dsColumn.getColumn() != null && StringUtils.equals(dsColumn.getColumnName(), extraStr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
List<String> tableDataArray = new ArrayList<>(); |
||||||
|
if (jTemplate != null && jTemplate.getTarget() instanceof TableDataSource) { |
||||||
|
TableDataSource source = (TableDataSource) jTemplate.getTarget(); |
||||||
|
Iterator dataIterator = source.getTableDataNameIterator(); |
||||||
|
while (dataIterator.hasNext()) { |
||||||
|
String dataName = (String) dataIterator.next(); |
||||||
|
tableDataArray.add(dataName); |
||||||
|
} |
||||||
|
} |
||||||
|
return tableDataArray; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getExtraItems(String str) { |
||||||
|
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
List<String> tableDataArray = new ArrayList<>(); |
||||||
|
if (jTemplate != null) { |
||||||
|
TableDataSource source = jTemplate.getTarget(); |
||||||
|
tableDataArray = Arrays.asList(DesignTableDataManager.getSelectedColumnNames(source, str)); |
||||||
|
} |
||||||
|
return tableDataArray; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasExpand(String str, String parentStr) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
DSColumn dsColumn = (DSColumn) cellElement.getValue(); |
||||||
|
dsColumn.setDSName(firstStr); |
||||||
|
dsColumn.setColumn(TableDataColumn.createColumn(secondStr)); |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 数据源-数据连接 |
||||||
|
*/ |
||||||
|
DATASOURCE_CONNECTION(SettingContent.DATASOURCE_CONNECTION_NAME) { |
||||||
|
@Override |
||||||
|
public List<? extends Info> showSearchValue(JTemplate jTemplate) { |
||||||
|
SearchConnectionAction.getInstance().search4Infos(jTemplate); |
||||||
|
return SearchConnectionAction.getInstance().getConnectionInfos(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> addMatchResult(List<? extends Info> list, String settingStr, String extraStr) { |
||||||
|
List<DataSourceInfo> connectionInfos = new ArrayList<>(); |
||||||
|
for (Info info : list) { |
||||||
|
if (StringUtils.equals(info.getContent().getShowStr(), settingStr)) { |
||||||
|
connectionInfos.add((DataSourceInfo) info); |
||||||
|
} |
||||||
|
} |
||||||
|
return connectionInfos; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
List<String> nameList = new ArrayList<>(); |
||||||
|
for (String name : ConnectionConfig.getInstance().getConnections().keySet()) { |
||||||
|
nameList.add(name); |
||||||
|
} |
||||||
|
return nameList; |
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
/** |
||||||
|
* 数据源-数据集 |
||||||
|
*/ |
||||||
|
DATASOURCE_COLLECT(SettingContent.DATASOURCE_COLLECT_NAME) { |
||||||
|
@Override |
||||||
|
public List<? extends Info> showSearchValue(JTemplate jTemplate) { |
||||||
|
SearchDSColumnAction.getInstance().search4Infos(jTemplate); |
||||||
|
return SearchDSColumnAction.getInstance().getDsColumnInfos(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public List<? extends Info> addMatchResult(List<? extends Info> list, String settingStr, String extraStr) { |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<String> getItems() { |
||||||
|
return ITReplaceNorthPanel.dsColumnItems; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
SettingController(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 匹配 |
||||||
|
* |
||||||
|
* @param name |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Nullable |
||||||
|
public static SettingController match(String name) { |
||||||
|
SettingController[] values = SettingController.values(); |
||||||
|
for (SettingController value : values) { |
||||||
|
if (StringUtils.equals(value.name, name)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取界面的数据,使之与选项匹配 |
||||||
|
* |
||||||
|
* @param name 选项 |
||||||
|
*/ |
||||||
|
public static List<String> getSettingRefreshItems(String name) { |
||||||
|
SettingController[] values = SettingController.values(); |
||||||
|
for (SettingController value : values) { |
||||||
|
if (StringUtils.equals(value.name, name)) { |
||||||
|
return value.getItems(); |
||||||
|
} |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取界面的数据,使之与选项匹配 |
||||||
|
* |
||||||
|
* @param parentStr 选项 |
||||||
|
*/ |
||||||
|
public static List<String> getSettingExtraRefreshItems(String str, String parentStr) { |
||||||
|
SettingController[] values = SettingController.values(); |
||||||
|
for (SettingController value : values) { |
||||||
|
if (StringUtils.equals(value.name, str)) { |
||||||
|
return value.getExtraItems(parentStr); |
||||||
|
} |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取界面数据 |
||||||
|
*/ |
||||||
|
public List<String> getItems() { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取扩展数据 |
||||||
|
* |
||||||
|
* @param str 父类名称 |
||||||
|
* @return 扩展的数据列表 |
||||||
|
*/ |
||||||
|
public List<String> getExtraItems(String str) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否能扩展选项 |
||||||
|
* |
||||||
|
* @return 能扩展则返回true |
||||||
|
*/ |
||||||
|
public boolean hasExpand(String str, String parentStr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 替换 |
||||||
|
* |
||||||
|
* @param info 存储信息的数据结构 |
||||||
|
* @param firstStr 用户设定的第一级下拉框的内容 |
||||||
|
* @param secondStr 用户设定的第二级下拉框的内容 |
||||||
|
*/ |
||||||
|
public void replace(Info info, String firstStr, String secondStr) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否修改过 |
||||||
|
* |
||||||
|
* @param info 存储信息的数据结构 |
||||||
|
* @param inputStr 用户搜索的一级下拉框内容 |
||||||
|
* @param extraStr 用户搜索的二级下拉框内容 |
||||||
|
* @return 没修改过则返回false |
||||||
|
*/ |
||||||
|
public boolean isEverChanged(Info info, String inputStr, String extraStr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting.action; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.action.SearchAction; |
||||||
|
import com.fr.design.actions.replace.action.content.cell.SearchCellAction; |
||||||
|
import com.fr.design.actions.replace.info.CellInfo; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.general.GeneralUtils; |
||||||
|
import com.fr.report.cell.CellElement; |
||||||
|
import com.fr.report.cell.cellattr.core.group.DSColumn; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 存储单元格-数据列 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public class SearchCellDSColumnAction implements SearchAction { |
||||||
|
private List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
|
||||||
|
private SearchCellDSColumnAction() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void search4Infos(JTemplate jTemplate) { |
||||||
|
List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
SearchCellAction.getInstance().search4Infos(jTemplate); |
||||||
|
for (CellInfo info : SearchCellAction.getInstance().getCellInfos()) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
if (cellElement.getValue() instanceof DSColumn) { |
||||||
|
info.getContent().setShowStr(GeneralUtils.objectToString(cellElement.getValue())); |
||||||
|
cellInfos.add(info); |
||||||
|
} |
||||||
|
} |
||||||
|
setCellInfos(cellInfos); |
||||||
|
} |
||||||
|
|
||||||
|
public List<CellInfo> getCellInfos() { |
||||||
|
return cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCellInfos(List<CellInfo> cellInfos) { |
||||||
|
this.cellInfos = cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对外开放的获取对象的方法 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static SearchCellDSColumnAction getInstance() { |
||||||
|
return SearchCellDSColumnActionEnum.SINGLETON.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 枚举实现单例 |
||||||
|
*/ |
||||||
|
private enum SearchCellDSColumnActionEnum { |
||||||
|
/** |
||||||
|
* 单例 |
||||||
|
*/ |
||||||
|
SINGLETON; |
||||||
|
|
||||||
|
private SearchCellDSColumnAction instance; |
||||||
|
|
||||||
|
SearchCellDSColumnActionEnum() { |
||||||
|
instance = new SearchCellDSColumnAction(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取对象 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public SearchCellDSColumnAction getInstance() { |
||||||
|
return instance; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting.action; |
||||||
|
|
||||||
|
import com.fr.chart.chartattr.ChartCollection; |
||||||
|
import com.fr.design.actions.replace.action.SearchAction; |
||||||
|
import com.fr.design.actions.replace.action.content.cell.SearchCellAction; |
||||||
|
import com.fr.design.actions.replace.info.CellInfo; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.general.GeneralUtils; |
||||||
|
import com.fr.general.ImageWithSuffix; |
||||||
|
import com.fr.report.cell.CellElement; |
||||||
|
import com.fr.report.cell.cellattr.core.RichText; |
||||||
|
import com.fr.report.cell.cellattr.core.SubReport; |
||||||
|
import com.fr.report.cell.painter.BiasTextPainter; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 存储有格式的单元格 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-25 |
||||||
|
*/ |
||||||
|
public class SearchCellFormatAction implements SearchAction { |
||||||
|
private List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
|
||||||
|
private SearchCellFormatAction() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void search4Infos(JTemplate jTemplate) { |
||||||
|
List<CellInfo> cellInfos = new ArrayList<>(); |
||||||
|
SearchCellAction.getInstance().search4Infos(jTemplate); |
||||||
|
for (CellInfo info : SearchCellAction.getInstance().getCellInfos()) { |
||||||
|
CellElement cellElement = (CellElement) info.getContent().getReplaceObject(); |
||||||
|
if (isFormatValid(cellElement)) { |
||||||
|
info.getContent().setShowStr(GeneralUtils.objectToString(cellElement.getValue())); |
||||||
|
cellInfos.add(info); |
||||||
|
} |
||||||
|
} |
||||||
|
setCellInfos(cellInfos); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 单元格的内容是否是在查找范围内 |
||||||
|
* |
||||||
|
* @param cellElement 单元格 |
||||||
|
* @return 在查找范围内返回true |
||||||
|
*/ |
||||||
|
public boolean isFormatValid(CellElement cellElement) { |
||||||
|
return cellElement.getStyle() != null |
||||||
|
&& !(cellElement.getValue() instanceof SubReport |
||||||
|
|| cellElement.getValue() instanceof BiasTextPainter |
||||||
|
|| cellElement.getValue() instanceof ChartCollection |
||||||
|
|| cellElement.getValue() instanceof RichText |
||||||
|
|| cellElement.getValue() instanceof ImageWithSuffix |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
public List<CellInfo> getCellInfos() { |
||||||
|
return cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCellInfos(List<CellInfo> cellInfos) { |
||||||
|
this.cellInfos = cellInfos; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对外开放的获取对象的方法 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static SearchCellFormatAction getInstance() { |
||||||
|
return SearchCellFormatActionEnum.SINGLETON.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 枚举实现单例 |
||||||
|
*/ |
||||||
|
private enum SearchCellFormatActionEnum { |
||||||
|
/** |
||||||
|
* 单例 |
||||||
|
*/ |
||||||
|
SINGLETON; |
||||||
|
|
||||||
|
private SearchCellFormatAction instance; |
||||||
|
|
||||||
|
SearchCellFormatActionEnum() { |
||||||
|
instance = new SearchCellFormatAction(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取对象 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public SearchCellFormatAction getInstance() { |
||||||
|
return instance; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,114 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting.action; |
||||||
|
|
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.base.TableDataConnection; |
||||||
|
import com.fr.data.TableDataSource; |
||||||
|
import com.fr.data.impl.Connection; |
||||||
|
import com.fr.data.impl.NameDatabaseConnection; |
||||||
|
import com.fr.design.actions.replace.action.SearchAction; |
||||||
|
import com.fr.design.actions.replace.info.DataSourceInfo; |
||||||
|
import com.fr.design.actions.replace.info.base.ITContent; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.file.ConnectionConfig; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 存储数据连接信息 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public class SearchConnectionAction implements SearchAction { |
||||||
|
private List<DataSourceInfo> connectionInfos = new ArrayList<>(); |
||||||
|
|
||||||
|
|
||||||
|
private SearchConnectionAction() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void search4Infos(JTemplate jTemplate) { |
||||||
|
List<DataSourceInfo> connectionInfos = new ArrayList<>(); |
||||||
|
Map<String, Connection> map = ConnectionConfig.getInstance().getConnections(); |
||||||
|
Map<String, Connection> needMap = new HashMap<>(); |
||||||
|
TableDataSource source = (TableDataSource) jTemplate.getTarget(); |
||||||
|
Iterator dataIterator = source.getTableDataNameIterator(); |
||||||
|
while (dataIterator.hasNext()) { |
||||||
|
String dataName = (String) dataIterator.next(); |
||||||
|
TableData data = source.getTableData(dataName); |
||||||
|
if (isNameDataBaseConnectionValid(data)) { |
||||||
|
NameDatabaseConnection connection = (NameDatabaseConnection) ((TableDataConnection) data).getDatabase(); |
||||||
|
if (map.containsKey(connection.getName())) { |
||||||
|
needMap.put(connection.getName(), connection); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
for (String name : needMap.keySet()) { |
||||||
|
ITContent content = new ITContent(); |
||||||
|
content.setReplaceObject(needMap.get(name)); |
||||||
|
content.setTemplateName(jTemplate.getTemplateName()); |
||||||
|
content.setJumpAble(false); |
||||||
|
content.setShowStr(name); |
||||||
|
connectionInfos.add(new DataSourceInfo(content)); |
||||||
|
} |
||||||
|
setConnectionInfos(connectionInfos); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据连接是否可用 |
||||||
|
* |
||||||
|
* @param data 数据库 |
||||||
|
* @return 可用返回true |
||||||
|
*/ |
||||||
|
public boolean isNameDataBaseConnectionValid(TableData data) { |
||||||
|
return data instanceof TableDataConnection && ((TableDataConnection) data).getDatabase() instanceof NameDatabaseConnection; |
||||||
|
} |
||||||
|
|
||||||
|
public List<DataSourceInfo> getConnectionInfos() { |
||||||
|
return connectionInfos; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConnectionInfos(List<DataSourceInfo> connectionInfos) { |
||||||
|
this.connectionInfos = connectionInfos; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对外开放的获取对象的方法 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static SearchConnectionAction getInstance() { |
||||||
|
return SearchConnectionActionEnum.SINGLETON.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 枚举实现单例 |
||||||
|
*/ |
||||||
|
private enum SearchConnectionActionEnum { |
||||||
|
/** |
||||||
|
* 单例 |
||||||
|
*/ |
||||||
|
SINGLETON; |
||||||
|
|
||||||
|
private SearchConnectionAction instance; |
||||||
|
|
||||||
|
SearchConnectionActionEnum() { |
||||||
|
instance = new SearchConnectionAction(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取对象 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public SearchConnectionAction getInstance() { |
||||||
|
return instance; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
package com.fr.design.actions.replace.action.setting.action; |
||||||
|
|
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.data.TableDataSource; |
||||||
|
import com.fr.design.actions.replace.action.SearchAction; |
||||||
|
import com.fr.design.actions.replace.info.DataSourceInfo; |
||||||
|
import com.fr.design.actions.replace.info.base.ITContent; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 搜索数据列 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-26 |
||||||
|
*/ |
||||||
|
public class SearchDSColumnAction implements SearchAction { |
||||||
|
private List<DataSourceInfo> dsColumnInfos = new ArrayList<>(); |
||||||
|
|
||||||
|
|
||||||
|
private SearchDSColumnAction() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void search4Infos(JTemplate jTemplate) { |
||||||
|
List<DataSourceInfo> dsColumnInfos = new ArrayList<>(); |
||||||
|
TableDataSource source = (TableDataSource) jTemplate.getTarget(); |
||||||
|
Iterator dataIterator = source.getTableDataNameIterator(); |
||||||
|
while (dataIterator.hasNext()) { |
||||||
|
String dataName = (String) dataIterator.next(); |
||||||
|
TableData data = source.getTableData(dataName); |
||||||
|
ITContent content = new ITContent(); |
||||||
|
content.setJumpAble(false); |
||||||
|
content.setReplaceObject(data); |
||||||
|
content.setShowStr(dataName); |
||||||
|
content.setTemplateName(jTemplate.getTemplateName()); |
||||||
|
dsColumnInfos.add(new DataSourceInfo(content)); |
||||||
|
} |
||||||
|
setDsColumnInfos(dsColumnInfos); |
||||||
|
} |
||||||
|
|
||||||
|
public List<DataSourceInfo> getDsColumnInfos() { |
||||||
|
return dsColumnInfos; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDsColumnInfos(List<DataSourceInfo> dsColumnInfos) { |
||||||
|
this.dsColumnInfos = dsColumnInfos; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对外开放的获取对象的方法 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static SearchDSColumnAction getInstance() { |
||||||
|
return SearchDSColumnActionEnum.SINGLETON.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 枚举实现单例 |
||||||
|
*/ |
||||||
|
private enum SearchDSColumnActionEnum { |
||||||
|
/** |
||||||
|
* 单例 |
||||||
|
*/ |
||||||
|
SINGLETON; |
||||||
|
|
||||||
|
private SearchDSColumnAction instance; |
||||||
|
|
||||||
|
SearchDSColumnActionEnum() { |
||||||
|
instance = new SearchDSColumnAction(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取对象 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public SearchDSColumnAction getInstance() { |
||||||
|
return instance; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.design.actions.replace.info; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.info.base.ITContent; |
||||||
|
|
||||||
|
/** |
||||||
|
* 存储数据源相关的信息,后续数据源部分如果有自己额外的信息把这个当成父类进行拓展即可 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-28 |
||||||
|
*/ |
||||||
|
public class DataSourceInfo implements Info{ |
||||||
|
private ITContent content; |
||||||
|
|
||||||
|
|
||||||
|
public DataSourceInfo(ITContent content) { |
||||||
|
this.content = content; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ITContent getContent() { |
||||||
|
return content; |
||||||
|
} |
||||||
|
|
||||||
|
public void setContent(ITContent content) { |
||||||
|
this.content = content; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
package com.fr.design.actions.replace.ui; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.design.dialog.UIDialog; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
|
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.FlowLayout; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
|
||||||
|
import static com.fr.design.actions.replace.ui.ITTableEditorPane.getEditTable; |
||||||
|
|
||||||
|
/** |
||||||
|
* 合法性校验的面板 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-28 |
||||||
|
*/ |
||||||
|
public class ITCheckDialog extends UIDialog { |
||||||
|
private UITableEditorPane editorPane; |
||||||
|
private ITCheckEditor editor; |
||||||
|
private static final int DIALOG_WIDTH = 660, DIALOG_HEIGHT = 400; |
||||||
|
private static final int TABLE_WIDTH = 640, TABLE_HEIGHT = 320; |
||||||
|
private static final int LABEL_HEIGHT = 20; |
||||||
|
|
||||||
|
public ITCheckDialog() { |
||||||
|
super(ITReplaceMainDialog.getInstance()); |
||||||
|
setModal(true); |
||||||
|
setTitle(Toolkit.i18nText("Fine-Design_Replace_Check_Title")); |
||||||
|
JPanel centerPanel = new JPanel(); |
||||||
|
JPanel southPanel = new JPanel(); |
||||||
|
southPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); |
||||||
|
|
||||||
|
editor = new ITCheckEditor(); |
||||||
|
editorPane = new UITableEditorPane(editor); |
||||||
|
editor.add(ITReplaceMainDialog.getCheckValidList()); |
||||||
|
|
||||||
|
UILabel label = new UILabel("<html>" + Toolkit.i18nText("Fine-Design_Replace_Check", "<font color = 'rgb(236,124,125)'>" + ITReplaceMainDialog.contentReplaceFailedCount + "</font>")); |
||||||
|
JPanel center = new JPanel(new BorderLayout()); |
||||||
|
UIButton location = new UIButton(Toolkit.i18nText("Fine-Design_Chart_Location")); |
||||||
|
UIButton cancel = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); |
||||||
|
|
||||||
|
location.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
for (int i : ITReplaceMainDialog.getSerialNumber()) { |
||||||
|
getEditTable().addRowSelectionInterval(i, i); |
||||||
|
} |
||||||
|
ITCheckDialog.this.dispose(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
cancel.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
ITCheckDialog.this.dispose(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
editorPane.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT)); |
||||||
|
label.setPreferredSize(new Dimension(TABLE_WIDTH, LABEL_HEIGHT)); |
||||||
|
|
||||||
|
centerPanel.add(editorPane); |
||||||
|
southPanel.add(location); |
||||||
|
southPanel.add(cancel); |
||||||
|
center.add(southPanel, BorderLayout.SOUTH); |
||||||
|
center.add(label, BorderLayout.NORTH); |
||||||
|
center.add(centerPanel, BorderLayout.CENTER); |
||||||
|
center.setVisible(true); |
||||||
|
//主体部分
|
||||||
|
add(center); |
||||||
|
|
||||||
|
|
||||||
|
setSize(DIALOG_WIDTH, DIALOG_HEIGHT); |
||||||
|
setMaximumSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); |
||||||
|
setMinimumSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); |
||||||
|
|
||||||
|
setLocation(ITReplaceMainDialog.getInstance().getX() + ITReplaceMainDialog.getInstance().getWidth() / 2 - DIALOG_WIDTH / 2, ITReplaceMainDialog.getInstance().getY()); |
||||||
|
setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkValid() throws Exception { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package com.fr.design.actions.replace.ui; |
||||||
|
|
||||||
|
import com.fr.design.actions.replace.info.Info; |
||||||
|
import com.fr.design.actions.replace.info.base.ITContent; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableModelAdapter; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 合法性校验表格的Model |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-28 |
||||||
|
*/ |
||||||
|
public class ITCheckEditor extends UITableModelAdapter { |
||||||
|
|
||||||
|
public ITCheckEditor() { |
||||||
|
super(new String[]{ |
||||||
|
Toolkit.i18nText("Fine-Design_Replace_Check_Content"), |
||||||
|
Toolkit.i18nText("Fine-Design_Replace_Check_Reason") |
||||||
|
}); |
||||||
|
|
||||||
|
this.setColumnClass(new Class[]{ |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
ITContent content = (ITContent) this.getList().get(rowIndex); |
||||||
|
if (columnIndex == 0) { |
||||||
|
return content.getShowStr(); |
||||||
|
} else { |
||||||
|
return content.getCheckStr(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isCellEditable(int row, int col) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UITableEditAction[] createAction() { |
||||||
|
return new UITableEditAction[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加数据 |
||||||
|
* |
||||||
|
* @param list |
||||||
|
*/ |
||||||
|
public void add(List<? extends Info> list) { |
||||||
|
for (Info info : list) { |
||||||
|
addRow(info.getContent()); |
||||||
|
} |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.fr.design.actions.replace.utils; |
||||||
|
|
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.form.main.Form; |
||||||
|
import com.fr.form.main.WidgetGatherAdapter; |
||||||
|
import com.fr.form.ui.Widget; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.main.impl.WorkBookHelper; |
||||||
|
import com.fr.stable.Filter; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.js.WidgetName; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用于合法性检验相关的工具类 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @version 11.0 |
||||||
|
* created by Destiny.Lin on 2022-10-31 |
||||||
|
*/ |
||||||
|
public class CheckUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取需要检测的控件名称 |
||||||
|
* |
||||||
|
* @param jTemplate 模板 |
||||||
|
* @return 控件名称列表 |
||||||
|
*/ |
||||||
|
public static List<WidgetName> getNeed2CheckWidgetsName(JTemplate<?, ?> jTemplate) { |
||||||
|
if (jTemplate.getTarget() instanceof WorkBook) { |
||||||
|
return getWorkBookNeedWidgetsName((WorkBook) jTemplate.getTarget()); |
||||||
|
} else if (jTemplate.getTarget() instanceof Form) { |
||||||
|
return getFormNeedWidgetsName((Form) jTemplate.getTarget()); |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
private static List<WidgetName> getFormNeedWidgetsName(Form target) { |
||||||
|
final List<WidgetName> list = new ArrayList<WidgetName>(); |
||||||
|
Form.traversalFormWidget(target.getContainer(), new WidgetGatherAdapter() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void dealWith(Widget widget) { |
||||||
|
if (widgetAccepted(widget)) { |
||||||
|
list.add(new WidgetName(widget.getWidgetName())); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean dealWithAllCards() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
}); |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<WidgetName> getWorkBookNeedWidgetsName(WorkBook wb) { |
||||||
|
return WorkBookHelper.listWidgetNamesInWorkBook(wb, new Filter<Widget>() { |
||||||
|
@Override |
||||||
|
public boolean accept(Widget widget) { |
||||||
|
return widgetAccepted(widget); |
||||||
|
} |
||||||
|
}, new Filter<Widget>() { |
||||||
|
@Override |
||||||
|
public boolean accept(Widget widget) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static boolean widgetAccepted(Widget widget) { |
||||||
|
return widget != null && StringUtils.isNotEmpty(widget.getWidgetName()); |
||||||
|
} |
||||||
|
} |