5 changed files with 929 additions and 787 deletions
@ -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<Iterator<String>, 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<Iterator<String>, Void>() { |
||||||
|
@Override |
||||||
|
protected Iterator<String> doInBackground() throws Exception { |
||||||
|
return items(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
try { |
||||||
|
Iterator<String> 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<String> items(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新ComboBox.items之后 |
||||||
|
*/ |
||||||
|
protected void afterRefreshItems() { |
||||||
|
// 空实现,供子类重写
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新ComboBox.items时出现异常 |
||||||
|
*/ |
||||||
|
protected void refreshItemsError() { |
||||||
|
// 空实现,供子类重写
|
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
* 弹出对话框编辑Items |
||||||
|
*/ |
||||||
|
protected abstract void editItems(); |
||||||
|
} |
||||||
|
@ -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> dbTableData = new MutableLiveData<>(); |
|
||||||
private MutableLiveData<List<String>> connectionList = new MutableLiveData<>(Collections.emptyList()); |
|
||||||
private MutableLiveData<Collection<TableProcedure>> tableProcedures = new MutableLiveData<>(Collections.emptyList()); |
|
||||||
|
|
||||||
public DBTableDataViewModel() { |
|
||||||
} |
|
||||||
|
|
||||||
public LiveData<DBTableData> getDbTableData() { |
|
||||||
return dbTableData; |
|
||||||
} |
|
||||||
|
|
||||||
public LiveData<List<String>> getConnectionList() { |
|
||||||
return connectionList; |
|
||||||
} |
|
||||||
|
|
||||||
public LiveData<Collection<TableProcedure>> 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<String> connectionName = mgr.getConnections().keySet(); |
|
||||||
|
|
||||||
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections(); |
|
||||||
|
|
||||||
ArrayList<String> 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<TableProcedure> 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<TableProcedure> 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<TableProcedure> processStoreProcedure(String[] schemas, Connection datasource, boolean isOracle, String searchFilter) throws Exception { |
|
||||||
List<TableProcedure> tableProcedures = new ArrayList<>(); |
|
||||||
boolean isBlank = StringUtils.isBlank(searchFilter); |
|
||||||
boolean isOracleSysSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); |
|
||||||
List<TableProcedure[]> 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<TableProcedure> processTableAndView(String[] schemas, Connection datasource, String searchFilter, boolean isOracle, String... typesFilter) |
|
||||||
throws Exception { |
|
||||||
List<TableProcedure> 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<String> 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); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue