Maximus
2 years ago
329 changed files with 14618 additions and 3280 deletions
@ -0,0 +1,19 @@
|
||||
package com.fr.design.actions.help.replace; |
||||
|
||||
|
||||
/** |
||||
* 定义一些底层操作 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @version 11.0 |
||||
* created by Destiny.Lin on 2022-09-27 |
||||
*/ |
||||
public interface ITReplaceOperator { |
||||
|
||||
|
||||
/** |
||||
* 关闭面板 |
||||
*/ |
||||
void close(); |
||||
|
||||
} |
@ -0,0 +1,136 @@
|
||||
package com.fr.design.data.datapane.preview.desensitization; |
||||
|
||||
|
||||
import com.fr.base.TableData; |
||||
import com.fr.data.TableDataSource; |
||||
import com.fr.data.desensitize.TableDataDesensitizeManager; |
||||
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.esd.query.StrategicTableData; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
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)) { |
||||
// 更新规则
|
||||
desensitizationItems = TableDataDesensitizeManager.getInstance().dealWithlatestRules(desensitizationItems); |
||||
// 对脱敏配置项集合做过滤和排序处理
|
||||
List<TableDataDesensitizationItem> items = desensitizationItems.stream() |
||||
.filter(item -> isAvaliableItem4Preview(item, model)) |
||||
.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); |
||||
} |
||||
|
||||
/** |
||||
* 判断是否为有效的用于预览脱敏效果的DesensitizationItem |
||||
* |
||||
* @param item 脱敏配置项 |
||||
* @param model 数据集预览数据 |
||||
* @return |
||||
*/ |
||||
private boolean isAvaliableItem4Preview(TableDataDesensitizationItem item, PreviewTableModel model) { |
||||
return item.getRule().isEnable() && |
||||
matchColumnIndex(item, model) >= 0; |
||||
} |
||||
|
||||
/** |
||||
* 通过TableData获取其列名,理论上一定存在缓存值 |
||||
* |
||||
* @param tableData |
||||
* @return |
||||
*/ |
||||
public List<String> getColumnNamesByTableData(TableData tableData) { |
||||
TableDataSource editingTableDataSource = DesignTableDataManager.getEditingTableDataSource(); |
||||
if (editingTableDataSource != null && tableData instanceof StrategicTableData) { |
||||
return Arrays.asList(DesignTableDataManager.getSelectedColumnNames(editingTableDataSource, ((StrategicTableData) tableData).getDsName())); |
||||
} |
||||
return Collections.EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* 根据列名,从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,133 @@
|
||||
package com.fr.design.data.datapane.preview.desensitization.view; |
||||
|
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.data.datapane.preview.PreviewTablePane; |
||||
import com.fr.design.gui.ibutton.UIToggleButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.itoolbar.UIToolbar; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.menu.SeparatorDef; |
||||
import com.fr.design.menu.ToolBarDef; |
||||
|
||||
import javax.swing.Icon; |
||||
import javax.swing.JPanel; |
||||
import java.awt.Component; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
/** |
||||
* 数据集预览-脱敏配置面板,主要展示当前脱敏开启状态、当前脱敏设定数量等 |
||||
* |
||||
* @author Yvan |
||||
* @version 11.0 |
||||
* Created by Yvan on 2022/11/14 |
||||
*/ |
||||
public class PreviewTableDesensitizationPane extends JPanel { |
||||
|
||||
private static final String DATA_DESENSITIZATION_CONFIG = Toolkit.i18nText("Fine-Design_Report_Desensitization_Config"); |
||||
private static final String LEFT_BRACKET = "("; |
||||
private static final String RIGHT_BRACKET = ")"; |
||||
private static final String COUNT = Toolkit.i18nText("Fine-Design_Report_Desensitization_Count"); |
||||
|
||||
/** |
||||
* 预览面板 |
||||
*/ |
||||
private PreviewTablePane previewTablePane; |
||||
|
||||
/** |
||||
* "数据脱敏设置"-标签 |
||||
*/ |
||||
private UILabel desensitizationLabel; |
||||
|
||||
/** |
||||
* 脱敏效果预览按钮 |
||||
*/ |
||||
private UIToggleButton previewToggle; |
||||
|
||||
|
||||
public PreviewTableDesensitizationPane(PreviewTablePane previewTablePane) { |
||||
this.previewTablePane = previewTablePane; |
||||
initComponents(); |
||||
} |
||||
|
||||
/** |
||||
* 初始化面板 |
||||
*/ |
||||
private void initComponents() { |
||||
this.setLayout(new FlowLayout(FlowLayout.LEFT)); |
||||
this.add(initDesensitizationLabel()); |
||||
this.add(initToolBar()); |
||||
this.add(initPreviewButton()); |
||||
} |
||||
|
||||
/** |
||||
* 初始化Label |
||||
* |
||||
* @return |
||||
*/ |
||||
private Component initDesensitizationLabel() { |
||||
// 初始化Label
|
||||
desensitizationLabel = new UILabel(DATA_DESENSITIZATION_CONFIG); |
||||
desensitizationLabel.setForeground(UIConstants.NORMAL_BLUE); |
||||
desensitizationLabel.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
previewTablePane.clickDesensitizationLabel(); |
||||
} |
||||
}); |
||||
return desensitizationLabel; |
||||
} |
||||
|
||||
/** |
||||
* 初始化分隔符 |
||||
* |
||||
* @return |
||||
*/ |
||||
private UIToolbar initToolBar() { |
||||
ToolBarDef toolbarDef = new ToolBarDef(); |
||||
toolbarDef.addShortCut(SeparatorDef.DEFAULT); |
||||
UIToolbar toolBar = ToolBarDef.createJToolBar(); |
||||
toolBar.setBorderPainted(false); |
||||
toolbarDef.updateToolBar(toolBar); |
||||
return toolBar; |
||||
} |
||||
|
||||
/** |
||||
* 初始化脱敏效果预览按钮 |
||||
* |
||||
* @return |
||||
*/ |
||||
private UIToggleButton initPreviewButton() { |
||||
previewToggle = new UIToggleButton(new Icon[]{IconUtils.readIcon("/com/fr/design/images/m_file/preview"), IconUtils.readIcon("/com/fr/design/images/m_file/preview")}, true); |
||||
previewToggle.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Preview")); |
||||
previewToggle.setSelected(false); |
||||
previewToggle.addActionListener(e -> { |
||||
// 切换TableModel的脱敏状态
|
||||
previewTablePane.togglePreviewTableModelDesensitizeStatus(); |
||||
// 刷新预览页面,展示
|
||||
previewTablePane.refreshTable(); |
||||
}); |
||||
return previewToggle; |
||||
} |
||||
|
||||
/** |
||||
* 设置Label的值,主要是需要动态修改配置的脱敏规则的数量 |
||||
* |
||||
* @param desensitizeOpen |
||||
* @param count |
||||
*/ |
||||
public void setDesensitizationCount(boolean desensitizeOpen, int count) { |
||||
desensitizationLabel.setText(desensitizeOpen ? |
||||
DATA_DESENSITIZATION_CONFIG + LEFT_BRACKET + count + RIGHT_BRACKET + COUNT : |
||||
DATA_DESENSITIZATION_CONFIG); |
||||
} |
||||
|
||||
/** |
||||
* 服务器数据集时,Label需要置灰 |
||||
*/ |
||||
public void dealWithTableDataType(boolean globalTableData) { |
||||
desensitizationLabel.setForeground(globalTableData ? UIConstants.DISABLED_ICON_COLOR : UIConstants.NORMAL_BLUE); |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.fr.design.data.datapane.preview.desensitization.view.common; |
||||
|
||||
import com.fr.design.gui.ibutton.UIRadioButton; |
||||
|
||||
import javax.swing.AbstractCellEditor; |
||||
import javax.swing.JTable; |
||||
import javax.swing.table.TableCellEditor; |
||||
import javax.swing.table.TableCellRenderer; |
||||
import java.awt.Component; |
||||
|
||||
/** |
||||
* 标记选中的CellEditor |
||||
* |
||||
* @author Yvan |
||||
* @version 11.0 |
||||
* Created by Yvan on 2022/12/20 |
||||
*/ |
||||
public class ChooseMark extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||
|
||||
private final UIRadioButton selectedButton; |
||||
|
||||
public ChooseMark() { |
||||
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; |
||||
} |
||||
} |
@ -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,364 @@
|
||||
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.data.desensitize.rule.base.DesensitizationRuleStatus; |
||||
import com.fr.design.data.datapane.preview.desensitization.view.common.ChooseMark; |
||||
import com.fr.design.dialog.BasicDialog; |
||||
import com.fr.design.dialog.DialogActionAdapter; |
||||
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.Color; |
||||
import java.awt.Component; |
||||
import java.awt.event.ActionEvent; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
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; |
||||
|
||||
private Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules; |
||||
|
||||
public DesensitizationRuleChoosePane(Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) { |
||||
this.latestRules = latestRules; |
||||
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(latestRules.get(DesensitizationRuleSource.SERVER).values().toArray(new DesensitizationRule[0])); |
||||
customRuleEditPane.populate(latestRules.get(DesensitizationRuleSource.CUSTOM).values().toArray(new DesensitizationRule[0])); |
||||
} |
||||
|
||||
/** |
||||
* 获取当前选中的规则 |
||||
* |
||||
* @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"), |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status"), |
||||
}); |
||||
this.parent = parent; |
||||
this.debugActionOnly = debugActionOnly; |
||||
this.setColumnClass(new Class[]{ |
||||
ChooseMark.class, |
||||
UILabel.class, |
||||
UILabel.class, |
||||
DesensitizationRuleStatusPane.class |
||||
}); |
||||
this.setDefaultEditor(ChooseMark.class, new ChooseMark()); |
||||
this.setDefaultRenderer(ChooseMark.class, new ChooseMark()); |
||||
this.setDefaultEditor(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); |
||||
this.setDefaultRenderer(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); |
||||
this.createTable().getColumnModel().getColumn(0).setMaxWidth(20); |
||||
this.createTable().getColumnModel().getColumn(3).setMaxWidth(60); |
||||
} |
||||
|
||||
@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); |
||||
case 3: |
||||
// 脱敏规则状态
|
||||
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules); |
||||
// 非正常状态需要标记为异常
|
||||
return ruleStatus == DesensitizationRuleStatus.NORMAL ? StringUtils.EMPTY : Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal"); |
||||
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 DesensitizationRuleStatusPane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||
|
||||
private UILabel ruleStatusLabel; |
||||
|
||||
DesensitizationRuleStatusPane() { |
||||
// 规则状态
|
||||
this.ruleStatusLabel = new UILabel(); |
||||
this.ruleStatusLabel.setForeground(Color.RED); |
||||
} |
||||
|
||||
/** |
||||
* 根据脱敏规则信息,刷新规则状态,主要用于与规则选择器的联动 |
||||
* |
||||
* @param rule |
||||
*/ |
||||
public void refreshRuleStatus(DesensitizationRule rule) { |
||||
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules); |
||||
if (ruleStatus == DesensitizationRuleStatus.NORMAL) { |
||||
// 正常规则时,重置提示Label
|
||||
this.ruleStatusLabel.setText(StringUtils.EMPTY); |
||||
this.ruleStatusLabel.setToolTipText(null); |
||||
} else { |
||||
this.ruleStatusLabel.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal")); |
||||
this.ruleStatusLabel.setToolTipText(ruleStatus.getDescription()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||
refreshRuleStatus(getList().get(row)); |
||||
return ruleStatusLabel; |
||||
} |
||||
|
||||
@Override |
||||
public Object getCellEditorValue() { |
||||
return ruleStatusLabel; |
||||
} |
||||
|
||||
@Override |
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||
refreshRuleStatus(getList().get(row)); |
||||
return ruleStatusLabel; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 添加规则 |
||||
*/ |
||||
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 = null; |
||||
try { |
||||
selectedValue = (DesensitizationRule) getSelectedValue().clone(); |
||||
} catch (CloneNotSupportedException ex) { |
||||
throw new RuntimeException(ex); |
||||
} |
||||
DesensitizationRuleEditPane editPane = new DesensitizationRuleEditPane(getCurrentExistRuleNames(selectedValue.getRuleName())); |
||||
editPane.populateBean(selectedValue); |
||||
final DesensitizationRule finalRule = 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(finalRule, rule); |
||||
} |
||||
setSelectedValue(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 && getList().get(table.getSelectedRow()).isEnable()); |
||||
} |
||||
|
||||
@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,309 @@
|
||||
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.DesensitizationRuleSource; |
||||
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_Part_One") + StringUtils.BLANK); |
||||
retainFrontTextField = new UINumberField(5); |
||||
retainFrontTextField.addFocusListener(retainFrontListener); |
||||
|
||||
UILabel retainBackLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Two") + StringUtils.BLANK); |
||||
retainBackTextField = new UINumberField(5); |
||||
retainBackTextField.addFocusListener(retainBackListener); |
||||
|
||||
UILabel replaceLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Three") + 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.setRuleName(this.ruleNameTextField.getText()); |
||||
rule.setRuleSource(DesensitizationRuleSource.CUSTOM); |
||||
DesensitizationRuleType ruleType = DesensitizationRuleType.matchByTypeName(String.valueOf(this.ruleTypeComboBox.getSelectedItem())); |
||||
rule.setRuleType(ruleType); |
||||
rule.getCondition().setRetainFront((int) this.retainFrontTextField.getValue()); |
||||
rule.getCondition().setRetainBack((int) this.retainBackTextField.getValue()); |
||||
rule.getCondition().setSymbol(ruleType == DesensitizationRuleType.CHARACTER_REPLACE ? |
||||
this.firstSymbolTextField.getText() : |
||||
this.secondSymbolTextField.getText()); |
||||
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,89 @@
|
||||
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; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 脱敏规则展示页 |
||||
* |
||||
* @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 Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules; |
||||
|
||||
/** |
||||
* 内容面板 |
||||
*/ |
||||
private JPanel contentPane; |
||||
|
||||
public DesensitizationRulePane(Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) { |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.latestRules = latestRules; |
||||
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(latestRules); |
||||
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,619 @@
|
||||
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.DesensitizationRuleManager; |
||||
import com.fr.data.desensitize.rule.base.DesensitizationRule; |
||||
import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; |
||||
import com.fr.data.desensitize.rule.base.DesensitizationRuleStatus; |
||||
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.FRGUIPaneFactory; |
||||
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.JComponent; |
||||
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.BorderLayout; |
||||
import java.awt.Color; |
||||
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.Iterator; |
||||
import java.util.LinkedHashMap; |
||||
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 static final String COMMA = ","; |
||||
|
||||
/** |
||||
* 当前数据集的所有列名 |
||||
*/ |
||||
private List<String> columnNames = new ArrayList<>(); |
||||
|
||||
/** |
||||
* key为用户组唯一标识(id拼接),value为用户组名称 |
||||
*/ |
||||
private Map<String, String> roleMap = new LinkedHashMap<>(); |
||||
|
||||
/** |
||||
* 当前最新的所有规则 |
||||
*/ |
||||
private Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules = new LinkedHashMap<>(); |
||||
|
||||
private Component parent; |
||||
|
||||
public TableDataDesensitizationTableModel(DesensitizationTableData tableData, Component parent, List<String> columnNames, Map<String, String> roleMap, Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) { |
||||
// table相关
|
||||
super(new String[]{ |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Column"), |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule"), |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description"), |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Effected_Roles"), |
||||
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status"), |
||||
}); |
||||
this.parent = parent; |
||||
this.columnNames = columnNames; |
||||
this.roleMap = roleMap; |
||||
this.latestRules = latestRules; |
||||
|
||||
initTable(); |
||||
} |
||||
|
||||
/** |
||||
* 初始化Table |
||||
*/ |
||||
private void initTable() { |
||||
this.setColumnClass(new Class[]{ |
||||
// 列名选择
|
||||
ColumnNamesComboBox.class, |
||||
// 规则选择
|
||||
DesensitizationRuleChooser.class, |
||||
// 规则详情展示
|
||||
DesensitizationRuleDescriptionPane.class, |
||||
// 生效用户组选择
|
||||
EffectedRolesChooser.class, |
||||
// 规则状态
|
||||
DesensitizationRuleStatusPane.class |
||||
}); |
||||
ColumnNamesComboBox columnNamesComboBox = new ColumnNamesComboBox(); |
||||
this.setDefaultEditor(ColumnNamesComboBox.class, columnNamesComboBox); |
||||
this.setDefaultEditor(DesensitizationRuleChooser.class, new DesensitizationRuleChooser()); |
||||
this.setDefaultEditor(DesensitizationRuleDescriptionPane.class, new DesensitizationRuleDescriptionPane()); |
||||
EffectedRolesChooser effectedRolesChooser = new EffectedRolesChooser(); |
||||
this.setDefaultEditor(EffectedRolesChooser.class, effectedRolesChooser); |
||||
this.setDefaultEditor(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); |
||||
this.setDefaultRenderer(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); |
||||
|
||||
this.createTable().getColumnModel().getColumn(TableSequences.DesensitizationRuleStatus.getNum()).setMaxWidth(60); |
||||
} |
||||
|
||||
@Override |
||||
public Object getValueAt(int rowIndex, int columnIndex) { |
||||
TableDataDesensitizationItem desensitizationItem = this.getList().get(rowIndex); |
||||
TableSequences match = TableSequences.match(columnIndex); |
||||
switch (match) { |
||||
case ColumnName: |
||||
// 选中的数据集字段名称
|
||||
return desensitizationItem.getColumnName(); |
||||
case DesensitizationRule: |
||||
// 脱敏规则名称
|
||||
return desensitizationItem.getRule().getRuleName(); |
||||
case DesensitizationRuleDescription: |
||||
// 脱敏规则详情
|
||||
return DesensitizationRule.getDescription(desensitizationItem.getRule()); |
||||
case EffectedRoles: |
||||
// 生效用户组
|
||||
return matchRoleNamesByIds(desensitizationItem.getRoleIds()); |
||||
case DesensitizationRuleStatus: |
||||
// 规则状态
|
||||
return needMarkRule(desensitizationItem.getRule()) ? StringUtils.EMPTY : Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal"); |
||||
default: |
||||
return StringUtils.EMPTY; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 通过id匹配此用户组对应的部门职位名称(或者说自定义角色名称),并拼接成字符串返回 |
||||
* |
||||
* @param roleIds |
||||
* @return |
||||
*/ |
||||
private String matchRoleNamesByIds(Collection<String> roleIds) { |
||||
StringBuilder builder = new StringBuilder(); |
||||
for (String roleId : roleIds) { |
||||
if (roleMap != null && roleMap.containsKey(roleId)) { |
||||
builder.append(roleMap.get(roleId)); |
||||
builder.append(COMMA); |
||||
} |
||||
} |
||||
return builder.length() <= 1 ? StringUtils.EMPTY : builder.substring(0, builder.length() - 1); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isCellEditable(int row, int col) { |
||||
TableSequences match = TableSequences.match(col); |
||||
return match != TableSequences.DesensitizationRuleStatus; |
||||
} |
||||
|
||||
@Override |
||||
public UITableEditAction[] createAction() { |
||||
return new UITableEditAction[]{ |
||||
new AddDesensitizationAction(), |
||||
new RemoveDesensitizationAction(parent), |
||||
new RefreshTableAction(), |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 获取当前选中的item,可能为null |
||||
* |
||||
* @return |
||||
*/ |
||||
@Nullable |
||||
private TableDataDesensitizationItem getCurrentSelectBean() { |
||||
return table.getSelectedRow() == -1 ? |
||||
null : |
||||
getList().get(table.getSelectedRow()); |
||||
} |
||||
|
||||
/** |
||||
* 列名选择下拉框 |
||||
*/ |
||||
private class ColumnNamesComboBox extends AbstractCellEditor implements TableCellEditor { |
||||
|
||||
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(); |
||||
} |
||||
} |
||||
|
||||
private class DesensitizationRuleChooser extends AbstractCellEditor implements TableCellEditor { |
||||
/** |
||||
* 规则选择页面 |
||||
*/ |
||||
private JPanel choosePane; |
||||
/** |
||||
* 规则名称 |
||||
*/ |
||||
private UITextField ruleNameTextField; |
||||
/** |
||||
* 规则选择按钮 |
||||
*/ |
||||
private UIButton chooseButton; |
||||
|
||||
private ActionListener chooseRuleListener = new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
// 重新获取一下本地规则缓存
|
||||
refreshCustomRuleCache(); |
||||
DesensitizationRulePane rulePane = new DesensitizationRulePane(latestRules); |
||||
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean(); |
||||
int selectedRow = table.getSelectedRow(); |
||||
BasicDialog ruleDialog = rulePane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() { |
||||
@Override |
||||
public void doOk() { |
||||
DesensitizationRule rule = rulePane.updateBean(); |
||||
if (Objects.nonNull(desensitizationItem) && DesensitizationRule.valid(rule)) { |
||||
desensitizationItem.setRule(rule); |
||||
desensitizationItem.setRuleName(rule.getRuleName()); |
||||
// 刷新规则名称、描述、状态
|
||||
ruleNameTextField.setText(rule.getRuleName()); |
||||
fireTableDataChanged(); |
||||
table.getSelectionModel().setSelectionInterval(selectedRow, selectedRow); |
||||
} |
||||
} |
||||
}, BasicDialog.DEFAULT); |
||||
ruleDialog.setVisible(true); |
||||
} |
||||
}; |
||||
|
||||
DesensitizationRuleChooser() { |
||||
// 规则名称展示
|
||||
ruleNameTextField = new UITextField(); |
||||
ruleNameTextField.setEnabled(false); |
||||
// 规则选择按钮
|
||||
chooseButton = new UIButton(APOSTROPHE); |
||||
chooseButton.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Click_To_Choose_Rule")); |
||||
chooseButton.addActionListener(chooseRuleListener); |
||||
// 规则选择页面
|
||||
Component[][] templateChooserComponent = {{ruleNameTextField, chooseButton}}; |
||||
double[] rowSize = {TableLayout.PREFERRED}; |
||||
double[] columnSize = {TableLayout.FILL, 22}; |
||||
choosePane = TableLayoutHelper.createCommonTableLayoutPane(templateChooserComponent, rowSize, columnSize, 0); |
||||
} |
||||
|
||||
@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(); |
||||
} |
||||
} |
||||
|
||||
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)); |
||||
this.descriptionLabel.setToolTipText(this.descriptionLabel.getText()); |
||||
} |
||||
|
||||
@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 { |
||||
|
||||
private UIComboCheckBox rolesCheckBox; |
||||
|
||||
EffectedRolesChooser() { |
||||
this.rolesCheckBox = new UIComboCheckBox(roleMap.values().toArray(), true) { |
||||
@Override |
||||
protected void setLayoutAndAddComponents() { |
||||
// 使用BorderLayout,否则默认使用的FlowLayout会让整个下拉选框使用最小Size,然后TableCell这边会出现空白
|
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.add(getEditor(), BorderLayout.CENTER); |
||||
this.add(getArrowButton(), BorderLayout.EAST); |
||||
} |
||||
|
||||
@Override |
||||
protected void setEditorToolTipText(JComponent editor, String text) { |
||||
// 选项过多时,已选中的值会做省略显示处理,此处添加一个Tooltips,显示完整值
|
||||
if (text != null) { |
||||
editor.setToolTipText(text); |
||||
} |
||||
} |
||||
}; |
||||
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(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 规则状态展示页面 |
||||
*/ |
||||
private class DesensitizationRuleStatusPane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { |
||||
|
||||
private UILabel ruleStatusLabel; |
||||
|
||||
DesensitizationRuleStatusPane() { |
||||
// 规则状态
|
||||
this.ruleStatusLabel = new UILabel(); |
||||
this.ruleStatusLabel.setForeground(Color.RED); |
||||
} |
||||
|
||||
/** |
||||
* 根据脱敏规则信息,刷新规则状态,主要用于与规则选择器的联动 |
||||
* |
||||
* @param currentItem |
||||
*/ |
||||
public void refreshRuleStatus(TableDataDesensitizationItem currentItem) { |
||||
DesensitizationRule rule = currentItem.getRule(); |
||||
if (needMarkRule(rule)) { |
||||
// 非正常规则,根据规则状态展示不同提示文字
|
||||
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules); |
||||
this.ruleStatusLabel.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal")); |
||||
this.ruleStatusLabel.setToolTipText(ruleStatus.getDescription()); |
||||
} else { |
||||
// 正常规则,重置提示Label
|
||||
this.ruleStatusLabel.setText(StringUtils.EMPTY); |
||||
this.ruleStatusLabel.setToolTipText(null); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { |
||||
refreshRuleStatus(getList().get(row)); |
||||
return ruleStatusLabel; |
||||
} |
||||
|
||||
@Override |
||||
public Object getCellEditorValue() { |
||||
return ruleStatusLabel; |
||||
} |
||||
|
||||
@Override |
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
||||
refreshRuleStatus(getList().get(row)); |
||||
return ruleStatusLabel; |
||||
} |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
||||
|
||||
private class RefreshTableAction extends UITableEditAction { |
||||
|
||||
public RefreshTableAction() { |
||||
this.setName(Toolkit.i18nText("Fine-Design_Basic_Refresh")); |
||||
this.setSmallIcon("/com/fr/design/standard/refresh/refresh", false); |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
// 刷新TableData的规则,主要是为了自动替换掉平台中被修改的规则
|
||||
List<TableDataDesensitizationItem> items = getList(); |
||||
Iterator<TableDataDesensitizationItem> iterator = items.iterator(); |
||||
while (iterator.hasNext()) { |
||||
TableDataDesensitizationItem item = iterator.next(); |
||||
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(item.getRule(), latestRules); |
||||
if (ruleStatus == DesensitizationRuleStatus.REMOVED) { |
||||
// 规则被移除,则删除整条脱敏Item
|
||||
iterator.remove(); |
||||
} else { |
||||
// 规则被修改、禁用等,更新一下规则
|
||||
item.setRule(DesensitizationRuleManager.getInstance().getLastedDesentizationRule(item.getRule(), latestRules)); |
||||
} |
||||
} |
||||
fireTableDataChanged(); |
||||
} |
||||
|
||||
@Override |
||||
public void checkEnabled() {} |
||||
} |
||||
|
||||
/** |
||||
* 规则表-列字段编号 |
||||
*/ |
||||
private enum TableSequences { |
||||
|
||||
/** |
||||
* 数据集列名选择 |
||||
*/ |
||||
ColumnName(0), |
||||
|
||||
/** |
||||
* 规则选择 |
||||
*/ |
||||
DesensitizationRule(1), |
||||
|
||||
/** |
||||
* 规则描述 |
||||
*/ |
||||
DesensitizationRuleDescription(2), |
||||
|
||||
/** |
||||
* 规则生效用户组 |
||||
*/ |
||||
EffectedRoles(3), |
||||
|
||||
/** |
||||
* 规则状态 |
||||
*/ |
||||
DesensitizationRuleStatus(4), |
||||
|
||||
/** |
||||
* 未知,用于无法匹配时的返回 |
||||
*/ |
||||
Unknown(100); |
||||
|
||||
|
||||
private int num; |
||||
|
||||
TableSequences(int num) { |
||||
this.num = num; |
||||
} |
||||
|
||||
public int getNum() { |
||||
return num; |
||||
} |
||||
|
||||
/** |
||||
* 根据列序号匹配列字段 |
||||
* |
||||
* @param num |
||||
* @return |
||||
*/ |
||||
public static TableSequences match(int num) { |
||||
for (TableSequences value : TableSequences.values()) { |
||||
if (value.getNum() == num) { |
||||
return value; |
||||
} |
||||
} |
||||
return Unknown; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 是否需要对异常规则做标记,需要满足 |
||||
* 1. 规则非默认空规则 |
||||
* 2. 规则本身异常 |
||||
* |
||||
* @return |
||||
*/ |
||||
private boolean needMarkRule(DesensitizationRule rule) { |
||||
return !rule.equals(DesensitizationRule.createDefaultEmptyRule()) && |
||||
DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules) != DesensitizationRuleStatus.NORMAL; |
||||
} |
||||
|
||||
/** |
||||
* 刷新当前页面的本地规则缓存,查询最新本地规则的逻辑也是使用了缓存,因此无需考虑耗时 |
||||
*/ |
||||
private void refreshCustomRuleCache() { |
||||
Map<String, DesensitizationRule> customRules = DesensitizationRuleManager.getInstance().getRulesBySource(DesensitizationRuleSource.CUSTOM); |
||||
latestRules.put(DesensitizationRuleSource.CUSTOM, customRules); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,153 @@
|
||||
package com.fr.design.data.datapane.preview.desensitization.view.setting; |
||||
|
||||
import com.fr.base.operator.org.OrganizationOperator; |
||||
import com.fr.data.desensitize.base.DesensitizationTableData; |
||||
import com.fr.data.desensitize.base.TableDataDesensitizationItem; |
||||
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.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager; |
||||
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane; |
||||
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.workspace.WorkContext; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingWorker; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.CardLayout; |
||||
import java.awt.Component; |
||||
import java.util.ArrayList; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* 脱敏字段设置页面中的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; |
||||
|
||||
private static final String LOADING_PANE = "loading"; |
||||
private static final String CONTENT_PANE = "content"; |
||||
|
||||
private CardLayout card; |
||||
|
||||
private JPanel loadingPane; |
||||
|
||||
private JPanel contentPane; |
||||
|
||||
public TableDataDesensitizationTablePane(DesensitizationTableData tableData, Component parent) { |
||||
this.tableData = tableData; |
||||
this.parent = parent; |
||||
initComponent(); |
||||
} |
||||
|
||||
private void initComponent() { |
||||
|
||||
card = new CardLayout(); |
||||
this.setLayout(card); |
||||
// 初始化Loading面板
|
||||
loadingPane = new TipsPane(true); |
||||
this.add(LOADING_PANE, loadingPane); |
||||
switchTo(LOADING_PANE); |
||||
|
||||
// 在SwingWorker中初始化Content面板并切换
|
||||
initContent(); |
||||
} |
||||
|
||||
/** |
||||
* 初始化内容面板 |
||||
* 考虑到远程设计下的性能,需要限制查询数据库的次数,所以这里查一次,之后子面板内复用 |
||||
*/ |
||||
private void initContent() { |
||||
final List<String> columnNames = new ArrayList<>(); |
||||
final Map<String, String> roleMap = new LinkedHashMap<>(); |
||||
final Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules = new LinkedHashMap<>(); |
||||
new SwingWorker<Void, Void>() { |
||||
|
||||
@Override |
||||
protected Void doInBackground() throws Exception { |
||||
// 获取当前数据集的所有列名
|
||||
columnNames.addAll(TableDataPreviewDesensitizeManager.getInstance().getColumnNamesByTableData(tableData)); |
||||
// 获取当前所有用户组
|
||||
roleMap.putAll(WorkContext.getCurrent().get(OrganizationOperator.class).getAllRoles4Desensitization()); |
||||
// 获取当前最新的所有规则
|
||||
latestRules.putAll(DesensitizationRuleManager.getInstance().getAllRules()); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
editorPane = new UITableEditorPane<>(new TableDataDesensitizationTableModel(tableData, parent, columnNames, roleMap, latestRules)); |
||||
editorPane.setHeaderResizing(false); |
||||
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0])); |
||||
contentPane.add(editorPane, BorderLayout.CENTER); |
||||
add(CONTENT_PANE, contentPane); |
||||
switchTo(CONTENT_PANE); |
||||
} |
||||
}.execute(); |
||||
} |
||||
|
||||
/** |
||||
* 切换面板 |
||||
* |
||||
* @param panelName |
||||
*/ |
||||
public void switchTo(String panelName) { |
||||
try { |
||||
if (panelName != null) { |
||||
card.show(this, panelName); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 展示此TableData中已配置的脱敏规则信息 |
||||
* |
||||
* @param tableData |
||||
*/ |
||||
public void populateDesensitizationSetting(DesensitizationTableData tableData) { |
||||
this.tableData = tableData; |
||||
if (editorPane != null) { |
||||
// editorPane的初始化在SwingWorker中完成,这里做个判空
|
||||
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0])); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取当前对TableData的配置脱敏规则信息 |
||||
*/ |
||||
public List<TableDataDesensitizationItem> updateDesensitizationSetting() { |
||||
|
||||
return editorPane == null ? |
||||
new ArrayList<>() : |
||||
editorPane.update() |
||||
.stream() |
||||
.filter(item -> TableDataDesensitizationItem.valid(item)) |
||||
.collect(Collectors.toList()); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
||||
package com.fr.design.fun; |
||||
|
||||
import com.fr.base.Utils; |
||||
import com.fr.base.chart.BaseChartCollection; |
||||
import com.fr.chartx.attr.ChartProvider; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.report.cell.CellElement; |
||||
import com.fr.stable.fun.mark.Selectable; |
||||
|
||||
import java.awt.Font; |
||||
|
||||
/** |
||||
* 主要用于fvs报表块内元素默认值的调整,以达到所见所得效果,后续fvs内置后删除 |
||||
*/ |
||||
public interface DefaultValueAdjustProvider extends Selectable { |
||||
String MARK_STRING = "DefaultValueAdjustProvider"; |
||||
int CURRENT_LEVEL = 1; |
||||
|
||||
/** |
||||
* 调整单元格对象默认值 |
||||
* |
||||
* @param cellElement |
||||
*/ |
||||
void adjustCellElement(CellElement cellElement); |
||||
|
||||
/** |
||||
* 调整富文本默认值 |
||||
* |
||||
* @param fontSize |
||||
* @return |
||||
*/ |
||||
int adjustRichTextTransform(int fontSize, double transformedFontSize); |
||||
|
||||
/** |
||||
* 调整ChartCollection |
||||
* |
||||
* @param chartCollection |
||||
*/ |
||||
void adjustChartCollectionStyle(BaseChartCollection chartCollection); |
||||
|
||||
/** |
||||
* 调整图表 |
||||
* |
||||
* @param chartProvider |
||||
*/ |
||||
void adjustChart(ChartProvider chartProvider); |
||||
|
||||
|
||||
/** |
||||
* 转成当前分辨率下显示的font |
||||
* @param font |
||||
* @param resolution |
||||
* @return |
||||
*/ |
||||
Font transformFontByResolution(FRFont font, int resolution); |
||||
|
||||
/** |
||||
* 修改设计可用字体默认列表 |
||||
* @return |
||||
*/ |
||||
default String[] getAvailableFontFamilyNames4Report() { |
||||
return Utils.getAvailableFontFamilyNames4Report(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.fun; |
||||
|
||||
import com.fr.design.beans.BasicBeanPane; |
||||
import com.fr.stable.fun.mark.Mutable; |
||||
|
||||
/** |
||||
* 设计器模板主题管理-细节定制部分,支持添加tab |
||||
* |
||||
* @author Bruce.Deng |
||||
* @version 11.0 |
||||
* Created by Bruce.Deng on 2023/2/7 |
||||
*/ |
||||
public interface TemplateThemePaneProvider<T> extends Mutable { |
||||
|
||||
String XML_TAG = "TemplateThemePaneProvider"; |
||||
|
||||
int CURRENT_LEVEL = 1; |
||||
|
||||
/** |
||||
* 插入tab的位置 |
||||
* |
||||
* @param total 已插入的tab数 |
||||
* @return 插入位置,如果想放到最后,则返回-1 |
||||
*/ |
||||
int getInsertPosition(int total); |
||||
|
||||
|
||||
/** |
||||
* 获取tab对象 |
||||
* |
||||
* @return tab对象 |
||||
*/ |
||||
BasicBeanPane<T> getTab(); |
||||
|
||||
} |
@ -0,0 +1,24 @@
|
||||
package com.fr.design.fun.impl; |
||||
|
||||
|
||||
import com.fr.design.fun.DefaultValueAdjustProvider; |
||||
import com.fr.stable.fun.assist.Selector; |
||||
import com.fr.stable.fun.impl.AbstractProvider; |
||||
import com.fr.stable.fun.mark.API; |
||||
|
||||
@API(level = DefaultValueAdjustProvider.CURRENT_LEVEL) |
||||
public abstract class AbstractDefaultValueAdjustProvider extends AbstractProvider implements DefaultValueAdjustProvider { |
||||
|
||||
@Override |
||||
public int currentAPILevel() { |
||||
return CURRENT_LEVEL; |
||||
} |
||||
|
||||
public String mark4Provider() { |
||||
return this.getClass().getName(); |
||||
} |
||||
|
||||
public Selector selector() { |
||||
return Selector.ALWAYS; |
||||
} |
||||
} |
@ -0,0 +1,26 @@
|
||||
package com.fr.design.fun.impl; |
||||
|
||||
import com.fr.design.fun.TemplateThemePaneProvider; |
||||
import com.fr.stable.fun.impl.AbstractProvider; |
||||
import com.fr.stable.fun.mark.API; |
||||
|
||||
/** |
||||
* @author Bruce.Deng |
||||
* @version 11.0 |
||||
* @see TemplateThemePaneProvider |
||||
* Created by Bruce.Deng on 2023/2/7 |
||||
*/ |
||||
@API(level = TemplateThemePaneProvider.CURRENT_LEVEL) |
||||
public abstract class AbstractTemplateThemePaneProvider<T> extends AbstractProvider implements TemplateThemePaneProvider<T> { |
||||
|
||||
@Override |
||||
public int currentAPILevel() { |
||||
return CURRENT_LEVEL; |
||||
} |
||||
|
||||
@Override |
||||
public String mark4Provider() { |
||||
return getClass().getName(); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.base.AutoChangeLineProvider; |
||||
import com.fr.base.DefaultAutoChangeLine; |
||||
import com.fr.base.ScreenResolution; |
||||
import com.fr.design.fun.ReportLengthUNITProvider; |
||||
import com.fr.design.unit.UnitConvertUtil; |
||||
|
||||
public class AbsoluteMeasureUIMode implements DesignerUIMode { |
||||
|
||||
private static class AbsoluteMeasureUIModeHolder { |
||||
private static final AbsoluteMeasureUIMode absoluteMeasureUIMode = new AbsoluteMeasureUIMode(); |
||||
} |
||||
|
||||
private AbsoluteMeasureUIMode() { |
||||
|
||||
} |
||||
|
||||
public static AbsoluteMeasureUIMode getInstance() { |
||||
return AbsoluteMeasureUIModeHolder.absoluteMeasureUIMode; |
||||
} |
||||
|
||||
@Override |
||||
public ReportLengthUNITProvider parseLengthUNIT(int unitType) { |
||||
return UnitConvertUtil.parseLengthUNIT(unitType); |
||||
} |
||||
|
||||
@Override |
||||
public AutoChangeLineProvider getAutoChangeLineStrategy() { |
||||
return new DefaultAutoChangeLine(); |
||||
} |
||||
|
||||
@Override |
||||
public int getScreenResolution() { |
||||
return ScreenResolution.getScreenResolution(); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.base.AutoChangeLineProvider;; |
||||
import com.fr.design.fun.ReportLengthUNITProvider; |
||||
|
||||
/** |
||||
* 设计器上和展示相关配置 |
||||
*/ |
||||
public interface DesignerUIMode { |
||||
|
||||
ReportLengthUNITProvider parseLengthUNIT(int unitType); |
||||
|
||||
AutoChangeLineProvider getAutoChangeLineStrategy(); |
||||
|
||||
int getScreenResolution(); |
||||
|
||||
} |
@ -0,0 +1,38 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.base.AutoChangeLineProvider; |
||||
import com.fr.design.fun.ReportLengthUNITProvider; |
||||
import com.fr.form.fit.NewUIModeAutoChangeLine; |
||||
import com.fr.stable.Constants; |
||||
|
||||
public class SimulateWebUIMode implements DesignerUIMode { |
||||
|
||||
private static class SimulateWebUIModeHolder { |
||||
private static final SimulateWebUIMode simulateWebUIMode = new SimulateWebUIMode(); |
||||
} |
||||
|
||||
private SimulateWebUIMode() { |
||||
|
||||
} |
||||
|
||||
public static SimulateWebUIMode getInstance() { |
||||
return SimulateWebUIModeHolder.simulateWebUIMode; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public ReportLengthUNITProvider parseLengthUNIT(int unitType) { |
||||
return new PXReportLengthUNIT(); |
||||
} |
||||
|
||||
@Override |
||||
public AutoChangeLineProvider getAutoChangeLineStrategy() { |
||||
return new NewUIModeAutoChangeLine(); |
||||
} |
||||
|
||||
@Override |
||||
public int getScreenResolution() { |
||||
return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.fr.design.mainframe.platform; |
||||
|
||||
import com.fr.design.actions.UpdateAction; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.utils.BrowseUtils; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.log.FineLoggerFactory; |
||||
|
||||
import java.awt.Desktop; |
||||
import java.awt.event.ActionEvent; |
||||
import java.net.URI; |
||||
|
||||
/** |
||||
* 帮助-服务平台 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @version 11.0 |
||||
* created by Destiny.Lin on 2022-12-14 |
||||
*/ |
||||
public class ServicePlatformAction extends UpdateAction { |
||||
public ServicePlatformAction() { |
||||
this.setName(Toolkit.i18nText("Fine-Design_Basic_Service_Platform_Title")); |
||||
this.setSmallIcon("/com/fr/design/images/platform/platform", false); |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
BrowseUtils.browser(CloudCenter.getInstance().acquireUrlByKind("service.platform")); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
|
||||
package com.fr.design.mainframe.theme.processor; |
||||
|
||||
import com.fr.stable.fun.mark.API; |
||||
|
||||
/** |
||||
* @author Bruce.Deng |
||||
* @version 11.0 |
||||
* Created by Bruce.Deng on 2023/2/14 |
||||
*/ |
||||
@API(level = ThemePreviewPaneProcessor.CURRENT_LEVEL) |
||||
public abstract class AbstractThemePreviewPaneProcessor implements ThemePreviewPaneProcessor { |
||||
|
||||
@Override |
||||
public int currentAPILevel() { |
||||
return CURRENT_LEVEL; |
||||
} |
||||
|
||||
@Override |
||||
public int layerIndex() { |
||||
return DEFAULT_LAYER_INDEX; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.theme.processor; |
||||
|
||||
import com.fr.base.theme.FormTheme; |
||||
import com.fr.base.theme.ReportTheme; |
||||
import com.fr.design.mainframe.theme.TemplateThemePreviewPane; |
||||
import com.fr.stable.fun.mark.Immutable; |
||||
|
||||
/** |
||||
* 主题样式预览界面接口 |
||||
* |
||||
* @author Bruce.Deng |
||||
* @version 11.0 |
||||
* Created by Bruce.Deng on 2023/2/14 |
||||
*/ |
||||
public interface ThemePreviewPaneProcessor extends Immutable { |
||||
|
||||
String XML_TAG = "ThemePreviewPaneProcessor"; |
||||
|
||||
int CURRENT_LEVEL = 1; |
||||
|
||||
/** |
||||
* 创建报表主题样式预览界面 |
||||
* |
||||
* @return 报表主题样式预览界面 |
||||
*/ |
||||
TemplateThemePreviewPane<ReportTheme> createReportThemePreviewPane(); |
||||
|
||||
/** |
||||
* 创建决策报表主题样式预览界面 |
||||
* |
||||
* @return 决策报表主题样式预览界面 |
||||
*/ |
||||
TemplateThemePreviewPane<FormTheme> createFormThemePreviewPane(); |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue