diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java index d3b1a720d7..76f32d6f0c 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java @@ -1,9 +1,7 @@ package com.fr.design.data.datapane.connect; -import com.fine.state.livedata.LiveData; -import com.fine.swing.ui.layout.Row; -import com.fr.base.BaseUtils; import com.fr.base.svg.IconUtils; +import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; import com.fr.data.impl.NameDatabaseConnection; import com.fr.design.DesignerEnvManager; @@ -11,23 +9,22 @@ import com.fr.design.editlock.ConnectionLockChangeChecker; import com.fr.design.editlock.EditLockUtils; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UILockButton; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.i18n.Toolkit; -import com.fr.log.FineLoggerFactory; +import com.fr.file.ConnectionConfig; import com.fr.report.LockItem; import com.fr.stable.StringUtils; import com.fr.workspace.WorkContext; -import org.jetbrains.annotations.Nullable; +import com.fr.workspace.server.connection.DBConnectAuth; -import javax.swing.DefaultComboBoxModel; import javax.swing.SwingUtilities; +import java.awt.Dimension; +import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; -import java.util.Objects; -import java.util.concurrent.CancellationException; -import java.util.function.Consumer; - -import static com.fine.swing.ui.layout.Layouts.cell; /** * 选择数据连接的下拉框 @@ -35,150 +32,86 @@ import static com.fine.swing.ui.layout.Layouts.cell; * @editor zhou * @since 2012-3-28下午3:02:30 */ -public class ConnectionComboBoxPanel extends Row { +public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { + /** + * + */ private static final long serialVersionUID = 1L; + private Class cls; // 所取的Connection都是cls及其子类 + private List nameList = new ArrayList(); - private static final String PENDING = Toolkit.i18nText("Fine-Design_Basic_Loading") + "..."; - - protected static final Object EMPTY = new Object() { - public String toString() { - return ""; - } - }; - - protected UIComboBox itemComboBox; - protected UIButton editButton; - - // 记录原来选中的Item,重新加载后需要再次选中 - private Object lastSelectedItem; - - private final LiveData> names; - private final Consumer fetchNames; - - public ConnectionComboBoxPanel( - LiveData> names, - LiveData selectedItem, - @Nullable Consumer fetchNames, - @Nullable Consumer selecteChangeConsumer - ) { + public ConnectionComboBoxPanel(Class cls) { super(); - this.names = names; - this.fetchNames = fetchNames; - initComponents(); + + this.cls = cls; // alex:添加item change监听,当改变时改变DesignerEnvManager中的最近选中的数据连接 - this.itemComboBox.addItemListener(e -> { - String selected = ConnectionComboBoxPanel.this.getSelectedItem(); - if(PENDING.equals(selected)){ - return; - } - if (StringUtils.isNotBlank(selected)) { - DesignerEnvManager.getEnvManager().setRecentSelectedConnection(selected); - } - if(!Objects.isNull(selecteChangeConsumer)){ - selecteChangeConsumer.accept(selected); - } - }); - names.observeForever(strings -> { - try { - itemComboBox.setModel(new DefaultComboBoxModel<>(strings.toArray(new String[0]))); -// // 如果加载成功 但是下拉框是可见的 下拉框高度是会固定为原始高度 不会因为填充了更多下拉项而变化 -// // 需要重新设置下拉框高度 但值一样时相关事件不会生效 所以先加再减下 -// if (itemComboBox.isPopupVisible()) { -// itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1); -// itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1); -// } -// // 存在两种场景之前只考虑了填充场景 有populate会填充下 把这边的填充逻辑删了 所以没有问题 -// // 如果是纯通过刷新按钮 没有populate 需要手动设置下上次选中的内容 - if (lastSelectedItem != null) { - itemComboBox.setSelectedItem(lastSelectedItem); - } - } catch (Exception e) { - if (!(e instanceof CancellationException)) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); + this.itemComboBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + String selected = ConnectionComboBoxPanel.this.getSelectedItem(); + if (StringUtils.isNotBlank(selected)) { + DesignerEnvManager.getEnvManager().setRecentSelectedConnection(selected); } } }); - - - lastSelectedItem = selectedItem.getValue(); refreshItems(); } - private void initComponents() { - setSpacing(5); - add( - cell(new UIComboBox()).weight(1.0).with(uiComboBox -> { - this.itemComboBox= uiComboBox; - uiComboBox.setEnabled(true); - - }), - cell(new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png"))) - .with(btn -> btn.addActionListener(e -> refreshItems())), - cell(initEditButton()).with(uiButton -> editButton = uiButton) - ); - } - - - /** - * 给itemComboBox添加ActionListener - */ - public void addComboBoxActionListener(ActionListener l) { - itemComboBox.addActionListener(l); - } - - /* - * 刷新itemComboBox的内容 - */ - protected void refreshItems() { - lastSelectedItem = itemComboBox.getSelectedItem(); - DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); - - model.removeAllElements(); - - // 先加EMPTY,再加items - model.addElement(PENDING); - if(!Objects.isNull(fetchNames)){ - fetchNames.accept(null); - } - } - - protected UIButton initEditButton() { - UIButton editButton = new UILockButton( + @Override + protected UIButton initEditButton(UIButton editButton, Dimension buttonSize) { + editButton = new UILockButton( EditLockUtils.CONNECTION_LOCKED_ICON, IconUtils.readIcon("/com/fr/design/images/m_web/connection"), EditLockUtils.CONNECTION_LOCKED_TOOLTIPS, null ); -// editButton.setPreferredSize(buttonSize); - editButton.addActionListener(evt -> editItems()); + editButton.setPreferredSize(buttonSize); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + editItems(); + } + }); ConnectionLockChangeChecker.getInstance().addEditLockChangeListener((UILockButton) editButton); return editButton; } /* - * 得到其中的itemComboBox所选中的Item + * 刷新ComboBox.items */ - public String getSelectedItem() { - Object selected = itemComboBox.getSelectedItem(); + protected Iterator items() { + ConnectionConfig mgr = ConnectionConfig.getInstance(); + Iterator nameIt = mgr.getConnections().keySet().iterator(); + + Collection noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections(); - return selected instanceof String ? (String)selected : null; + nameList = new ArrayList<>(); + + if (noAuthConnections == null) { + return nameList.iterator(); + } + while (nameIt.hasNext()) { + String conName = nameIt.next(); + if (noAuthConnections.contains(conName)) { + continue; + } + Connection connection = mgr.getConnection(conName); + // nameList依赖items方法初始化,父类ItemEditableComboBoxPanel里异步执行item方法 + filterConnection(connection, conName, nameList); + } + + return nameList.iterator(); } - /* - * 选中name项 - */ - public void setSelectedItem(String name) { - DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); - model.setSelectedItem(name); + protected void filterConnection(Connection connection, String conName, List nameList) { + connection.addConnection(nameList, conName, new Class[]{AbstractDatabaseConnection.class}); } public int getConnectionSize() { - return names.getValue().size(); + return nameList.size(); } public String getConnection(int i) { - return names.getValue().get(i); + return nameList.get(i); } /* @@ -215,7 +148,9 @@ public class ConnectionComboBoxPanel extends Row { protected void setRecentConnection() { String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); if (StringUtils.isNotBlank(s)) { - if (names.getValue().contains(s)) { + // 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白 + // 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置 + if (nameList.contains(s)) { this.setSelectedItem(s); } } @@ -225,5 +160,12 @@ public class ConnectionComboBoxPanel extends Row { } } - -} \ No newline at end of file + /** + * 是否无选中状态(空白item也视为无选中) + * @return + */ + protected boolean isSelectedItemEmpty() { + String selectedItem = this.getSelectedItem(); + return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java index de5d1ed8a7..41556dae83 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java @@ -1,14 +1,13 @@ package com.fr.design.data.datapane.connect; -import com.fine.state.livedata.LiveData; -import com.fine.state.livedata.MutableLiveData; import com.fr.base.BaseUtils; import com.fr.base.svg.IconUtils; import com.fr.data.core.db.TableProcedure; +import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; -import com.fr.design.DesignerEnvManager; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; +import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; @@ -19,24 +18,21 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.general.GeneralContext; import com.fr.stable.ArrayUtils; -import com.fr.stable.StringUtils; import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; import javax.swing.JPanel; import javax.swing.ToolTipManager; -import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.BorderLayout; import java.awt.Dimension; +import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.function.Consumer; /** * 数据集编辑面板左边的部分 @@ -45,269 +41,277 @@ import java.util.function.Consumer; * @since 2012-3-28下午10:14:59 */ public class ConnectionTableProcedurePane extends BasicPane { - private static int WIDTH = 155; - private ConnectionComboBoxPanel connectionComboBox; - private UICheckBox tableCheckBox; - private UICheckBox viewCheckBox; - protected UITextField searchField; - private TableViewList tableViewList; - private List listeners = new ArrayList(); - - private ConnectionTableState state; - - public MutableLiveData selected = new MutableLiveData<>(); - public Consumer selecteChangeConsumer; - - public static class ConnectionTableState { - public LiveData> names; - public Consumer namesConsumer; - public LiveData> tableProcedures; - public Consumer tableProcedureBeanConsumer; - - public ConnectionTableState(LiveData> names, Consumer namesConsumer, LiveData> tableProcedures, Consumer tableProcedureBeanConsumer) { - this.names = names; - this.namesConsumer = namesConsumer; - this.tableProcedures = tableProcedures; - this.tableProcedureBeanConsumer = tableProcedureBeanConsumer; - } - } - - public ConnectionTableProcedurePane() { - init(); - } - - public ConnectionTableProcedurePane(ConnectionTableState state) { - this.state = state; - init(); - } - - - private void init() { - selecteChangeConsumer = selectedName -> { - selected.setValue(selectedName); - }; - this.setLayout(new BorderLayout(4, 4)); - - // 初始化中间的面板 - JPanel centerPane = initCenterPane(); - this.add(centerPane, BorderLayout.CENTER); - // 初始化数据连接下拉框 - initConnectionComboBox(); - this.add(connectionComboBox, BorderLayout.NORTH); - setBorder(new EmptyBorder( - 10, 10, 10, 10 - )); - this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height)); - addKeyMonitor(); - state.names.observeForever(strings -> { - search(true); - }); - } - - - protected void filter(Connection connection, String conName, List nameList) { - - } - - private JPanel initCenterPane() { - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - // 搜索面板 - centerPane.add(createSearchPane(), BorderLayout.NORTH); - // 数据库表视图面板 - centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER); - return centerPane; - } - - private void initConnectionComboBox() { - connectionComboBox = new ConnectionComboBoxPanel(state.names, selected,state.namesConsumer, selecteChangeConsumer); - connectionComboBox.addComboBoxActionListener(filter); - } - - - - private JPanel createTableViewBorderPane() { - tableViewList = new TableViewList(state.tableProcedures, state.tableProcedureBeanConsumer); - ToolTipManager.sharedInstance().registerComponent(tableViewList); - - tableViewList.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent evt) { - if (evt.getClickCount() >= 2) { - Object obj = tableViewList.getSelectedValue(); - TableProcedure tableProcedure = null; - if (obj instanceof TableProcedure) { - tableProcedure = (TableProcedure) obj; - } else { - return; - } - for (DoubleClickSelectedNodeOnTreeListener listener : ConnectionTableProcedurePane.this.listeners) { - listener.actionPerformed(tableProcedure); - } - } - } - }); - UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); - tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); - JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER); - JPanel checkBoxgroupPane = createCheckBoxgroupPane(); - if (checkBoxgroupPane != null) { - tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH); - } - return tableViewBorderPane; - } - - /** - * 创建搜索Panel,用于搜索表或视图 - * - * @return - */ - private JPanel createSearchPane() { - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel searchPane = new JPanel(new BorderLayout(10, 0)); - searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + private static int WIDTH = 155; + private ConnectionComboBoxPanel connectionComboBox; + private UICheckBox tableCheckBox; + private UICheckBox viewCheckBox; + protected UITextField searchField; + private TableViewList tableViewList; + private java.util.List listeners = new java.util.ArrayList(); + + public ConnectionTableProcedurePane() { + init(null); + } + + /** + * 传入父容器 + * @param parent + */ + public ConnectionTableProcedurePane(SwitchableTableDataPane parent) { + init(parent); + } + + private void init(SwitchableTableDataPane parent) { + this.setLayout(new BorderLayout(4, 4)); + // 初始化数据连接下拉框 + initConnectionComboBox(parent); + // 初始化中间的面板 + JPanel centerPane = initCenterPane(); + this.add(connectionComboBox, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height)); + addKeyMonitor(); + } + + private JPanel initCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + // 搜索面板 + centerPane.add(createSearchPane(), BorderLayout.NORTH); + // 数据库表视图面板 + centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER); + return centerPane; + } + + private void initConnectionComboBox(SwitchableTableDataPane parent) { + connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) { + + @Override + protected void filterConnection(Connection connection, String conName, List nameList) { + filter(connection, conName, nameList); + } + + @Override + protected void refreshItems() { + super.refreshItems(); + if (tableViewList != null) { + search(true); + } + } + + @Override + protected void afterRefreshItems() { + // 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置 + if (isSelectedItemEmpty()) { + setRecentConnection(); + } + // 获取数据连接之后,让父容器切换面板 + if (parent != null) { + parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME); + } + DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); + model.removeElement(EMPTY); + } + + @Override + protected void refreshItemsError() { + // 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板 + if (parent != null) { + parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME); + } + } + }; + connectionComboBox.addComboBoxActionListener(filter); + } + + private JPanel createTableViewBorderPane() { + tableViewList = new TableViewList(); + ToolTipManager.sharedInstance().registerComponent(tableViewList); + + tableViewList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() >= 2) { + Object obj = tableViewList.getSelectedValue(); + TableProcedure tableProcedure = null; + if (obj instanceof TableProcedure) { + tableProcedure = (TableProcedure) obj; + } else { + return; + } + for (int i = 0; i < ConnectionTableProcedurePane.this.listeners.size(); i++) { + ConnectionTableProcedurePane.this.listeners.get(i).actionPerformed(tableProcedure); + } + } + } + }); + UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); + tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER); + JPanel checkBoxgroupPane = createCheckBoxgroupPane(); + if (checkBoxgroupPane != null) { + tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH); + } + return tableViewBorderPane; + } + + /** + * 创建搜索Panel,用于搜索表或视图 + * @return + */ + private JPanel createSearchPane() { + JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel searchPane = new JPanel(new BorderLayout(10, 0)); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); // searchPane.setBackground(Color.WHITE); - searchField = new UITextField(); - searchField.setBorderPainted(false); - searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search")); - searchField.getDocument().addDocumentListener(searchListener); - searchField.addMouseListener(new MouseAdapter() { - @Override - public void mouseEntered(MouseEvent e) { - super.mouseEntered(e); - searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED)); - } - - @Override - public void mouseExited(MouseEvent e) { - super.mouseExited(e); - searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); - } - }); - // 搜索图标 - UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search")); - searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - searchPane.add(searchField, BorderLayout.CENTER); - searchPane.add(searchLabel, BorderLayout.EAST); - panel.add(searchPane, BorderLayout.CENTER); - return panel; - } - - protected void addKeyMonitor() { - //do nothing - } - - protected JPanel createCheckBoxgroupPane() { - JPanel checkBoxgroupPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2); - JPanel first = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - tableCheckBox = new UICheckBox(); - tableCheckBox.setSelected(true); - tableCheckBox.addActionListener(filter); - first.add(tableCheckBox); - - JPanel second = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - viewCheckBox = new UICheckBox(); - viewCheckBox.setSelected(true); - viewCheckBox.addActionListener(filter); - second.add(viewCheckBox); - - // 根据环境是否为中文设置不同的显示 - if (GeneralContext.isChineseEnv()) { - first.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"), - BaseUtils.readIcon("/com/fr/design/images/data/tables.png"), UILabel.LEADING)); - second.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"), - BaseUtils.readIcon("/com/fr/design/images/data/views.png"), UILabel.LEADING)); - } else { - UILabel ui1 = new UILabel(BaseUtils.readIcon("/com/fr/design/images/data/tables.png"), UILabel.LEADING); - UILabel ui2 = new UILabel(BaseUtils.readIcon("/com/fr/design/images/data/views.png"), UILabel.LEADING); - ui1.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); - ui2.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); - first.add(ui1); - second.add(ui2); - } - checkBoxgroupPane.add(first); - checkBoxgroupPane.add(second); - - return checkBoxgroupPane; - } - - /** - * 给 itemComboBox 加上 itemListener - * - * @param itemListener - */ - public void addItemListener(ItemListener itemListener) { - connectionComboBox.itemComboBox.addItemListener(itemListener); - } - - private final DocumentListener searchListener = new DocumentListener() { - - @Override - public void removeUpdate(DocumentEvent e) { - search(false); - } - - @Override - public void insertUpdate(DocumentEvent e) { - search(false); - } - - @Override - public void changedUpdate(DocumentEvent e) { - search(false); - } - }; - - private final ActionListener filter = e -> search(false); - - /** - * 选项改变,需要重新刷新下拉列表里面的项 - */ - protected void search(boolean refresh) { - String selectedObj = selected.getValue(); - if(StringUtils.isBlank(selectedObj)){ - selectedObj = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); - } - - String[] types = ArrayUtils.EMPTY_STRING_ARRAY; - if (tableCheckBox != null) { - if (tableCheckBox.isSelected()) { - types = ArrayUtils.add(types, TableProcedure.TABLE); - } - if (viewCheckBox.isSelected()) { - types = ArrayUtils.add(types, TableProcedure.VIEW); - } - } else { - types = ArrayUtils.add(types, TableProcedure.PROCEDURE); - } - tableViewList.populate(selectedObj, searchField.getText().trim(), refresh, types); - } - - @Override - protected String title4PopupWindow() { - return "Connection"; - } - - /** - * @param l - */ - public void addDoubleClickListener(DoubleClickSelectedNodeOnTreeListener l) { - this.listeners.add(l); - } - - public void setSelectedDatabaseConnection(com.fr.data.impl.Connection db) { - connectionComboBox.populate(db); - } - - public String getSelectedDatabaseConnnectonName() { - return connectionComboBox.getSelectedItem(); - } - - public static interface DoubleClickSelectedNodeOnTreeListener { - /** - * 处理双击事件 - * - * @param target - */ - public void actionPerformed(TableProcedure target); - } + searchField = new UITextField(); + searchField.setBorderPainted(false); + searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search")); + searchField.getDocument().addDocumentListener(searchListener); + searchField.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED)); + } + + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + } + }); + // 搜索图标 + UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search")); + searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + searchPane.add(searchField, BorderLayout.CENTER); + searchPane.add(searchLabel, BorderLayout.EAST); + panel.add(searchPane, BorderLayout.CENTER); + return panel; + } + + protected void filter(Connection connection, String conName, List nameList) { + connection.addConnection(nameList, conName, new Class[]{AbstractDatabaseConnection.class}); + } + + protected void addKeyMonitor() { + //do nothing + } + + protected JPanel createCheckBoxgroupPane() { + JPanel checkBoxgroupPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2); + JPanel first = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + tableCheckBox = new UICheckBox(); + tableCheckBox.setSelected(true); + tableCheckBox.addActionListener(filter); + first.add(tableCheckBox); + + JPanel second = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + viewCheckBox = new UICheckBox(); + viewCheckBox.setSelected(true); + viewCheckBox.addActionListener(filter); + second.add(viewCheckBox); + + // 根据环境是否为中文设置不同的显示 + if (GeneralContext.isChineseEnv()) { + first.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"), + BaseUtils.readIcon("/com/fr/design/images/data/tables.png"), UILabel.LEADING)); + second.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"), + BaseUtils.readIcon("/com/fr/design/images/data/views.png"), UILabel.LEADING)); + } else { + UILabel ui1 = new UILabel(BaseUtils.readIcon("/com/fr/design/images/data/tables.png"), UILabel.LEADING); + UILabel ui2 = new UILabel(BaseUtils.readIcon("/com/fr/design/images/data/views.png"), UILabel.LEADING); + ui1.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); + ui2.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); + first.add(ui1); + second.add(ui2); + } + checkBoxgroupPane.add(first); + checkBoxgroupPane.add(second); + + return checkBoxgroupPane; + } + + /** + * 给 itemComboBox 加上 itemListener + * + * @param itemListener + */ + public void addItemListener(ItemListener itemListener) { + connectionComboBox.itemComboBox.addItemListener(itemListener); + } + + private DocumentListener searchListener = new DocumentListener() { + + @Override + public void removeUpdate(DocumentEvent e) { + search(false); + } + + @Override + public void insertUpdate(DocumentEvent e) { + search(false); + } + + @Override + public void changedUpdate(DocumentEvent e) { + search(false); + } + }; + + private ActionListener filter = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + search(false); + } + }; + + /** + * 选项改变,需要重新刷新下拉列表里面的项 + */ + protected void search(boolean refresh) { + String selectedObj = connectionComboBox.getSelectedItem(); + + String[] types = ArrayUtils.EMPTY_STRING_ARRAY; + if (tableCheckBox != null) { + if (tableCheckBox.isSelected()) { + types = (String[]) ArrayUtils.add(types, TableProcedure.TABLE); + } + if (viewCheckBox.isSelected()) { + types = (String[]) ArrayUtils.add(types, TableProcedure.VIEW); + } + } else { + types = (String[]) ArrayUtils.add(types, TableProcedure.PROCEDURE); + } + tableViewList.populate(selectedObj, searchField.getText().trim(), refresh, types); + } + + @Override + protected String title4PopupWindow() { + return "Connection"; + } + + /** + * @param l + */ + public void addDoubleClickListener(DoubleClickSelectedNodeOnTreeListener l) { + this.listeners.add(l); + } + + public void setSelectedDatabaseConnection(com.fr.data.impl.Connection db) { + connectionComboBox.populate(db); + } + + public String getSelectedDatabaseConnnectonName() { + return connectionComboBox.getSelectedItem(); + } + + public static interface DoubleClickSelectedNodeOnTreeListener { + /** + * 处理双击事件 + * + * @param target + */ + public void actionPerformed(TableProcedure target); + } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java index 8b13789179..a430a13bd1 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java @@ -1 +1,183 @@ +package com.fr.design.data.datapane.connect; +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; + +import com.fr.log.FineLoggerFactory; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.Iterator; +import java.util.concurrent.CancellationException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JPanel; +import javax.swing.SwingWorker; + +public abstract class ItemEditableComboBoxPanel extends JPanel { + /** + * + */ + private static final long serialVersionUID = 1L; + + private static final String PENDING = Toolkit.i18nText("Fine-Design_Basic_Loading") + "..."; + + protected static final Object EMPTY = new Object() { + public String toString() { + return ""; + } + }; + + protected UIComboBox itemComboBox; + protected UIButton editButton; + protected UIButton refreshButton; + + private SwingWorker, Void> refreshWorker; + + public ItemEditableComboBoxPanel() { + super(); + + initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + Dimension buttonSize = new Dimension(26, 20); + itemComboBox = new UIComboBox(); + itemComboBox.setEnabled(true); + this.add(itemComboBox, BorderLayout.CENTER); + refreshButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + JPanel jPanel = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(2, 4 ,4); + editButton = initEditButton(editButton, buttonSize); + jPanel.add(editButton); + jPanel.add(refreshButton); + this.add(jPanel, BorderLayout.EAST); + refreshButton.setPreferredSize(buttonSize); + refreshButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + refreshItems(); + } + }); + } + + protected UIButton initEditButton(UIButton editButton, Dimension buttonSize) { + editButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/control-center2.png")); + editButton.setPreferredSize(buttonSize); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + editItems(); + } + }); + return editButton; + } + + + /** + * 给itemComboBox添加ActionListener + */ + public void addComboBoxActionListener(ActionListener l) { + itemComboBox.addActionListener(l); + } + + /* + * 刷新itemComboBox的内容 + */ + protected void refreshItems() { + + if (refreshWorker != null && !refreshWorker.isDone()) { + refreshWorker.cancel(true); + } + + // 记录原来选中的Item,重新加载后需要再次选中 + Object lastSelectedItem = itemComboBox.getSelectedItem(); + + DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); + model.removeAllElements(); + + // 先加EMPTY,再加items + model.addElement(EMPTY); + model.addElement(PENDING); + + // 存在两种场景之前只考虑了填充场景 有populate会填充下 把这边的填充逻辑删了 所以没有问题 + // 如果是纯通过刷新按钮 没有populate 需要手动设置下上次选中的内容 + if (lastSelectedItem != null) { + model.setSelectedItem(lastSelectedItem); + } + + refreshWorker = new SwingWorker, Void>() { + @Override + protected Iterator doInBackground() throws Exception { + return items(); + } + + @Override + protected void done() { + try { + Iterator itemIt = get(); + model.removeElement(PENDING); + while(itemIt.hasNext()) { + model.addElement(itemIt.next()); + } + // 如果加载成功 但是下拉框是可见的 下拉框高度是会固定为原始高度 不会因为填充了更多下拉项而变化 + // 需要重新设置下拉框高度 但值一样时相关事件不会生效 所以先加再减下 + if (itemComboBox.isPopupVisible()) { + itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1); + itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1); + } + afterRefreshItems(); + } catch (Exception e) { + if (!(e instanceof CancellationException)) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + refreshItemsError(); + } + + } + }; + refreshWorker.execute(); + } + + /* + * 得到其中的itemComboBox所选中的Item + */ + public String getSelectedItem() { + Object selected = itemComboBox.getSelectedItem(); + + return selected instanceof String ? (String)selected : null; + } + + /* + * 选中name项 + */ + public void setSelectedItem(String name) { + DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); + model.setSelectedItem(name); + } + + /* + * 刷新ComboBox.items + */ + protected abstract java.util.Iterator items(); + + /** + * 刷新ComboBox.items之后 + */ + protected void afterRefreshItems() { + // 空实现,供子类重写 + } + + /** + * 刷新ComboBox.items时出现异常 + */ + protected void refreshItemsError() { + // 空实现,供子类重写 + } + + /* + * 弹出对话框编辑Items + */ + protected abstract void editItems(); +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java index db0f03e72b..d0ffd7f22c 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java @@ -1,24 +1,35 @@ package com.fr.design.data.tabledata.tabledatapane; -import com.fine.state.livedata.DocumentLiveData; +import com.fr.base.Parameter; +import com.fr.base.ParameterHelper; +import com.fr.data.core.db.TableProcedure; import com.fr.data.impl.Connection; import com.fr.data.impl.DBTableData; import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JNDIDatabaseConnection; +import com.fr.data.impl.NameDatabaseConnection; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; +import com.fr.design.data.StrategyConfigAttrUtils; +import com.fr.design.data.datapane.ESDStrategyConfigPane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane; import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.design.data.tabledata.strategy.StrategyConfigHandler; +import com.fr.design.data.tabledata.tabledatapane.db.StrategyConfigFrom; import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane; import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.DBTableDataMenuHandler; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itableeditorpane.ParameterTableModel; import com.fr.design.gui.itableeditorpane.UITableEditAction; @@ -31,15 +42,25 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; +import com.fr.design.utils.ParameterUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.core.strategy.config.service.StrategyConfigService; +import com.fr.esd.data.db.DBTableDataSavedHook; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; +import com.fr.general.sql.SqlUtils; import com.fr.log.FineLoggerFactory; import com.fr.script.Calculator; import com.fr.stable.ArrayUtils; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; import javax.swing.BorderFactory; import javax.swing.Box; @@ -48,16 +69,20 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JToolBar; +import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import java.awt.BorderLayout; import java.awt.CardLayout; +import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.util.ArrayList; import java.util.List; /** @@ -74,22 +99,27 @@ public class DBTableDataPane extends AbstractTableDataPane implemen private UITableEditorPane editorPane; private DBTableDataMenuHandler dbTableDataMenuHandler; private SQLEditPane sqlTextPane; + private String pageQuery; + private DBTableData dbTableData; + //ESD + private UILabel esdSettingsLabel; + private UIComboBox esdConfigOption; + private UICheckBox esdEnabled; + private UIButton esdSettingsBtn; + private UILabel barErrorTips; + //配置 + private StrategyConfig strategyConfig; + + private StrategyConfigHandler configHandler; private CardLayout card; - /** - * 数据库查询面板真正的内容面板 - */ + /** 数据库查询面板真正的内容面板 */ private JPanel contentPane; - /** - * 加载中面板 - */ + /** 加载中面板 */ private JPanel loadingPane; - private DBTableDataViewModel viewModel; - public DBTableDataPane() { - viewModel = new DBTableDataViewModel(); initCards(); initContentPane(); } @@ -114,7 +144,7 @@ public class DBTableDataPane extends AbstractTableDataPane implemen add(LOADING_PANE_NAME, loadingPane); add(CONTENT_PANE_NAME, contentPane); - switchTo(CONTENT_PANE_NAME); + switchTo(LOADING_PANE_NAME); } private void init() { @@ -132,13 +162,7 @@ public class DBTableDataPane extends AbstractTableDataPane implemen editorPane = new UITableEditorPane<>(model); - this.connectionTableProcedurePane = new ConnectionTableProcedurePane( - new ConnectionTableProcedurePane.ConnectionTableState( - viewModel.getConnectionList(), - unused -> viewModel.fetchConnectionNameAction(), - viewModel.getTableProcedures(), - bean -> viewModel.fetchTableProceduresAction(bean) - )) { + this.connectionTableProcedurePane = new ConnectionTableProcedurePane(this) { @Override protected void filter(Connection connection, String conName, List nameList) { connection.addConnection(nameList, conName, new Class[]{ @@ -171,31 +195,35 @@ public class DBTableDataPane extends AbstractTableDataPane implemen }); } }; - this.connectionTableProcedurePane.addDoubleClickListener(target -> { - Document document = DBTableDataPane.this.sqlTextPane.getDocument(); - try { - document.insertString(DBTableDataPane.this.sqlTextPane.getCaretPosition(), target.toString(), null); - } catch (BadLocationException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); + this.connectionTableProcedurePane.addDoubleClickListener(new ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener() { + @Override + public void actionPerformed(TableProcedure target) { + Document document = DBTableDataPane.this.sqlTextPane.getDocument(); + try { + document.insertString(DBTableDataPane.this.sqlTextPane.getCaretPosition(), target.toString(), null); + } catch (BadLocationException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + + DBTableDataPane.this.sqlTextPane.requestFocus(); } - DBTableDataPane.this.sqlTextPane.requestFocus(); }); this.sqlTextPane.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { + barErrorTips.setVisible(false); } @Override public void focusLost(FocusEvent e) { if (DBTableDataPane.this.isPreviewOrRefreshButton(e)) { - viewModel.refreshParameters(); + DBTableDataPane.this.checkParameter(); } } }); - DocumentLiveData.fromDocumentEventsOf(sqlTextPane.getDocument()) - .observeForever(documentEvent -> viewModel.updateQuery(sqlTextPane.getText())); } private void initMainSplitPane() { @@ -265,6 +293,16 @@ public class DBTableDataPane extends AbstractTableDataPane implemen return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); } + private void refreshParameters() { + String[] paramTexts = new String[2]; + paramTexts[0] = SqlUtils.tryPureSqlText(this.sqlTextPane.getText()); + paramTexts[1] = SqlUtils.tryPureSqlText(this.pageQuery); + List existParameterList = this.editorPane.update(); + Parameter[] ps = (existParameterList == null) ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); + + this.editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps)); + } + private JToolBar createToolBar() { ToolBarDef toolBarDef = new ToolBarDef(); toolBarDef.addShortCut(new PreviewAction()); @@ -281,105 +319,248 @@ public class DBTableDataPane extends AbstractTableDataPane implemen toolBarDef.updateToolBar(editToolBar); //esd相关组件初始化 -// createToolbarEsdComponents(editToolBar); + createToolbarEsdComponents(editToolBar); return editToolBar; } + private void createToolbarEsdComponents(final UIToolbar editToolBar) { + this.esdSettingsLabel = new UILabel(Toolkit.i18nText("Fine-Design_ESD_Cache_Settings")); + this.esdConfigOption = new UIComboBox(StrategyConfigFrom.values()); + this.esdEnabled = new UICheckBox(Toolkit.i18nText("Fine-Design_ESD_Enable_Cache")); + this.barErrorTips = new UILabel(); + this.barErrorTips.setForeground(Color.RED); + this.barErrorTips.setVisible(false); + + esdSettingsBtn = new UIButton(Toolkit.i18nText("Fine-Design_ESD_Strategy_Config")); + esdSettingsBtn.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final boolean global = globalOptionSelected(); + + final ESDStrategyConfigPane strategyConfigPane = new ESDStrategyConfigPane(global); + + StrategyConfig populateStrategyConfig; + if (global) { + populateStrategyConfig = StrategyConfigService.getGlobalConfig(); + } else { + populateStrategyConfig = strategyConfig; + } + + //显示对应的配置 + strategyConfigPane.populateBean(populateStrategyConfig); + + BasicDialog dlg = strategyConfigPane.showMediumWindow(SwingUtilities.getWindowAncestor(DBTableDataPane.this), new DialogActionAdapter() { + @Override + public void doOk() { + super.doOk(); + if (!global) { + //点击策略配置面板的确定,重新设置策略配置 + strategyConfig = strategyConfigPane.updateBean(); + // TODO: 2021/3/12 这个直接使用不太好 + } + } + }); + //dlg.setAlwaysOnTop(true); + dlg.setVisible(true); + } + }); + + this.esdConfigOption.setSelectedIndex(StrategyConfigFrom.GLOBAL.getIndex()); + this.esdConfigOption.addActionListener(e -> setEsdEnabled()); + + + //工具栏加上esd相关组件 + editToolBar.add(this.esdSettingsLabel); + editToolBar.add(this.esdConfigOption); + editToolBar.add(this.esdEnabled); + editToolBar.add(this.esdSettingsBtn); + editToolBar.add(this.barErrorTips); + } + + private boolean globalOptionSelected() { + return esdConfigOption.getSelectedIndex() == StrategyConfigFrom.GLOBAL.getIndex(); + } + + private void setEsdEnableStatus(boolean selected, boolean enabled) { + this.esdEnabled.setSelected(selected); + this.esdEnabled.setEnabled(enabled); + } + + private void setEsdEnabled() { + boolean useIndividualConfig = !this.globalOptionSelected(); + if (useIndividualConfig) { + if (this.strategyConfig == null) { + //新建的数据集,选择单独时,可用但是不勾选 + setEsdEnableStatus(false, true); + } else { + setEsdEnableStatus(!this.strategyConfig.isUseGlobal() && this.strategyConfig.enabled(), true); + } + } else { + //判断是不是模版数据集 + switch (this.dbTableData.getScope()) { + case TEMPLATE: + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + setEsdEnableStatus(StrategyConfigService.isTemplateEnabled(tplPath), false); + break; + case SERVER: + //不会走到这里 + default: + break; + } + } + } public StrategyConfig updateStrategyConfig() { - return null; + return this.strategyConfig; } - @Override - public void populateBean(DBTableData tableData) { - this.viewModel.updateTableData(tableData); - this.viewModel.getDbTableData().observeForever(dbTableData -> { - if (this.dbTableDataMenuHandler != null) { - this.dbTableDataMenuHandler.populate(dbTableData); + private void checkParameter() { + String[] paramTexts = new String[2]; + paramTexts[0] = this.sqlTextPane.getText(); + paramTexts[1] = this.pageQuery; + Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); + + if (parameters.length < 1 && this.editorPane.update().size() < 1) { + return; + } + boolean isIn = true; + List list = this.editorPane.update(); + List name = new ArrayList<>(); + for (ParameterProvider parameter : list) { + name.add(parameter.getName()); + } + for (Parameter parameter : parameters) { + if (!name.contains(parameter.getName())) { + isIn = false; + break; } - editorPane.populate(dbTableData.getParameters(Calculator.createCalculator())); - connectionTableProcedurePane.setSelectedDatabaseConnection(dbTableData.getDatabase()); - connectionTableProcedurePane.addItemListener(event -> { - String dbName = connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); -// if (StringUtils.isBlank(dbName) || StringUtils.isBlank(sqlTextPane.getText())) { -// try { -// throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); -// } catch (Exception e) { -// FineLoggerFactory.getLogger().error(e.getMessage(), e); -// } -// } - viewModel.updateDBName(dbName); - }); + } + if (list.size() == parameters.length && isIn) { + return; + } - }); + refreshParameters(); + } - this.sqlTextPane.setText(tableData.getQuery()); - this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition()); + @Override + public void populateBean(DBTableData dbTableData) { + this.dbTableData = dbTableData; + if (this.dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler.populate(dbTableData); + } + + + Calculator c = Calculator.createCalculator(); + + ParameterProvider[] parameters = dbTableData.getParameters(c); + this.editorPane.populate(parameters); + + + Connection db = dbTableData.getDatabase(); + String query = dbTableData.getQuery(); + this.pageQuery = dbTableData.getPageQuerySql(); + this.connectionTableProcedurePane.setSelectedDatabaseConnection(db); + this.sqlTextPane.setText(query); this.sqlTextPane.requestFocus(); + this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition()); + switch (dbTableData.getScope()) { + + case TEMPLATE: + this.configHandler = new TemplateStrategyConfigHandler(dbTableData); + break; + case SERVER: + //服务器数据集 + default: + //新建服务器数据集 + this.configHandler = new ServerStrategyConfigHandler(dbTableData); + break; + } //设置esd相关组件显示状态 -// populateESDComponents(); + populateESDComponents(); } -// private void populateESDComponents() { -// //查找映射的配置 -// this.strategyConfig = configHandler.find(); -// -// boolean shouldEnable = false; -// StrategyConfigFrom from = StrategyConfigFrom.GLOBAL; -// -// if (this.strategyConfig != null) { -// if (this.strategyConfig.enabled()) { -// shouldEnable = true; -// } -// if (!this.strategyConfig.isUseGlobal()) { -// from = StrategyConfigFrom.INDIVIDUAL; -// } -// } -// -// //服务器数据集不允许设置来源,只能单独配置 -// if (dbTableData.getScope() != StrategicTableData.Scope.TEMPLATE) { -// from = StrategyConfigFrom.INDIVIDUAL; -// this.esdConfigOption.setEnabled(false); -// } -// this.esdEnabled.setSelected(shouldEnable); -// this.esdConfigOption.setSelectedIndex(from.getIndex()); -// } + private void populateESDComponents() { + //查找映射的配置 + this.strategyConfig = configHandler.find(); + + boolean shouldEnable = false; + StrategyConfigFrom from = StrategyConfigFrom.GLOBAL; + + if (this.strategyConfig != null) { + if (this.strategyConfig.enabled()) { + shouldEnable = true; + } + if (!this.strategyConfig.isUseGlobal()) { + from = StrategyConfigFrom.INDIVIDUAL; + } + } + + //服务器数据集不允许设置来源,只能单独配置 + if (dbTableData.getScope() != StrategicTableData.Scope.TEMPLATE) { + from = StrategyConfigFrom.INDIVIDUAL; + this.esdConfigOption.setEnabled(false); + } + this.esdEnabled.setSelected(shouldEnable); + this.esdConfigOption.setSelectedIndex(from.getIndex()); + } @Override public DBTableData updateBean() { updateDBTableData(); -// internalUpdateStrategyConfig(); + internalUpdateStrategyConfig(); - return viewModel.getDbTableData().getValue(); + return this.dbTableData; } -// private void internalUpdateStrategyConfig() { -// //这边只修改enable和useGlobal -// boolean global = globalOptionSelected(); -// boolean enable = this.esdEnabled.isSelected(); -// -// -// //未开启缓存的,如果选择了单独配置,需要创建配置 -// if (this.strategyConfig == null && !global) { -// this.strategyConfig = StrategyConfig.createDefault(); -// } -// -// //设置配置来源和开启状态 -// if (this.strategyConfig != null) { -// this.strategyConfig.setEnable(enable); -// this.strategyConfig.setUseGlobal(global); -// } -// -// //保存 -// this.configHandler.save(this.dbTableData, this.strategyConfig); -// } + private void internalUpdateStrategyConfig() { + //这边只修改enable和useGlobal + boolean global = globalOptionSelected(); + boolean enable = this.esdEnabled.isSelected(); + + + //未开启缓存的,如果选择了单独配置,需要创建配置 + if (this.strategyConfig == null && !global) { + this.strategyConfig = StrategyConfig.createDefault(); + } + + //设置配置来源和开启状态 + if (this.strategyConfig != null) { + this.strategyConfig.setEnable(enable); + this.strategyConfig.setUseGlobal(global); + } + + //保存 + this.configHandler.save(this.dbTableData, this.strategyConfig); + } private void updateDBTableData() { + String dbName = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); + if (StringUtils.isBlank(dbName) || StringUtils.isBlank(this.sqlTextPane.getText())) { + try { + throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + + // 保存前 刷新下参数列表 保证获取到最新的参数 + refreshParameters(); + + List parameterList = this.editorPane.update(); + ParameterProvider[] parameters = parameterList.toArray(new ParameterProvider[0]); + + dbTableData.setDatabase(new NameDatabaseConnection(dbName)); + - viewModel.refreshParameters(); + dbTableData.setParameters(parameters); + dbTableData.setQuery(this.sqlTextPane.getText().trim()); + + dbTableData.setPageQuerySql(this.pageQuery); if (this.dbTableDataMenuHandler != null) { this.dbTableDataMenuHandler.update(); } @@ -394,7 +575,7 @@ public class DBTableDataPane extends AbstractTableDataPane implemen @Override public void actionPerformed(ActionEvent e) { - viewModel.refreshParameters(); + DBTableDataPane.this.refreshParameters(); } @@ -413,6 +594,7 @@ public class DBTableDataPane extends AbstractTableDataPane implemen @Override public void actionPerformed(ActionEvent evt) { + DBTableDataPane.this.checkParameter(); PreviewTablePane.previewTableData(DBTableDataPane.this.updateBean()); } } @@ -426,7 +608,7 @@ public class DBTableDataPane extends AbstractTableDataPane implemen @Override public void actionPerformed(ActionEvent e) { - viewModel.refreshParameters(); + checkParameter(); PreviewPerformedSqlPane.previewPerformedSql(DBTableDataPane.this.updateBean()); } } @@ -441,13 +623,13 @@ public class DBTableDataPane extends AbstractTableDataPane implemen @Override public void actionPerformed(ActionEvent e) { final QueryPane pane = new QueryPane(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL")); - pane.populate(viewModel.getDbTableData().getValue().getPageQuerySql()); + pane.populate(pageQuery); BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame()); dialog.addDialogActionListener(new DialogActionAdapter() { @Override public void doOk() { - viewModel.updatePageQuery(pane.update()); - viewModel.refreshParameters(); + pageQuery = pane.update(); + checkParameter(); } }); dialog.setVisible(true); @@ -491,4 +673,117 @@ public class DBTableDataPane extends AbstractTableDataPane implemen } } + /** + * 服务器数据集配置处理器 + */ + private static class ServerStrategyConfigHandler extends StrategyConfigHandler { + private final String origName; + + private final String origConnection; + + private final String origQuery; + + public ServerStrategyConfigHandler(DBTableData tableData) { + super(tableData); + this.origName = tableData.getDsName(); + this.origConnection = tableData.getDatabase().toString(); + this.origQuery = tableData.getQuery(); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + if (getTableData() != null) { + strategyConfig = getTableData().getStrategyConfig(); + if (strategyConfig == null) { + //共享数据集 + if (getTableData().isShare()) { + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + } + + return strategyConfig; + } + + @Override + public void save(DBTableData saved, StrategyConfig strategyConfig) { + String conn = saved.getDatabase().toString(); + String query = saved.getQuery(); + + + //检查数据链接和sql是否修改,如果修改需要触发缓存监听事件 + if (!conn.equals(origConnection) || !query.equals(origQuery)) { + if (StringUtils.isNotEmpty(origName)) { + //新建数据集的origName为null,不用触发 + StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(origName))); + } + } + + + //配置变动事件 + try { + final StrategyConfig orig = getTableData().getStrategyConfig(); + saved.setStrategyConfig(strategyConfig.clone()); + StrategyEventsNotifier.compareAndFireConfigEvents(orig, strategyConfig, DSMapping.ofServerDS(new DsNameTarget(saved.getDsName()))); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + + /** + * 模版数据集配置处理器 + */ + private static class TemplateStrategyConfigHandler extends StrategyConfigHandler { + public TemplateStrategyConfigHandler(DBTableData tableData) { + super(tableData); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + if (getTableData() != null && StringUtils.isNotEmpty(tplPath)) { + //设置保存数据集的事件检查钩子 + //新建模版此时不存在,不需要注册钩子 + if (getTableData().getXmlSavedHook() == null && WorkContext.getWorkResource().exist(tplPath)) { + getTableData().setXmlSavedHook(new DBTableDataSavedHook(tplPath, getTableData())); + } + + //获取当前的缓存配置,没有就创建一份 + String dsName = getTableData().getDsName(); + + //这里为了之前兼容插件创建的配置,缓存配置不在DBTableData,而是从模版attr读取 + strategyConfig = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + + if (useGlobal(getTableData(), strategyConfig)) { + //使用全局配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true); + } else if (strategyConfig == null && getTableData().isShare()) { + //没有配置时,使用共享数据集兼容配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + + return strategyConfig; + } + + private boolean useGlobal(DBTableData dbTableData, StrategyConfig strategyConfig) { + //非共享且配置为空或者指定使用全局配置时,检查是否全局开启 + if (strategyConfig == null) { + return !dbTableData.isShare(); + } else { + return strategyConfig.isUseGlobal(); + } + } + + @Override + public void save(DBTableData saved, StrategyConfig config) { + + //DBTableDataSavedHook处理了 + } + } } diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataViewModel.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataViewModel.java deleted file mode 100644 index 6260e4960b..0000000000 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataViewModel.java +++ /dev/null @@ -1,281 +0,0 @@ -package com.fr.design.data.tabledata.tabledatapane; - -import com.fine.state.livedata.LiveData; -import com.fine.state.livedata.MutableLiveData; -import com.fr.base.Parameter; -import com.fr.base.ParameterHelper; -import com.fr.base.TableData; -import com.fr.data.core.DataCoreUtils; -import com.fr.data.core.db.TableProcedure; -import com.fr.data.core.db.dialect.base.key.check.DataBaseDetail; -import com.fr.data.core.db.dialect.base.key.check.DataBaseType; -import com.fr.data.impl.AbstractDatabaseConnection; -import com.fr.data.impl.Connection; -import com.fr.data.impl.DBTableData; -import com.fr.data.impl.NameDatabaseConnection; -import com.fr.data.operator.DataOperator; -import com.fr.design.DesignerEnvManager; -import com.fr.design.gui.ilist.TableViewList; -import com.fr.design.utils.ParameterUtils; -import com.fr.file.ConnectionConfig; -import com.fr.general.ComparatorUtils; -import com.fr.general.sql.SqlUtils; -import com.fr.stable.ArrayUtils; -import com.fr.stable.ParameterProvider; -import com.fr.stable.StringUtils; -import com.fr.workspace.WorkContext; -import com.fr.workspace.server.connection.DBConnectAuth; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -import static com.fr.data.core.db.TableProcedure.ERROR_TABLE_PROCEDURE; - -/** - * 数据集界面视图模型 - * - * @author vito - * @since 11.0 - * Created on 2023/11/7 - */ -public class DBTableDataViewModel { - - private MutableLiveData dbTableData = new MutableLiveData<>(); - private MutableLiveData> connectionList = new MutableLiveData<>(Collections.emptyList()); - private MutableLiveData> tableProcedures = new MutableLiveData<>(Collections.emptyList()); - - public DBTableDataViewModel() { - } - - public LiveData getDbTableData() { - return dbTableData; - } - - public LiveData> getConnectionList() { - return connectionList; - } - - public LiveData> getTableProcedures() { - return tableProcedures; - } - - /* ---------action--------- */ - public void updateTableData(TableData tableData) { - if (!(tableData instanceof DBTableData)) { - return; - } - dbTableData.postValue((DBTableData) tableData); - } - - - public void fetchConnectionNameAction() { - new Thread(() -> { - - ConnectionConfig mgr = ConnectionConfig.getInstance(); - Set connectionName = mgr.getConnections().keySet(); - - Collection noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections(); - - ArrayList nameList = new ArrayList<>(); - - if (noAuthConnections == null) { - connectionList.postValue(Collections.emptyList()); - return; - } - for (String conName : connectionName) { - if (noAuthConnections.contains(conName)) { - continue; - } - Connection connection = mgr.getConnection(conName); - connection.addConnection(nameList, conName, new Class[]{AbstractDatabaseConnection.class}); - } - connectionList.postValue(nameList); - }).start(); - } - - public void fetchTableProceduresAction(TableViewList.TableProcedureBean tableProcedureBean) { - new Thread(() -> { - List list; - try { - list = fetchTableProcedures(tableProcedureBean); - } catch (Exception e) { - list = new ArrayList<>(); - list.add(ERROR_TABLE_PROCEDURE); - } - tableProcedures.postValue(list); - }).start(); - } - - /** - * august:databaseName是数据库名字,searchFilter是输入的过滤条件,typesFilter是视图、表、 - * 存储过程中的一者或者几者 - * - * @param bean 数据 - */ - private List fetchTableProcedures(TableViewList.TableProcedureBean bean) throws Exception { - if (bean.refresh) { - clearCache(ConnectionConfig.getInstance().getConnection(bean.databaseName)); - } - Connection datasource = ConnectionConfig.getInstance().getConnection(bean.databaseName); - if (datasource == null) { - return Collections.emptyList(); - } - String[] schemas = DataCoreUtils.getDatabaseSchema(datasource); - - String searchFilter = bean.searchFilter.toLowerCase(); - boolean isOracleSystemSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); - // oracle不勾选显示所有表,则只显示用户下的(包括存储过程和table表) - DataBaseDetail detail = DataOperator.getInstance().getDataBaseDetail(datasource, isOracleSystemSpace); - if (ArrayUtils.isNotEmpty(detail.getSchemas())) { - schemas = detail.getSchemas(); - } - if (bean.typesFilter.length == 1 && ComparatorUtils.equals(bean.typesFilter[0], TableProcedure.PROCEDURE)) { - return processStoreProcedure(schemas, datasource, DataBaseType.ORACLE.equals(detail.getType()), searchFilter); - } else { - return processTableAndView(schemas, datasource, searchFilter, DataBaseType.ORACLE.equals(detail.getType()), bean.typesFilter); - } - } - - private void clearCache(Connection datasource) { - String[] schemas = DataCoreUtils.getDatabaseSchema(datasource); - schemas = (schemas == null || schemas.length == 0) ? new String[]{null} : schemas; - for (String schema : schemas) { - doClearCache(datasource, schema); - } - doClearCache(datasource, null); - } - - private void doClearCache(Connection datasource, String schema) { - DataCoreUtils.refreshTables(datasource, TableProcedure.TABLE, schema); - DataCoreUtils.refreshTables(datasource, TableProcedure.VIEW, schema); - DataCoreUtils.refreshTables(datasource, TableProcedure.PROCEDURE, schema); - } - - private List processStoreProcedure(String[] schemas, Connection datasource, boolean isOracle, String searchFilter) throws Exception { - List tableProcedures = new ArrayList<>(); - boolean isBlank = StringUtils.isBlank(searchFilter); - boolean isOracleSysSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); - List sqlTablees = DataCoreUtils.getProcedures(datasource, schemas, isOracle, isOracleSysSpace); - for (TableProcedure[] sqlTables : sqlTablees) { - if (sqlTables == null) { - continue; - } - for (TableProcedure sqlTable : sqlTables) { - String name = sqlTable.toString().toLowerCase(); - if (isBlank || name.contains(searchFilter)) { - tableProcedures.add(sqlTable); - } - } - } - return tableProcedures; - } - - private List processTableAndView(String[] schemas, Connection datasource, String searchFilter, boolean isOracle, String... typesFilter) - throws Exception { - List tableProcedures = new ArrayList<>(); - boolean isBlank = StringUtils.isBlank(searchFilter); - boolean isOracleSystemSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); - if (!isOracle) { - String schema = null; - for (String type : typesFilter) { - //非oracle数据库,默认都是显示所有表的,参数为true - TableProcedure[] sqlTables = DataCoreUtils.getTables(datasource, type, schema, true); - if (Objects.isNull(sqlTables)) { - return tableProcedures; - } - for (TableProcedure sqlTable : sqlTables) { - if (isBlank || sqlTable.getName().toLowerCase().contains(searchFilter)) { - tableProcedures.add(sqlTable); - } - } - } - } else { - for (String type : typesFilter) { - for (String schema : schemas) { - TableProcedure[] sqlTables = DataCoreUtils.getTables(datasource, type, schema, isOracleSystemSpace); - if (Objects.isNull(sqlTables)) { - return tableProcedures; - } - // oracle的表名加上模式 - for (TableProcedure ta : sqlTables) { - String name = ta.getSchema() + '.' + ta.getName(); - if (isBlank || name.toLowerCase().contains(searchFilter)) { - tableProcedures.add(ta); - } - } - } - } - } - return tableProcedures; - } - - public void updatePageQuery(String pageQuery) { - DBTableData tableData = dbTableData.getValue(); - if (ComparatorUtils.equals(pageQuery, tableData.getPageQuerySql())) { - return; - } - tableData.setPageQuerySql(pageQuery); - dbTableData.postValue(tableData); - } - - public void updateQuery(String query) { - DBTableData tableData = dbTableData.getValue(); - if (ComparatorUtils.equals(query, tableData.getQuery())) { - return; - } - tableData.setQuery(query); - dbTableData.postValue(tableData); - } - - public void refreshParameters() { - DBTableData tableData = dbTableData.getValue(); - if (needRefreshParameter(tableData)) { - tableData.setParameters(calParameter(tableData)); - } - dbTableData.postValue(tableData); - } - - private boolean needRefreshParameter(DBTableData tableData) { - String[] paramTexts = new String[2]; - paramTexts[0] = tableData.getQuery(); - paramTexts[1] = tableData.getPageQuerySql(); - Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); - - if (parameters.length < 1 && tableData.getParameters().length < 1) { - return false; - } - boolean isIn = true; - ParameterProvider[] list = tableData.getParameters(); - List name = new ArrayList<>(); - for (ParameterProvider parameter : list) { - name.add(parameter.getName()); - } - for (Parameter parameter : parameters) { - if (!name.contains(parameter.getName())) { - isIn = false; - break; - } - } - return list.length != parameters.length || !isIn; - } - - private Parameter[] calParameter(DBTableData tableData) { - - String[] paramTexts = new String[2]; - paramTexts[0] = SqlUtils.tryPureSqlText(tableData.getQuery()); - paramTexts[1] = SqlUtils.tryPureSqlText(tableData.getPageQuerySql()); - Parameter[] oldParameters = Arrays.asList(tableData.getParameters()).toArray(new Parameter[0]); - return ParameterUtils.analyzeAndUnionParameters(paramTexts, oldParameters); - } - - public void updateDBName(String dbName) { - DBTableData tableData = dbTableData.getValue(); - tableData.setDatabase(new NameDatabaseConnection(dbName)); - dbTableData.postValue(tableData); - } -}