Browse Source
Merge in DESIGN/design from ~YVAN/design:feature/x to feature/x * commit '10bcd9acdece78afedb635299765b7a4c2bd02b8': REPORT-75091 - 数据脱敏(报表) 代码质量相关 REPORT-75091 - 数据脱敏(报表) 【问题原因】rt 【改动思路】详见开发文档:https://kms.fineres.com/pages/viewpage.action?pageId=504469104 【review建议】提交晚是因为虽然任务是一期,但是放到二期发布,需要在合并release/11.0后才提交featurefeature/x
Yvan-欧阳帆
2 years ago
21 changed files with 2175 additions and 89 deletions
@ -0,0 +1,182 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.data.desensitize.base.AbstractDesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationBean; |
||||||
|
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.design.data.tabledata.wrapper.TableDataWrapper; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
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 AbstractDesensitizationTableData && |
||||||
|
DesentizationUtils.isCollectionNotEmpty(((AbstractDesensitizationTableData) tableData).getDesensitizationBeans()) && |
||||||
|
((AbstractDesensitizationTableData) tableData).getDesensitizationBeans().stream().noneMatch(TableDataDesensitizationBean::invalid); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据集预览脱敏,使用DesensitizedPreviewTableModel对当前的预览TableModel做包装 |
||||||
|
* |
||||||
|
* @param model |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public PreviewTableModel desensitizeTableModel(TableData tableData, PreviewTableModel model) { |
||||||
|
if (needDesensitize(tableData)) { |
||||||
|
Map<Integer, TableDataDesensitizationBean> desensitizationBeanMap = new LinkedHashMap<>(); |
||||||
|
// 获取此数据集的所有脱敏信息
|
||||||
|
Collection<TableDataDesensitizationBean> desensitizationBeans = ((AbstractDesensitizationTableData) tableData).getDesensitizationBeans(); |
||||||
|
// 排个序
|
||||||
|
List<TableDataDesensitizationBean> sortedBeans = desensitizationBeans.stream().sorted(Comparator.comparingInt(TableDataDesensitizationBean::getColumnIndex)).collect(Collectors.toList()); |
||||||
|
int columnIndex = 0; |
||||||
|
for (TableDataDesensitizationBean sortedBean : sortedBeans) { |
||||||
|
// 当map中已包含列序号时,代表对这一列设置了不同的脱敏规则,将key + 1
|
||||||
|
if (desensitizationBeanMap.containsKey(columnIndex)) { |
||||||
|
columnIndex++; |
||||||
|
} |
||||||
|
desensitizationBeanMap.put(columnIndex, sortedBean); |
||||||
|
} |
||||||
|
// 包装TableModel
|
||||||
|
return new DesensitizedPreviewTableModel(model, desensitizationBeanMap); |
||||||
|
} |
||||||
|
return model; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过TableData获取其列名 |
||||||
|
* 实现逻辑有点绕,TableData本身并不能返回列名集合,只能先去获取当前模板所有数据集,然后匹配名称拿到TableDataWrapper再获取列名 |
||||||
|
* @param tableData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<String> getColumnNamesByTableData(TableData tableData) { |
||||||
|
List<Map<String, TableDataWrapper>> editingDataSet = DesignTableDataManager.getEditingDataSet(DesignTableDataManager.getEditingTableDataSource()); |
||||||
|
// 当前所有模板数据集Wrapper,不包括存储过程
|
||||||
|
Map<String, TableDataWrapper> templeteDataMap = editingDataSet.get(0); |
||||||
|
// 当前所有模板数据集Wrapper,包括存储过程
|
||||||
|
Map<String, TableDataWrapper> dataWrapperMap = DesignTableDataManager.getAllDataSetIncludingProcedure(templeteDataMap); |
||||||
|
// 找到匹配当前数据集名称的Wrapper
|
||||||
|
TableDataWrapper tableDataWrapper = dataWrapperMap.get(tableData.getName()); |
||||||
|
return tableDataWrapper == null ? |
||||||
|
new ArrayList<>() : |
||||||
|
tableDataWrapper.calculateColumnNameList(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 这个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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.model; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationBean; |
||||||
|
import com.fr.data.desensitize.calculate.DesensitizationCalculator; |
||||||
|
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||||
|
import com.fr.design.data.datapane.preview.PreviewTableModel; |
||||||
|
|
||||||
|
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, TableDataDesensitizationBean> desensitizationBeanMap; |
||||||
|
|
||||||
|
private boolean needDesensitize = false; |
||||||
|
|
||||||
|
public DesensitizedPreviewTableModel(PreviewTableModel previewTableModel, Map<Integer, TableDataDesensitizationBean> desensitizationBeanMap) { |
||||||
|
this.previewTableModel = previewTableModel; |
||||||
|
this.desensitizationBeanMap = desensitizationBeanMap; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getColumnName(int column) { |
||||||
|
int originIndex = needDesensitize && Objects.nonNull(desensitizationBeanMap.get(column)) ? |
||||||
|
desensitizationBeanMap.get(column).getColumnIndex() : column; |
||||||
|
return previewTableModel.getColumnName(originIndex); |
||||||
|
} |
||||||
|
|
||||||
|
@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(desensitizationBeanMap.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 = desensitizationBeanMap.get(columnIndex).getColumnIndex(); |
||||||
|
// 获取原值
|
||||||
|
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) { |
||||||
|
TableDataDesensitizationBean desensitizationBean = desensitizationBeanMap.get(columnIndex); |
||||||
|
DesensitizationRule desensitizationRule = desensitizationBean.getDesensitizationRule(); |
||||||
|
return DesensitizationCalculator.getInstance().desensitize(strValue, desensitizationRule); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前有效的脱敏字段个数 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public int getDesensitizeColumnsCount() { |
||||||
|
return desensitizationBeanMap.size(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 切换脱敏状态 |
||||||
|
*/ |
||||||
|
public void toggleNeedDesensite() { |
||||||
|
this.needDesensitize = !needDesensitize; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,312 @@ |
|||||||
|
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(); |
||||||
|
DesensitizationRuleDebugPane ruleDebugPane = new DesensitizationRuleDebugPane(selectedRule); |
||||||
|
BasicDialog ruleDebugDialog = ruleDebugPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), null, BasicDialog.DEFAULT); |
||||||
|
ruleDebugDialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,127 @@ |
|||||||
|
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().getTypeName()); |
||||||
|
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,296 @@ |
|||||||
|
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.getTypeName()); |
||||||
|
ruleConditionPane.add(characterAllReplacePane, DesensitizationRuleType.ALL_CHARACTERS_REPLACE.getTypeName()); |
||||||
|
// 初始化状态为字符替换
|
||||||
|
switchRuleConditionPane(DesensitizationRuleType.CHARACTER_REPLACE); |
||||||
|
|
||||||
|
panel.add(ruleConditionPane, BorderLayout.CENTER); |
||||||
|
return panel; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 切换规则类型面板 |
||||||
|
* @param ruleType |
||||||
|
*/ |
||||||
|
private void switchRuleConditionPane(DesensitizationRuleType ruleType) { |
||||||
|
this.cardLayout.show(ruleConditionPane, ruleType.getTypeName()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化规则类型下拉框 |
||||||
|
*/ |
||||||
|
private void initRuleTypeComboBox() { |
||||||
|
ruleTypeComboBox = new UIComboBox(Arrays.stream(DesensitizationRuleType.values()).map(DesensitizationRuleType::getTypeName).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().getTypeName(); |
||||||
|
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,80 @@ |
|||||||
|
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,48 @@ |
|||||||
|
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,110 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.AbstractDesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationBean; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
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 javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
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<AbstractDesensitizationTableData> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置针对的数据集 |
||||||
|
*/ |
||||||
|
private AbstractDesensitizationTableData tableData; |
||||||
|
|
||||||
|
private UICheckBox desensitizeOpen; |
||||||
|
|
||||||
|
private TableDataDesensitizationTablePane tableDataDesensitizationTablePane; |
||||||
|
|
||||||
|
|
||||||
|
public TableDataDesensitizationSettingPane(AbstractDesensitizationTableData 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() { |
||||||
|
JPanel northPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Desensitization_Config")); |
||||||
|
this.desensitizeOpen = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Desensitization_Opened")); |
||||||
|
northPane.add(desensitizeOpen); |
||||||
|
UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Opened_Tooltips")); |
||||||
|
tipLabel.setForeground(UIConstants.CHECK_BOX_TIP_FONT_COLOR); |
||||||
|
northPane.add(tipLabel); |
||||||
|
return northPane; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化数据脱敏规则表面板 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private JComponent initCenterPane() { |
||||||
|
this.tableDataDesensitizationTablePane = new TableDataDesensitizationTablePane(tableData, this); |
||||||
|
return tableDataDesensitizationTablePane; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否启用脱敏 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean isDesensitizeOpened() { |
||||||
|
return desensitizeOpen.isSelected(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Desensitization_Config"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(AbstractDesensitizationTableData tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
this.desensitizeOpen.setSelected(tableData.getDesensitizeOpen()); |
||||||
|
tableDataDesensitizationTablePane.populateDesensitizationSetting(tableData); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public AbstractDesensitizationTableData updateBean() { |
||||||
|
saveDesensitizeOpened(); |
||||||
|
saveDesensitizationBeans(tableDataDesensitizationTablePane.updateDesensitizationSetting()); |
||||||
|
return tableData; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存脱敏启用状态 |
||||||
|
*/ |
||||||
|
public void saveDesensitizeOpened() { |
||||||
|
tableData.setDesensitizeOpen(desensitizeOpen.isSelected()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存脱敏规则配置信息 |
||||||
|
* @param tableDataDesensitizationBeans |
||||||
|
*/ |
||||||
|
public void saveDesensitizationBeans(List<TableDataDesensitizationBean> tableDataDesensitizationBeans) { |
||||||
|
tableData.setDesensitizationBeans(tableDataDesensitizationBeans); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,459 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.AbstractDesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationBean; |
||||||
|
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 com.fr.stable.collections.CollectionUtils; |
||||||
|
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.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<TableDataDesensitizationBean> { |
||||||
|
|
||||||
|
private static final String APOSTROPHE = "..."; |
||||||
|
|
||||||
|
private AbstractDesensitizationTableData tableData; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前数据集的所有列名 |
||||||
|
*/ |
||||||
|
private List<String> columnNames; |
||||||
|
|
||||||
|
/** |
||||||
|
* key为用户组唯一标识(id拼接),value为用户组名称 |
||||||
|
*/ |
||||||
|
private Map<String, String> roleMap; |
||||||
|
|
||||||
|
private Component parent; |
||||||
|
|
||||||
|
private DesensitizationRuleChooser ruleChooser; |
||||||
|
|
||||||
|
private DesensitizationRuleDescriptionPane descriptionPane; |
||||||
|
|
||||||
|
public TableDataDesensitizationTableModel(AbstractDesensitizationTableData 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) { |
||||||
|
TableDataDesensitizationBean desensitizationBean = this.getList().get(rowIndex); |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
return getColumnNameValue(desensitizationBean); |
||||||
|
case 1: |
||||||
|
return desensitizationBean.getDesensitizationRule().getRuleName(); |
||||||
|
case 2: |
||||||
|
return DesensitizationRule.getDescription(desensitizationBean.getDesensitizationRule()); |
||||||
|
case 3: |
||||||
|
return matchRoleNamesByIds(desensitizationBean.getRoleIds()); |
||||||
|
default: |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据当前选中的Bean,获取其对应的列名字段 |
||||||
|
* @param desensitizationBean |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Object getColumnNameValue(TableDataDesensitizationBean desensitizationBean) { |
||||||
|
// 内部列名list为空时直接返回空字符串
|
||||||
|
if (CollectionUtils.isEmpty(columnNames)) { |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
// bean的列字段index不对劲时,返回空字符串
|
||||||
|
return validColumnIndex(desensitizationBean.getColumnIndex()) ? |
||||||
|
columnNames.get(desensitizationBean.getColumnIndex()) : |
||||||
|
StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断字段索引是否越界 |
||||||
|
* @param columnIndex |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private boolean validColumnIndex(int columnIndex) { |
||||||
|
return columnIndex >= 0 && columnIndex < columnNames.size(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过id匹配此用户组对应的部门职位名称(或者说自定义角色名称) |
||||||
|
* |
||||||
|
* @param roleIds |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private List<String> matchRoleNamesByIds(Set<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 TableDataDesensitizationBean 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) { |
||||||
|
|
||||||
|
TableDataDesensitizationBean desensitizationBean = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationBean)) { |
||||||
|
desensitizationBean.setColumnIndex(columnNameComboBox.getSelectedIndex()); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void editingCanceled(ChangeEvent e) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
columnNameComboBox.setSelectedIndex(getList().get(row).getColumnIndex()); |
||||||
|
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.setSelectedIndex(getList().get(row).getColumnIndex()); |
||||||
|
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(); |
||||||
|
TableDataDesensitizationBean desensitizationBean = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationBean) && Objects.nonNull(rule)) { |
||||||
|
desensitizationBean.setDesensitizationRule(rule); |
||||||
|
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) { |
||||||
|
TableDataDesensitizationBean desensitizationBean = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationBean) && Objects.nonNull(rule)) { |
||||||
|
desensitizationBean.setDesensitizationRule(rule); |
||||||
|
fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||||
|
ruleNameTextField.setText(getList().get(row).getDesensitizationRule().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).getDesensitizationRule()); |
||||||
|
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) { |
||||||
|
TableDataDesensitizationBean desensitizationBean = getCurrentSelectBean(); |
||||||
|
if (Objects.nonNull(desensitizationBean)) { |
||||||
|
desensitizationBean.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 desensitizationBean |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Map<Object, Boolean> generateRolesCheckBoxSelectedValues(TableDataDesensitizationBean desensitizationBean) { |
||||||
|
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 (desensitizationBean.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(TableDataDesensitizationBean.createEmyptBean()); |
||||||
|
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,64 @@ |
|||||||
|
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||||
|
|
||||||
|
import com.fr.data.desensitize.base.AbstractDesensitizationTableData; |
||||||
|
import com.fr.data.desensitize.base.TableDataDesensitizationBean; |
||||||
|
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 AbstractDesensitizationTableData tableData; |
||||||
|
|
||||||
|
/** |
||||||
|
* 父页面 |
||||||
|
*/ |
||||||
|
private Component parent; |
||||||
|
|
||||||
|
/** |
||||||
|
* 脱敏信息Table |
||||||
|
*/ |
||||||
|
private UITableEditorPane<TableDataDesensitizationBean> editorPane; |
||||||
|
|
||||||
|
public TableDataDesensitizationTablePane(AbstractDesensitizationTableData 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(AbstractDesensitizationTableData tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
editorPane.populate(tableData.getDesensitizationBeans().toArray(new TableDataDesensitizationBean[0])); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前对TableData的配置脱敏规则信息 |
||||||
|
*/ |
||||||
|
public List<TableDataDesensitizationBean> updateDesensitizationSetting() { |
||||||
|
return editorPane.update(); |
||||||
|
} |
||||||
|
} |
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 |
Loading…
Reference in new issue