diff --git a/src/main/engine/net/sf/jailer/JailerVersion.java b/src/main/engine/net/sf/jailer/JailerVersion.java index 1334dc582..bf31d025d 100644 --- a/src/main/engine/net/sf/jailer/JailerVersion.java +++ b/src/main/engine/net/sf/jailer/JailerVersion.java @@ -25,7 +25,7 @@ public class JailerVersion { /** * The Jailer version. */ - public static final String VERSION = "9.4.2.4"; + public static final String VERSION = "9.4.3"; /** * The Jailer working tables version. diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/BrowserContentPane.java b/src/main/gui/net/sf/jailer/ui/databrowser/BrowserContentPane.java index dad199528..85e5fe0b8 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/BrowserContentPane.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/BrowserContentPane.java @@ -1,6498 +1,6505 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser; - -import java.awt.BasicStroke; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; -import java.math.BigDecimal; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.SQLXML; -import java.sql.Types; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.PriorityBlockingQueue; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ActionMap; -import javax.swing.BorderFactory; -import javax.swing.DefaultCellEditor; -import javax.swing.DefaultComboBoxModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.InputMap; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.JTree; -import javax.swing.KeyStroke; -import javax.swing.ListCellRenderer; -import javax.swing.RowSorter; -import javax.swing.RowSorter.SortKey; -import javax.swing.SortOrder; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.border.LineBorder; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.event.RowSorterEvent; -import javax.swing.event.RowSorterListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; - -import net.coderazzi.filters.gui.AutoChoices; -import net.coderazzi.filters.gui.TableFilterHeader; -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.configuration.Configuration; -import net.sf.jailer.database.InlineViewStyle; -import net.sf.jailer.database.Session; -import net.sf.jailer.database.Session.AbstractResultSetReader; -import net.sf.jailer.database.SqlException; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.Cardinality; -import net.sf.jailer.datamodel.Column; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.PrimaryKey; -import net.sf.jailer.datamodel.RestrictionDefinition; -import net.sf.jailer.datamodel.RowIdSupport; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.extractionmodel.ExtractionModel; -import net.sf.jailer.extractionmodel.SubjectLimitDefinition; -import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; -import net.sf.jailer.modelbuilder.MemorizedResultSet.MemorizedResultSetMetaData; -import net.sf.jailer.subsetting.ScriptFormat; -import net.sf.jailer.ui.DataModelManager; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.Environment; -import net.sf.jailer.ui.ExtractionModelFrame; -import net.sf.jailer.ui.JComboBox; -import net.sf.jailer.ui.QueryBuilderDialog; -import net.sf.jailer.ui.QueryBuilderDialog.Relationship; -import net.sf.jailer.ui.StringSearchPanel; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; -import net.sf.jailer.ui.databrowser.Desktop.RowToRowLink; -import net.sf.jailer.ui.databrowser.RowCounter.RowCount; -import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; -import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; -import net.sf.jailer.ui.scrollmenu.JScrollC2Menu; -import net.sf.jailer.ui.scrollmenu.JScrollMenu; -import net.sf.jailer.ui.syntaxtextarea.BasicFormatterImpl; -import net.sf.jailer.util.CancellationException; -import net.sf.jailer.util.CancellationHandler; -import net.sf.jailer.util.CellContentConverter; -import net.sf.jailer.util.CellContentConverter.PObjectWrapper; -import net.sf.jailer.util.Pair; -import net.sf.jailer.util.Quoting; -import net.sf.jailer.util.SqlUtil; - -/** - * Content UI of a row browser frame (as {@link JInternalFrame}s). Contains a - * table for rendering rows. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public abstract class BrowserContentPane extends javax.swing.JPanel { - - /** - * Concurrently loads rows. - */ - public class LoadJob implements RunnableWithPriority { - private List rows = Collections.synchronizedList(new ArrayList()); - private Throwable exception; - private boolean isCanceled; - private final int limit; - private final String andCond; - private final boolean selectDistinct; - private boolean finished; - private final ResultSet inputResultSet; - private final RowBrowser parentBrowser; - private Session theSession; - private final Boolean forceAdjustRows; - public boolean closureLimitExceeded = false; - - public LoadJob(int limit, String andCond, RowBrowser parentBrowser, boolean selectDistinct) { - this.andCond = andCond; - this.selectDistinct = selectDistinct; - this.inputResultSet = null; - synchronized (this) { - this.limit = limit; - finished = false; - isCanceled = false; - this.parentBrowser = parentBrowser; - this.forceAdjustRows = Desktop.forceAdjustRows; - } - } - - public LoadJob(ResultSet inputResultSet, int limit) { - this.andCond = ""; - this.selectDistinct = false; - this.inputResultSet = inputResultSet; - synchronized (this) { - this.limit = limit; - finished = false; - isCanceled = false; - parentBrowser = null; - this.forceAdjustRows = Desktop.forceAdjustRows; - } - } - - private boolean reconnectIfConnectionIsInvalid(boolean updateMode) { - try { - if (inputResultSet == null) { - if (!session.getConnection().isValid(8)) { - if (updateMode) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - loadingLabel.setText("reconnecting..."); - } - }); - } - session.reconnect(); - return true; - } - } - } catch (Throwable t) { - // ignore - } - return false; - } - - @Override - public void run() { - int l; - synchronized (this) { - theSession = session; - l = limit; - if (isCanceled) { - CancellationHandler.reset(this); - return; - } - } - - boolean reconnectAndRetry = false; - - rowCountCache.clear(); - try { - reloadRows(inputResultSet, andCond, rows, this, l + 1, selectDistinct); - CancellationHandler.checkForCancellation(this); - synchronized (this) { - finished = true; - } - } catch (SQLException e) { - reconnectAndRetry = true; - } catch (CancellationException e) { - Session._log.info("cancelled"); - CancellationHandler.reset(this); - return; - } catch (Throwable e) { - reconnectAndRetry = true; - } - - if (reconnectAndRetry) { - rowCountCache.clear(); - boolean reconnected = reconnectIfConnectionIsInvalid(true); - try { - if (reconnected) { - session.getMetaData(); // fail-fast - } - reloadRows(inputResultSet, andCond, rows, this, l + 1, selectDistinct); - CancellationHandler.checkForCancellation(this); - synchronized (this) { - finished = true; - } - } catch (SQLException e) { - synchronized (rows) { - exception = e; - } - } catch (CancellationException e) { - Session._log.info("cancelled"); - CancellationHandler.reset(this); - return; - } catch (Throwable e) { - synchronized (rows) { - exception = e; - } - } - } - - if (!finished) { - reconnectIfConnectionIsInvalid(false); - } - CancellationHandler.reset(this); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = forceAdjustRows; - Throwable e; - int l; - boolean limitExceeded = false; - synchronized (rows) { - e = exception; - l = limit; - while (rows.size() > limit) { - limitExceeded = true; - rows.remove(rows.size() - 1); - } - isCanceled = true; // done - sortRowsByParentViewIndex(); - } - if (e != null) { - updateMode("error", null); - unhide(); - if (theSession == null || !theSession.isDown()) { - errorMessageTextArea.setText(e.getMessage()); - errorMessageTextArea.setToolTipText(UIUtil.toHTML(UIUtil.lineWrap(e.getMessage(), 100).toString(), 120)); - errorMessageTextArea.setCaretPosition(0); - if (shouldShowLoadErrors()) { - SQLException sqlException = null; - if (e instanceof SqlException && e.getCause() != null && e.getCause() instanceof SQLException) { - sqlException = (SQLException) e.getCause(); - } - if (sqlException != null && sqlException.getMessage() != null && sqlException.getMessage().trim().length() > 0) { - currentErrorDetail = e; - errorDetailsButton.setVisible(true); - errorMessageTextArea.setText(sqlException.getMessage()); - errorMessageTextArea.setToolTipText(UIUtil.toHTML(UIUtil.lineWrap(e.getMessage(), 100).toString(), 120)); - if (e instanceof SqlException) { - String sqlStatement = ((SqlException) e).sqlStatement; - if (sqlStatement != null && sqlStatement.trim().length() > 0) { - String HR = "(!insHorizontRulHere!)"; - String sql = HR - + new BasicFormatterImpl().format(sqlStatement); - errorMessageTextArea.setToolTipText( - UIUtil.toHTML(UIUtil.lineWrap(sqlException.getMessage().trim(), 100).toString() - + UIUtil.LINE_SEPARATOR + sql, 120).replace(HR, "
")); - } - } - errorMessageTextArea.setCaretPosition(0); - } else if (!showingLoadErrorNow) { - if (getRowBrowser() != null && getRowBrowser().internalFrame != null && getRowBrowser().internalFrame.isVisible()) { - try { - showingLoadErrorNow = true; - UIUtil.showException(BrowserContentPane.this, "Error", e); - } finally { - showingLoadErrorNow = false; - } - } - } - } - } else { - theSession = null; - } - } else { - Set prevIDs = new TreeSet(); - long prevHash = 0; - for (Row r: BrowserContentPane.this.rows) { - prevIDs.add(r.nonEmptyRowId); - try { - for (Object v: r.values) { - if (v != null) { - prevHash = 2 * prevHash + v.hashCode(); - } - } - } catch (RuntimeException e1) { - // ignore - } - } - onContentChange(new ArrayList(), false); - BrowserContentPane.this.rows.clear(); - BrowserContentPane.this.rows.addAll(rows); - updateTableModel(l, limitExceeded, closureLimitExceeded); - Set currentIDs = new TreeSet(); - long currentHash = 0; - if (rows != null) { - for (Row r: rows) { - currentIDs.add(r.nonEmptyRowId); - try { - for (Object v: r.values) { - if (v != null) { - currentHash = 2 * currentHash + v.hashCode(); - } - } - } catch (RuntimeException e1) { - // ignore - } - } - } - setPendingState(false, true); - onContentChange(rows, true); // rows.isEmpty() || currentHash != prevHash || rows.size() != prevSize || !prevIDs.equals(currentIDs) || rows.size() != currentIDs.size()); - updateMode("table", null); - updateWhereField(); - if (reloadAction != null) { - reloadAction.run(); - } - } - afterReload(); - } finally { - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } - }); - } - - protected void sortRowsByParentViewIndex() { - // inherit from child-ancestor - RowBrowser rb = getRowBrowser(); - Map parentRow = new HashMap(); - Set distinctParentRowModelIndex = new HashSet(); - Set singleBlockRows = new HashSet(); - if (rb != null && rb.browserContentPane != null && rb.parent != null && rb.association != null && rb.rowToRowLinks != null && rb.association.isInsertDestinationBeforeSource()) { - for (RowToRowLink l: rb.rowToRowLinks) { - if (!parentRow.containsKey(l.childRow)) { - parentRow.put(l.childRow, l.parentRow); - distinctParentRowModelIndex.add(l.parentRow.getParentModelIndex()); - } else { - singleBlockRows.add(l.childRow); - } - } - } - - useInheritedBlockNumbers = false; - - if (rb != null && rb.parent != null && rb.parent.browserContentPane != null && rb.parent.browserContentPane.rowsTable != null) { - final RowSorter parentSorter = rb.parent.browserContentPane.rowsTable.getRowSorter(); - Comparator comparator = new Comparator() { - @Override - public int compare(Row a, Row b) { - int avi = a.getParentModelIndex(); - if (avi >= 0 && avi < parentSorter.getModelRowCount()) { - avi = parentSorter.convertRowIndexToView(avi); - } - int bvi = b.getParentModelIndex(); - if (bvi >= 0 && avi < parentSorter.getModelRowCount()) { - bvi = parentSorter.convertRowIndexToView(bvi); - } - return avi - bvi; - } - }; - Collections.sort(rows, comparator); - if (!parentRow.isEmpty() && singleBlockRows.isEmpty() && distinctParentRowModelIndex.size() < parentRow.size() && !rb.parent.browserContentPane.useInheritedBlockNumbers) { - useInheritedBlockNumbers = true; - for (Row row: rows) { - Row pRow = parentRow.get(row); - if (pRow != null) { - row.setInheritedParentModelIndex(pRow.getParentModelIndex()); - } - } - } - } - } - - public synchronized void cancel() { - if (isCanceled) { - return; - } - isCanceled = true; - if (finished) { - return; - } - CancellationHandler.cancel(this); - } - - public synchronized void checkCancellation() { - CancellationHandler.checkForCancellation(this); - } - - @Override - public int getPriority() { - return 100; - } - } - - private Runnable reloadAction; - - public void setOnReloadAction(final Runnable runnable) { - if (reloadAction == null) { - reloadAction = runnable; - } else { - final Runnable prevReloadAction = reloadAction; - reloadAction = new Runnable() { - @Override - public void run() { - prevReloadAction.run(); - runnable.run(); - } - }; - } - } - - /** - * Current LoadJob. - */ - private LoadJob currentLoadJob; - - /** - * Table to read rows from. - */ - Table table; - - /** - * The data model. - */ - private final DataModel dataModel; - - /** - * The execution context. - */ - protected final ExecutionContext executionContext; - - /** - * {@link RowIdSupport} for data model. - */ - private final RowIdSupport rowIdSupport; - - /** - * {@link Association} with parent row, or null. - */ - Association association; - - /** - * Rows to render. - */ - public List rows = new ArrayList(); - - /** - * For in-place editing. - */ - private BrowserContentCellEditor browserContentCellEditor = new BrowserContentCellEditor(new int[0], new String[0], null); - - /** - * Cache for association row count. - */ - private final Map, Pair> rowCountCache = - Collections.synchronizedMap(new HashMap, Pair>()); - - private final long MAX_ROWCOUNTCACHE_RETENTION_TIME = 5 * 60 * 1000L; - - /** - * Number of non-distinct rows; - */ - private int noNonDistinctRows; - - /** - * Number of distinct rows; - */ - private int noDistinctRows; - - /** - * Indexes of primary key columns. - */ - private Set pkColumns = new HashSet(); - - /** - * Indexes of foreign key columns. - */ - private Set fkColumns = new HashSet(); - - /** - * Edit mode? - */ - private boolean isEditMode = false; - - /** - * To be shown as "Detail..." in error view. - */ - private Throwable currentErrorDetail; - - /** - * DB session. - */ - Session session; - - private int currentRowSelection = -1; - - public int getCurrentRowSelection() { - return currentRowSelection; - } - - private List parentRows; - private DetailsView singleRowDetailsView; - private MouseListener rowTableListener; - private int initialRowHeight; - private boolean useInheritedBlockNumbers; - boolean ignoreSortKey = false; - - public static class RowsClosure { - Set> currentClosure = Collections.synchronizedSet(new HashSet>()); - Set> currentClosureRowIDs = new HashSet>(); - Set currentClosureRootID = new HashSet(); - BrowserContentPane currentClosureRootPane; - Set parentPath = new HashSet(); - - Set tempClosure = new HashSet(); - }; - - private final RowsClosure rowsClosure; - - private boolean suppressReload; - - /** - * Alias for row number column. - */ - private static final String ROWNUMBERALIAS = "RN"; - - protected static final String UNKNOWN = "- unknown column -"; - - protected static final int MAXLOBLENGTH = 2000; - - private static final KeyStroke KS_COPY_TO_CLIPBOARD = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK); - private static final KeyStroke KS_SQLCONSOLE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK); - private static final KeyStroke KS_QUERYBUILDER = KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK); - private static final KeyStroke KS_FILTER = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK); - private static final KeyStroke KS_EDIT = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK); - private static final KeyStroke KS_DETAILS = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK); - - /** - * And-condition-combobox model. - */ - private final DefaultComboBoxModel andCondModel = new DefaultComboBoxModel(); - - private boolean isTableFilterEnabled = false; - - public void setTableFilterEnabled(boolean isTableFilterEnabled) { - this.isTableFilterEnabled = isTableFilterEnabled; - } - - static class SqlStatementTable extends Table { - public SqlStatementTable(String name, PrimaryKey primaryKey, boolean defaultUpsert) { - super(name, primaryKey, defaultUpsert, false); - } - } - - /** - * Constructor. - * - * @param dataModel - * the data model - * @param table - * to read rows from. Opens SQL browser if table is null. - * @param condition - * initial condition - * @param session - * DB session - * @param parentRow - * parent row - * @param parentRows - * all parent rows, if there are more than 1 - * @param association - * {@link Association} with parent row - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public BrowserContentPane(final DataModel dataModel, final Table table, String condition, Session session, List parentRows, - final Association association, final Frame parentFrame, RowsClosure rowsClosure, - Boolean selectDistinct, boolean reload, ExecutionContext executionContext) { - this.table = table; - this.session = session; - this.dataModel = dataModel; - this.rowIdSupport = new RowIdSupport(dataModel, session.dbms, executionContext); - this.parentRows = parentRows; - this.association = association; - this.rowsClosure = rowsClosure; - this.executionContext = executionContext; - - rowIdSupport.setUseRowIdsOnlyForTablesWithoutPK(true); - - suppressReload = true; - - if (table == null) { - this.table = new SqlStatementTable(null, null, false); - } - - initComponents(); - try { - Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon"); - errorLabel.setIcon(errorIcon); - errorLabel.setText(null); - } catch (Throwable t) { - // ignore - } - - loadingCauseLabel.setVisible(false); - sortColumnsCheckBox.setVisible(false); - - findColumnsLabel.setText(null); - findColumnsLabel.setToolTipText("Find Column..."); - findColumnsLabel.setIcon(StringSearchPanel.getSearchIcon(false, this)); - - findColumnsLabel.addMouseListener(new java.awt.event.MouseAdapter() { - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - if (findColumnsLabel.isEnabled()) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - in = false; - updateBorder(); - if (findColumnsPanel.isShowing()) { - Point point = new Point(); - SwingUtilities.convertPointToScreen(point, findColumnsPanel); - findColumns((int) point.getX(), (int) point.getY(), currentRowsTableReference == null? rowsTable : currentRowsTableReference.get()); - } - } - }); - } - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - if (findColumnsLabel.isEnabled()) { - in = true; - updateBorder(); - } - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - findColumnsPanel.setBackground(in? new Color(255, 255, 100) : null); - findColumnsPanel.setOpaque(in); - } - }); - - andCondition = new JComboBox(); - andCondition.setEditable(true); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - jPanel7.add(andCondition, gridBagConstraints); - - setPendingState(false, false); - - sqlLabel1.setIcon(dropDownIcon); - sortColumnsLabel.setIcon(dropDownIcon); - - final ListCellRenderer acRenderer = andCondition.getRenderer(); - andCondition.setRenderer(new ListCellRenderer() { - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) { - Component render = acRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (render instanceof JLabel) { - if (value != null && value.toString().trim().length() > 0) { - String tooltip = (value.toString()); - ((JLabel) render).setToolTipText(UIUtil.toHTML(tooltip, 200)); - } else { - ((JLabel) render).setToolTipText(null); - } - } - return render; - } - }); - if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { - JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); - f.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void removeUpdate(DocumentEvent e) { - updateTooltip(); - } - @Override - public void insertUpdate(DocumentEvent e) { - updateTooltip(); - } - @Override - public void changedUpdate(DocumentEvent e) { - updateTooltip(); - } - private void updateTooltip() { - if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { - JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); - String value = f.getText(); - String ttInfo = "Ctrl+Space for code completion."; - if (value != null && value.toString().trim().length() > 0) { - String tooltip = (value.toString()); - andCondition.setToolTipText("" + UIUtil.toHTMLFragment(tooltip, 200) + "
" + ttInfo); - } else { - andCondition.setToolTipText("" + ttInfo); - } - } - }; - }); - } - - andCondModel.addElement(""); - andCondition.setModel(andCondModel); - - andCondition.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (!suppessReloadOnAndConditionAction) { - if (e.getStateChange() == ItemEvent.SELECTED) { - historizeAndCondition(e.getItem()); - reloadRows(); - } - } - if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { - JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); - f.setCaretPosition(0); - } - } - }); - - initialRowHeight = rowsTable.getRowHeight(); - - rowsTable = new JTable() { - private int x[] = new int[2]; - private int y[] = new int[2]; - private Color color = new Color(0, 0, 200); - - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - if (!(graphics instanceof Graphics2D)) { - return; - } - - int maxI = Math.min(rowsTable.getRowCount(), rows.size()); - Rectangle visRect = rowsTable.getVisibleRect(); - - RowSorter sorter = getRowSorter(); - if (sorter != null) { - maxI = sorter.getViewRowCount(); - } - - Graphics2D g2d = (Graphics2D) graphics; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(1)); - - int width = (int) (visRect.width * 1.4); - - for (int i = 0; i < maxI; ++i) { - int mi = sorter == null? i : sorter.convertRowIndexToModel(i); - if (mi >= rows.size()) { - continue; - } - Row row = rows.get(mi); - if (BrowserContentPane.this.rowsClosure.tempClosure.contains(row)) { - int vi = i; - g2d.setColor(new Color(255, 0, 0, 50)); - Rectangle r = rowsTable.getCellRect(vi, 0, false); - x[0] = (int) visRect.getMinX(); - y[0] = (int) r.getMinY(); - r = rowsTable.getCellRect(vi, rowsTable.getColumnCount() - 1, false); - x[1] = (int) visRect.getMinX() + width; - y[1] = (int) r.getMaxY(); - GradientPaint paint = new GradientPaint( - x[0], y[0], new Color(255, 0, 0, 50), - x[0] + width, y[1], new Color(255, 0, 0, 0)); - g2d.setPaint(paint); - g2d.fillRect(x[0], y[0], x[1] - x[0], y[1] - y[0]); - } - } - - g2d.setPaint(null); - - if (!useInheritedBlockNumbers && BrowserContentPane.this.association != null && BrowserContentPane.this.association.isInsertDestinationBeforeSource()) { - return; - } - - double lastPMIndex = -1; - for (int i = 0; i < maxI; ++i) { - int mi = sorter == null? i : sorter.convertRowIndexToModel(i); - if (mi >= rows.size()) { - continue; - } - Row row = rows.get(mi); - double parentModelIndex = useInheritedBlockNumbers? row.getInheritedParentModelIndex() : row.getParentModelIndex(); - if (parentModelIndex != lastPMIndex) { - lastPMIndex = parentModelIndex; - int vi = i; - g2d.setColor(color); - Rectangle r = rowsTable.getCellRect(vi, 0, false); - x[0] = (int) r.getMinX(); - y[0] = (int) r.getMinY(); - r = rowsTable.getCellRect(vi, rowsTable.getColumnCount() - 1, false); - x[1] = (int) r.getMaxX(); - y[1] = (int) r.getMinY(); - g2d.drawPolyline(x, y, 2); - } - } - } - }; - - InputMap im = rowsTable.getInputMap(); - Object key = "copyClipboard"; - im.put(KS_COPY_TO_CLIPBOARD, key); - ActionMap am = rowsTable.getActionMap(); - Action a = new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - UIUtil.copyToClipboard(rowsTable, true); - } - }; - am.put(key, a); - - registerAccelerator(KS_SQLCONSOLE, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - rowsTable.grabFocus(); - UIUtil.invokeLater(8, new Runnable() { - @Override - public void run() { - openQueryBuilder(true); - } - }); - } - }); - registerAccelerator(KS_QUERYBUILDER, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - rowsTable.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - openQueryBuilder(false); - } - }); - } - }); - registerAccelerator(KS_FILTER, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - isTableFilterEnabled = !isTableFilterEnabled; - updateTableModel(); - } - }); - registerAccelerator(KS_EDIT, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - setEditMode(!isEditMode); - updateTableModel(); - } - }); - registerAccelerator(KS_DETAILS, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - Point loc = new Point(18, 16); - SwingUtilities.convertPointToScreen(loc, rowsTable); - openDetails(loc.x, loc.y); - } - }); - - rowsTable.setAutoCreateRowSorter(true); - rowsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); - rowsTableScrollPane.setViewportView(rowsTable); - rowsTable.setAutoscrolls(false); - - setAndCondition((condition), true); - from.setText(table == null? "" : this.dataModel.getDisplayName(table)); - adjustGui(); - rowsTable.setShowGrid(false); - final TableCellRenderer defaultTableCellRenderer = rowsTable.getDefaultRenderer(String.class); - - rowsTable.setDefaultRenderer(Object.class, new TableCellRenderer() { - - final Color BG1 = new Color(255, 255, 255); - final Color BG2 = new Color(242, 255, 242); - final Color BG1_EM = new Color(255, 255, 236); - final Color BG2_EM = new Color(230, 255, 236); - final Color BG3 = new Color(192, 236, 255); - final Color BG3_2 = new Color(184, 226, 255); - final Color BG4 = new Color(32, 210, 255, 200); - final Color BG4_2 = new Color(30, 196, 255, 200); - final Color BG4_LIGHT = new Color(30, 200, 255, 60); - final Color FG1 = new Color(155, 0, 0); - final Color FG2 = new Color(0, 0, 255); - final Font font = new JLabel().getFont(); - final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize()); - final Font italic = new Font(nonbold.getName(), nonbold.getStyle() | Font.ITALIC, nonbold.getSize()); - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, final int column) { - boolean cellSelected = isSelected; - - if (BrowserContentPane.this.getQueryBuilderDialog() != null || // SQL Console - table.getSelectedColumnCount() <= 1 && table.getSelectedRowCount() <= 1) { - - if (table == rowsTable) { - cellSelected = false; - } - } - - isSelected = currentRowSelection == row || currentRowSelection == -2; - - if (table != rowsTable) { - isSelected = false; - if (table.getSelectedRows().length <= 1 && table.getSelectedColumns().length <= 1) { - for (int sr: table.getSelectedRows()) { - if (sr == column) { - isSelected = true; - break; - } - } - } - } - - Component render = defaultTableCellRenderer.getTableCellRendererComponent(rowsTable, value, isSelected, false, row, column); - final RowSorter rowSorter = rowsTable.getRowSorter(); - if (rowSorter.getViewRowCount() == 0 && table == rowsTable) { - return render; - } - - boolean renderRowAsPK = false; - if (render instanceof JLabel) { - Row r = null; - int rowIndex = row; - ((JLabel) render).setIcon(null); - if (row < rowSorter.getViewRowCount()) { - rowIndex = rowSorter.convertRowIndexToModel(row); - if (rowIndex < rows.size()) { - r = rows.get(rowIndex); - if (r != null) { - renderRowAsPK = renderRowAsPK(r); - Object cellContent = r.values.length > column? r.values[column] : null; - if (cellContent instanceof UIUtil.IconWithText) { - ((JLabel) render).setIcon(((UIUtil.IconWithText) cellContent).icon); - ((JLabel) render).setText(((UIUtil.IconWithText) cellContent).text); - } - } - } - } - ((JLabel) render).setBorder(cellSelected? BorderFactory.createEtchedBorder() : null); - int convertedColumnIndex = rowsTable.convertColumnIndexToModel(column); - if (!isSelected && (table == rowsTable || !cellSelected)) { - if (BrowserContentPane.this.getQueryBuilderDialog() != null && // SQL Console - BrowserContentPane.this.rowsClosure.currentClosureRowIDs != null && - row < rows.size() && - row < rowSorter.getViewRowCount() && - rowSorter.convertRowIndexToModel(row) < rows.size() && - BrowserContentPane.this.rowsClosure.currentClosureRowIDs.contains(new Pair(BrowserContentPane.this, rows.get(rowSorter.convertRowIndexToModel(row)).nonEmptyRowId))) { - ((JLabel) render).setBackground((row % 2) == 0? BG3 : BG3_2); - if (BrowserContentPane.this.rowsClosure.currentClosureRootID != null - && !BrowserContentPane.this.rowsClosure.currentClosureRootID.isEmpty() - && BrowserContentPane.this.rowsClosure.currentClosureRootPane == BrowserContentPane.this) { - String rid = rows.get(rowSorter.convertRowIndexToModel(row)).nonEmptyRowId; - if (!rid.isEmpty() && BrowserContentPane.this.rowsClosure.currentClosureRootID.contains(rid)) { - ((JLabel) render).setBackground(currentRowSelection >= 0? BG4_LIGHT : (row % 2 == 0? BG4 : BG4_2)); - } - } - } else { - Table type = getResultSetTypeForColumn(convertedColumnIndex); - if (isEditMode && r != null && (r.rowId != null && !r.rowId.isEmpty()) && browserContentCellEditor.isEditable(type, rowIndex, convertedColumnIndex, r.values[convertedColumnIndex]) - && isPKComplete(type, r) && !rowIdSupport.getPrimaryKey(type, BrowserContentPane.this.session).getColumns().isEmpty()) { - ((JLabel) render).setBackground((row % 2 == 0) ? BG1_EM : BG2_EM); - } else { - ((JLabel) render).setBackground((row % 2 == 0) ? BG1 : BG2); - } - } - } else { - ((JLabel) render).setBackground(currentRowSelection == row? BG4.brighter() : (row % 2 == 0? BG4 : BG4_2)); - } - ((JLabel) render).setForeground( - renderRowAsPK || pkColumns.contains(convertedColumnIndex) ? FG1 : - fkColumns.contains(convertedColumnIndex) ? FG2 : - Color.BLACK); - boolean isNull = false; - if (((JLabel) render).getText() == UIUtil.NULL || ((JLabel) render).getText() == UNKNOWN) { - ((JLabel) render).setForeground(Color.gray); - ((JLabel) render).setFont(italic); - isNull = true; - } - TableColumnModel columnModel = rowsTable.getColumnModel(); - if (!foundColumn.isEmpty() && column < columnModel.getColumnCount() && foundColumn.contains(columnModel.getColumn(column).getModelIndex())) { - Color background = render.getBackground(); - render.setBackground( - new Color( - Math.max((int)(background.getRed()), 0), - Math.max((int)(background.getGreen() * 0.90), 0), - Math.max((int)(background.getBlue() * 0.91), 0), - background.getAlpha())); - } - try { - ((JLabel) render).setToolTipText(null); - if (isNull) { - ((JLabel) render).setFont( - // highlightedRows.contains(rowSorter.convertRowIndexToModel(row)) ? italicBold : - italic); - } else { - ((JLabel) render).setFont( - // highlightedRows.contains(rowSorter.convertRowIndexToModel(row)) ? bold : - nonbold); - String text = ((JLabel) render).getText(); - if (text.indexOf('\n') >= 0) { - ((JLabel) render).setToolTipText(UIUtil.toHTML(text, 200)); - } else if (text.length() > 20) { - ((JLabel) render).setToolTipText(text); - } - } - } catch (Exception e) { - // ignore - } - } - // indent 1. column - if (render instanceof JLabel) { - ((JLabel) render).setText(" " + ((JLabel) render).getText()); - } - return render; - } - }); - rowsTable.setRowSelectionAllowed(true); - rowsTable.setColumnSelectionAllowed(true); - rowsTable.setCellSelectionEnabled(true); - rowsTable.setEnabled(true); - - rowsTableScrollPane.getVerticalScrollBar().setUnitIncrement(32); - singleRowViewScrollPane.getVerticalScrollBar().setUnitIncrement(32); - - rowTableListener = new MouseListener() { - private JPopupMenu lastMenu; - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - int ri; - JComponent source = (JComponent) e.getSource(); - if (source == rowsTable) { - ri = rowsTable.rowAtPoint(e.getPoint()); - } else { - ri = 0; - } - if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { - int i = 0; - if (source == rowsTable) { - i = rowsTable.getRowSorter().convertRowIndexToModel(ri); - } else if (source == rowsTableScrollPane || source == singleRowViewContainterPanel) { - if (rows.size() != 1 || getQueryBuilderDialog() == null /* SQL Console */) { - return; - } - ri = 0; - i = 0; - } - Row row = rows.get(i); - - if (getQueryBuilderDialog() == null // SQL Console - || ((e.getButton() != MouseEvent.BUTTON1 || e.getClickCount() != 1) && (lastMenu == null || !lastMenu.isVisible()))) { - currentRowSelection = ri; - onRedraw(); - int x, y; - if (source != rowsTable) { - x = e.getX(); - y = e.getY(); - } else { - Rectangle r = rowsTable.getCellRect(ri, 0, false); - x = Math.max(e.getPoint().x, (int) r.getMinX()); - y = (int) r.getMaxY() - 2; - } - Point p = SwingUtilities.convertPoint(source, x, y, null); - if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() > 1) { - openDetailsView(i, p.x + getOwner().getX(), p.y + getOwner().getY()); - } else if (e.getButton() != MouseEvent.BUTTON1) { - JPopupMenu popup; - popup = createPopupMenu(row, i, p.x + getOwner().getX(), p.y + getOwner().getY(), rows.size() == 1); - if (popup != null) { - if (!row.nonEmptyRowId.isEmpty()) { - for (Row r: rows) { - if (r.nonEmptyRowId.equals(row.nonEmptyRowId) && BrowserContentPane.this.rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId)) { - currentRowSelection = -1; - onRedraw(); - break; - } - } - } - UIUtil.showPopup(source, x, y, popup); - popup.addPropertyChangeListener("visible", new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.FALSE.equals(evt.getNewValue())) { - currentRowSelection = -1; - onRedraw(); - } - } - }); - } - lastMenu = popup; - } else { - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(ri, false); - } - } else if (e.getComponent() == singleRowViewScrollContentPanel || e.getSource() == singleRowViewContainterPanel) { - if (getQueryBuilderDialog() != null) { // !SQL Console - for (RowBrowser tb: getTableBrowser()) { - try { - tb.browserContentPane.isUpdatingTableModel = true; - tb.browserContentPane.rowsTable.clearSelection(); - } finally { - tb.browserContentPane.isUpdatingTableModel = false; - } - } - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(0, false); - } - } - } - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseClicked(MouseEvent e) { - } - }; - - rowsTable.addMouseListener(rowTableListener); - rowsTableScrollPane.addMouseListener(rowTableListener); - singleRowViewScrollPane.addMouseListener(rowTableListener); - singleRowViewContainterPanel.addMouseListener(rowTableListener); - - TempClosureListener tempClosureListener = new TempClosureListener(); - rowsTable.addMouseListener(tempClosureListener); - rowsTable.addMouseMotionListener(tempClosureListener); - rowsTableScrollPane.addMouseListener(tempClosureListener); - rowsTableScrollPane.addMouseMotionListener(tempClosureListener); - singleRowViewContainterPanel.addMouseListener(tempClosureListener); - singleRowViewContainterPanel.addMouseMotionListener(tempClosureListener); - - if (getQueryBuilderDialog() != null) { // !SQL Console - rowsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - List prevSelectedRows = null; - Timer timer = null; - @Override - public void valueChanged(ListSelectionEvent e) { - List selectedRows = new ArrayList(); - if (isUpdatingTableModel) { - prevSelectedRows = selectedRows; - return; - } else { - for (RowBrowser tb: getTableBrowser()) { - if (tb.browserContentPane != BrowserContentPane.this) { - try { - tb.browserContentPane.isUpdatingTableModel = true; - tb.browserContentPane.rowsTable.clearSelection(); - } finally { - tb.browserContentPane.isUpdatingTableModel = false; - } - } - } - } - for (int si: rowsTable.getSelectedRows()) { - selectedRows.add(si); - } - if (prevSelectedRows == null || !prevSelectedRows.equals(selectedRows)) { - prevSelectedRows = selectedRows; - resetCurrentRowSelection(); - for (int si: selectedRows) { - setCurrentRowSelection(si, true); - } - setCurrentRowSelection(-1, true); - startTimer(); - } - } - private void startTimer() { - final Timer newTimer = new Timer(100, null); - timer = newTimer; - timer.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (newTimer == timer) { - reloadChildrenIfLimitIsExceeded(); - } - } - }); - timer.setRepeats(false); - timer.start(); - } - }); - } - - openEditorButton.setIcon(UIUtil.scaleIcon(this, conditionEditorIcon)); - openEditorButton.setText(null); - - final Runnable openConditionEditor = new Runnable() { - @Override - public void run() { - openConditionEditor(); - } - - public void openConditionEditor() { - openEditorButton.setSelected(true); - final Point pos = new Point(andCondition.getX(), andCondition.getY()); - SwingUtilities.convertPointToScreen(pos, andCondition.getParent()); - Window owner = SwingUtilities.getWindowAncestor(BrowserContentPane.this); - andConditionEditor.setLocationAndFit(pos, owner != null? owner.getX() + owner.getWidth() - 8: Integer.MAX_VALUE); - andConditionEditor.edit(getAndConditionText(), "Table", "A", table, null, null, null, false, true); - } - }; - - final Runnable createConditionEditor = new Runnable() { - @Override - public void run() { - createConditionEditor(); - } - - public void createConditionEditor() { - if (andConditionEditor == null) { - andConditionEditor = new DBConditionEditor(parentFrame, dataModel) { - @Override - protected void consume(String cond) { - if (cond != null) { - if (!getAndConditionText().equals((cond))) { - setAndCondition((cond), true); - loadButton.grabFocus(); - reloadRows(); - } - } - openEditorButton.setSelected(false); - } - }; - if (andCondition.getEditor().getEditorComponent() instanceof JTextField) { - andConditionEditor.observe((JTextField) andCondition.getEditor().getEditorComponent(), openConditionEditor); - } - } - } - }; - - openEditorButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - loadButton.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - createConditionEditor.run(); - openConditionEditor.run(); - } - }); - } - }); - if (andCondition.getEditor().getEditorComponent() instanceof JTextField) { - DBConditionEditor.initialObserve((JTextField) andCondition.getEditor().getEditorComponent(), new Runnable() { - @Override - public void run() { - createConditionEditor.run(); - andConditionEditor.doCompletion((JTextField) andCondition.getEditor().getEditorComponent(), openConditionEditor); - } - }); - } - relatedRowsLabel.setIcon(UIUtil.scaleIcon(this, relatedRowsIcon)); - relatedRowsLabel.setFont(relatedRowsLabel.getFont().deriveFont(relatedRowsLabel.getFont().getSize() * 1.1f)); - if (createPopupMenu(null, -1, 0, 0, false).getComponentCount() == 0) { - relatedRowsLabel.setEnabled(false); - } else { - relatedRowsPanel.addMouseListener(new java.awt.event.MouseAdapter() { - private JPopupMenu popup; - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - loadButton.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - popup = createPopupMenu(null, -1, 0, 0, false); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2, false); - popup.addPropertyChangeListener("visible", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.FALSE.equals(evt.getNewValue())) { - popup = null; - updateBorder(); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); - } - } - }); - UIUtil.showPopup(relatedRowsPanel, 0, relatedRowsPanel.getHeight(), popup); - } - }); - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - in = true; - updateBorder(); - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - relatedRowsPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED - : javax.swing.border.BevelBorder.RAISED)); - } - }); - } - sqlPanel.addMouseListener(new java.awt.event.MouseAdapter() { - private JPopupMenu popup; - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - loadButton.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - Point loc = sqlPanel.getLocationOnScreen(); - popup = createSqlPopupMenu(0, (int) loc.getX(), (int) loc.getY(), false, BrowserContentPane.this); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2, false); - popup.addPropertyChangeListener("visible", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.FALSE.equals(evt.getNewValue())) { - popup = null; - updateBorder(); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); - } - } - }); - UIUtil.showPopup(sqlPanel, 0, sqlPanel.getHeight(), popup); - } - }); - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - in = true; - updateBorder(); - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - sqlPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED - : javax.swing.border.BevelBorder.RAISED)); - } - }); - if (selectDistinct != null) { - selectDistinctCheckBox.setSelected(selectDistinct); - } - sortColumnsPanel.addMouseListener(new java.awt.event.MouseAdapter() { - private JPopupMenu popup; - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - loadButton.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - popup = new JPopupMenu(); - JCheckBoxMenuItem natural = new JCheckBoxMenuItem("Natural column order "); - natural.setSelected(!sortColumnsCheckBox.isSelected()); - natural.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sortColumnsCheckBox.setSelected(false); - sortColumnsCheckBoxActionPerformed(null); - sortColumnsLabel.setText("Natural column order"); - } - }); - popup.add(natural); - JCheckBoxMenuItem sorted = new JCheckBoxMenuItem("Alphabetical column order "); - sorted.setSelected(sortColumnsCheckBox.isSelected()); - sorted.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sortColumnsCheckBox.setSelected(true); - sortColumnsCheckBoxActionPerformed(null); - sortColumnsLabel.setText("A-Z column order"); - } - }); - popup.add(sorted); - popup.addSeparator(); - JMenuItem changeOrder = new JMenuItem("Change natural column order "); - changeOrder.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sortColumnsCheckBox.setSelected(false); - sortColumnsCheckBoxActionPerformed(null); - sortColumnsLabel.setText("Natural column order"); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - changeColumnOrder(table); - } - }); - } - }); - popup.add(changeOrder); - popup.addPropertyChangeListener("visible", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.FALSE.equals(evt.getNewValue())) { - popup = null; - updateBorder(); - } - } - }); - UIUtil.showPopup(sortColumnsPanel, 0, sortColumnsPanel.getHeight(), popup); - } - }); - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - in = true; - updateBorder(); - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - sortColumnsPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED - : javax.swing.border.BevelBorder.RAISED)); - } - }); - updateTableModel(0, false, false); - - suppressReload = false; - if (reload) { - reloadRows(); - } - } - - private void registerAccelerator(KeyStroke ks, AbstractAction a) { - registerAccelerator(ks, a, this); - registerAccelerator(ks, a, rowsTable); - registerAccelerator(ks, a, loadButton); - registerAccelerator(ks, a, sqlLabel1); - registerAccelerator(ks, a, relatedRowsLabel); - registerAccelerator(ks, a, andCondition); - Component editor = andCondition.getEditor().getEditorComponent(); - if (editor instanceof JComponent) { - registerAccelerator(ks, a, (JComponent) editor); - } - } - - private void registerAccelerator(KeyStroke ks, AbstractAction a, JComponent comp) { - InputMap im = comp.getInputMap(); - im.put(ks, a); - ActionMap am = comp.getActionMap(); - am.put(a, a); - } - - protected abstract boolean renderRowAsPK(Row theRow); - - boolean isPending = false; - - void setPendingState(boolean pending, boolean propagate) { - isPending = pending; - ((CardLayout) pendingNonpendingPanel.getLayout()).show(pendingNonpendingPanel, "nonpending"); - if (pending) { - updateMode("pending", null); - } - if (propagate) { - for (RowBrowser child: getChildBrowsers()) { - child.browserContentPane.setPendingState(pending, propagate); - } - } - } - - protected void historizeAndCondition(Object item) { - if (item == null || (item.toString().trim().isEmpty() && !item.toString().isEmpty())) { - return; - } - for (int i = 0; i < andCondModel.getSize(); ++i) { - if (item.equals(andCondModel.getElementAt(i))) { - return; - } - } - andCondModel.insertElementAt(item, 1); - } - - private boolean suppessReloadOnAndConditionAction = false; - - void setAndCondition(String cond, boolean historize) { - try { - suppessReloadOnAndConditionAction = true; - andCondition.setSelectedItem(cond); - if (historize) { - historizeAndCondition(cond); - } - } finally { - suppessReloadOnAndConditionAction = false; - } - } - - String getAndConditionText() { - if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { - JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); - return f.getText(); - } - Object sel = andCondition.getSelectedItem(); - if (sel == null) { - return ""; - } - return sel.toString().trim(); - } - - private void adjustGui() { - if (this.association == null) { - joinPanel.setVisible(false); - onPanel.setVisible(false); - - jLabel1.setText(" "); - jLabel4.setText(" "); - - jLabel6.setVisible(false); - java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 8; - gridBagConstraints.gridy = 4; - gridBagConstraints.gridheight = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; - } else { - join.setText(this.dataModel.getDisplayName(this.association.source)); - on.setText(!this.association.reversed ? SqlUtil.reversRestrictionCondition(this.association.getUnrestrictedJoinCondition()) : this.association - .getUnrestrictedJoinCondition()); - updateWhereField(); - join.setToolTipText(join.getText()); - on.setToolTipText(assocToolTip(on.getText(), this.association)); - } - } - - private static String assocToolTip(String condition, Association assoc) { - return "" + UIUtil.toHTMLFragment(condition, 0) + "

FK: " - + UIUtil.toHTML(assoc.reversed? assoc.reversalAssociation.getName() : assoc.getName(), 0) + ""; - } - - private class AllNonEmptyItem extends JMenuItem { - int todo; - int done; - private List todoList = new ArrayList(); - private final String initText = "Counting rows... "; - - AllNonEmptyItem() { - setEnabled(false); - addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Component parent = SwingUtilities.getWindowAncestor(BrowserContentPane.this); - if (parent == null) { - parent = BrowserContentPane.this; - } - UIUtil.setWaitCursor(parent); - try { - Desktop.noArrangeLayoutOnNewTableBrowser = true; - Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = todoList.size() > 1; - Desktop.resetLastArrangeLayoutOnNewTableBrowser(); - for (int i = 0; i < todoList.size(); ++i) { - if (i == todoList.size() - 1) { - Desktop.noArrangeLayoutOnNewTableBrowser = false; - } - todoList.get(i).actionPerformed(e); - } - } finally { - Desktop.noArrangeLayoutOnNewTableBrowser = false; - Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = false; - UIUtil.resetWaitCursor(parent); - } - } - }); - } - - public void rowsCounted(long count, ActionListener itemAction) { - ++done; - if (count != 0) { - todoList.add(itemAction); - } - int p = todo > 0? (100 * done) / todo : 0; - if (done < todo) { - setText(initText + p + "%"); - } else { - setText("All non-empty (" + todoList.size() + ")"); - setEnabled(true); - } - } - - public void setInitialText() { - if (todoList.isEmpty()) { - setText("All non-empty (0)"); - } else { - setText(initText + "100%"); - } - } - - }; - - private String currentSelectedRowCondition = ""; - - /** - * Creates popup menu for navigation. - * @param navigateFromAllRows - * @param copyTCB - * @param runnable - * @param runnable - */ - public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows) { - return createPopupMenu(row, rowIndex, x, y, navigateFromAllRows, null, null); - } - - /** - * Creates popup menu for navigation. - * @param navigateFromAllRows - * @param runnable - */ - public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint) { - return createPopupMenu(rowsTable, row, rowIndex, x, y, navigateFromAllRows, altCopyTCB, repaint, true); - } - - /** - * Creates popup menu for navigation. - * @param navigateFromAllRows - * @param runnable - */ - public JPopupMenu createPopupMenu(final JTable contextJTable, final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint, final boolean withKeyStroke) { - JMenuItem tableFilter = new JCheckBoxMenuItem("Table Filter"); - if (withKeyStroke) { - tableFilter.setAccelerator(KS_FILTER); - } else { - tableFilter.setVisible(false); - } - tableFilter.setSelected(isTableFilterEnabled); - if (isLimitExceeded) { - tableFilter.setForeground(Color.red); - tableFilter.setToolTipText("Row limit exceeded. Filtering may be incomplete."); - } - tableFilter.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Component parent = null; - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = null; - parent = SwingUtilities.getWindowAncestor(contextJTable); - UIUtil.setWaitCursor(parent); - isTableFilterEnabled = !isTableFilterEnabled; - updateTableModel(); - } finally { - UIUtil.resetWaitCursor(parent); - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } - }); - JMenuItem copyTCB; - if (altCopyTCB != null) { - copyTCB = altCopyTCB; - } else { - copyTCB = null; -// if (getQueryBuilderDialog() != null) { // !SQL Console -// copyTCB = null; -// } else { -// copyTCB = new JMenuItem("Copy to Clipboard"); -// if (withKeyStroke) { -// copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD); -// } -// copyTCB.setEnabled(rowsTable.getSelectedColumnCount() > 0); -// copyTCB.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// UIUtil.copyToClipboard(rowsTable, true); -// } -// }); -// } - } - - if (table instanceof SqlStatementTable && resultSetType == null) { - JPopupMenu jPopupMenu = new JPopupMenu(); - if (row != null) { - JMenuItem det = new JMenuItem("Details"); - if (withKeyStroke) { - det.setAccelerator(KS_DETAILS); - } - jPopupMenu.add(det); - jPopupMenu.add(new JSeparator()); - det.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openDetailsView(rowIndex, x, y); - } - }); - } - JMenu script = new JMenu("Create SQL"); - script.setEnabled(false); - jPopupMenu.add(script); - jPopupMenu.addSeparator(); - if (copyTCB != null) { - jPopupMenu.add(copyTCB); - jPopupMenu.addSeparator(); - } - jPopupMenu.add(tableFilter); - JMenuItem editMode = new JMenuItem("Edit Mode"); - if (withKeyStroke) { - editMode.setAccelerator(KS_EDIT); - } - jPopupMenu.add(editMode); - editMode.setEnabled(false); - return jPopupMenu; - } - - List assList = new ArrayList(); - Map assMap = new HashMap(); - for (Association a : table.associations) { - int n = 0; - for (Association a2 : table.associations) { - if (a.destination == a2.destination) { - ++n; - } - } - char c = ' '; - if (a.isIgnored()) { - c = '4'; - } else if (a.isInsertDestinationBeforeSource()) { - c = '1'; - } else if (a.isInsertSourceBeforeDestination()) { - c = '2'; - } else { - c = '3'; - } - String name = c + a.getDataModel().getDisplayName(a.destination) + (n > 1 ? " (" + (a.reversed? a.reversalAssociation.getName() : a.getName()) + ")": ""); - assList.add(name); - assMap.put(name, a); - } - Collections.sort(assList); - - final Object context = new Object(); - AllNonEmptyItem allNonEmpty = new AllNonEmptyItem(); - - JPopupMenu popup = new JPopupMenu(); - popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Parents", "1", navigateFromAllRows, 80, allNonEmpty, context); - popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Children", "2", navigateFromAllRows, 60, allNonEmpty, context); - popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Associated Rows", "3", navigateFromAllRows, 40, allNonEmpty, context); - popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Detached Rows", "4", navigateFromAllRows, 40, allNonEmpty, context); - - popup.addPopupMenuListener(new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - cancel(); - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - cancel(); - } - - private void cancel() { - CancellationHandler.cancelSilently(context); - getRunnableQueue().add(new RunnableWithPriority() { - - @Override - public void run() { - CancellationHandler.reset(context); - } - - @Override - public int getPriority() { - return 0; - } - }); - } - }); - - if (!isPending && !rows.isEmpty()) { - popup.add(allNonEmpty); - allNonEmpty.setInitialText(); - } - - if (row != null) { - JMenuItem det = new JMenuItem("Details"); - if (withKeyStroke) { - det.setAccelerator(KS_DETAILS); - } - popup.insert(det, 0); - popup.insert(new JSeparator(), 1); - det.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openDetailsView(rowIndex, x, y); - } - }); - - if (!(table instanceof SqlStatementTable) || resultSetType != null) { - if (popup.getComponentCount() > 0) { - popup.add(new JSeparator()); - } - - JMenuItem qb = new JMenuItem("Query Builder"); - qb.setAccelerator(KS_QUERYBUILDER); - popup.add(qb); - qb.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openQueryBuilder(false, SqlUtil.replaceAliases(row.rowId, "A", "A")); - } - }); - - JMenuItem sqlConsole = new JMenuItem("SQL Console"); - sqlConsole.setAccelerator(KS_SQLCONSOLE); - popup.add(sqlConsole); - sqlConsole.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openQueryBuilder(true, SqlUtil.replaceAliases(row.rowId, "A", "A")); - } - }); - - final List toSelect = new ArrayList(); - if (!row.nonEmptyRowId.isEmpty()) { - for (Row r: rows) { - if (!r.nonEmptyRowId.isEmpty() && rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId)) { - toSelect.add(r); - } - } - } - if (!toSelect.contains(row)) { - toSelect.clear(); - toSelect.add(row); - } - if (!currentSelectedRowCondition.equals("") && - (rows.size() == 1 || toSelect.size() == rows.size())) { - JMenuItem sr = new JMenuItem(rows.size() == 1? "Deselect Row" : ("Deselect Rows (" + rows.size() + ")")); - popup.insert(sr, 0); - sr.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - andCondition.setSelectedItem(""); - } - }); - } else { - JMenuItem sr = new JMenuItem(toSelect.size() <= 1? "Select Row" : ("Select Rows (" + toSelect.size() + ")")); - sr.setEnabled(rows.size() > 1 && !row.rowId.isEmpty()); - popup.insert(sr, 0); - sr.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - selectRow(toSelect); - } - }); - } - - JMenu sql = new JMenu("Create SQL"); - final String rowName = !(table instanceof SqlStatementTable)? dataModel.getDisplayName(table) + "(" + SqlUtil.replaceAliases(row.rowId, null, null) + ")" : ""; - JMenuItem update = new JMenuItem("Update"); - sql.add(update); - update.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Update Row " + rowName, x, y, SQLDMLBuilder.buildUpdate(table, toSelect, true, session)); - } - }); - JMenuItem insert = new JMenuItem("Insert"); - sql.add(insert); - insert.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Insert Row " + rowName, x, y, SQLDMLBuilder.buildInsert(table, toSelect, true, session)); - } - }); - JMenuItem insertNewRow = createInsertChildMenu(toSelect, x, y); - sql.add(insertNewRow); - JMenuItem delete = new JMenuItem("Delete"); - sql.add(delete); - delete.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Delete Row " + rowName, x, y, SQLDMLBuilder.buildDelete(table, toSelect, true, session)); - } - }); - insert.setEnabled(resultSetType == null); - update.setEnabled(resultSetType == null); - delete.setEnabled(resultSetType == null); - if (getQueryBuilderDialog() == null) { - popup.removeAll(); - popup.add(det); - popup.addSeparator(); - JMenu script = new JMenu("Create SQL"); - popup.add(script); - if (table.getName() == null) { - script.setEnabled(false); - } else { - final String tableName = dataModel.getDisplayName(table); - script.add(update); - script.add(insert); - script.add(insertNewRow); - script.add(delete); - script.addSeparator(); - JMenuItem updates = new JMenuItem("Updates (all rows)"); - script.add(updates); - updates.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Update " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildUpdate(table, sortedAndFiltered(rows), false, session); }}); - } - }); - JMenuItem inserts = new JMenuItem("Inserts (all rows)"); - script.add(inserts); - inserts.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Insert Into " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildInsert(table, sortedAndFiltered(rows), false, session); }}); - } - }); - JMenuItem deletes = new JMenuItem("Deletes (all rows)"); - script.add(deletes); - deletes.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Delete from " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildDelete(table, sortedAndFiltered(rows), false, session); } - }); - } - }); - boolean hasPK = !rowIdSupport.getPrimaryKey(table).getColumns().isEmpty(); - if (!hasPK) { - delete.setEnabled(false); - } - inserts.setEnabled(rows.size() > 0); - updates.setEnabled(hasPK && rows.size() > 0); - deletes.setEnabled(hasPK && rows.size() > 0); - } - } else { - popup.add(sql); - } - } - popup.addSeparator(); - if (copyTCB != null) { - popup.add(copyTCB); - popup.addSeparator(); - } - popup.add(createFindColumnMenuItem(x, y, contextJTable)); - popup.add(new JSeparator()); - popup.add(tableFilter); - JCheckBoxMenuItem editMode = new JCheckBoxMenuItem("Edit Mode"); - editMode.setEnabled(isTableEditable(table)); - if (withKeyStroke) { - editMode.setAccelerator(KS_EDIT); - } - editMode.setSelected(isEditMode); - editMode.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = null; - setEditMode(!isEditMode); - updateTableModel(); - if (repaint != null) { - UIUtil.invokeLater(repaint); - } - } finally { - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } - }); - popup.add(editMode); - } - - return popup; - } - - private JMenuItem createFindColumnMenuItem(final int x, final int y, final JTable contextJTable) { - final JMenuItem menuItem = new JMenuItem("Find Column..."); - menuItem.setEnabled(singleRowDetailsView == null); - menuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - findColumns(x, y, contextJTable); - } - }); - return menuItem; - } - - /** - * Creates popup menu for SQL. - * @param forNavTree - * @param browserContentPane - */ - public JPopupMenu createSqlPopupMenu(final int rowIndex, final int x, final int y, boolean forNavTree, final Component parentComponent) { - JPopupMenu popup = new JPopupMenu(); - - JMenuItem rebase = new JMenuItem("Start Navigation here"); - popup.add(rebase); - rebase.setEnabled(getParentBrowser() != null); - rebase.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - rebase(); - } - }); - popup.addSeparator(); - JMenuItem qb = new JMenuItem("Query Builder"); - qb.setAccelerator(KS_QUERYBUILDER); - popup.add(qb); - qb.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openQueryBuilder(false); - } - }); - JMenuItem sqlConsole = new JMenuItem("SQL Console"); - sqlConsole.setAccelerator(KS_SQLCONSOLE); - popup.add(sqlConsole); - sqlConsole.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openQueryBuilder(true); - } - }); - JMenu sqlDml = new JMenu("Create SQL"); - popup.add(sqlDml); - final String tableName = dataModel.getDisplayName(table); - JMenuItem update = new JMenuItem("Updates"); - sqlDml.add(update); - update.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Update " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildUpdate(table, sortedAndFiltered(rows), false, session); }}); - } - }); - JMenuItem insert = new JMenuItem("Inserts"); - sqlDml.add(insert); - insert.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Insert Into " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildInsert(table, sortedAndFiltered(rows), false, session); }}); - } - }); - JMenuItem insertNewRow = createInsertChildMenu(sortedAndFiltered(rows), x, y); - sqlDml.add(insertNewRow); - JMenuItem delete = new JMenuItem("Deletes"); - sqlDml.add(delete); - delete.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Delete from " + tableName, x, y, new Object() { @Override - public String toString() { return SQLDMLBuilder.buildDelete(table, sortedAndFiltered(rows), false, session); }}); - } - }); - boolean hasPK = !rowIdSupport.getPrimaryKey(table).getColumns().isEmpty(); - insert.setEnabled(rows.size() > 0); - update.setEnabled(hasPK && rows.size() > 0); - delete.setEnabled(hasPK && rows.size() > 0); - - popup.add(new JSeparator()); - JMenuItem exportData = new JMenuItem("Export Data"); - popup.add(exportData); - exportData.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openExtractionModelEditor(true); - } - }); - - JMenuItem extractionModel = new JMenuItem("Create Extraction Model"); - popup.add(extractionModel); - extractionModel.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openExtractionModelEditor(false); - } - }); - - popup.add(new JSeparator()); - - if (!forNavTree) { - JMenuItem det = new JMenuItem("Details"); - det.setAccelerator(KS_DETAILS); - popup.add(det); - det.setEnabled(rows.size() > 0); - det.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openDetails(x, y); - } - }); - } -// popup.add(new JSeparator()); - JMenuItem snw = new JMenuItem("Show in New Window"); - popup.add(snw); - snw.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - showInNewWindow(); - } - }); - -// JMenuItem al = new JMenuItem("Append Layout..."); -// popup.add(al); -// al.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// appendLayout(); -// } -// }); -// -// popup.addSeparator(); - - JMenuItem m = new JMenuItem("Hide (Minimize)"); - popup.add(m); - m.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onHide(); - } - }); - m = new JMenuItem("Close"); - popup.add(m); - m.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - closeWithChildren(parentComponent); - } - }); - popup.add(new JSeparator()); - if (!forNavTree) { - popup.add(createFindColumnMenuItem(x, y, rowsTable)); - popup.add(new JSeparator()); - } - JMenuItem tableFilter = new JCheckBoxMenuItem("Table Filter"); - tableFilter.setAccelerator(KS_FILTER); - tableFilter.setSelected(isTableFilterEnabled); - if (isLimitExceeded) { - tableFilter.setForeground(Color.red); - tableFilter.setToolTipText("Row limit exceeded. Filtering may be incomplete."); - } - tableFilter.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Component parent = null; - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = null; - parent = SwingUtilities.getWindowAncestor(parentComponent); - UIUtil.setWaitCursor(parent); - isTableFilterEnabled = !isTableFilterEnabled; - updateTableModel(); - } finally { - UIUtil.resetWaitCursor(parent); - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } - }); - popup.add(tableFilter); - JCheckBoxMenuItem editMode = new JCheckBoxMenuItem("Edit Mode"); - editMode.setEnabled(isTableEditable(table)); - editMode.setAccelerator(KS_EDIT); - editMode.setSelected(isEditMode); - editMode.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = null; - setEditMode(!isEditMode); - updateTableModel(); - } finally { - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } - }); - popup.add(editMode); - return popup; - } - - protected boolean isTableEditable(Table theTable) { - return resultSetType != null || !rowIdSupport.getPrimaryKey(theTable).getColumns().isEmpty(); - } - - public boolean closeWithChildren(Component parentComponent) { - int count = countSubNodes(this); - Component parent = SwingUtilities.getWindowAncestor(this); - if (parent == null) { - parent = BrowserContentPane.this; - } - boolean closeThisToo = true; - if (count > 1) { - int o = JOptionPane.showOptionDialog(parentComponent, "Which tables do you want to close?", "Close", - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, - new Object[] { - "Only this table", - "This and related tables (" + (count) + ")", - "Related tables (" + (count - 1) + ")" - }, - null); - if (o == 0) { - UIUtil.setWaitCursor(parent); - try { - close(); - } finally { - UIUtil.resetWaitCursor(parent); - } - return true; - } - if (o == 1) { - closeThisToo = true; - } else if (o == 2) { - closeThisToo = false; - } else { - return false; - } - } - UIUtil.setWaitCursor(parent); - try { - closeSubTree(BrowserContentPane.this, closeThisToo); - } finally { - UIUtil.resetWaitCursor(parent); - } - return true; - } - - private int countSubNodes(BrowserContentPane cp) { - int count = 0; - for (RowBrowser c: cp.getChildBrowsers()) { - count += countSubNodes(c.browserContentPane); - } - return count + 1; - } - - protected void closeSubTree(BrowserContentPane cp, boolean closeThisToo) { - for (RowBrowser c: cp.getChildBrowsers()) { - closeSubTree(c.browserContentPane, true); - } - if (closeThisToo) { - cp.close(); - } - } - - private JMenu createInsertChildMenu(List parents, final int x, final int y) { - JScrollMenu insertNewRow = new JScrollMenu("Insert Child"); - if (parents == null || parents.isEmpty() || parents.size() > 1 || table == null || table.getName() == null) { - insertNewRow.setEnabled(false); - return insertNewRow; - } - List tableAssociations = table.associations; - - if (tableAssociations == null || tableAssociations.isEmpty()) { - // artificial table from SQL Console? - Table t = dataModel.getTable(table.getName()); - if (t == null) { - insertNewRow.setEnabled(false); - return insertNewRow; - } - tableAssociations = t.associations; - } - - List assocs = new ArrayList(); - Map> children = new HashMap>(); - - if (tableAssociations != null) { - for (Association association: tableAssociations) { - List child = createNewRow(parents, table, association); - if (child != null && !child.isEmpty()) { - assocs.add(association); - children.put(association, child); - } - } - } - Collections.sort(assocs, new Comparator() { - @Override - public int compare(Association a, Association b) { - String dNameA = dataModel.getDisplayName(a.destination); - String dNameB = dataModel.getDisplayName(b.destination); - return dNameA.compareTo(dNameB); - } - }); - for (int i = 0; i < assocs.size(); ++i) { - final Association association = assocs.get(i); - Association pred = i > 0? assocs.get(i - 1) : null; - Association succ = i < assocs.size() - 1? assocs.get(i + 1) : null; - final String dName = dataModel.getDisplayName(association.destination); - JMenuItem item; - if (pred != null && pred.destination == association.destination || succ != null && succ.destination == association.destination) { - item = new JMenuItem(dName + " on " + association.getName()); - } else { - item = new JMenuItem(dName); - } - final List child = children.get(association); - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openSQLDialog("Insert Child into " + dName, x, y, SQLDMLBuilder.buildInsert(association.destination, child, true, session)); - } - }); - insertNewRow.add(item); - } - - insertNewRow.setEnabled(!assocs.isEmpty()); - return insertNewRow; - } - - void openExtractionModelEditor(boolean doExport) { - Component parent = SwingUtilities.getWindowAncestor(this); - if (parent == null) { - parent = this; - } - UIUtil.setWaitCursor(parent); - try { - String file; - String ts = new SimpleDateFormat("HH-mm-ss-SSS", Locale.ENGLISH).format(new Date()); - - Table stable = table; - String subjectCondition; - - QueryBuilderDialog.Relationship root = createQBRelations(false); - Collection restrictedAssociations = new HashSet(); - Collection restrictedDependencies = new HashSet(); - Collection restrictedDependencyDefinitions = new HashSet(); - List restrictionDefinitions = createRestrictions(root, stable, restrictedAssociations, restrictedDependencies, restrictedDependencyDefinitions); - -// if (!restrictedDependencies.isEmpty()) { - Set parents = new TreeSet(); - for (Association association: restrictedDependencies) { - parents.add(dataModel.getDisplayName(association.destination)); - } -// String pList = ""; -// int i = 0; -// for (String p: parents) { -// pList += p + "\n"; -// if (++i > 20) { -// break; -// } -// } - - final SbEDialog sbEDialog = new SbEDialog(SwingUtilities.getWindowAncestor(this), - (doExport? "Export rows and related rows from \"" : "Create Extraction Model for Subject \"") + dataModel.getDisplayName(stable) + "\".", (parents.isEmpty()? "" : ("\n\n" + parents.size() + " disregarded parent tables."))); - if (doExport) { - sbEDialog.setTitle("Export Data"); - } - sbEDialog.regardButton.setVisible(!parents.isEmpty()); - sbEDialog.dispose(); - DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, - boolean hasFocus) { - Component result = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - if (value instanceof DefaultMutableTreeNode) { - if (!(((DefaultMutableTreeNode) value).getUserObject() instanceof String)) { - if (result instanceof JLabel) { - ((JLabel) result).setForeground(Color.red); - } else { - ((JLabel) result).setForeground(Color.black); - } - } - } - return result; - } - - }; - renderer.setOpenIcon(null); - renderer.setLeafIcon(null); - renderer.setClosedIcon(null); - sbEDialog.browserTree.setCellRenderer(renderer); - int[] count = new int[] { 0 }; - DefaultTreeModel treeModel = new DefaultTreeModel(addChildNodes(this, restrictedDependencies, count)); - sbEDialog.browserTree.setModel(treeModel); - for (int i = 0; i < count[0]; ++i) { - sbEDialog.browserTree.expandRow(i); - } - sbEDialog.browserTree.scrollRowToVisible(0); - sbEDialog.browserTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - sbEDialog.browserTree.getSelectionModel().clearSelection(); - } - }); - sbEDialog.grabFocus(); - sbEDialog.setVisible(true); - - if (!sbEDialog.ok) { - return; - } - if (sbEDialog.regardButton.isSelected()) { - restrictionDefinitions.removeAll(restrictedDependencyDefinitions); - for (Association a: restrictedDependencies) { - disableDisregardedNonParentsOfDestination(a, restrictedAssociations, restrictionDefinitions); - } - } - -// int option = JOptionPane.showOptionDialog(parent, "Disregarded parent tables:\n\n" + pList + "\n", "Disregarded parent tables", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "regard parent tables", "Ok" }, "regard parent tables"); -// switch (option) { -// case 0: -// restrictionDefinitions.removeAll(restrictedDependencyDefinitions); -// for (Association a: restrictedDependencies) { -// disableDisregardedNonParentsOfDestination(a, restrictedAssociations, restrictionDefinitions); -// } -// break; -// case 1: -// break; -// default: return; -// } -// } - - subjectCondition = root.whereClause; - if (doExport && (getParentBrowser() != null /* || isLimitExceeded */)) { - subjectCondition = root.whereClause; - if (subjectCondition != null) { - subjectCondition = subjectCondition.replace('\r', ' ').replace('\n', ' '); - } - StringBuilder sb = new StringBuilder(); - boolean f = true; - for (Row row: rows) { - if (f) { - f = false; - } else { - sb.append(" or "); - } - sb.append("(" + row.rowId + ")"); - } - - if (subjectCondition != null && subjectCondition.trim().length() > 0) { - subjectCondition = "(" + subjectCondition + ") and (" + sb + ")"; - } else { - subjectCondition = sb.toString(); - } - } - if (subjectCondition == null) { - subjectCondition = ""; - } -// if (doExport && isLimitExceeded && rows != null && !rows.isEmpty()) { -// StringBuilder sb = new StringBuilder(); -// boolean f = true; -// for (Row row: rows) { -// if (f) { -// f = false; -// } else { -// sb.append(" or "); -// } -// sb.append("(" + row.rowId + ")"); -// } -// subjectCondition = sb.toString(); -// } - subjectCondition = SqlUtil.replaceAliases(subjectCondition, "T", "T"); - - if (!doExport) { - for (int i = 1; ; ++i) { - file = Environment.newFile("extractionmodel" + File.separator + "by-example").getPath(); - File newFile = new File(file); - newFile.mkdirs(); - file += File.separator + "SbE-" + (dataModel.getDisplayName(stable).replaceAll("['`\"/\\\\\\~]+", "")) + "-" + ts + (i > 1? "-" + Integer.toString(i) : "") + ".jm"; - newFile = new File(file); - if (!newFile.exists()) { - break; - } - } - } else { - file = Configuration.getInstance().createTempFile().getPath(); - } - - Map> positions = new TreeMap>(); - collectPositions(positions); - String currentModelSubfolder = DataModelManager.getCurrentModelSubfolder(executionContext); - dataModel.save(file, stable, new SubjectLimitDefinition(null, null), subjectCondition, ScriptFormat.SQL, restrictionDefinitions, positions, new ArrayList(), currentModelSubfolder); - - final ExtractionModelFrame extractionModelFrame = ExtractionModelFrame.createFrame(file, false, !doExport, null, executionContext); - extractionModelFrame.setDbConnectionDialogClone(getDbConnectionDialog()); - if (doExport) { - extractionModelFrame.openExportDialog(false, - new Runnable() { - @Override - public void run() { - try { - reloadDataModel(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }, - new Runnable() { - @Override - public void run() { - extractionModelFrame.dispose(); - } - }); - } else { - extractionModelFrame.markDirty(); - extractionModelFrame.expandAll(); - } - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } finally { - UIUtil.resetWaitCursor(parent); - } - } - - private DefaultMutableTreeNode addChildNodes(BrowserContentPane browserContentPane, Collection restrictedDependencies, int[] count) { - DefaultMutableTreeNode node = new DefaultMutableTreeNode(dataModel.getDisplayName(browserContentPane.table)); - count[0]++; - Set regardedChildren = new HashSet
(); - for (RowBrowser rb: browserContentPane.getChildBrowsers()) { - DefaultMutableTreeNode childNode = addChildNodes(rb.browserContentPane, restrictedDependencies, count); - node.add(childNode); - regardedChildren.add(rb.browserContentPane.table); - } - for (final Association dep: restrictedDependencies) { - if (dep.source == browserContentPane.table && !regardedChildren.contains(dep.destination)) { - node.add(new DefaultMutableTreeNode(new Object() { - String item = dataModel.getDisplayName(dep.destination); - @Override - public String toString() { - return item; - } - })); - count[0]++; - } - } - return node; - } - - private void disableDisregardedNonParentsOfDestination(Association a, - Collection regardedAssociations, - List restrictionDefinitions) { - for (Association npa: a.destination.associations) { - if (!regardedAssociations.contains(npa)) { - regardedAssociations.add(npa); - if (npa.isInsertDestinationBeforeSource()) { - disableDisregardedNonParentsOfDestination(npa, regardedAssociations, restrictionDefinitions); - } else { - RestrictionDefinition rest = new RestrictionDefinition(npa.source, npa.destination, npa.getName(), null, true); - restrictionDefinitions.add(rest); - } - } - } - } - - private static class RestrictionLiteral { - public String condition; - public int distanceFromRoot; - public boolean isIgnored; - public boolean isIgnoredIfReversalIsRestricted = false; - @Override - public String toString() { - return "Cond:" + condition + " Dist: " + distanceFromRoot + " isIgnored: " + isIgnored + " isIgnoredIfReversalIsRestricted: " + isIgnoredIfReversalIsRestricted; - } - } - - /** - * Creates restriction according to the given {@link Relationship} tree. - * - * @param root root of tree - * @return restrictions - */ - private List createRestrictions(Relationship root, Table subject, Collection regardedAssociations, Collection restrictedDependencies, Collection restrictedDependencyDefinitions) { - List restrictionDefinitions = new ArrayList(); - - Map> restrictionLiterals = new HashMap>(); - collectRestrictionLiterals(restrictionLiterals, root, subject, 0); - - for (Association association: restrictionLiterals.keySet()) { - RestrictionDefinition rest = createRestrictionDefinition(association, restrictionLiterals, true); - - regardedAssociations.add(association); - if (rest.isIgnored || (rest.condition != null && rest.condition.trim().length() != 0)) { - restrictionDefinitions.add(rest); - if (association.isInsertDestinationBeforeSource() && rest.isIgnored) { - restrictedDependencies.add(association); - restrictedDependencyDefinitions.add(rest); - } - } - } - - return restrictionDefinitions; - } - - private RestrictionDefinition createRestrictionDefinition(Association association, Map> restrictionLiterals, boolean checkReversal) { - List lits = restrictionLiterals.get(association); - boolean useDistance = false; - boolean hasTrue = false; - boolean hasNotTrue = false; - boolean hasNotFalse = false; - Integer lastDist = null; - for (RestrictionLiteral l: lits) { - - if (l.isIgnoredIfReversalIsRestricted) { - - if (checkReversal) { - RestrictionDefinition revRest = createRestrictionDefinition(association.reversalAssociation, restrictionLiterals, false); - if (revRest.isIgnored || (revRest.condition != null && revRest.condition.trim().length() > 0)) { - l.isIgnored = true; - } else { - l.isIgnored = false; - l.condition = null; - } - l.isIgnoredIfReversalIsRestricted = false; - } else { - l.isIgnored = true; - l.isIgnoredIfReversalIsRestricted = false; - } - } - - // disabled since 5.0 - -// if (lastDist != null && lastDist != l.distanceFromRoot) { -// useDistance = true; -// } -// lastDist = l.distanceFromRoot; - - if (!l.isIgnored) { - hasNotFalse = true; - if (l.condition == null || l.condition.trim().length() == 0) { - hasTrue = true; - } else { - hasNotTrue = true; - } - } else { - hasNotTrue = true; - } - } - - boolean isIgnored; - String condition = null; - - if (!hasNotFalse) { - isIgnored = true; - } else if (!hasNotTrue) { - isIgnored = false; - } else if (hasTrue && !useDistance) { - isIgnored = false; - } else { - for (RestrictionLiteral l: lits) { - if (!l.isIgnored) { - String c = null; - if (useDistance) { - c = l.distanceFromRoot == 0? "A.$IS_SUBJECT" : ("A.$DISTANCE=" + l.distanceFromRoot); - } - if (l.condition != null && l.condition.trim().length() > 0) { - if (c == null) { - c = l.condition; - } else { - c = c + " and (" + l.condition + ")"; - } - } - if (condition == null) { - condition = c; - } else { - condition += " or " + c; - } - } - } - isIgnored = false; - } - RestrictionDefinition rest = new RestrictionDefinition(association.source, association.destination, association.getName(), condition, isIgnored); - return rest; - } - - /** - * Collects restriction literals per association according to a given {@link Relationship} tree. - * - * @param restrictionLiterals to put literals into - * @param root root of tree - * @param distanceFromRoot distance - */ - private void collectRestrictionLiterals(Map> restrictionLiterals, Relationship root, Table subject, int distanceFromRoot) { - for (Association association: subject.associations) { - List children = new ArrayList(); - for (Relationship r: root.children) { - if (r.association == association) { - children.add(r); - } - } - if (children.isEmpty()) { - children.add(null); - } - for (Relationship child: children) { - RestrictionLiteral restrictionLiteral = new RestrictionLiteral(); - restrictionLiteral.distanceFromRoot = distanceFromRoot; - restrictionLiteral.isIgnored = false; - if (child == null) { - restrictionLiteral.isIgnored = true; -// if (association.isInsertDestinationBeforeSource()) { - if (root.association != null && association == root.association.reversalAssociation) { - if (association.getCardinality() == Cardinality.MANY_TO_ONE - || - association.getCardinality() == Cardinality.ONE_TO_ONE) { - restrictionLiteral.isIgnoredIfReversalIsRestricted = true; - } - } -// } - } else { - restrictionLiteral.condition = child.whereClause == null? "" : SqlUtil.replaceAliases(child.whereClause, "B", "A"); - collectRestrictionLiterals(restrictionLiterals, child, association.destination, distanceFromRoot + 1); - } - List literals = restrictionLiterals.get(association); - if (literals == null) { - literals = new ArrayList(); - restrictionLiterals.put(association, literals); - } - literals.add(restrictionLiteral); - } - } - } - - private void openSQLDialog(String titel, int x, int y, Object sql) { - UIUtil.setWaitCursor(this); - JDialog d; - try { - String LF = System.getProperty("line.separator", "\n"); - String sqlString = sql.toString().trim() + LF; - if (sqlString.length() > 10L*1024L*1024L) { - int o = JOptionPane.showOptionDialog(this, "SQL Script is large (" + (sqlString.length() / 1024) + " KB)", "SQL Script is large", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Open", "Cancel", "Save Script" }, "Save Script"); - if (o == 2) { - String fn = UIUtil.choseFile(null, ".", "Save SQL Script", ".sql", this, false, false, false); - if (fn != null) { - try { - PrintWriter out = new PrintWriter(new FileWriter(fn)); - out.print(sqlString); - out.close(); - } catch (Throwable e) { - UIUtil.showException(this, "Error saving script", e, UIUtil.EXCEPTION_CONTEXT_USER_ERROR); - } - } - } - if (o != 0) { - return; - } - } - d = new JDialog(getOwner(), "Create SQL - " + titel, true); - d.getContentPane().add(new SQLDMLPanel(sqlString, getSqlConsole(false), session, getMetaDataSource(), - new Runnable() { - @Override - public void run() { - reloadRows(); - } - }, - new Runnable() { - @Override - public void run() { - getSqlConsole(true); - } - }, - d, executionContext)); - d.pack(); - d.setLocation(x - 50, y - 100); - d.setSize(700, Math.max(d.getHeight() + 20, 400)); - d.setLocation(getOwner().getX() + (getOwner().getWidth() - d.getWidth()) / 2, Math.max(0, getOwner().getY() + (getOwner().getHeight() - d.getHeight()) / 2)); - UIUtil.fit(d); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e); - return; - } finally { - UIUtil.resetWaitCursor(this); - } - d.setVisible(true); - } - - protected abstract SQLConsole getSqlConsole(boolean switchToConsole); - - private void appendClosure() { - if (getParentBrowser() != null) { - if (rowsClosure.currentClosureRootPane == this) { - List selectedRows = new ArrayList(); - RowSorter rowSorter = rowsTable.getRowSorter(); - for (int i = rows.size() - 1; i >= 0; --i) { - if (rowsClosure.currentClosureRootID.contains(rows.get(i).nonEmptyRowId)) { - int vi = rowSorter.convertRowIndexToView(i); - if (vi >= 0) { - selectedRows.add(vi); - } - } - } - resetCurrentRowSelection(); - for (int si: selectedRows ) { - setCurrentRowSelection(si, true); - } - setCurrentRowSelection(-1, true); - } else { - BrowserContentPane parentContentPane = getParentBrowser().browserContentPane; - - Set> newElements = new HashSet>(); - for (Pair e: rowsClosure.currentClosure) { - if (e.a == parentContentPane) { - parentContentPane.findClosure(e.b, newElements, true); - } - } - rowsClosure.currentClosure.addAll(newElements); - rowsClosure.currentClosureRowIDs.clear(); - for (Pair r: rowsClosure.currentClosure) { - rowsClosure.currentClosureRowIDs.add(new Pair(r.a, r.b.nonEmptyRowId)); - } - rowsTable.repaint(); - adjustClosure(null, this); - } - } - } - - protected void setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(int i, boolean append) { - setCurrentRowSelection(i, append); - if (i >= 0) { - reloadChildrenIfLimitIsExceeded(); - } - } - - protected void setCurrentRowSelection(int i, boolean append) { - currentRowSelection = i; - if (i >= 0) { - int mi = rowsTable.getRowSorter().convertRowIndexToModel(i); - if (mi >= 0 && mi < rows.size()) { - Row row = rows.get(mi); - if (!append) { - for (Pair e: rowsClosure.currentClosure) { - e.a.currentRowSelection = -1; - } - rowsClosure.currentClosure.clear(); - rowsClosure.parentPath.clear(); - rowsClosure.currentClosureRootID.clear(); - } - rowsClosure.currentClosureRootID.add(row.nonEmptyRowId); - rowsClosure.currentClosureRootPane = this; - findClosure(row); - Rectangle visibleRect = rowsTable.getVisibleRect(); - Rectangle pos = rowsTable.getCellRect(i, 0, false); - rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, pos.y, 1, pos.height)); - } - } - rowsClosure.currentClosureRowIDs.clear(); - for (Pair r: rowsClosure.currentClosure) { - rowsClosure.currentClosureRowIDs.add(new Pair(r.a, r.b.nonEmptyRowId)); - } - rowsTable.repaint(); - adjustClosure(this, null); - } - - private void resetCurrentRowSelection() { - currentRowSelection = -1; - rowsClosure.currentClosure.clear(); - rowsClosure.parentPath.clear(); - rowsClosure.currentClosureRootID.clear(); - rowsTable.repaint(); - adjustClosure(this, null); - } - - private void reloadChildrenIfLimitIsExceeded() { - for (RowBrowser ch: getChildBrowsers()) { - if (ch.browserContentPane != null) { - if (ch.browserContentPane.isLimitExceeded) { - Boolean oldForceAdjustRows = Desktop.forceAdjustRows; - try { - Desktop.forceAdjustRows = true; - ch.browserContentPane.reloadRows("because rows limit is exceeded"); - } finally { - Desktop.forceAdjustRows = oldForceAdjustRows; - } - } else { - ch.browserContentPane.reloadChildrenIfLimitIsExceeded(); - } - } - } - } - - private JPopupMenu createNavigationMenu(JPopupMenu popup, final Row row, final int rowIndex, List assList, Map assMap, - String title, String prefix, final boolean navigateFromAllRows, final int rowCountPriority, final AllNonEmptyItem allNonEmptyItem, final Object context) { - JScrollC2Menu nav = new JScrollC2Menu(title); - - if (prefix.equals("1")) { - nav.setIcon(UIUtil.scaleIcon(this, redDotIcon)); - } - if (prefix.equals("2")) { - nav.setIcon(UIUtil.scaleIcon(this, greenDotIcon)); - } - if (prefix.equals("3")) { - nav.setIcon(UIUtil.scaleIcon(this, blueDotIcon)); - } - if (prefix.equals("4")) { - nav.setIcon(UIUtil.scaleIcon(this, greyDotIcon)); - } - JMenu current = nav; - - final List pRows; - if (row == null) { - pRows = Collections.emptyList(); - } else { - pRows = getSelectedRows(row); - } - String countCondition = toCondition(pRows); - - int l = 0; - for (String name : assList) { - if (!name.startsWith(prefix)) { - continue; - } - - final Association association = assMap.get(name); - - ++l; - - final JMenuItem item = new JMenuItem(" " + (name.substring(1)) + " "); - item.setToolTipText(assocToolTip(association.getUnrestrictedJoinCondition(), association)); - final JLabel countLabel = new JLabel(". >99999 ") { - @Override - public void paint(Graphics g) { - if (!getText().startsWith(".")) { - super.paint(g); - } - } - }; - - boolean excludeFromANEmpty = false; - for (RowBrowser child: getChildBrowsers()) { - if (association == child.association && - (child.browserContentPane.getAndConditionText().trim().length() == 0 - || child.browserContentPane.getAndConditionText().trim().equals(countCondition))) { - item.setFont(new Font(item.getFont().getName(), item.getFont().getStyle() | Font.ITALIC, item.getFont().getSize())); - excludeFromANEmpty = true; - break; - } - } - - if (association.reversalAssociation == this.association) { - excludeFromANEmpty = true; - } - - final ActionListener itemAction = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (navigateFromAllRows) { - navigateTo(association, null); - } else { - navigateTo(association, pRows); - } - } - }; - item.addActionListener(itemAction); - if (!excludeFromANEmpty) { - allNonEmptyItem.todo++; - } - final boolean fExcludeFromANEmpty = excludeFromANEmpty; - - if (!isPending && !rows.isEmpty()) { - getRunnableQueue().add(new RunnableWithPriority() { - - final int MAX_RC = 1000; - - String andConditionText = getAndConditionText(); - - @Override - public int getPriority() { - return rowCountPriority; - } - - @Override - public void run() { - List r; - Pair key; - if (rowIndex < 0) { - r = rows; - key = new Pair("", association); - } else { - r = pRows; - key = new Pair(row.nonEmptyRowId, association); - } - - Pair cachedCount = rowCountCache.get(key); - RowCount rowCount; - - if (cachedCount != null && cachedCount.b > System.currentTimeMillis()) { - rowCount = cachedCount.a; - } else { - RowCounter rc = new RowCounter(table, association, r, session, rowIdSupport); - try { - rowCount = rc.countRows(andConditionText, context, MAX_RC + 1, false); - } catch (SQLException e) { - rowCount = new RowCount(-1, true); - } - rowCountCache.put(key, new Pair(rowCount, System.currentTimeMillis() + MAX_ROWCOUNTCACHE_RETENTION_TIME)); - } - - final RowCount count = rowCount; - - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - String cs = " " + (count.count < 0? "?" : (count.count > MAX_RC)? (">" + MAX_RC) : count.isExact? count.count : (">" + count.count)) + " "; - countLabel.setText(cs); - if (count.count == 0) { - countLabel.setForeground(Color.lightGray); - } - if (!fExcludeFromANEmpty) { - allNonEmptyItem.rowsCounted(count.count, itemAction); - } - } - }); - } - }); - } - - if (current != null) { - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = l; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - current.getPopupMenu().add(item, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = l; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - current.getPopupMenu().add(countLabel, gridBagConstraints); - } else { - popup.add(item); - } - } - if (l > 0) { - popup.add(nav); - } - return popup; - } - - private long lastReloadTS = 0; - - /** - * Reloads rows. - */ - public void reloadRows() { - reloadRows(null); - } - - boolean loadedRowsAreRestricted = false; - - /** - * Reloads rows. - */ - public void reloadRows(String cause) { - if (!suppressReload) { - lastReloadTS = System.currentTimeMillis(); - cancelLoadJob(true); - setPendingState(true, true); - rows.clear(); - updateMode("loading", cause); - setPendingState(false, false); - int limit = getReloadLimit(); - LoadJob reloadJob; - loadedRowsAreRestricted = false; - if (statementForReloading != null) { - reloadJob = new LoadJob(limit, statementForReloading, getParentBrowser(), false); - } else { - loadedRowsAreRestricted = !(table instanceof SqlStatementTable) && !getAndConditionText().trim().isEmpty(); - reloadJob = new LoadJob(limit, (table instanceof SqlStatementTable)? "" : getAndConditionText(), getParentBrowser(), selectDistinctCheckBox.isSelected()); - currentSelectedRowCondition = getAndConditionText(); - } - synchronized (this) { - currentLoadJob = reloadJob; - } - getRunnableQueue().add(reloadJob); - } - } - - /** - * Reload rows from {@link #table}. - * - * @param rows - * to put the rows into - * @param loadJob - * cancellation context - * @param limit - * row number limit - */ - private void reloadRows(ResultSet inputResultSet, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct) throws SQLException { - try { - session.setSilent(true); - reloadRows(inputResultSet, andCond, rows, loadJob, limit, selectDistinct, null); - return; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another strategy (" + e.getMessage() + ")"); - } finally { - session.setSilent(false); - } - Set existingColumnsLowerCase = null; - if (!(table instanceof SqlStatementTable) && statementForReloading == null) { - existingColumnsLowerCase = findColumnsLowerCase(table, session); - } - reloadRows(inputResultSet, andCond, rows, loadJob, limit, selectDistinct, existingColumnsLowerCase); - } - - /** - * Finds the columns of a given {@link Table}. - * - * @param table the table - * @param session the statement executor for executing SQL-statements - */ - private Set findColumnsLowerCase(Table table, Session session) { - try { - Set columns = new HashSet(); - DatabaseMetaData metaData = session.getMetaData(); - Quoting quoting = Quoting.getQuoting(session); - String defaultSchema = JDBCMetaDataBasedModelElementFinder.getDefaultSchema(session, session.getSchema()); - String schema = quoting.unquote(table.getOriginalSchema(defaultSchema)); - String tableName = quoting.unquote(table.getUnqualifiedName()); - ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, false, null); - while (resultSet.next()) { - String colName = resultSet.getString(4).toLowerCase(Locale.ENGLISH); - columns.add(colName); - } - resultSet.close(); - if (columns.isEmpty()) { - if (session.getMetaData().storesUpperCaseIdentifiers()) { - schema = schema.toUpperCase(Locale.ENGLISH); - tableName = tableName.toUpperCase(Locale.ENGLISH); - } else { - schema = schema.toLowerCase(Locale.ENGLISH); - tableName = tableName.toLowerCase(Locale.ENGLISH); - } - resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, false, null); - while (resultSet.next()) { - String colName = resultSet.getString(4).toLowerCase(Locale.ENGLISH); - columns.add(colName); - } - } - if (columns.isEmpty()) { - return null; - } - return columns; - } catch (Exception e) { - return null; - } - } - - /** - * Reload rows from {@link #table}. - * - * @param rows - * to put the rows into - * @param loadJob - * cancellation context - * @param limit - * row number limit - */ - private void reloadRows(ResultSet inputResultSet, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct, Set existingColumnsLowerCase) throws SQLException { - if (table instanceof SqlStatementTable || statementForReloading != null) { - try { - session.setSilent(true); - Map> rowsMap = new HashMap>(); - reloadRows(inputResultSet, null, andCond, null, rowsMap, loadJob, limit, false, null, existingColumnsLowerCase); - if (rowsMap.get("") != null) { - rows.addAll(rowsMap.get("")); - } - } finally { - session.setSilent(false); - } - return; - } - - List pRows = parentRows; - if (pRows == null) { - pRows = Collections.singletonList(null); - } else { - pRows = new ArrayList(pRows); - } - Map rowSet = new HashMap(); - loadJob.checkCancellation(); - if (parentRows != null) { - beforeReload(); - } - noNonDistinctRows = 0; - noDistinctRows = 0; - - if (association != null && rowIdSupport.getPrimaryKey(association.source, session).getColumns().isEmpty()) { - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 1, existingColumnsLowerCase); - } else { - if (useInlineViewForResolvingAssociation(session)) { - try { - InlineViewStyle inlineViewStyle = session.getInlineViewStyle(); - if (inlineViewStyle != null) { - loadRowBlocks(inputResultSet, inlineViewStyle, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 510, existingColumnsLowerCase); - return; - } - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); - } - } - try { - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 510, existingColumnsLowerCase); - return; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); - } - try { - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 300, existingColumnsLowerCase); - return; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); - } - try { - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 100, existingColumnsLowerCase); - return; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); - } - try { - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 40, existingColumnsLowerCase); - return; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); - } - } - - loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 1, existingColumnsLowerCase); - } - - static boolean useInlineViewForResolvingAssociation(Session session) { - return session.dbms.isUseInlineViewsInDataBrowser(); - } - - private void loadRowBlocks(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct, List pRows, - Map rowSet, int NUM_PARENTS, Set existingColumnsLowerCase) throws SQLException { - List> parentBlocks = new ArrayList>(); - List currentBlock = new ArrayList(); - Set regPRows = new HashSet(); - Map parentRowIndex = new IdentityHashMap(); - for (int i = 0; i < pRows.size(); ++i) { - parentRowIndex.put(pRows.get(i), i); - } - parentBlocks.add(currentBlock); - BrowserContentPane parentPane = null; - if (getParentBrowser() != null) { - parentPane = getParentBrowser().browserContentPane; - } - for (boolean inClosure: new boolean[] { true, false }) { - boolean firstNonClosure = false; - for (Row pRow : pRows) { - if (parentPane != null) { - if (rowsClosure.currentClosure.contains(new Pair(parentPane, pRow))) { - if (!inClosure) { - continue; - } - } else { - if (inClosure) { - continue; - } - } - } else if (!inClosure) { - break; - } - if (currentBlock.size() >= NUM_PARENTS || (!inClosure && !firstNonClosure)) { - if (!currentBlock.isEmpty()) { - currentBlock = new ArrayList(); - parentBlocks.add(currentBlock); - } - if (!inClosure) { - firstNonClosure = true; - } - } - currentBlock.add(pRow); - } - } - int parentIndex = 0; - - if (!pRows.isEmpty()) for (List pRowBlockI : parentBlocks) { - List pRowBlock = pRowBlockI; - Map> newBlockRows = new HashMap>(); - boolean loaded = false; - - if (pRowBlock.size() == 1 && pRowBlock.get(0) == null) { - pRowBlock = null; - } - - if (session.dbms.getSqlLimitSuffix() != null) { - try { - session.setSilent(true); - reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, false, session.dbms.getSqlLimitSuffix(), existingColumnsLowerCase); - loaded = true; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another limit-strategy (" + e.getMessage() + ")"); - } finally { - session.setSilent(false); - } - } - if (!loaded) { - try { - session.setSilent(true); - reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, true, null, existingColumnsLowerCase); - loaded = true; - } catch (Throwable e) { // embedded DBMS may throw non-SQLException - Session._log.warn("failed, try another limit-strategy (" + e.getMessage() + ")"); - } finally { - session.setSilent(false); - } - if (!loaded) { - try { - session.setSilent(true); - reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, false, null, existingColumnsLowerCase); - } finally { - session.setSilent(false); - } - } - } - if (pRowBlock == null) { - pRowBlock = new ArrayList(); - pRowBlock.add(null); - } - for (Row pRow: pRowBlock) { - loadJob.checkCancellation(); - boolean dupParent = false; - if (pRow != null) { - if (regPRows.contains(pRow.nonEmptyRowId)) { - dupParent = true; - } - regPRows.add(pRow.nonEmptyRowId); - } - List newRows = new ArrayList(); - String rId = pRow == null? "" : pRow.nonEmptyRowId; - if (newBlockRows.get(rId) != null) { - newRows.addAll(newBlockRows.get(rId)); - } - sortNewRows(newRows); - if (parentRows != null) { - if (!newRows.isEmpty()) { - Integer i = parentRowIndex.get(pRow); - for (Row r: newRows) { - r.setParentModelIndex(i != null? i : parentIndex); - } - } - ++parentIndex; - for (Row row : newRows) { - Row exRow = rowSet.get(row.nonEmptyRowId); - if (!dupParent) { - if (exRow != null) { - ++noNonDistinctRows; - } else { - ++noDistinctRows; - } - } - if (exRow != null && (selectDistinct || dupParent)) { - addRowToRowLink(pRow, exRow); - } else { - rows.add(row); - addRowToRowLink(pRow, row); - rowSet.put(row.nonEmptyRowId, row); - --limit; - } - } - } else { - rows.addAll(newRows); - limit -= newRows.size(); - } - if (limit <= 0) { - if (parentPane != null) { - if (rowsClosure.currentClosure.contains(new Pair(parentPane, pRow))) { - loadJob.closureLimitExceeded = true; - } - } - break; - } - } - if (limit <= 0) { - break; - } - } - } - - private void sortNewRows(List newRows) { - if (rowsTable != null && rowsTable.getRowSorter() != null) { - List sk = rowsTable.getRowSorter().getSortKeys(); - final int col; - final boolean asc; - if (!sk.isEmpty()) { - col = sk.get(0).getColumn(); - asc = sk.get(0).getSortOrder() == SortOrder.ASCENDING; - } else { - col = getDefaultSortColumn(); - asc = true; - } - if (col >= 0) { - Collections.sort(newRows, new Comparator() { - @Override - public int compare(Row a, Row b) { - Object va = null; - if (a != null && a.values != null && a.values.length > col) { - va = a.values[col]; - } - Object vb = null; - if (b != null && b.values != null && b.values.length > col) { - vb = b.values[col]; - } - if (va == null && vb == null) { - return 0; - } - if (va == null) { - return -1; - } - if (vb == null) { - return 1; - } - if (va.getClass().equals(vb.getClass())) { - if (va instanceof Comparable) { - int cmp = ((Comparable) va).compareTo(vb); - return asc? cmp : -cmp; - } - return 0; - } - int cmp = va.getClass().getName().compareTo(vb.getClass().getName()); - return asc? cmp : -cmp; - } - }); - } - } - } - - /** - * Reload rows from {@link #table}. - * - * @param rows - * to put the rows into - * @param context - * cancellation context - * @param rowCache - * @param allPRows - */ - private void reloadRows(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List parentRows, final Map> rows, LoadJob loadJob, int limit, boolean useOLAPLimitation, - String sqlLimitSuffix, Set existingColumnsLowerCase) throws SQLException { - reloadRows0(inputResultSet, inlineViewStyle, andCond, parentRows, rows, loadJob, parentRows == null? limit : Math.max(5000, limit), useOLAPLimitation, sqlLimitSuffix, existingColumnsLowerCase); - } - - /** - * Gets qualified table name. - * - * @param t the table - * @return qualified name of t - */ - private String qualifiedTableName(Table t, Quoting quoting) { - String schema = t.getSchema(""); - if (schema.length() == 0) { - return quoting.requote(t.getUnqualifiedName()); - } - return quoting.requote(schema) + "." + quoting.requote(t.getUnqualifiedName()); - } - - /** - * Reload rows from {@link #table}. - * - * @param rows - * to put the rows into - * @param loadJob - * cancellation context - */ - private void reloadRows0(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List parentRows, final Map> rows, LoadJob loadJob, int limit, boolean useOLAPLimitation, - String sqlLimitSuffix, Set existingColumnsLowerCase) throws SQLException { - String sql = "Select "; - final Quoting quoting = Quoting.getQuoting(session); - final Set pkColumnNames = new HashSet(); - final Set parentPkColumnNames = new HashSet(); - final boolean selectParentPK = association != null && parentRows != null && parentRows.size() > 1; - final Set unknownColumnIndexes = new HashSet(); - int numParentPKColumns = 0; - - if (table instanceof SqlStatementTable || statementForReloading != null) { - sql = andCond; - if (!(table instanceof SqlStatementTable)) { - for (Column pk: rowIdSupport.getPrimaryKey(table, session).getColumns()) { - pkColumnNames.add(quoting.requote(pk.name)); - } - } else { - table.setColumns(new ArrayList()); - } - } else { - String olapPrefix = "Select "; - String olapSuffix = ") S Where S." + ROWNUMBERALIAS + " <= " + limit; - boolean limitSuffixInSelectClause = sqlLimitSuffix != null && - (sqlLimitSuffix.toLowerCase(Locale.ENGLISH).startsWith("top ") || sqlLimitSuffix.toLowerCase(Locale.ENGLISH).startsWith("first ")); - if (sqlLimitSuffix != null && limitSuffixInSelectClause) { - sql += (sqlLimitSuffix.replace("%s", Integer.toString(limit))) + " "; - } - int colI = 1; - boolean f = true; - if (selectParentPK) { - int i = 0; - for (Column column: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { - String name = quoting.requote(column.name); - sql += (!f ? ", " : "") + "B." + name + " AS B" + i; - olapPrefix += (!f ? ", " : "") + "S.B" + i; - ++numParentPKColumns; - ++i; - ++colI; - f = false; - } - } - int i = 0; - - for (Column column : rowIdSupport.getColumns(table, session)) { - String name = quoting.requote(column.name); - if (existingColumnsLowerCase != null && !rowIdSupport.isRowIdColumn(column) && !existingColumnsLowerCase.contains(quoting.unquote(name).toLowerCase(Locale.ENGLISH))) { - sql += (!f ? ", " : "") + "'?' AS A" + i; - unknownColumnIndexes.add(colI); - } else { - sql += (!f ? ", " : "") + "A." + name + " AS A" + i; - } - olapPrefix += (!f ? ", " : "") + "S.A" + i; - ++i; - ++colI; - f = false; - } - f = true; - if (selectParentPK) { - int j = 0; - for (Column pk: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { - parentPkColumnNames.add(quoting.requote(pk.name)); - ++j; - f = false; - } - } - int j = 0; - for (Column pk: rowIdSupport.getPrimaryKey(table, session).getColumns()) { - pkColumnNames.add(quoting.requote(pk.name)); - ++j; - f = false; - } - if (useOLAPLimitation) { - sql += ", row_number() over("; - if (useOLAPLimitation) { - sql += "order by -1"; // + orderBy; - } - sql += ") as " + ROWNUMBERALIAS + ""; - } - sql += " From "; - if (association != null) { - sql += qualifiedTableName(association.source, quoting) + " B join "; - } - sql += qualifiedTableName(table, quoting) + " A"; - if (association != null) { - if (association.reversed) { - sql += " on " + association.getUnrestrictedJoinCondition(); - } else { - sql += " on " + SqlUtil.reversRestrictionCondition(association.getUnrestrictedJoinCondition()); - } - } - - boolean whereExists = false; - if (parentRows != null && !parentRows.isEmpty()) { - if (association != null && parentRows.get(0).rowId.length() == 0) { - throw new SqlException("Missing primary key for table: \"" + Quoting.staticUnquote(association.source.getName()) + "\"\n" - + "Resolution: define the primary key manually using the data model editor.", "", null); - } - if (parentRows.size() == 1) { - sql += " Where (" + parentRows.get(0).rowId + ")"; - } else { - StringBuilder sb = new StringBuilder(); - if (inlineViewStyle != null && association != null) { - sb.append(" join "); - List columnNames = new ArrayList(); - for (Column pkColumn: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { - columnNames.add(pkColumn.name); - } - String[] columnNamesAsArray = columnNames.toArray(new String[columnNames.size()]); - sb.append(inlineViewStyle.head(columnNamesAsArray)); - int rowNumber = 0; - for (Row parentRow: parentRows) { - if (rowNumber > 0) { - sb.append(inlineViewStyle.separator()); - } - sb.append(inlineViewStyle.item(parentRow.primaryKey, columnNamesAsArray, rowNumber)); - ++rowNumber; - } - sb.append(inlineViewStyle.terminator("C", columnNamesAsArray)); - sb.append(" on ("); - boolean f2 = true; - for (String pkColumnName: columnNames) { - if (!f2) { - sb.append(" and "); - } - sb.append("B." + pkColumnName + " = " + "C." + pkColumnName); - f2 = false; - } - sb.append(")"); - } else { - for (Row parentRow: parentRows) { - if (sb.length() == 0) { - sb.append(" Where (("); - } else { - sb.append(" or ("); - } - sb.append(parentRow.rowId).append(")"); - } - sb.append(")"); - } - sql += sb.toString(); - } - whereExists = true; - } - if (andCond.trim().length() > 0) { - sql += (whereExists ? " and" : " Where") + " (" + (andCond) + ")"; - } - olapPrefix += " From ("; - if (useOLAPLimitation) { - sql = olapPrefix + sql + olapSuffix; - } - if (sqlLimitSuffix != null && !limitSuffixInSelectClause) { - sql += " " + (sqlLimitSuffix.replace("%s", Integer.toString(limit))); - } - } - - if (sql.length() > 0 || inputResultSet != null) { - final Map pkPosToColumnPos = new HashMap(); - if (!(table instanceof SqlStatementTable) && statementForReloading == null) { - List pks = rowIdSupport.getPrimaryKey(table, session).getColumns(); - List columns = rowIdSupport.getColumns(table, session); - for (int i = 0; i < columns.size(); ++i) { - Column column = columns.get(i); - for (int j = 0; j < pks.size(); ++j) { - if (column.name.equals(pks.get(j).name)) { - pkPosToColumnPos.put(j, i); - break; - } - } - } - } - final int finalNumParentPKColumns = numParentPKColumns; - AbstractResultSetReader reader = new AbstractResultSetReader() { - Map typeCache = new HashMap(); - int rowNr = 0; - - @Override - public void init(ResultSet resultSet) throws SQLException { - ResultSetMetaData metaData = getMetaData(resultSet); - int columnCount = metaData.getColumnCount(); - if (table instanceof SqlStatementTable) { - for (int ci = 1; ci <= columnCount; ++ci) { - table.getColumns().add(new Column(metaData.getColumnLabel(ci), metaData.getColumnTypeName(ci), -1, -1)); - } - } - int[] columnTypes = new int[columnCount]; - String[] columnTypeNames = new String[columnCount]; - for (int ci = 1 + finalNumParentPKColumns; ci <= columnCount; ++ci) { - if (metaData instanceof MemorizedResultSetMetaData) { - columnTypes[ci - 1 - finalNumParentPKColumns] = ((MemorizedResultSetMetaData) metaData).types[ci - 1]; - columnTypeNames[ci - 1 - finalNumParentPKColumns] = ((MemorizedResultSetMetaData) metaData).typeNames[ci - 1]; - } else { - columnTypes[ci - 1 - finalNumParentPKColumns] = metaData.getColumnType(ci); - columnTypeNames[ci - 1 - finalNumParentPKColumns] = metaData.getColumnTypeName(ci); - } - } - browserContentCellEditor = new BrowserContentCellEditor(columnTypes, columnTypeNames, session); - } - - @Override - public void readCurrentRow(ResultSet resultSet) throws SQLException { - int i = 1, vi = 0; - String parentRowId = ""; - if (selectParentPK) { - Object v[] = new Object[rowIdSupport.getPrimaryKey(association.source, session).getColumns().size()]; - for (Column column: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { - parentRowId = readRowFromResultSet(parentPkColumnNames, resultSet, i, vi, parentRowId, v, column, null, null, unknownColumnIndexes); - ++i; - ++vi; - } - } else { - if (parentRows != null && parentRows.size() == 1) { - parentRowId = parentRows.get(0).rowId; - } - } - - Map pkColumn = new HashMap(); - Map pkColumnValue = new HashMap(); - - Object v[] = new Object[rowIdSupport.getColumns(table, session).size()]; - vi = 0; - for (Column column: rowIdSupport.getColumns(table, session)) { - readRowFromResultSet(pkColumnNames, resultSet, i, vi, "", v, column, pkColumn, pkColumnValue, unknownColumnIndexes); - ++i; - ++vi; - } - - String rowId = ""; - String[] primaryKey = null; - PrimaryKey primaryKeys = rowIdSupport.getPrimaryKey(table, session); - if (primaryKeys != null && resultSetType == null) { - int pkPos = 0; - primaryKey = new String[primaryKeys.getColumns().size()]; - for (Column column : primaryKeys.getColumns()) { - if (rowId.length() > 0) { - rowId += " and "; - } - rowId += pkColumn.get(column.name); - Integer colPos = pkPosToColumnPos.get(pkPos); - if (colPos != null) { - primaryKey[pkPos] = pkColumnValue.get(column.name); - } - ++pkPos; - } - } else { - rowId = Integer.toString(++rowNr); - } - - List cRows = rows.get(parentRowId); - if (cRows == null) { - cRows = new ArrayList(); - rows.put(parentRowId, cRows); - } - cRows.add(new Row(rowId, primaryKey, v)); - } - - private String readRowFromResultSet(final Set pkColumnNames, ResultSet resultSet, int i, int vi, String rowId, Object[] v, Column column, Map pkColumn, Map pkColumnValue, Set unknownColumnIndexes) - throws SQLException { - Object value = ""; - if (unknownColumnIndexes.contains(i)) { - value = new UnknownValue() { - @Override - public String toString() { - return "?"; - } - }; - } else { - int type = SqlUtil.getColumnType(resultSet, getMetaData(resultSet), i, typeCache); - Object lob = null; - if (type == 0) { - lob = resultSet.getObject(i); - } - if (type == Types.BLOB || type == Types.CLOB || type == Types.NCLOB || type == Types.SQLXML - || (type == 0 && - (lob instanceof Blob || lob instanceof Clob || lob instanceof SQLXML) - )) { - Object object = resultSet.getObject(i); - if (object == null || resultSet.wasNull()) { - value = null; - } else { - Object lobValue = toLobRender(object); - if (lobValue != null) { - value = lobValue; - } - } - } else { - CellContentConverter cellContentConverter = getCellContentConverter(resultSet, session, session.dbms); - Object o; - try { - o = cellContentConverter.getObject(resultSet, i); - if (o instanceof byte[]) { - final long length = ((byte[]) o).length; - StringBuilder sb = new StringBuilder(); - int j; - for (j = 0; j < length && j < 16; ++j) { - byte b = ((byte[]) o)[j]; - sb.append(" "); - sb.append(CellContentConverter.hexChar[(b >> 4) & 15]); - sb.append(CellContentConverter.hexChar[b & 15]); - } - if (j < length) { - sb.append("... " + length + " bytes"); - } - final String content = sb.toString(); - final byte[] finalO = (byte[]) o; - o = new BinValue() { - @Override - public String toString() { - return "" + content; - } - - @Override - public byte[] getContent() { - return finalO; - } - }; - } - } catch (Throwable e) { - o = "ERROR: " + e.getClass().getName() + ": " + e.getMessage(); - } - boolean isPK = false; - if (pkColumnNames.isEmpty()) { - isPK = type != Types.BLOB && type != Types.CLOB && type != Types.DATALINK && type != Types.JAVA_OBJECT && type != Types.NCLOB - && type != Types.NULL && type != Types.OTHER && type != Types.REF && type != Types.SQLXML && type != Types.STRUCT; - } - if (pkColumnNames.contains(quoting.requote(column.name)) || isPK) { - String cVal = cellContentConverter.toSql(o instanceof BinValue? ((BinValue) o).getContent() : o); - String pkValue = "B." + quoting.requote(column.name) + ("null".equalsIgnoreCase(cVal)? " is null" : ("=" + cVal)); - if (pkColumn != null) { - pkColumn.put(column.name, pkValue); - } - if (pkColumnValue != null) { - pkColumnValue.put(column.name, cVal); - } - rowId += (rowId.length() == 0 ? "" : " and ") + pkValue; - } - if (o == null || resultSet.wasNull()) { - value = null; - } - if (o != null) { - value = o; - } - } - } - v[vi] = value; - return rowId; - } - }; - if (inputResultSet != null) { - reader.init(inputResultSet); - while (inputResultSet.next()) { - reader.readCurrentRow(inputResultSet); - } - inputResultSet.close(); - } - else { - session.executeQuery(sql, reader, null, loadJob, limit); - } - } - } - - /** - * True if row-limit is exceeded. - */ - private boolean isLimitExceeded = false; - private boolean isClosureLimitExceeded = false; - - /** - * Show single row in special view? - */ - protected boolean noSingleRowDetailsView = false; - protected String singleRowDetailsViewTitel = "Single Row Details"; - - /** - * Parent having row-limit exceeded. - */ - private RowBrowser parentWithExceededLimit() { - RowBrowser parent = getParentBrowser(); - - while (parent != null) { - if (parent.browserContentPane.isLimitExceeded) { - return parent; - } - parent = parent.browserContentPane.getParentBrowser(); - } - - return null; - } - - public static class TableModelItem { - public final int blockNr; - public final double inheritedBlockNumber; - public final Object value; - private String valueAsString = null; - - public TableModelItem(int blockNr, double inheritedBlockNumber, Object value) { - this.blockNr = blockNr; - this.inheritedBlockNumber = inheritedBlockNumber; - this.value = value; - } - - @Override - public String toString() { - if (valueAsString == null) { - if (value instanceof Double) { - valueAsString = SqlUtil.toString((Double) value); - } else if (value instanceof BigDecimal) { - valueAsString = SqlUtil.toString((BigDecimal) value); - } else { - valueAsString = String.valueOf(value); - } - } - return valueAsString; - } - } - - private int lastLimit; - private boolean lastLimitExceeded; - private boolean lastClosureLimitExceeded; - private boolean isUpdatingTableModel; - private Set foundColumn = new HashSet(); - - /** - * Updates the model of the {@link #rowsTable}. - * - * @param limit - * row limit - * @param limitExceeded - */ - private void updateTableModel() { - updateTableModel(lastLimit, lastLimitExceeded, lastClosureLimitExceeded); - } - - /** - * Updates the model of the {@link #rowsTable}. - * - * @param limit - * row limit - * @param limitExceeded - */ - private void updateTableModel(int limit, boolean limitExceeded, boolean closureLimitExceeded) { - try { - isUpdatingTableModel = true; - doUpdateTableModel(limit, limitExceeded, closureLimitExceeded); - } finally { - isUpdatingTableModel = false; - } - } - - private boolean dontPaintSortIcon = false; - - private void doUpdateTableModel(int limit, boolean limitExceeded, boolean closureLimitExceeded) { - lastLimit = limit; - lastLimitExceeded = limitExceeded; - lastClosureLimitExceeded = closureLimitExceeded; - pkColumns.clear(); - List columns = rowIdSupport.getColumns(table, session); - String[] columnNames = new String[columns.size()]; - final Set pkColumnNames = new HashSet(); - if (rowIdSupport.getPrimaryKey(table, session) != null) { - for (Column pk : rowIdSupport.getPrimaryKey(table, session).getColumns()) { - pkColumnNames.add(pk.name); - } - } - for (int i = 0; i < columnNames.length; ++i) { - columnNames[i] = columns.get(i).name; - if ("".equals(columnNames[i])) { - columnNames[i] = " "; - } - if (pkColumnNames.contains(columnNames[i])) { - pkColumns.add(i); - } - if (columnNames[i] == null) { - if (alternativeColumnLabels != null && i < alternativeColumnLabels.length) { - columnNames[i] = alternativeColumnLabels[i]; - } - } - } - - fkColumns.clear(); - final Set fkColumnNames = new HashSet(); - for (Association a: table.associations) { - if (a.isInsertDestinationBeforeSource()) { - Map m = a.createSourceToDestinationKeyMapping(); - for (Column fkColumn: m.keySet()) { - fkColumnNames.add(fkColumn.name); - } - } - } - if (rowIdSupport.getPrimaryKey(table, session) != null) { - for (Column pk : rowIdSupport.getPrimaryKey(table, session).getColumns()) { - pkColumnNames.add(pk.name); - } - } - for (int i = 0; i < columnNames.length; ++i) { - if (fkColumnNames.contains(columnNames[i])) { - fkColumns.add(i); - } - } - - DefaultTableModel dtm; - findColumnsLabel.setEnabled(true); - singleRowDetailsView = null; - singleRowViewScrollPaneContainer.setVisible(false); - rowsTableContainerPanel.setVisible(true); - boolean noFilter = true; - int rn = 0; - if (rows.size() != 1 || isEditMode || noSingleRowDetailsView) { - noFilter = false; - Map columnNameMap = new HashMap(); - for (int i = 0; i < columns.size(); ++i) { - columnNameMap.put(columnNames[i], i); - } - String[] uqColumnNames = new String[columnNames.length]; - for (int i = 0; i < uqColumnNames.length; ++i) { - if (columnNames[i] != null) { - uqColumnNames[i] = Quoting.staticUnquote(columnNames[i]); - } - } - dtm = new DefaultTableModel(uqColumnNames, 0) { - @Override - public boolean isCellEditable(int row, int column) { - Row r = null; - if (row < rows.size()) { - r = rows.get(row); - } - Table type = getResultSetTypeForColumn(column); - if (isEditMode && r != null && (r.rowId != null && !r.rowId.isEmpty()) && browserContentCellEditor.isEditable(type, row, column, r.values[column]) && isPKComplete(type, r)) { - return !rowIdSupport.getPrimaryKey(type, session).getColumns().isEmpty(); - } - return false; - } - - @Override - public void setValueAt(Object aValue, int row, int column) { - String text = aValue.toString(); - Row theRow = null; - if (row < rows.size()) { - theRow = rows.get(row); - Object content = browserContentCellEditor.textToContent(row, column, text, theRow.values[column]); - if (content != BrowserContentCellEditor.INVALID) { - if (!browserContentCellEditor.cellContentToText(row, column, theRow.values[column]).equals(text)) { - Table type = getResultSetTypeForColumn(column); - if (resultSetType != null) { - theRow = createRowWithNewID(theRow, type); - } - Object oldContent = theRow.values[column]; - theRow.values[column] = content; - final String updateStatement = SQLDMLBuilder.buildUpdate(type, theRow, false, column, session); - theRow.values[column] = oldContent; - updateMode("updating", null); - - getRunnableQueue().add(new RunnableWithPriority() { - private Exception exception; - - @Override - public void run() { - final Object context = new Object(); - ActionListener listener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - CancellationHandler.cancel(context); - } - }; - cancelLoadButton.addActionListener(listener); - try { - session.execute(updateStatement, context, false); - } catch (Exception e) { - exception = e; - } finally { - CancellationHandler.reset(context); - cancelLoadButton.removeActionListener(listener); - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - if (exception != null && !(exception instanceof CancellationException)) { - UIUtil.showException(BrowserContentPane.this, "Error", exception); - updateMode("table", null); - } else { - reloadRows(); - } - } - }); - } - - @Override - public int getPriority() { - return 50; - } - }); - } - } - } - } - }; - - boolean stripHour[] = new boolean[columns.size()]; - final String HOUR = " 00:00:00.0"; - for (int i = 0; i < columns.size(); ++i) { - stripHour[i] = true; - for (Row row : rows) { - Object value = row.values[i]; - if (value == null) { - continue; - } - if (!(value instanceof java.sql.Date) && !(value instanceof java.sql.Timestamp)) { - stripHour[i] = false; - break; - } - String asString = value.toString(); - if (asString.endsWith(HOUR)) { - continue; - } - stripHour[i] = false; - break; - } - } - - for (Row row : rows) { - Object[] rowData = new Object[columns.size()]; - for (int i = 0; i < columns.size(); ++i) { - rowData[i] = row.values[i]; - if (rowData[i] instanceof PObjectWrapper) { - rowData[i] = ((PObjectWrapper) rowData[i]).getValue(); - } - if (rowData[i] == null) { - rowData[i] = UIUtil.NULL; - } else if (rowData[i] instanceof UnknownValue) { - rowData[i] = UNKNOWN; - } - if (stripHour[i] && (rowData[i] instanceof java.sql.Date || rowData[i] instanceof java.sql.Timestamp)) { - String asString = rowData[i].toString(); - rowData[i] = asString.substring(0, asString.length() - HOUR.length()); - } - } - if (tableContentViewFilter != null) { - tableContentViewFilter.filter(rowData, columnNameMap); - } - for (int i = 0; i < columns.size(); ++i) { - TableModelItem item = new TableModelItem(row.getParentModelIndex(), row.getInheritedParentModelIndex(), rowData[i]); - rowData[i] = item; - } - dtm.addRow(rowData); - if (++rn >= limit) { - break; - } - } - - //set the editor as default on every column - JTextField textField = new JTextField(); - textField.setBorder(new LineBorder(Color.black)); - DefaultCellEditor anEditor = new DefaultCellEditor(textField) { - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - if (table != rowsTable) { - column = table.convertColumnIndexToModel(column); - if (column == 0) { - return null; - } - int h = row; - row = column - 1; - column = h; - } - if (row < rows.size()) { - Row r = rows.get(rowsTable.getRowSorter().convertRowIndexToModel(row)); - int convertedColumnIndex = rowsTable.convertColumnIndexToModel(column); - if (r != null) { - value = browserContentCellEditor.cellContentToText(row, convertedColumnIndex, r.values[convertedColumnIndex]); - } - } - return super.getTableCellEditorComponent(table, value, isSelected, row, column); - } - }; - anEditor.setClickCountToStart(1); - for (int i = 0; i < rowsTable.getColumnCount(); i++) { - rowsTable.setDefaultEditor(rowsTable.getColumnClass(i), anEditor); - } - - List sortKeys = new ArrayList(rowsTable.getRowSorter().getSortKeys()); - List filterContent = new ArrayList(); - if (filterHeader != null) { - try { - for (int i = 0; i < rowsTable.getColumnCount(); ++i) { - filterContent.add(filterHeader.getFilterEditor(i).getContent()); - } - } catch (Exception e) { - // ignore - } - } - - rowsTable.setModel(dtm); - rowsTable.getSelectionModel().clearSelection(); - rowsTable.setRowHeight(initialRowHeight); - - noRowsFoundPanel.setVisible(dtm.getRowCount() == 0 && getAndConditionText().length() > 0); - - final int defaultSortColumn = getDefaultSortColumn(); - - TableRowSorter sorter = new TableRowSorter(dtm) { - @Override - protected boolean useToString(int column) { - return false; - } - - @Override - public List getSortKeys() { - if (dontPaintSortIcon) { - return new ArrayList(); - } - return super.getSortKeys(); - } - - @Override - public void toggleSortOrder(int column) { - if (association != null && association.isInsertDestinationBeforeSource()) { - if (!useInheritedBlockNumbers) { - return; - } - } - ignoreSortKey = false; - boolean toggled = false; - List sortKeys = getSortKeys(); - if (sortKeys.size() > 0) { - if (sortKeys.get(0).getColumn() == column && sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING) { - List sk = new ArrayList(); - if (defaultSortColumn >= 0) { - sk.add(new SortKey(defaultSortColumn, SortOrder.ASCENDING)); - } - setSortKeys(sk); - toggled = true; - } - } - if (!toggled) { - super.toggleSortOrder(column); - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - sortChildren(); - } - }); - } - - @Override - public Comparator getComparator(int n) { - List sortKeys = super.getSortKeys(); - final boolean desc = sortKeys.size() > 0 && sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING; - - return new Comparator() { - @SuppressWarnings("unchecked") - @Override - public int compare(Object o1, Object o2) { - RowSorter pSorter = null; - RowSorter ppSorter = null; - RowBrowser pb = getParentBrowser(); - if (pb != null) { - if (pb.browserContentPane != null) { - if (pb.browserContentPane.rowsTable != null) { - pSorter = pb.browserContentPane.rowsTable.getRowSorter(); - if (pb.browserContentPane.getParentBrowser() != null) { - if (pb.browserContentPane.getParentBrowser().browserContentPane != null) { - if (pb.browserContentPane.getParentBrowser().browserContentPane.rowsTable != null) { - ppSorter = pb.browserContentPane.getParentBrowser().browserContentPane.rowsTable.getRowSorter(); - } - } - } - } - } - } - if (o1 instanceof TableModelItem && o2 instanceof TableModelItem) { - if (useInheritedBlockNumbers && !ignoreSortKey) { - double b1 = ((TableModelItem) o1).inheritedBlockNumber; - double b2 = ((TableModelItem) o2).inheritedBlockNumber; - - if (ppSorter != null) { - double b; - b = b1 < ppSorter.getModelRowCount()? ppSorter.convertRowIndexToView((int) b1) : -1; - if (b < 0) { - b = b1 + Integer.MAX_VALUE / 2; - } - b1 = b; - b = b2 < ppSorter.getModelRowCount()? ppSorter.convertRowIndexToView((int) b2) : -1; - if (b < 0) { - b = b2 + Integer.MAX_VALUE / 2; - } - b2 = b; - } - if (b1 != b2) { - return (int) ((b1 - b2) * (desc? -1 : 1)); - } - } else { - int b1 = ((TableModelItem) o1).blockNr; - int b2 = ((TableModelItem) o2).blockNr; - - if (pSorter != null) { - int b; - b = b1 < pSorter.getModelRowCount()? pSorter.convertRowIndexToView(b1) : -1; - if (b < 0) { - b = b1 + Integer.MAX_VALUE / 2; - } - b1 = b; - b = b2 < pSorter.getModelRowCount()? pSorter.convertRowIndexToView(b2) : -1; - if (b < 0) { - b = b2 + Integer.MAX_VALUE / 2; - } - b2 = b; - } - if (b1 != b2) { - return (b1 - b2) * (desc? -1 : 1); - } - } - } - - if (ignoreSortKey) { - return 0; - } - - if (o1 instanceof TableModelItem) { - o1 = ((TableModelItem) o1).value; - } - if (o2 instanceof TableModelItem) { - o2 = ((TableModelItem) o2).value; - } - if (o1 == null && o2 == null) { - return 0; - } - if (o1 == null) { - return -1; - } - if (o2 == null) { - return 1; - } - if (o1.getClass().equals(o2.getClass())) { - if (o1 instanceof Comparable) { - return ((Comparable) o1).compareTo(o2); - } - return 0; - } - return o1.getClass().getName().compareTo(o2.getClass().getName()); - } - }; - } - }; - sorter.addRowSorterListener(new RowSorterListener() { - @Override - public void sorterChanged(RowSorterEvent e) { - if (e.getType() == RowSorterEvent.Type.SORTED) { - List chBrs = getChildBrowsers(); - if (chBrs != null) { - for (RowBrowser chBr: chBrs) { - if (chBr.browserContentPane != null) { - if (chBr.browserContentPane.rowsTable != null) { - final RowSorter chSorter = chBr.browserContentPane.rowsTable.getRowSorter(); - if (chSorter instanceof TableRowSorter) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - ((TableRowSorter) chSorter).sort(); - } - }); - } - } - } - } - } - } - } - }); - rowsTable.setRowSorter(sorter); - try { - if (!sortKeys.isEmpty()) { - rowsTable.getRowSorter().setSortKeys(sortKeys); - } else { - List sk = new ArrayList(); - if (defaultSortColumn >= 0) { - sk.add(new SortKey(defaultSortColumn, SortOrder.ASCENDING)); - } - rowsTable.getRowSorter().setSortKeys(sk); - } - if (filterHeader != null) { - for (int i = 0; i < rowsTable.getColumnCount(); ++i) { - filterHeader.getFilterEditor(i).setContent(filterContent.get(i)); - } - } - } catch (Exception e) { - // ignore - } - } else { - final boolean deselect = !getAndConditionText().equals("") - && rows.size() == 1; - singleRowDetailsView = new DetailsView(Collections.singletonList(rows.get(0)), 1, dataModel, BrowserContentPane.this.table, 0, null, false, false, rowIdSupport, deselect, session) { - @Override - protected void onRowChanged(int row) { - } - @Override - protected void onClose() { - } - @Override - protected void onSelectRow(Row row) { - } - }; - singleRowDetailsView.setSortColumns(sortColumnsCheckBox.isSelected()); - dtm = new DefaultTableModel(new String[] { singleRowDetailsViewTitel }, 0) { - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - findColumnsLabel.setEnabled(false); - - for (Row row : rows) { - dtm.addRow(new Object[] { row }); - if (++rn >= limit) { - break; - } - } - rowsTable.setModel(dtm); - - JPanel detailsPanel = new JPanel(new java.awt.BorderLayout(0, 0)) { - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - if (!(graphics instanceof Graphics2D)) { - return; - } - if (rows.size() == 1 && BrowserContentPane.this.rowsClosure.tempClosure.size() > 1 && BrowserContentPane.this.rowsClosure.tempClosure.contains(rows.get(0))) { - Rectangle visRect = singleRowViewContainterPanel.getVisibleRect(); - - Graphics2D g2d = (Graphics2D) graphics; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(1)); - - int width = (int) (visRect.width * 1.4); - - g2d.setColor(new Color(255, 0, 0, 20)); - int[] x = new int[2]; - int[] y = new int[2]; - x[0] = (int) visRect.getMinX(); - y[0] = (int) visRect.getMinY(); - x[1] = (int) visRect.getMinX() + width; - y[1] = (int) visRect.getMaxY(); - GradientPaint paint = new GradientPaint( - x[0], y[0], new Color(255, 0, 0, 20), - x[0] + width, y[1], new Color(255, 0, 0, 0)); - g2d.setPaint(paint); - g2d.fillRect(x[0], y[0], x[1] - x[0], y[1] - y[0]); - g2d.setPaint(null); - } - } - }; - detailsPanel.add(singleRowDetailsView.getDetailsPanel(), java.awt.BorderLayout.CENTER); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - singleRowViewContainterPanel.removeAll(); - singleRowViewContainterPanel.add(detailsPanel, gridBagConstraints); - - singleRowViewScrollPaneContainer.setVisible(true); - rowsTableContainerPanel.setVisible(false); - deselectButton.setVisible(deselect); - } - - adjustRowTableColumnsWidth(); - - if (sortColumnsCheckBox.isSelected()) { - TableColumnModel cm = rowsTable.getColumnModel(); - for (int a = 0; a < rowsTable.getColumnCount(); ++a) { - for (int b = a + 1; b < rowsTable.getColumnCount(); ++b) { - if (cm.getColumn(a).getHeaderValue().toString().compareToIgnoreCase(cm.getColumn(b).getHeaderValue().toString()) > 0) { - cm.moveColumn(b, a); - } - } - } - } - - rowsTable.setIntercellSpacing(new Dimension(0, 0)); - Set browserInClosure = new HashSet(); - for (Pair rid: rowsClosure.currentClosure) { - browserInClosure.add(rid.a); - } - updateRowsCountLabel(browserInClosure); - - final TableCellRenderer origRenderer = rowsTable.getTableHeader().getDefaultRenderer(); - rowsTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() { - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, - boolean hasFocus, int row, int column) { - try { - dontPaintSortIcon = ignoreSortKey; - return origRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - } finally { - dontPaintSortIcon = false; - } - } - }); - - int nndr = noNonDistinctRows; - if (noDistinctRows + noNonDistinctRows >= limit) { - --nndr; - } - selectDistinctCheckBox.setVisible(nndr > 0); - selectDistinctCheckBox.setText("select distinct (-" + nndr + ")"); - if (getParentBrowser() != null) { - BrowserContentPane pBrowser = getParentBrowser().browserContentPane; - if (pBrowser.selectDistinctCheckBox.isVisible() && !pBrowser.selectDistinctCheckBox.isSelected()) { - if (selectDistinctCheckBox.isSelected()) { - selectDistinctCheckBox.setVisible(false); - } - } - } - - if (filterHeader != null) { - if (rowsTable.getRowSorter() != null && rowsTable.getRowSorter().getViewRowCount() == 0) { - filterHeader.setTable(null); - filterHeader = null; - adjustRowTableColumnsWidth(); - } - } - - if (isTableFilterEnabled && !noFilter) { - if (filterHeader == null) { - filterHeader = new TableFilterHeader(); - filterHeader.setRowHeightDelta(2); - filterHeader.setAutoChoices(AutoChoices.ENABLED); - filterHeader.setTable(rowsTable); - filterHeader.setMaxVisibleRows(20); - try { - for (int i = 0; i < rowsTable.getColumnCount(); ++i) { - filterHeader.getFilterEditor(i).setChoicesComparator(new Comparator() { - @SuppressWarnings("unchecked") - @Override - public int compare(Object o1, Object o2) { - if (o1 instanceof TableModelItem) { - o1 = ((TableModelItem) o1).value; - } - if (o2 instanceof TableModelItem) { - o2 = ((TableModelItem) o2).value; - } - if (o1 == null && o2 == null) { - return 0; - } - if (o1 == null) { - return -1; - } - if (o2 == null) { - return 1; - } - if (o1.getClass().equals(o2.getClass())) { - if (o1 instanceof Comparable) { - return ((Comparable) o1).compareTo(o2); - } - return 0; - } - return o1.getClass().getName().compareTo(o2.getClass().getName()); - } - }); - } - } - catch (Exception e) { - // ignore - } - } - } else { - if (filterHeader != null) { - filterHeader.setTable(null); - filterHeader = null; - } - } - - isLimitExceeded = limitExceeded; - isClosureLimitExceeded = closureLimitExceeded; - appendClosure(); - } - - public void updateRowsCountLabel(Set browserInClosure) { - int limit = lastLimit; - boolean limitExceeded = lastLimitExceeded; - boolean closureLimitExceeded = lastClosureLimitExceeded; - - int size = rows.size(); - if (size > limit) { - size = limit; - } - rowsCount.setText((limitExceeded ? " more than " : " ") + size + " row" + (size != 1 ? "s" : "")); - RowBrowser theParentWithExceededLimit = parentWithExceededLimit(); - boolean cle = closureLimitExceeded; - boolean cleRelevant = true; -// if (theParentWithExceededLimit != null && theParentWithExceededLimit.browserContentPane.isClosureLimitExceeded) { -// cle = true; -// } - if (rowsClosure.parentPath.contains(this) || rowsClosure.currentClosureRowIDs.isEmpty()) { - cleRelevant = false; - } else if (getParentBrowser() != null) { - BrowserContentPane parent = getParentBrowser().browserContentPane; - if (!browserInClosure.contains(parent)) { - cleRelevant = false; - } - } - boolean bold = false; - if (limitExceeded || theParentWithExceededLimit != null) { - if (cle || !cleRelevant) { - rowsCount.setForeground(Color.RED); - bold = true; - } else { - rowsCount.setForeground(new Color(140, 0, 0)); - } - } else { - rowsCount.setForeground(new JLabel().getForeground()); - } - if (bold) { - rowsCount.setFont(rowsCount.getFont().deriveFont(rowsCount.getFont().getStyle() | Font.BOLD)); - } else { - rowsCount.setFont(rowsCount.getFont().deriveFont(rowsCount.getFont().getStyle() & ~Font.BOLD)); - } - - if (cle && cleRelevant) { - rowsCount.setToolTipText("row selection incomplete"); - } else if (!limitExceeded && theParentWithExceededLimit != null) { - rowsCount.setToolTipText("potentially incomplete because " + theParentWithExceededLimit.internalFrame.getTitle() + " exceeded row limit"); - } else { - rowsCount.setToolTipText(null); - } - } - - private int getDefaultSortColumn() { - if (table == null || table instanceof SqlStatementTable || getQueryBuilderDialog() == null /* SQL Console */) { - return -1; - } - if (association != null && association.isInsertDestinationBeforeSource()) { - return -1; - } - if (table.primaryKey.getColumns() != null && table.primaryKey.getColumns().size() > 0) { - Column pk = table.primaryKey.getColumns().get(0); - for (int i = 0; i < table.getColumns().size(); ++i) { - if (table.getColumns().get(i).equals(pk)) { - return i; - } - } - } - return 0; - } - - private TableFilterHeader filterHeader; - - protected Row createRowWithNewID(Row theRow, Table type) { - CellContentConverter cellContentConverter = new CellContentConverter(null, session, session.dbms); - String rowId = ""; - PrimaryKey primaryKeys = type.primaryKey; - for (Column pkColumn : primaryKeys.getColumns()) { - List cols = type.getColumns(); - int colSize = cols.size(); - for (int i = 0; i < colSize; ++i) { - Column column = cols.get(i); - if (column != null && pkColumn.name.equals(column.name)) { - if (rowId.length() > 0) { - rowId += " and "; - } - rowId += pkColumn.name + "=" + cellContentConverter.toSql(theRow.values[i]); - break; - } - } - } - return new Row(rowId, theRow.primaryKey, theRow.values); - } - - public void adjustRowTableColumnsWidth() { - DefaultTableModel dtm = (DefaultTableModel) rowsTable.getModel(); - int MAXLINES = 400; - if (rowsTable.getColumnCount() > 0) { - MAXLINES = Math.max(10 * MAXLINES / rowsTable.getColumnCount(), 10); - } - DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer(); - int minTotalWidth = (int) (Desktop.BROWSERTABLE_DEFAULT_WIDTH * getLayoutFactor()) - 18; - int totalWidth = 0; - final int maxColumnWidth = 300; - - for (int i = 0; i < rowsTable.getColumnCount(); i++) { - TableColumn column = rowsTable.getColumnModel().getColumn(i); - int width = minTotalWidth / rowsTable.getColumnCount(); - - Component comp = defaultTableCellRenderer.getTableCellRendererComponent(rowsTable, column.getHeaderValue(), false, false, 0, i); - int pw = comp.getPreferredSize().width; - if (pw < 100) { - pw = (pw * 110) / 100 + 2; - } - width = Math.min(Math.max(width, pw), 150); - - int line = 0; - for (; line < rowsTable.getRowCount(); ++line) { - comp = rowsTable.getCellRenderer(line, i).getTableCellRendererComponent(rowsTable, dtm.getValueAt(line, i), false, false, line, i); - width = Math.max(width, comp.getPreferredSize().width + 24); - if (line > MAXLINES) { - break; - } - } - Object maxValue = null; - int maxValueLength = 0; - for (; line < rowsTable.getRowCount(); ++line) { - Object value = dtm.getValueAt(line, i); - if (value != null) { - int valueLength = value.toString().length(); - if (maxValue == null || maxValueLength < valueLength) { - maxValue = value; - maxValueLength = valueLength; - } - } - if (line > 4 * MAXLINES) { - break; - } - } - if (maxValue != null) { - comp = rowsTable.getCellRenderer(line, i).getTableCellRendererComponent(rowsTable, maxValue, false, false, line, i); - int maxValueWidth = comp.getPreferredSize().width + 16; - if (maxValueWidth > width) { - width = maxValueWidth; - } - } - - column.setPreferredWidth(width); - totalWidth += width; - if (i == rowsTable.getColumnCount() - 1) { - if (totalWidth < minTotalWidth) { - width = width + minTotalWidth - totalWidth; - } - } - column.setPreferredWidth(Math.min(maxColumnWidth, width)); - } - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - andCondition = new javax.swing.JComboBox(); - openEditorLabel = new javax.swing.JLabel(); - pendingNonpendingPanel = new javax.swing.JPanel(); - cardPanel = new javax.swing.JPanel(); - tablePanel = new javax.swing.JPanel(); - jLayeredPane1 = new javax.swing.JLayeredPane(); - statusPanel = new javax.swing.JPanel(); - sortColumnsCheckBox = new javax.swing.JCheckBox(); - rowsCount = new javax.swing.JLabel(); - selectDistinctCheckBox = new javax.swing.JCheckBox(); - sortColumnsPanel = new javax.swing.JPanel(); - sortColumnsLabel = new javax.swing.JLabel(); - findColumnsPanel = new javax.swing.JPanel(); - findColumnsLabel = new javax.swing.JLabel(); - loadingPanel = new javax.swing.JPanel(); - jPanel1 = new javax.swing.JPanel(); - cancelLoadButton = new javax.swing.JButton(); - jLabel2 = new javax.swing.JLabel(); - jPanel13 = new javax.swing.JPanel(); - loadingCauseLabel = new javax.swing.JLabel(); - loadingLabel = new javax.swing.JLabel(); - jPanel2 = new javax.swing.JPanel(); - rowsTableContainerPanel = new javax.swing.JPanel(); - jLayeredPane2 = new javax.swing.JLayeredPane(); - rowsTableScrollPane = new javax.swing.JScrollPane(); - rowsTable = new javax.swing.JTable(); - noRowsFoundPanel = new javax.swing.JPanel(); - jLabel9 = new javax.swing.JLabel(); - removeConditionButton = new javax.swing.JButton(); - singleRowViewScrollPaneContainer = new javax.swing.JPanel(); - singleRowViewScrollPane = new javax.swing.JScrollPane(); - singleRowViewScrollContentPanel = new javax.swing.JPanel(); - singleRowViewContainterPanel = new javax.swing.JPanel(); - jPanel12 = new javax.swing.JPanel(); - jPanel11 = new javax.swing.JPanel(); - jLabel7 = new javax.swing.JLabel(); - deselectButton = new javax.swing.JButton(); - jPanel5 = new javax.swing.JPanel(); - errorLabel = new javax.swing.JLabel(); - errorDetailsButton = new javax.swing.JButton(); - jScrollPane2 = new javax.swing.JScrollPane(); - errorMessageTextArea = new javax.swing.JTextArea(); - jPanel4 = new javax.swing.JPanel(); - jLabel8 = new javax.swing.JLabel(); - jPanel8 = new javax.swing.JPanel(); - jLabel11 = new javax.swing.JLabel(); - menuPanel = new javax.swing.JPanel(); - jPanel7 = new javax.swing.JPanel(); - loadButton = new javax.swing.JButton(); - openEditorButton = new javax.swing.JToggleButton(); - onPanel = new javax.swing.JPanel(); - on = new javax.swing.JLabel(); - joinPanel = new javax.swing.JPanel(); - join = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); - jPanel10 = new javax.swing.JPanel(); - from = new javax.swing.JLabel(); - jLabel5 = new javax.swing.JLabel(); - jLabel1 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); - jLabel3 = new javax.swing.JLabel(); - rrPanel = new javax.swing.JPanel(); - relatedRowsPanel = new javax.swing.JPanel(); - relatedRowsLabel = new javax.swing.JLabel(); - sqlPanel = new javax.swing.JPanel(); - sqlLabel1 = new javax.swing.JLabel(); - jPanel9 = new javax.swing.JPanel(); - jPanel14 = new javax.swing.JPanel(); - wherejLabel = new javax.swing.JLabel(); - - andCondition.setEditable(true); - andCondition.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - - openEditorLabel.setText(" And "); - - setLayout(new java.awt.GridBagLayout()); - - pendingNonpendingPanel.setLayout(new java.awt.CardLayout()); - - cardPanel.setLayout(new java.awt.CardLayout()); - - tablePanel.setLayout(new java.awt.GridBagLayout()); - - jLayeredPane1.setLayout(new java.awt.GridBagLayout()); - - statusPanel.setLayout(new java.awt.GridBagLayout()); - - sortColumnsCheckBox.setText("sort columns "); - sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - sortColumnsCheckBoxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 1; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); - statusPanel.add(sortColumnsCheckBox, gridBagConstraints); - - rowsCount.setText("jLabel3"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - statusPanel.add(rowsCount, gridBagConstraints); - - selectDistinctCheckBox.setSelected(true); - selectDistinctCheckBox.setText("select distinct (-100 rows)"); - selectDistinctCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - selectDistinctCheckBoxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); - statusPanel.add(selectDistinctCheckBox, gridBagConstraints); - - sortColumnsPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - sortColumnsPanel.setLayout(new javax.swing.BoxLayout(sortColumnsPanel, javax.swing.BoxLayout.LINE_AXIS)); - - sortColumnsLabel.setText("Natural column order "); - sortColumnsPanel.add(sortColumnsLabel); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - statusPanel.add(sortColumnsPanel, gridBagConstraints); - - findColumnsPanel.setLayout(new java.awt.GridBagLayout()); - - findColumnsLabel.setText("Find Columns"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 6); - findColumnsPanel.add(findColumnsLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - statusPanel.add(findColumnsPanel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - jLayeredPane1.add(statusPanel, gridBagConstraints); - - loadingPanel.setOpaque(false); - loadingPanel.setLayout(new java.awt.GridBagLayout()); - - jPanel1.setBackground(new Color(255,255,255,150)); - jPanel1.setLayout(new java.awt.GridBagLayout()); - - cancelLoadButton.setText("Cancel"); - cancelLoadButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelLoadButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel1.add(cancelLoadButton, gridBagConstraints); - - jLabel2.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.weightx = 1.0; - jPanel1.add(jLabel2, gridBagConstraints); - - jPanel13.setOpaque(false); - jPanel13.setLayout(new java.awt.GridBagLayout()); - - loadingCauseLabel.setFont(loadingCauseLabel.getFont().deriveFont(loadingCauseLabel.getFont().getSize()+3f)); - loadingCauseLabel.setForeground(new java.awt.Color(141, 16, 16)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel13.add(loadingCauseLabel, gridBagConstraints); - - loadingLabel.setFont(loadingLabel.getFont().deriveFont(loadingLabel.getFont().getStyle() | java.awt.Font.BOLD, loadingLabel.getFont().getSize()+3)); - loadingLabel.setForeground(new java.awt.Color(141, 16, 16)); - loadingLabel.setText("loading... "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel13.add(loadingLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8); - jPanel1.add(jPanel13, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(4, 4, 2, 4); - loadingPanel.add(jPanel1, gridBagConstraints); - - jLayeredPane1.setLayer(loadingPanel, javax.swing.JLayeredPane.MODAL_LAYER); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridheight = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - jLayeredPane1.add(loadingPanel, gridBagConstraints); - - jPanel2.setLayout(new java.awt.GridBagLayout()); - - rowsTableContainerPanel.setLayout(new java.awt.GridBagLayout()); - - jLayeredPane2.setLayout(new java.awt.GridBagLayout()); - - rowsTableScrollPane.setWheelScrollingEnabled(false); - - rowsTable.setAutoCreateRowSorter(true); - rowsTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null} - }, - new String [] { - "Title 1", "Title 2", "Title 3", "Title 4" - } - )); - rowsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); - rowsTableScrollPane.setViewportView(rowsTable); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jLayeredPane2.add(rowsTableScrollPane, gridBagConstraints); - - noRowsFoundPanel.setOpaque(false); - noRowsFoundPanel.setLayout(new java.awt.GridBagLayout()); - - jLabel9.setText("No rows found."); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - gridBagConstraints.weighty = 1.0; - noRowsFoundPanel.add(jLabel9, gridBagConstraints); - - removeConditionButton.setText("Remove condition"); - removeConditionButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - removeConditionButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - gridBagConstraints.weighty = 1.0; - noRowsFoundPanel.add(removeConditionButton, gridBagConstraints); - - jLayeredPane2.setLayer(noRowsFoundPanel, javax.swing.JLayeredPane.PALETTE_LAYER); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jLayeredPane2.add(noRowsFoundPanel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - rowsTableContainerPanel.add(jLayeredPane2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel2.add(rowsTableContainerPanel, gridBagConstraints); - - singleRowViewScrollPaneContainer.setLayout(new java.awt.GridBagLayout()); - - singleRowViewScrollPane.setWheelScrollingEnabled(false); - - singleRowViewScrollContentPanel.setLayout(new java.awt.GridBagLayout()); - - singleRowViewContainterPanel.setBackground(java.awt.Color.white); - singleRowViewContainterPanel.setBorder(new javax.swing.border.LineBorder(java.awt.Color.gray, 1, true)); - singleRowViewContainterPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - gridBagConstraints.weightx = 1.0; - singleRowViewScrollContentPanel.add(singleRowViewContainterPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 4; - gridBagConstraints.weighty = 1.0; - singleRowViewScrollContentPanel.add(jPanel12, gridBagConstraints); - - singleRowViewScrollPane.setViewportView(singleRowViewScrollContentPanel); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - singleRowViewScrollPaneContainer.add(singleRowViewScrollPane, gridBagConstraints); - - jPanel11.setBackground(new java.awt.Color(228, 228, 232)); - jPanel11.setLayout(new java.awt.GridBagLayout()); - - jLabel7.setBackground(new java.awt.Color(200, 200, 200)); - jLabel7.setForeground(new java.awt.Color(1, 0, 0)); - jLabel7.setText(" Single Row Details "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(2, 2, 0, 2); - jPanel11.add(jLabel7, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - singleRowViewScrollPaneContainer.add(jPanel11, gridBagConstraints); - - deselectButton.setText("Deselect Row"); - deselectButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - deselectButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; - singleRowViewScrollPaneContainer.add(deselectButton, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel2.add(singleRowViewScrollPaneContainer, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jLayeredPane1.add(jPanel2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - tablePanel.add(jLayeredPane1, gridBagConstraints); - - cardPanel.add(tablePanel, "table"); - - jPanel5.setLayout(new java.awt.GridBagLayout()); - - errorLabel.setForeground(new java.awt.Color(141, 16, 16)); - errorLabel.setText("Error"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8); - jPanel5.add(errorLabel, gridBagConstraints); - - errorDetailsButton.setText("Details..."); - errorDetailsButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - errorDetailsButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - jPanel5.add(errorDetailsButton, gridBagConstraints); - - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - - errorMessageTextArea.setEditable(false); - errorMessageTextArea.setColumns(20); - errorMessageTextArea.setLineWrap(true); - errorMessageTextArea.setWrapStyleWord(true); - jScrollPane2.setViewportView(errorMessageTextArea); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - jPanel5.add(jScrollPane2, gridBagConstraints); - - cardPanel.add(jPanel5, "error"); - - jPanel4.setLayout(new java.awt.GridBagLayout()); - - jLabel8.setFont(jLabel8.getFont().deriveFont(jLabel8.getFont().getStyle() | java.awt.Font.BOLD, jLabel8.getFont().getSize()+3)); - jLabel8.setForeground(new java.awt.Color(141, 16, 16)); - jLabel8.setText("Cancelled"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); - jPanel4.add(jLabel8, gridBagConstraints); - - cardPanel.add(jPanel4, "cancelled"); - - pendingNonpendingPanel.add(cardPanel, "nonpending"); - - jPanel8.setLayout(new java.awt.GridBagLayout()); - - jLabel11.setFont(jLabel11.getFont().deriveFont(jLabel11.getFont().getStyle() | java.awt.Font.BOLD, jLabel11.getFont().getSize()+3)); - jLabel11.setForeground(new java.awt.Color(141, 16, 16)); - jLabel11.setText("pending..."); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); - jPanel8.add(jLabel11, gridBagConstraints); - - pendingNonpendingPanel.add(jPanel8, "pending"); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - add(pendingNonpendingPanel, gridBagConstraints); - - menuPanel.setLayout(new java.awt.GridBagLayout()); - - jPanel7.setLayout(new java.awt.GridBagLayout()); - - loadButton.setText("Reload"); - loadButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - loadButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - jPanel7.add(loadButton, gridBagConstraints); - - openEditorButton.setText("Where"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - jPanel7.add(openEditorButton, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 8; - gridBagConstraints.gridwidth = 6; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - menuPanel.add(jPanel7, gridBagConstraints); - - onPanel.setMinimumSize(new java.awt.Dimension(66, 17)); - onPanel.setLayout(new java.awt.BorderLayout()); - - on.setFont(on.getFont().deriveFont(on.getFont().getStyle() | java.awt.Font.BOLD)); - on.setText("jLabel3"); - onPanel.add(on, java.awt.BorderLayout.CENTER); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 6; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - menuPanel.add(onPanel, gridBagConstraints); - - joinPanel.setMinimumSize(new java.awt.Dimension(66, 17)); - joinPanel.setLayout(new java.awt.GridBagLayout()); - - join.setFont(join.getFont().deriveFont(join.getFont().getStyle() | java.awt.Font.BOLD)); - join.setText("jLabel3"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - joinPanel.add(join, gridBagConstraints); - - jLabel6.setText(" as B "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - joinPanel.add(jLabel6, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 5; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - menuPanel.add(joinPanel, gridBagConstraints); - - jPanel10.setMinimumSize(new java.awt.Dimension(66, 17)); - jPanel10.setLayout(new java.awt.GridBagLayout()); - - from.setFont(from.getFont().deriveFont(from.getFont().getStyle() | java.awt.Font.BOLD)); - from.setText("jLabel3"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - jPanel10.add(from, gridBagConstraints); - - jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - jLabel5.setText(" as A"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - jPanel10.add(jLabel5, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - menuPanel.add(jPanel10, gridBagConstraints); - - jLabel1.setText(" Join "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 5; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weighty = 1.0; - menuPanel.add(jLabel1, gridBagConstraints); - - jLabel4.setText(" On "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 6; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weighty = 1.0; - menuPanel.add(jLabel4, gridBagConstraints); - - jLabel3.setText(" From "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 4; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weighty = 1.0; - menuPanel.add(jLabel3, gridBagConstraints); - - rrPanel.setLayout(new java.awt.GridBagLayout()); - - relatedRowsPanel.setBackground(new java.awt.Color(224, 240, 255)); - relatedRowsPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - relatedRowsPanel.setLayout(new java.awt.GridBagLayout()); - - relatedRowsLabel.setBackground(new java.awt.Color(224, 240, 255)); - relatedRowsLabel.setText(" Related Rows "); - relatedRowsLabel.setOpaque(true); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3); - relatedRowsPanel.add(relatedRowsLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 7; - gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0); - rrPanel.add(relatedRowsPanel, gridBagConstraints); - - sqlPanel.setBackground(new java.awt.Color(255, 243, 218)); - sqlPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - sqlPanel.setLayout(new java.awt.GridBagLayout()); - - sqlLabel1.setForeground(new java.awt.Color(1, 0, 0)); - sqlLabel1.setText(" Menu "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3); - sqlPanel.add(sqlLabel1, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 8; - gridBagConstraints.gridy = 5; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); - rrPanel.add(sqlPanel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 7; - gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.gridheight = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - menuPanel.add(rrPanel, gridBagConstraints); - - jPanel9.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 5; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - menuPanel.add(jPanel9, gridBagConstraints); - - jPanel14.setLayout(new java.awt.GridBagLayout()); - - wherejLabel.setText(" Where "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - jPanel14.add(wherejLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 8; - menuPanel.add(jPanel14, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - add(menuPanel, gridBagConstraints); - }// //GEN-END:initComponents - - private void cancelLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelLoadButtonActionPerformed - cancelLoadJob(false); - updateMode("cancelled", null); - }//GEN-LAST:event_cancelLoadButtonActionPerformed - - private void selectDistinctCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectDistinctCheckBoxActionPerformed - reloadRows(); - }//GEN-LAST:event_selectDistinctCheckBoxActionPerformed - - private void sortColumnsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortColumnsCheckBoxActionPerformed - updateTableModel(); - }//GEN-LAST:event_sortColumnsCheckBoxActionPerformed - - private void deselectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectButtonActionPerformed - andCondition.setSelectedItem(""); - }//GEN-LAST:event_deselectButtonActionPerformed - - private void removeConditionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeConditionButtonActionPerformed - andCondition.setSelectedItem(""); - }//GEN-LAST:event_removeConditionButtonActionPerformed - - private void errorDetailsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_errorDetailsButtonActionPerformed - UIUtil.showException(this, "Error", currentErrorDetail); - }//GEN-LAST:event_errorDetailsButtonActionPerformed - - private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_loadButtonActionPerformed - if (System.currentTimeMillis() - lastReloadTS > 200) { - reloadRows(); - } - }// GEN-LAST:event_loadButtonActionPerformed - - private void limitBoxItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_limitBoxItemStateChanged - if (evt.getStateChange() == ItemEvent.SELECTED) { - reloadRows(); - } - }// GEN-LAST:event_limitBoxItemStateChanged - - void openQueryBuilder(boolean openSQLConsole) { - openQueryBuilder(openSQLConsole, null); - } - - void openQueryBuilder(boolean openSQLConsole, String alternativeWhere) { - QueryBuilderDialog.Relationship root = createQBRelations(true); - if (root != null) { - if (alternativeWhere != null) { - root.whereClause = alternativeWhere; - } - root.selectColumns = true; - getQueryBuilderDialog().buildQuery(table, root, dataModel, session, getMetaDataSource(), openSQLConsole); - } - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - javax.swing.JComboBox andCondition; - private javax.swing.JButton cancelLoadButton; - private javax.swing.JPanel cardPanel; - private javax.swing.JButton deselectButton; - private javax.swing.JButton errorDetailsButton; - private javax.swing.JLabel errorLabel; - private javax.swing.JTextArea errorMessageTextArea; - private javax.swing.JLabel findColumnsLabel; - public javax.swing.JPanel findColumnsPanel; - private javax.swing.JLabel from; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel11; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; - private javax.swing.JLabel jLabel7; - private javax.swing.JLabel jLabel8; - private javax.swing.JLabel jLabel9; - private javax.swing.JLayeredPane jLayeredPane1; - private javax.swing.JLayeredPane jLayeredPane2; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel10; - private javax.swing.JPanel jPanel11; - private javax.swing.JPanel jPanel12; - private javax.swing.JPanel jPanel13; - private javax.swing.JPanel jPanel14; - private javax.swing.JPanel jPanel2; - private javax.swing.JPanel jPanel4; - private javax.swing.JPanel jPanel5; - private javax.swing.JPanel jPanel7; - private javax.swing.JPanel jPanel8; - private javax.swing.JPanel jPanel9; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JLabel join; - private javax.swing.JPanel joinPanel; - public javax.swing.JButton loadButton; - private javax.swing.JLabel loadingCauseLabel; - private javax.swing.JLabel loadingLabel; - private javax.swing.JPanel loadingPanel; - javax.swing.JPanel menuPanel; - private javax.swing.JPanel noRowsFoundPanel; - private javax.swing.JLabel on; - private javax.swing.JPanel onPanel; - private javax.swing.JToggleButton openEditorButton; - private javax.swing.JLabel openEditorLabel; - private javax.swing.JPanel pendingNonpendingPanel; - private javax.swing.JLabel relatedRowsLabel; - javax.swing.JPanel relatedRowsPanel; - private javax.swing.JButton removeConditionButton; - public javax.swing.JLabel rowsCount; - public javax.swing.JTable rowsTable; - private javax.swing.JPanel rowsTableContainerPanel; - protected javax.swing.JScrollPane rowsTableScrollPane; - private javax.swing.JPanel rrPanel; - javax.swing.JCheckBox selectDistinctCheckBox; - protected javax.swing.JPanel singleRowViewContainterPanel; - private javax.swing.JPanel singleRowViewScrollContentPanel; - javax.swing.JScrollPane singleRowViewScrollPane; - private javax.swing.JPanel singleRowViewScrollPaneContainer; - public javax.swing.JCheckBox sortColumnsCheckBox; - private javax.swing.JLabel sortColumnsLabel; - public javax.swing.JPanel sortColumnsPanel; - private javax.swing.JLabel sqlLabel1; - javax.swing.JPanel sqlPanel; - protected javax.swing.JPanel statusPanel; - private javax.swing.JPanel tablePanel; - private javax.swing.JLabel wherejLabel; - // End of variables declaration//GEN-END:variables - - JPanel thumbnail; - private DBConditionEditor andConditionEditor; - private ImageIcon conditionEditorIcon; - { - // load images - conditionEditorIcon = UIUtil.readImage("/edit.png"); - } - - /** - * Cancels current load job. - * @param propagate - * @return - */ - public void cancelLoadJob(boolean propagate) { - LoadJob cLoadJob; - synchronized (this) { - cLoadJob = currentLoadJob; - } - if (cLoadJob != null) { - cLoadJob.cancel(); - } - if (propagate) { - for (RowBrowser child: getChildBrowsers()) { - child.browserContentPane.cancelLoadJob(propagate); - } - } - } - - private void updateMode(String mode, String cause) { - String suffix; - if (cause != null) { - suffix = cause; - } else { - suffix = ""; - } - loadingCauseLabel.setVisible(false); - if ("table".equals(mode)) { - loadingPanel.setVisible(false); - rowsTable.setEnabled(true); - } else if ("loading".equals(mode)) { - mode = "table"; - loadingPanel.setVisible(true); - loadingLabel.setText("loading..."); - loadingCauseLabel.setText(suffix); - loadingCauseLabel.setVisible(true); - cancelLoadButton.setVisible(true); - rowsTable.setEnabled(false); - } else if ("pending".equals(mode)) { - mode = "table"; - loadingPanel.setVisible(true); - loadingLabel.setText("pending..."); - cancelLoadButton.setVisible(false); - rowsTable.setEnabled(false); - } else if ("updating".equals(mode)) { - mode = "table"; - loadingPanel.setVisible(true); - loadingLabel.setText("updating..."); - cancelLoadButton.setVisible(true); - rowsTable.setEnabled(false); - } - errorDetailsButton.setVisible(false); - ((CardLayout) cardPanel.getLayout()).show(cardPanel, mode); - } - - /** - * Creates new row. Fills in foreign key. - * - * @param parents rows holding the primary key - * @param table the table of the new row - * @return new row of table - */ - private List createNewRow(List parents, Table table, Association association) { - List children = new ArrayList(); - try { - if (parents != null && association != null && !association.isInsertDestinationBeforeSource()) { - for (Row par: parents) { - Map sToDMap = association.createSourceToDestinationKeyMapping(); - if (!sToDMap.isEmpty()) { - Row row = new Row("", null, new Object[association.destination.getColumns().size()]); - for (Map.Entry e: sToDMap.entrySet()) { - int iS = -1; - for (int i = 0; i < table.getColumns().size(); ++i) { - if (Quoting.equalsIgnoreQuotingAndCase(e.getKey().name, table.getColumns().get(i).name)) { - iS = i; - break; - } - } - int iD = -1; - for (int i = 0; i < association.destination.getColumns().size(); ++i) { - if (Quoting.equalsIgnoreQuotingAndCase(e.getValue().name, association.destination.getColumns().get(i).name)) { - iD = i; - break; - } - } - if (iS >= 0 && iD >= 0) { - row.values[iD] = par.values[iS]; - } else { - break; - } - } - children.add(row); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return children; - } - - protected abstract RowBrowser navigateTo(Association association, List pRows); - - protected abstract void onContentChange(List rows, boolean reloadChildren); - - protected abstract void onRedraw(); - protected abstract void onHide(); - - protected abstract void beforeReload(); - protected void afterReload() {} - - protected abstract QueryBuilderDialog.Relationship createQBRelations(boolean withParents); - protected abstract List createQBChildrenRelations(RowBrowser tabu, boolean all); - - protected abstract void addRowToRowLink(Row pRow, Row exRow); - - protected abstract JFrame getOwner(); - - protected abstract void findClosure(Row row); - protected void findTempClosure(Row row) {}; - protected abstract void findClosure(Row row, Set> closure, boolean forward); - - protected abstract QueryBuilderDialog getQueryBuilderDialog(); - - protected abstract void openSchemaMappingDialog(); - protected abstract void openSchemaAnalyzer(); - protected abstract DbConnectionDialog getDbConnectionDialog(); - protected abstract double getLayoutFactor(); - protected abstract List getChildBrowsers(); - protected abstract RowBrowser getParentBrowser(); - protected abstract List getTableBrowser(); - protected abstract void unhide(); - protected abstract void close(); - protected abstract void showInNewWindow(); - protected abstract void appendLayout(); - protected abstract void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne); - protected abstract void reloadDataModel() throws Exception; - protected abstract MetaDataSource getMetaDataSource(); - protected abstract void deselectChildrenIfNeededWithoutReload(); - protected abstract int getReloadLimit(); - protected void changeColumnOrder(Table table) { - } - protected void rebase() { - } - protected RowBrowser copy(RowBrowser tableBrowser, Association association, Row parentRow, RowBrowser childToIgnore, boolean newParent) { - return null; - } - protected RowBrowser getRowBrowser() { - return null; - }; - protected boolean shouldShowLoadErrors() { - return true; - } - - public interface RunnableWithPriority extends Runnable { - int getPriority(); - }; - - protected abstract PriorityBlockingQueue getRunnableQueue(); - - /** - * Collect layout of tables in a extraction model. - * - * @param positions to put positions into - */ - protected abstract void collectPositions(Map> positions); - - - private void openDetails(final int x, final int y) { - final JDialog d = new JDialog(getOwner(), (table instanceof SqlStatementTable)? "" : dataModel.getDisplayName(table), true); - final boolean deselect = !currentSelectedRowCondition.equals("") - && currentSelectedRowCondition.equals(getAndConditionText()) - && rows.size() == 1; - d.getContentPane().add(new DetailsView(rows, rowsTable.getRowCount(), dataModel, table, 0, rowsTable.getRowSorter(), true, getQueryBuilderDialog() != null, rowIdSupport, deselect, session) { - @Override - protected void onRowChanged(int row) { - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(row, false); - } - @Override - protected void onClose() { - d.setVisible(false); - } - @Override - protected void onSelectRow(Row row) { - d.setVisible(false); - if (deselect) { - andCondition.setSelectedItem(""); - } else { - List rowList = new ArrayList(); - rowList.add(row); - selectRow(rowList); - } - } - }); - d.pack(); - d.setLocation(x, y); - d.setSize(400, d.getHeight() + 20); - UIUtil.fit(d); - Window p = SwingUtilities.getWindowAncestor(this); - if (p != null) { - int maxX = p.getX() + p.getWidth() - d.getWidth(); - d.setLocation(Math.max(0, Math.min(maxX, d.getX())), d.getY()); - int maxY = p.getY() + p.getHeight() - d.getHeight(); - if (maxY < d.getY()) { - int deltaH = Math.min(d.getY() - maxY, (int) (0.30 * d.getHeight())); - maxY += deltaH; - d.setSize(d.getWidth(), d.getHeight() - deltaH); - d.setLocation(d.getX(), Math.max(0, maxY)); - } - } - d.setVisible(true); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); - onRedraw(); - } - - private void updateWhereField() { - if (association != null) { - if (parentRows != null && parentRows.size() > 0) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < parentRows.size(); ++i) { - if (i > 0) { - sb.append(" or\n"); - } - sb.append(parentRows.get(i).rowId); - if (i > 50) { - sb.append("\n..."); - break; - } - } - String currentCond = getAndConditionText().trim(); - String toolTip; - if (currentCond.length() > 0) { - toolTip = currentCond + "\nand (\n" + sb + ")"; - } else { - toolTip = sb.toString(); - } - wherejLabel.setToolTipText(UIUtil.toHTML(toolTip, 0)); - } else { - wherejLabel.setToolTipText(null); - } - } else { - wherejLabel.setToolTipText(null); - } - } - - public void convertToRoot() { - association = null; - parentRows = null; - rowsClosure.currentClosureRowIDs.clear(); - adjustGui(); - reloadRows(); - } - - public void openDetailsView(int rowIndex, int x, int y) { - final JDialog d = new JDialog(getOwner(), (table instanceof SqlStatementTable)? "" : dataModel.getDisplayName(table), true); - final boolean deselect = !currentSelectedRowCondition.equals("") - && currentSelectedRowCondition.equals(getAndConditionText()) - && rows.size() == 1; - d.getContentPane().add(new DetailsView(rows, rowsTable.getRowCount(), dataModel, table, rowIndex, rowsTable.getRowSorter(), true, getQueryBuilderDialog() != null, rowIdSupport, deselect, session) { - @Override - protected void onRowChanged(int row) { - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(row, false); - } - @Override - protected void onClose() { - d.setVisible(false); - } - @Override - protected void onSelectRow(Row row) { - d.setVisible(false); - if (deselect) { - andCondition.setSelectedItem(""); - } else { - List rowList = new ArrayList(); - rowList.add(row); - selectRow(rowList); - } - } - }); - d.pack(); - d.setLocation(x, y); - d.setSize(400, d.getHeight() + 20); - int h = d.getHeight(); - UIUtil.fit(d); - if (d.getHeight() < h) { - y = Math.max(y - Math.min(h - d.getHeight(), Math.max(400 - d.getHeight(), 0)), 20); - d.pack(); - d.setLocation(x, y); - d.setSize(400, d.getHeight() + 20); - UIUtil.fit(d); - } - Window p = SwingUtilities.getWindowAncestor(this); - if (p != null) { - int maxX = p.getX() + p.getWidth() - d.getWidth(); - d.setLocation(Math.max(0, Math.min(maxX, d.getX())), d.getY()); - int maxY = p.getY() + p.getHeight() - d.getHeight(); - if (maxY < d.getY()) { - int deltaH = Math.min(d.getY() - maxY, (int) (0.30 * d.getHeight())); - maxY += deltaH; - d.setSize(d.getWidth(), d.getHeight() - deltaH); - d.setLocation(d.getX(), Math.max(0, maxY)); - } - } - d.setVisible(true); - setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); - onRedraw(); - } - - public void updateSingleRowDetailsView() { - if (singleRowDetailsView != null) { - if (rowsClosure != null && rowsClosure.currentClosureRowIDs != null) { - singleRowDetailsView.updateInClosureState(rows.size() == 1 && rowsClosure.currentClosureRowIDs.contains(new Pair(this, rows.get(0).nonEmptyRowId))); - } - } - } - - private static TableContentViewFilter tableContentViewFilter = TableContentViewFilter.create(); - - private Icon dropDownIcon; - private ImageIcon relatedRowsIcon; - private ImageIcon redDotIcon; - private ImageIcon blueDotIcon; - private ImageIcon greenDotIcon; - private ImageIcon greyDotIcon; - { - // load images - dropDownIcon = UIUtil.readImage("/dropdown.png"); - relatedRowsIcon = UIUtil.readImage("/right.png"); - redDotIcon = UIUtil.readImage("/reddot.gif"); - blueDotIcon = UIUtil.readImage("/bluedot.gif"); - greenDotIcon = UIUtil.readImage("/greendot.gif"); - greyDotIcon = UIUtil.readImage("/greydot.gif"); - } - - public void resetRowsTableContainer() { - cardPanel.setVisible(true); - } - - public JComponent getRowsTableContainer() { - return cardPanel; - } - - public JTable getRowsTable() { - return rowsTable; - } - - public LoadJob newLoadJob(ResultSet resultSet, Integer limit) { - return new LoadJob(resultSet, limit == null? Integer.MAX_VALUE : limit); - } - - public boolean isEditMode() { - return isEditMode; - } - - public void setEditMode(boolean isEditMode) { - this.isEditMode = isEditMode; - } - - private String statementForReloading; - - public synchronized void setStatementForReloading(String statementForReloading) { - this.statementForReloading = statementForReloading; - } - - /** - * Type of result set for in-place editing of query result. - */ - private List
resultSetType; - - /** - * Sets type of result set for in-place editing of query result. - * - * @param resultSetType the type - */ - public void setResultSetType(List
resultSetType) { - this.resultSetType = resultSetType; - } - - /** - * Gets a table from {@link #resultSetType} where a given column is defined. - * - * @param column the column - * @return suitable table for column or {@link #table} - */ - private Table getResultSetTypeForColumn(int column) { - if (resultSetType == null) { - return table; - } - if (typePerColumn.containsKey(column)) { - return typePerColumn.get(column); - } - for (Table type: resultSetType) { - if (type.getColumns().size() > column) { - Column col = type.getColumns().get(column); - if (col != null && col.name != null) { - typePerColumn.put(column, type); - return type; - } - } - } - typePerColumn.put(column, table); - return table; - } - - private boolean isPKComplete(Table type, Row r) { - if (type.primaryKey == null) { - return false; - } - int[] indexes = pkColumnIndexes.get(type); - if (indexes == null) { - indexes = new int[type.primaryKey.getColumns().size()]; - int ii = 0; - for (Column pk: type.primaryKey.getColumns()) { - Integer index = null; - int i = 0; - for (Column c: type.getColumns()) { - if (c.name != null && c.name.equals(pk.name)) { - index = i; - break; - } - ++i; - } - if (index == null) { - return false; - } - indexes[ii++] = index; - } - pkColumnIndexes.put(type, indexes); - } - for (int i: indexes) { - if (i >= r.values.length) { - return false; - } - Object content = r.values[i]; - if (/*content == null || */ content instanceof TableModelItem && (((TableModelItem) content).value == UIUtil.NULL || ((TableModelItem) content).value == null)) { - return false; - } - } - return true; - } - - private static boolean showingLoadErrorNow = false; - - private Map typePerColumn = new HashMap(); - private Map pkColumnIndexes = new HashMap(); - - private String[] alternativeColumnLabels; - - public void setAlternativeColumnLabels(String[] columnLabels) { - this.alternativeColumnLabels = columnLabels; - } - - private void selectRow(final List toSelect) { - StringBuilder conds = new StringBuilder(); - int numConds = 0; - boolean append = false; - for (int i = 0; i < rows.size(); ++i) { - String rowId = rows.get(i).rowId; - for (Row r: toSelect) { - if (!r.rowId.isEmpty()) { - if (r.rowId.equals(rowId)) { - int vi = rowsTable.getRowSorter().convertRowIndexToView(i); - if (vi >= 0) { - setCurrentRowSelection(vi, append); - append = true; - } - currentRowSelection = -1; - String cond = SqlUtil.replaceAliases(rowId, "A", "A"); - if (numConds == 1) { - conds = new StringBuilder("(" + conds + ")"); - } - if (conds.length() != 0) { - conds.append(" or "); - } - if (numConds > 0) { - conds.append("("); - } - conds.append(cond); - if (numConds > 0) { - conds.append(")"); - } - ++numConds; - break; - } - } - } - } - deselectChildrenIfNeededWithoutReload(); -// String currentCond = getAndConditionText().trim(); - String cond = conds.toString(); -// if (currentCond.length() > 0) { -// cond = "(" + cond + ") and (" + currentCond + ")"; -// } - andCondition.setSelectedItem(cond); - } - - protected void deselectIfNeededWithoutReload() { - if (rows.size() == 1) { - String rowId = rows.get(0).rowId; - if (rowId != null && !rowId.isEmpty()) { - String cond = SqlUtil.replaceAliases(rowId, "A", "A"); - String currentCond = getAndConditionText().trim(); - if (cond.equals(currentCond)) { - boolean isSingleRowNotInClosure = false; - if (rowsClosure != null && rowsClosure.currentClosureRowIDs != null) { - isSingleRowNotInClosure = !rowsClosure.currentClosureRowIDs.contains(new Pair(this, rowId)); - } - if (isSingleRowNotInClosure) { - try { - suppessReloadOnAndConditionAction = true; - andCondition.setSelectedItem(""); - } finally { - suppessReloadOnAndConditionAction = false; - } - } - } - } - } - } - - private static String readCharacterStream(final Reader reader) - throws IOException { - final StringBuilder sb = new StringBuilder(); - final BufferedReader br = new BufferedReader(reader); - - int b; - while(-1 != (b = br.read())) - { - sb.append((char)b); - if (sb.length() > MAXLOBLENGTH) { - sb.append("..."); - break; - } - } - br.close(); - return sb.toString(); - } - - private List sortedAndFiltered(List rows) { - RowSorter sorter = rowsTable.getRowSorter(); - if (sorter != null && !rows.isEmpty()) { - List result = new ArrayList(); - for (int i = 0; i < sorter.getViewRowCount(); ++i) { - result.add(rows.get(sorter.convertRowIndexToModel(i))); - } - return result; - } - return rows; - } - - private void sortChildren() { - try { - if (rowsTable.getRowSorter().getSortKeys().isEmpty()) { - List sk = new ArrayList(); - sk.add(new SortKey(rowsTable.getColumnCount() - 1, SortOrder.ASCENDING)); - rowsTable.getRowSorter().setSortKeys(sk); - ignoreSortKey = true; - } - adjustClosure(null, BrowserContentPane.this); - } catch (Exception e) { - // ignore - } - ((TableRowSorter) rowsTable.getRowSorter()).sort(); - for (RowBrowser ch: getChildBrowsers()) { - if (ch.browserContentPane != null) { - ch.browserContentPane.sortChildren(); - } - } - } - - private static String readClob(Clob clob) throws SQLException, IOException { - return readCharacterStream(clob.getCharacterStream()); - } - - private static String readSQLXML(SQLXML xml) throws SQLException, IOException { - return readCharacterStream(xml.getCharacterStream()); - } - - public static Object toLobRender(Object object) { - Object value = null; - if (object instanceof Blob) { - try { - final long length = ((Blob) object).length(); - value = new LobValue() { - @Override - public String toString() { - return " " + length + " bytes"; - } - }; - } catch (Exception e) { - value = new LobValue() { - @Override - public String toString() { - return ""; - } - }; - } - } - if (object instanceof Clob) { - try { - final String content = readClob((Clob) object); - value = new LobValue() { - @Override - public String toString() { - return content; - } - }; - } catch (Exception e) { - value = new LobValue() { - @Override - public String toString() { - return ""; - } - };e.printStackTrace(); - } - } - if (object instanceof SQLXML) { - try { - final String content = readSQLXML((SQLXML) object); - value = new LobValue() { - @Override - public String toString() { - return content; - } - }; - } catch (Exception e) { - value = new LobValue() { - @Override - public String toString() { - return ""; - } - }; - e.printStackTrace(); - } - } - return value; - } - - public List getSelectedRows(Row additionalRow) { - final List toSelect = new ArrayList(); - if (rowsClosure.currentClosureRootID.contains(additionalRow.nonEmptyRowId)) { - for (Row r: rows) { - if (!r.nonEmptyRowId.isEmpty() && - (rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId) || additionalRow == r)) { - toSelect.add(r); - } - } - } else { - toSelect.add(additionalRow); - } - return toSelect; - } - - public String toCondition(List r) { - if (r == null) { - return ""; - } - StringBuilder sb = new StringBuilder(); - int neCount = 0; - for (Row row: r) { - if (row.rowId != null) { - neCount++; - } - } - for (Row row: r) { - if (row.rowId != null) { - if (sb.length() > 0) { - sb.append(" or "); - } - if (neCount > 1) { - sb.append("("); - } - sb.append(row.rowId); - if (neCount > 1) { - sb.append(")"); - } - } - } - return sb.toString(); - } - - private Reference currentRowsTableReference = null; - - public void setCurrentRowsTable(Reference reference) { - currentRowsTableReference = reference; - } - - private void findColumns(final int x, final int y, final JTable contextJTable) { - TableColumnModel columnModel = rowsTable.getColumnModel(); - List columNames = new ArrayList(); - Map columNamesCount = new HashMap(); - for (int i = 0; i < columnModel.getColumnCount(); ++i) { - Object nameObj = columnModel.getColumn(i).getHeaderValue(); - if (nameObj != null) { - String name = nameObj.toString(); - if (columNamesCount.containsKey(name)) { - columNamesCount.put(name, columNamesCount.get(name) + 1); - } else { - columNames.add(name); - columNamesCount.put(name, 1); - } - } - } - Collections.sort(columNames, new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - }); - - final Window owner = SwingUtilities.getWindowAncestor(contextJTable); - - final JComboBox combobox = new JComboBox(); - combobox.setModel(new DefaultComboBoxModel(columNames.toArray())); - StringSearchPanel searchPanel = new StringSearchPanel(null, combobox, null, null, null, new Runnable() { - @Override - public void run() { - Object selected = combobox.getSelectedItem(); - if (selected != null) { - TableColumnModel columnModel = rowsTable.getColumnModel(); - foundColumn.clear(); - boolean scrolled = false; - for (int i = 0; i < columnModel.getColumnCount(); ++i) { - Object name = columnModel.getColumn(i).getHeaderValue(); - if (name != null && name.equals(selected)) { - int mi = i; - if (!scrolled) { - if (contextJTable != null && contextJTable != rowsTable) { - Rectangle visibleRect = contextJTable.getVisibleRect(); - Rectangle cellRect = contextJTable.getCellRect(mi, 0, true); - contextJTable.scrollRectToVisible( - new Rectangle( - visibleRect.x + visibleRect.width / 2, - cellRect.y - 16, - 1, cellRect.width + 16)); - contextJTable.repaint(); - } else { - Rectangle visibleRect = rowsTable.getVisibleRect(); - Rectangle cellRect = rowsTable.getCellRect(0, mi, true); - rowsTable.scrollRectToVisible( - new Rectangle( - cellRect.x - 32, visibleRect.y + visibleRect.height / 2, - cellRect.width + 64, 1)); - rowsTable.repaint(); - } - scrolled = true; - } - foundColumn.add(columnModel.getColumn(i).getModelIndex()); - } - } - } - } - }) { - @Override - protected Integer preferredWidth() { - return 260; - } - @Override - protected Integer maxX() { - if (owner != null) { - return owner.getX() + owner.getWidth() - preferredWidth(); - } else { - return null; - } - } - @Override - protected Integer maxY(int height) { - if (owner != null) { - return owner.getY() + owner.getHeight() - height - 8; - } else { - return null; - } - } - }; - - searchPanel.setStringCount(columNamesCount); - searchPanel.find(owner, "Find Column", x, y, true); - } - - /** - * Calculates temporary closure when mouse cursor is on new row. - */ - private class TempClosureListener implements MouseListener, MouseMotionListener { - Row currentRow = null; - - private Row rowAt(Point point) { - int ri = rowsTable.rowAtPoint(point); - if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { - int i = rowsTable.getRowSorter().convertRowIndexToModel(ri); - if (i >= 0 && i < rows.size()) { - return rows.get(i); - } - } - return null; - } - - private void updateClosure(Row row) { - if (currentRow != row) { - currentRow = row; - rowsClosure.tempClosure.clear(); - if (currentRow != null) { - findTempClosure(currentRow); - } - onRedraw(); - } - } - - @Override - public void mouseMoved(MouseEvent e) { - Row row = null; - if (e.getSource() == rowsTable) { - row = rowAt(e.getPoint()); - } else if (e.getSource() == singleRowViewContainterPanel && rows.size() == 1) { - row = rows.get(0); - } - updateClosure(row); - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - updateClosure(null); - } - - @Override - public void mouseDragged(MouseEvent e) { - mouseMoved(e); - } - @Override - public void mouseClicked(MouseEvent e) { - } - @Override - public void mousePressed(MouseEvent e) { - } - @Override - public void mouseReleased(MouseEvent e) { - } - } -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser; + +import java.awt.BasicStroke; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.math.BigDecimal; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Types; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.PriorityBlockingQueue; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.BorderFactory; +import javax.swing.DefaultCellEditor; +import javax.swing.DefaultComboBoxModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.ListCellRenderer; +import javax.swing.RowSorter; +import javax.swing.RowSorter.SortKey; +import javax.swing.SortOrder; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.border.LineBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.event.RowSorterEvent; +import javax.swing.event.RowSorterListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; + +import net.coderazzi.filters.gui.AutoChoices; +import net.coderazzi.filters.gui.TableFilterHeader; +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.configuration.Configuration; +import net.sf.jailer.database.InlineViewStyle; +import net.sf.jailer.database.Session; +import net.sf.jailer.database.Session.AbstractResultSetReader; +import net.sf.jailer.database.SqlException; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.Cardinality; +import net.sf.jailer.datamodel.Column; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.PrimaryKey; +import net.sf.jailer.datamodel.RestrictionDefinition; +import net.sf.jailer.datamodel.RowIdSupport; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.extractionmodel.ExtractionModel; +import net.sf.jailer.extractionmodel.SubjectLimitDefinition; +import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; +import net.sf.jailer.modelbuilder.MemorizedResultSet.MemorizedResultSetMetaData; +import net.sf.jailer.subsetting.ScriptFormat; +import net.sf.jailer.ui.DataModelManager; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.Environment; +import net.sf.jailer.ui.ExtractionModelFrame; +import net.sf.jailer.ui.JComboBox; +import net.sf.jailer.ui.QueryBuilderDialog; +import net.sf.jailer.ui.QueryBuilderDialog.Relationship; +import net.sf.jailer.ui.StringSearchPanel; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.databrowser.Desktop.FindClosureContext; +import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; +import net.sf.jailer.ui.databrowser.Desktop.RowToRowLink; +import net.sf.jailer.ui.databrowser.RowCounter.RowCount; +import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; +import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; +import net.sf.jailer.ui.scrollmenu.JScrollC2Menu; +import net.sf.jailer.ui.scrollmenu.JScrollMenu; +import net.sf.jailer.ui.syntaxtextarea.BasicFormatterImpl; +import net.sf.jailer.util.CancellationException; +import net.sf.jailer.util.CancellationHandler; +import net.sf.jailer.util.CellContentConverter; +import net.sf.jailer.util.CellContentConverter.PObjectWrapper; +import net.sf.jailer.util.Pair; +import net.sf.jailer.util.Quoting; +import net.sf.jailer.util.SqlUtil; + +/** + * Content UI of a row browser frame (as {@link JInternalFrame}s). Contains a + * table for rendering rows. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public abstract class BrowserContentPane extends javax.swing.JPanel { + + /** + * Concurrently loads rows. + */ + public class LoadJob implements RunnableWithPriority { + private List rows = Collections.synchronizedList(new ArrayList()); + private Throwable exception; + private boolean isCanceled; + private final int limit; + private final String andCond; + private final boolean selectDistinct; + private boolean finished; + private final ResultSet inputResultSet; + private final RowBrowser parentBrowser; + private Session theSession; + private final Boolean forceAdjustRows; + public boolean closureLimitExceeded = false; + + public LoadJob(int limit, String andCond, RowBrowser parentBrowser, boolean selectDistinct) { + this.andCond = andCond; + this.selectDistinct = selectDistinct; + this.inputResultSet = null; + synchronized (this) { + this.limit = limit; + finished = false; + isCanceled = false; + this.parentBrowser = parentBrowser; + this.forceAdjustRows = Desktop.forceAdjustRows; + } + } + + public LoadJob(ResultSet inputResultSet, int limit) { + this.andCond = ""; + this.selectDistinct = false; + this.inputResultSet = inputResultSet; + synchronized (this) { + this.limit = limit; + finished = false; + isCanceled = false; + parentBrowser = null; + this.forceAdjustRows = Desktop.forceAdjustRows; + } + } + + private boolean reconnectIfConnectionIsInvalid(boolean updateMode) { + try { + if (inputResultSet == null) { + if (!session.getConnection().isValid(8)) { + if (updateMode) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + loadingLabel.setText("reconnecting..."); + } + }); + } + session.reconnect(); + return true; + } + } + } catch (Throwable t) { + // ignore + } + return false; + } + + @Override + public void run() { + int l; + synchronized (this) { + theSession = session; + l = limit; + if (isCanceled) { + CancellationHandler.reset(this); + return; + } + } + + boolean reconnectAndRetry = false; + + rowCountCache.clear(); + try { + reloadRows(inputResultSet, andCond, rows, this, l + 1, selectDistinct); + CancellationHandler.checkForCancellation(this); + synchronized (this) { + finished = true; + } + } catch (SQLException e) { + reconnectAndRetry = true; + } catch (CancellationException e) { + Session._log.info("cancelled"); + CancellationHandler.reset(this); + return; + } catch (Throwable e) { + reconnectAndRetry = true; + } + + if (reconnectAndRetry) { + rowCountCache.clear(); + boolean reconnected = reconnectIfConnectionIsInvalid(true); + try { + if (reconnected) { + session.getMetaData(); // fail-fast + } + reloadRows(inputResultSet, andCond, rows, this, l + 1, selectDistinct); + CancellationHandler.checkForCancellation(this); + synchronized (this) { + finished = true; + } + } catch (SQLException e) { + synchronized (rows) { + exception = e; + } + } catch (CancellationException e) { + Session._log.info("cancelled"); + CancellationHandler.reset(this); + return; + } catch (Throwable e) { + synchronized (rows) { + exception = e; + } + } + } + + if (!finished) { + reconnectIfConnectionIsInvalid(false); + } + CancellationHandler.reset(this); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = forceAdjustRows; + Throwable e; + int l; + boolean limitExceeded = false; + synchronized (rows) { + e = exception; + l = limit; + while (rows.size() > limit) { + limitExceeded = true; + rows.remove(rows.size() - 1); + } + isCanceled = true; // done + sortRowsByParentViewIndex(); + } + if (e != null) { + updateMode("error", null); + unhide(); + if (theSession == null || !theSession.isDown()) { + errorMessageTextArea.setText(e.getMessage()); + errorMessageTextArea.setToolTipText(UIUtil.toHTML(UIUtil.lineWrap(e.getMessage(), 100).toString(), 120)); + errorMessageTextArea.setCaretPosition(0); + if (shouldShowLoadErrors()) { + SQLException sqlException = null; + if (e instanceof SqlException && e.getCause() != null && e.getCause() instanceof SQLException) { + sqlException = (SQLException) e.getCause(); + } + if (sqlException != null && sqlException.getMessage() != null && sqlException.getMessage().trim().length() > 0) { + currentErrorDetail = e; + errorDetailsButton.setVisible(true); + errorMessageTextArea.setText(sqlException.getMessage()); + errorMessageTextArea.setToolTipText(UIUtil.toHTML(UIUtil.lineWrap(e.getMessage(), 100).toString(), 120)); + if (e instanceof SqlException) { + String sqlStatement = ((SqlException) e).sqlStatement; + if (sqlStatement != null && sqlStatement.trim().length() > 0) { + String HR = "(!insHorizontRulHere!)"; + String sql = HR + + new BasicFormatterImpl().format(sqlStatement); + errorMessageTextArea.setToolTipText( + UIUtil.toHTML(UIUtil.lineWrap(sqlException.getMessage().trim(), 100).toString() + + UIUtil.LINE_SEPARATOR + sql, 120).replace(HR, "
")); + } + } + errorMessageTextArea.setCaretPosition(0); + } else if (!showingLoadErrorNow) { + if (getRowBrowser() != null && getRowBrowser().internalFrame != null && getRowBrowser().internalFrame.isVisible()) { + try { + showingLoadErrorNow = true; + UIUtil.showException(BrowserContentPane.this, "Error", e); + } finally { + showingLoadErrorNow = false; + } + } + } + } + } else { + theSession = null; + } + } else { + Set prevIDs = new TreeSet(); + long prevHash = 0; + for (Row r: BrowserContentPane.this.rows) { + prevIDs.add(r.nonEmptyRowId); + try { + for (Object v: r.values) { + if (v != null) { + prevHash = 2 * prevHash + v.hashCode(); + } + } + } catch (RuntimeException e1) { + // ignore + } + } + onContentChange(new ArrayList(), false); + BrowserContentPane.this.rows.clear(); + BrowserContentPane.this.rows.addAll(rows); + updateTableModel(l, limitExceeded, closureLimitExceeded); + Set currentIDs = new TreeSet(); + long currentHash = 0; + if (rows != null) { + for (Row r: rows) { + currentIDs.add(r.nonEmptyRowId); + try { + for (Object v: r.values) { + if (v != null) { + currentHash = 2 * currentHash + v.hashCode(); + } + } + } catch (RuntimeException e1) { + // ignore + } + } + } + setPendingState(false, true); + onContentChange(rows, true); // rows.isEmpty() || currentHash != prevHash || rows.size() != prevSize || !prevIDs.equals(currentIDs) || rows.size() != currentIDs.size()); + updateMode("table", null); + updateWhereField(); + if (reloadAction != null) { + reloadAction.run(); + } + } + afterReload(); + } finally { + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } + }); + } + + protected void sortRowsByParentViewIndex() { + // inherit from child-ancestor + RowBrowser rb = getRowBrowser(); + Map parentRow = new HashMap(); + Set distinctParentRowModelIndex = new HashSet(); + Set singleBlockRows = new HashSet(); + if (rb != null && rb.browserContentPane != null && rb.parent != null && rb.association != null && rb.rowToRowLinks != null && rb.association.isInsertDestinationBeforeSource()) { + for (RowToRowLink l: rb.rowToRowLinks) { + if (!parentRow.containsKey(l.childRow)) { + parentRow.put(l.childRow, l.parentRow); + distinctParentRowModelIndex.add(l.parentRow.getParentModelIndex()); + } else { + singleBlockRows.add(l.childRow); + } + } + } + + useInheritedBlockNumbers = false; + + if (rb != null && rb.parent != null && rb.parent.browserContentPane != null && rb.parent.browserContentPane.rowsTable != null) { + final RowSorter parentSorter = rb.parent.browserContentPane.rowsTable.getRowSorter(); + Comparator comparator = new Comparator() { + @Override + public int compare(Row a, Row b) { + int avi = a.getParentModelIndex(); + if (avi >= 0 && avi < parentSorter.getModelRowCount()) { + avi = parentSorter.convertRowIndexToView(avi); + } + int bvi = b.getParentModelIndex(); + if (bvi >= 0 && avi < parentSorter.getModelRowCount()) { + bvi = parentSorter.convertRowIndexToView(bvi); + } + return avi - bvi; + } + }; + Collections.sort(rows, comparator); + if (!parentRow.isEmpty() && singleBlockRows.isEmpty() && distinctParentRowModelIndex.size() < parentRow.size() && !rb.parent.browserContentPane.useInheritedBlockNumbers) { + useInheritedBlockNumbers = true; + for (Row row: rows) { + Row pRow = parentRow.get(row); + if (pRow != null) { + row.setInheritedParentModelIndex(pRow.getParentModelIndex()); + } + } + } + } + } + + public synchronized void cancel() { + if (isCanceled) { + return; + } + isCanceled = true; + if (finished) { + return; + } + CancellationHandler.cancel(this); + } + + public synchronized void checkCancellation() { + CancellationHandler.checkForCancellation(this); + } + + @Override + public int getPriority() { + return 100; + } + } + + private Runnable reloadAction; + + public void setOnReloadAction(final Runnable runnable) { + if (reloadAction == null) { + reloadAction = runnable; + } else { + final Runnable prevReloadAction = reloadAction; + reloadAction = new Runnable() { + @Override + public void run() { + prevReloadAction.run(); + runnable.run(); + } + }; + } + } + + /** + * Current LoadJob. + */ + private LoadJob currentLoadJob; + + /** + * Table to read rows from. + */ + Table table; + + /** + * The data model. + */ + private final DataModel dataModel; + + /** + * The execution context. + */ + protected final ExecutionContext executionContext; + + /** + * {@link RowIdSupport} for data model. + */ + private final RowIdSupport rowIdSupport; + + /** + * {@link Association} with parent row, or null. + */ + Association association; + + /** + * Rows to render. + */ + public List rows = new ArrayList(); + + /** + * For in-place editing. + */ + private BrowserContentCellEditor browserContentCellEditor = new BrowserContentCellEditor(new int[0], new String[0], null); + + /** + * Cache for association row count. + */ + private final Map, Pair> rowCountCache = + Collections.synchronizedMap(new HashMap, Pair>()); + + private final long MAX_ROWCOUNTCACHE_RETENTION_TIME = 5 * 60 * 1000L; + + /** + * Number of non-distinct rows; + */ + private int noNonDistinctRows; + + /** + * Number of distinct rows; + */ + private int noDistinctRows; + + /** + * Indexes of primary key columns. + */ + private Set pkColumns = new HashSet(); + + /** + * Indexes of foreign key columns. + */ + private Set fkColumns = new HashSet(); + + /** + * Edit mode? + */ + private boolean isEditMode = false; + + /** + * To be shown as "Detail..." in error view. + */ + private Throwable currentErrorDetail; + + /** + * DB session. + */ + Session session; + + private int currentRowSelection = -1; + + public int getCurrentRowSelection() { + return currentRowSelection; + } + + private List parentRows; + private DetailsView singleRowDetailsView; + private MouseListener rowTableListener; + private int initialRowHeight; + private boolean useInheritedBlockNumbers; + boolean ignoreSortKey = false; + + public static class RowsClosure { + Set> currentClosure = Collections.synchronizedSet(new HashSet>()); + Set> currentClosureRowIDs = new HashSet>(); + Set currentClosureRootID = new HashSet(); + BrowserContentPane currentClosureRootPane; + Set parentPath = new HashSet(); + + Set tempClosure = new HashSet(); + }; + + private final RowsClosure rowsClosure; + + private boolean suppressReload; + + /** + * Alias for row number column. + */ + private static final String ROWNUMBERALIAS = "RN"; + + protected static final String UNKNOWN = "- unknown column -"; + + protected static final int MAXLOBLENGTH = 2000; + + private static final KeyStroke KS_COPY_TO_CLIPBOARD = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK); + private static final KeyStroke KS_SQLCONSOLE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK); + private static final KeyStroke KS_QUERYBUILDER = KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK); + private static final KeyStroke KS_FILTER = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK); + private static final KeyStroke KS_EDIT = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK); + private static final KeyStroke KS_DETAILS = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK); + + /** + * And-condition-combobox model. + */ + private final DefaultComboBoxModel andCondModel = new DefaultComboBoxModel(); + + private boolean isTableFilterEnabled = false; + + public void setTableFilterEnabled(boolean isTableFilterEnabled) { + this.isTableFilterEnabled = isTableFilterEnabled; + } + + static class SqlStatementTable extends Table { + public SqlStatementTable(String name, PrimaryKey primaryKey, boolean defaultUpsert) { + super(name, primaryKey, defaultUpsert, false); + } + } + + /** + * Constructor. + * + * @param dataModel + * the data model + * @param table + * to read rows from. Opens SQL browser if table is null. + * @param condition + * initial condition + * @param session + * DB session + * @param parentRow + * parent row + * @param parentRows + * all parent rows, if there are more than 1 + * @param association + * {@link Association} with parent row + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public BrowserContentPane(final DataModel dataModel, final Table table, String condition, Session session, List parentRows, + final Association association, final Frame parentFrame, RowsClosure rowsClosure, + Boolean selectDistinct, boolean reload, ExecutionContext executionContext) { + this.table = table; + this.session = session; + this.dataModel = dataModel; + this.rowIdSupport = new RowIdSupport(dataModel, session.dbms, executionContext); + this.parentRows = parentRows; + this.association = association; + this.rowsClosure = rowsClosure; + this.executionContext = executionContext; + + rowIdSupport.setUseRowIdsOnlyForTablesWithoutPK(true); + + suppressReload = true; + + if (table == null) { + this.table = new SqlStatementTable(null, null, false); + } + + initComponents(); + try { + Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon"); + errorLabel.setIcon(errorIcon); + errorLabel.setText(null); + } catch (Throwable t) { + // ignore + } + + loadingCauseLabel.setVisible(false); + sortColumnsCheckBox.setVisible(false); + + findColumnsLabel.setText(null); + findColumnsLabel.setToolTipText("Find Column..."); + findColumnsLabel.setIcon(StringSearchPanel.getSearchIcon(false, this)); + + findColumnsLabel.addMouseListener(new java.awt.event.MouseAdapter() { + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + if (findColumnsLabel.isEnabled()) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + in = false; + updateBorder(); + if (findColumnsPanel.isShowing()) { + Point point = new Point(); + SwingUtilities.convertPointToScreen(point, findColumnsPanel); + findColumns((int) point.getX(), (int) point.getY(), currentRowsTableReference == null? rowsTable : currentRowsTableReference.get()); + } + } + }); + } + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + if (findColumnsLabel.isEnabled()) { + in = true; + updateBorder(); + } + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + findColumnsPanel.setBackground(in? new Color(255, 255, 100) : null); + findColumnsPanel.setOpaque(in); + } + }); + + andCondition = new JComboBox(); + andCondition.setEditable(true); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + jPanel7.add(andCondition, gridBagConstraints); + + setPendingState(false, false); + + sqlLabel1.setIcon(dropDownIcon); + sortColumnsLabel.setIcon(dropDownIcon); + + final ListCellRenderer acRenderer = andCondition.getRenderer(); + andCondition.setRenderer(new ListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + Component render = acRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (render instanceof JLabel) { + if (value != null && value.toString().trim().length() > 0) { + String tooltip = (value.toString()); + ((JLabel) render).setToolTipText(UIUtil.toHTML(tooltip, 200)); + } else { + ((JLabel) render).setToolTipText(null); + } + } + return render; + } + }); + if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { + JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); + f.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void removeUpdate(DocumentEvent e) { + updateTooltip(); + } + @Override + public void insertUpdate(DocumentEvent e) { + updateTooltip(); + } + @Override + public void changedUpdate(DocumentEvent e) { + updateTooltip(); + } + private void updateTooltip() { + if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { + JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); + String value = f.getText(); + String ttInfo = "Ctrl+Space for code completion."; + if (value != null && value.toString().trim().length() > 0) { + String tooltip = (value.toString()); + andCondition.setToolTipText("" + UIUtil.toHTMLFragment(tooltip, 200) + "
" + ttInfo); + } else { + andCondition.setToolTipText("" + ttInfo); + } + } + }; + }); + } + + andCondModel.addElement(""); + andCondition.setModel(andCondModel); + + andCondition.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (!suppessReloadOnAndConditionAction) { + if (e.getStateChange() == ItemEvent.SELECTED) { + historizeAndCondition(e.getItem()); + reloadRows(); + } + } + if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { + JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); + f.setCaretPosition(0); + } + } + }); + + initialRowHeight = rowsTable.getRowHeight(); + + rowsTable = new JTable() { + private int x[] = new int[2]; + private int y[] = new int[2]; + private Color color = new Color(0, 0, 200); + + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + if (!(graphics instanceof Graphics2D)) { + return; + } + + int maxI = Math.min(rowsTable.getRowCount(), rows.size()); + Rectangle visRect = rowsTable.getVisibleRect(); + + RowSorter sorter = getRowSorter(); + if (sorter != null) { + maxI = sorter.getViewRowCount(); + } + + Graphics2D g2d = (Graphics2D) graphics; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(1)); + + int width = (int) (visRect.width * 1.4); + + for (int i = 0; i < maxI; ++i) { + int mi = sorter == null? i : sorter.convertRowIndexToModel(i); + if (mi >= rows.size()) { + continue; + } + Row row = rows.get(mi); + if (BrowserContentPane.this.rowsClosure.tempClosure.contains(row)) { + int vi = i; + g2d.setColor(new Color(255, 0, 0, 50)); + Rectangle r = rowsTable.getCellRect(vi, 0, false); + x[0] = (int) visRect.getMinX(); + y[0] = (int) r.getMinY(); + r = rowsTable.getCellRect(vi, rowsTable.getColumnCount() - 1, false); + x[1] = (int) visRect.getMinX() + width; + y[1] = (int) r.getMaxY(); + GradientPaint paint = new GradientPaint( + x[0], y[0], new Color(255, 0, 0, 50), + x[0] + width, y[1], new Color(255, 0, 0, 0)); + g2d.setPaint(paint); + g2d.fillRect(x[0], y[0], x[1] - x[0], y[1] - y[0]); + } + } + + g2d.setPaint(null); + + if (!useInheritedBlockNumbers && BrowserContentPane.this.association != null && BrowserContentPane.this.association.isInsertDestinationBeforeSource()) { + return; + } + + double lastPMIndex = -1; + for (int i = 0; i < maxI; ++i) { + int mi = sorter == null? i : sorter.convertRowIndexToModel(i); + if (mi >= rows.size()) { + continue; + } + Row row = rows.get(mi); + double parentModelIndex = useInheritedBlockNumbers? row.getInheritedParentModelIndex() : row.getParentModelIndex(); + if (parentModelIndex != lastPMIndex) { + lastPMIndex = parentModelIndex; + int vi = i; + g2d.setColor(color); + Rectangle r = rowsTable.getCellRect(vi, 0, false); + x[0] = (int) r.getMinX(); + y[0] = (int) r.getMinY(); + r = rowsTable.getCellRect(vi, rowsTable.getColumnCount() - 1, false); + x[1] = (int) r.getMaxX(); + y[1] = (int) r.getMinY(); + g2d.drawPolyline(x, y, 2); + } + } + } + }; + + InputMap im = rowsTable.getInputMap(); + Object key = "copyClipboard"; + im.put(KS_COPY_TO_CLIPBOARD, key); + ActionMap am = rowsTable.getActionMap(); + Action a = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + UIUtil.copyToClipboard(rowsTable, true); + } + }; + am.put(key, a); + + registerAccelerator(KS_SQLCONSOLE, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + rowsTable.grabFocus(); + UIUtil.invokeLater(8, new Runnable() { + @Override + public void run() { + openQueryBuilder(true); + } + }); + } + }); + registerAccelerator(KS_QUERYBUILDER, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + rowsTable.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + openQueryBuilder(false); + } + }); + } + }); + registerAccelerator(KS_FILTER, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + isTableFilterEnabled = !isTableFilterEnabled; + updateTableModel(); + } + }); + registerAccelerator(KS_EDIT, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + setEditMode(!isEditMode); + updateTableModel(); + } + }); + registerAccelerator(KS_DETAILS, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + Point loc = new Point(18, 16); + SwingUtilities.convertPointToScreen(loc, rowsTable); + openDetails(loc.x, loc.y); + } + }); + + rowsTable.setAutoCreateRowSorter(true); + rowsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); + rowsTableScrollPane.setViewportView(rowsTable); + rowsTable.setAutoscrolls(false); + + setAndCondition((condition), true); + from.setText(table == null? "" : this.dataModel.getDisplayName(table)); + adjustGui(); + rowsTable.setShowGrid(false); + final TableCellRenderer defaultTableCellRenderer = rowsTable.getDefaultRenderer(String.class); + + rowsTable.setDefaultRenderer(Object.class, new TableCellRenderer() { + + final Color BG1 = new Color(255, 255, 255); + final Color BG2 = new Color(242, 255, 242); + final Color BG1_EM = new Color(255, 255, 236); + final Color BG2_EM = new Color(230, 255, 236); + final Color BG3 = new Color(192, 236, 255); + final Color BG3_2 = new Color(184, 226, 255); + final Color BG4 = new Color(32, 210, 255, 200); + final Color BG4_2 = new Color(30, 196, 255, 200); + final Color BG4_LIGHT = new Color(30, 200, 255, 60); + final Color FG1 = new Color(155, 0, 0); + final Color FG2 = new Color(0, 0, 255); + final Font font = new JLabel().getFont(); + final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize()); + final Font italic = new Font(nonbold.getName(), nonbold.getStyle() | Font.ITALIC, nonbold.getSize()); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, final int column) { + boolean cellSelected = isSelected; + + if (BrowserContentPane.this.getQueryBuilderDialog() != null || // SQL Console + table.getSelectedColumnCount() <= 1 && table.getSelectedRowCount() <= 1) { + + if (table == rowsTable) { + cellSelected = false; + } + } + + isSelected = currentRowSelection == row || currentRowSelection == -2; + + if (table != rowsTable) { + isSelected = false; + if (table.getSelectedRows().length <= 1 && table.getSelectedColumns().length <= 1) { + for (int sr: table.getSelectedRows()) { + if (sr == column) { + isSelected = true; + break; + } + } + } + } + + Component render = defaultTableCellRenderer.getTableCellRendererComponent(rowsTable, value, isSelected, false, row, column); + final RowSorter rowSorter = rowsTable.getRowSorter(); + if (rowSorter.getViewRowCount() == 0 && table == rowsTable) { + return render; + } + + boolean renderRowAsPK = false; + if (render instanceof JLabel) { + Row r = null; + int rowIndex = row; + ((JLabel) render).setIcon(null); + if (row < rowSorter.getViewRowCount()) { + rowIndex = rowSorter.convertRowIndexToModel(row); + if (rowIndex < rows.size()) { + r = rows.get(rowIndex); + if (r != null) { + renderRowAsPK = renderRowAsPK(r); + Object cellContent = r.values.length > column? r.values[column] : null; + if (cellContent instanceof UIUtil.IconWithText) { + ((JLabel) render).setIcon(((UIUtil.IconWithText) cellContent).icon); + ((JLabel) render).setText(((UIUtil.IconWithText) cellContent).text); + } + } + } + } + ((JLabel) render).setBorder(cellSelected? BorderFactory.createEtchedBorder() : null); + int convertedColumnIndex = rowsTable.convertColumnIndexToModel(column); + if (!isSelected && (table == rowsTable || !cellSelected)) { + if (BrowserContentPane.this.getQueryBuilderDialog() != null && // SQL Console + BrowserContentPane.this.rowsClosure.currentClosureRowIDs != null && + row < rows.size() && + row < rowSorter.getViewRowCount() && + rowSorter.convertRowIndexToModel(row) < rows.size() && + BrowserContentPane.this.rowsClosure.currentClosureRowIDs.contains(new Pair(BrowserContentPane.this, rows.get(rowSorter.convertRowIndexToModel(row)).nonEmptyRowId))) { + ((JLabel) render).setBackground((row % 2) == 0? BG3 : BG3_2); + if (BrowserContentPane.this.rowsClosure.currentClosureRootID != null + && !BrowserContentPane.this.rowsClosure.currentClosureRootID.isEmpty() + && BrowserContentPane.this.rowsClosure.currentClosureRootPane == BrowserContentPane.this) { + String rid = rows.get(rowSorter.convertRowIndexToModel(row)).nonEmptyRowId; + if (!rid.isEmpty() && BrowserContentPane.this.rowsClosure.currentClosureRootID.contains(rid)) { + ((JLabel) render).setBackground(currentRowSelection >= 0? BG4_LIGHT : (row % 2 == 0? BG4 : BG4_2)); + } + } + } else { + Table type = getResultSetTypeForColumn(convertedColumnIndex); + if (isEditMode && r != null && (r.rowId != null && !r.rowId.isEmpty()) && browserContentCellEditor.isEditable(type, rowIndex, convertedColumnIndex, r.values[convertedColumnIndex]) + && isPKComplete(type, r) && !rowIdSupport.getPrimaryKey(type, BrowserContentPane.this.session).getColumns().isEmpty()) { + ((JLabel) render).setBackground((row % 2 == 0) ? BG1_EM : BG2_EM); + } else { + ((JLabel) render).setBackground((row % 2 == 0) ? BG1 : BG2); + } + } + } else { + ((JLabel) render).setBackground(currentRowSelection == row? BG4.brighter() : (row % 2 == 0? BG4 : BG4_2)); + } + ((JLabel) render).setForeground( + renderRowAsPK || pkColumns.contains(convertedColumnIndex) ? FG1 : + fkColumns.contains(convertedColumnIndex) ? FG2 : + Color.BLACK); + boolean isNull = false; + if (((JLabel) render).getText() == UIUtil.NULL || ((JLabel) render).getText() == UNKNOWN) { + ((JLabel) render).setForeground(Color.gray); + ((JLabel) render).setFont(italic); + isNull = true; + } + TableColumnModel columnModel = rowsTable.getColumnModel(); + if (!foundColumn.isEmpty() && column < columnModel.getColumnCount() && foundColumn.contains(columnModel.getColumn(column).getModelIndex())) { + Color background = render.getBackground(); + render.setBackground( + new Color( + Math.max((int)(background.getRed()), 0), + Math.max((int)(background.getGreen() * 0.90), 0), + Math.max((int)(background.getBlue() * 0.91), 0), + background.getAlpha())); + } + try { + ((JLabel) render).setToolTipText(null); + if (isNull) { + ((JLabel) render).setFont( + // highlightedRows.contains(rowSorter.convertRowIndexToModel(row)) ? italicBold : + italic); + } else { + ((JLabel) render).setFont( + // highlightedRows.contains(rowSorter.convertRowIndexToModel(row)) ? bold : + nonbold); + String text = ((JLabel) render).getText(); + if (text.indexOf('\n') >= 0) { + ((JLabel) render).setToolTipText(UIUtil.toHTML(text, 200)); + } else if (text.length() > 20) { + ((JLabel) render).setToolTipText(text); + } + } + } catch (Exception e) { + // ignore + } + } + // indent 1. column + if (render instanceof JLabel) { + ((JLabel) render).setText(" " + ((JLabel) render).getText()); + } + return render; + } + }); + rowsTable.setRowSelectionAllowed(true); + rowsTable.setColumnSelectionAllowed(true); + rowsTable.setCellSelectionEnabled(true); + rowsTable.setEnabled(true); + + rowsTableScrollPane.getVerticalScrollBar().setUnitIncrement(32); + singleRowViewScrollPane.getVerticalScrollBar().setUnitIncrement(32); + + rowTableListener = new MouseListener() { + private JPopupMenu lastMenu; + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + int ri; + JComponent source = (JComponent) e.getSource(); + if (source == rowsTable) { + ri = rowsTable.rowAtPoint(e.getPoint()); + } else { + ri = 0; + } + if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { + int i = 0; + if (source == rowsTable) { + i = rowsTable.getRowSorter().convertRowIndexToModel(ri); + } else if (source == rowsTableScrollPane || source == singleRowViewContainterPanel) { + if (rows.size() != 1 || getQueryBuilderDialog() == null /* SQL Console */) { + return; + } + ri = 0; + i = 0; + } + Row row = rows.get(i); + + if (getQueryBuilderDialog() == null // SQL Console + || ((e.getButton() != MouseEvent.BUTTON1 || e.getClickCount() != 1) && (lastMenu == null || !lastMenu.isVisible()))) { + currentRowSelection = ri; + onRedraw(); + int x, y; + if (source != rowsTable) { + x = e.getX(); + y = e.getY(); + } else { + Rectangle r = rowsTable.getCellRect(ri, 0, false); + x = Math.max(e.getPoint().x, (int) r.getMinX()); + y = (int) r.getMaxY() - 2; + } + Point p = SwingUtilities.convertPoint(source, x, y, null); + if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() > 1) { + openDetailsView(i, p.x + getOwner().getX(), p.y + getOwner().getY()); + } else if (e.getButton() != MouseEvent.BUTTON1) { + JPopupMenu popup; + popup = createPopupMenu(row, i, p.x + getOwner().getX(), p.y + getOwner().getY(), rows.size() == 1); + if (popup != null) { + if (!row.nonEmptyRowId.isEmpty()) { + for (Row r: rows) { + if (r.nonEmptyRowId.equals(row.nonEmptyRowId) && BrowserContentPane.this.rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId)) { + currentRowSelection = -1; + onRedraw(); + break; + } + } + } + UIUtil.showPopup(source, x, y, popup); + popup.addPropertyChangeListener("visible", new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.FALSE.equals(evt.getNewValue())) { + currentRowSelection = -1; + onRedraw(); + } + } + }); + } + lastMenu = popup; + } else { + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(ri, false); + } + } else if (e.getComponent() == singleRowViewScrollContentPanel || e.getSource() == singleRowViewContainterPanel) { + if (getQueryBuilderDialog() != null) { // !SQL Console + for (RowBrowser tb: getTableBrowser()) { + try { + tb.browserContentPane.isUpdatingTableModel = true; + tb.browserContentPane.rowsTable.clearSelection(); + } finally { + tb.browserContentPane.isUpdatingTableModel = false; + } + } + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(0, false); + } + } + } + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseClicked(MouseEvent e) { + } + }; + + rowsTable.addMouseListener(rowTableListener); + rowsTableScrollPane.addMouseListener(rowTableListener); + singleRowViewScrollPane.addMouseListener(rowTableListener); + singleRowViewContainterPanel.addMouseListener(rowTableListener); + + TempClosureListener tempClosureListener = new TempClosureListener(); + rowsTable.addMouseListener(tempClosureListener); + rowsTable.addMouseMotionListener(tempClosureListener); + rowsTableScrollPane.addMouseListener(tempClosureListener); + rowsTableScrollPane.addMouseMotionListener(tempClosureListener); + singleRowViewContainterPanel.addMouseListener(tempClosureListener); + singleRowViewContainterPanel.addMouseMotionListener(tempClosureListener); + + if (getQueryBuilderDialog() != null) { // !SQL Console + rowsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + List prevSelectedRows = null; + Timer timer = null; + @Override + public void valueChanged(ListSelectionEvent e) { + List selectedRows = new ArrayList(); + if (isUpdatingTableModel) { + prevSelectedRows = selectedRows; + return; + } else { + for (RowBrowser tb: getTableBrowser()) { + if (tb.browserContentPane != BrowserContentPane.this) { + try { + tb.browserContentPane.isUpdatingTableModel = true; + tb.browserContentPane.rowsTable.clearSelection(); + } finally { + tb.browserContentPane.isUpdatingTableModel = false; + } + } + } + } + for (int si: rowsTable.getSelectedRows()) { + selectedRows.add(si); + } + if (prevSelectedRows == null || !prevSelectedRows.equals(selectedRows)) { + prevSelectedRows = selectedRows; + resetCurrentRowSelection(); + for (int si: selectedRows) { + setCurrentRowSelection(si, true); + } + setCurrentRowSelection(-1, true); + startTimer(); + } + } + private void startTimer() { + final Timer newTimer = new Timer(100, null); + timer = newTimer; + timer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (newTimer == timer) { + reloadChildrenIfLimitIsExceeded(); + } + } + }); + timer.setRepeats(false); + timer.start(); + } + }); + } + + openEditorButton.setIcon(UIUtil.scaleIcon(this, conditionEditorIcon)); + openEditorButton.setText(null); + + final Runnable openConditionEditor = new Runnable() { + @Override + public void run() { + openConditionEditor(); + } + + public void openConditionEditor() { + openEditorButton.setSelected(true); + final Point pos = new Point(andCondition.getX(), andCondition.getY()); + SwingUtilities.convertPointToScreen(pos, andCondition.getParent()); + Window owner = SwingUtilities.getWindowAncestor(BrowserContentPane.this); + andConditionEditor.setLocationAndFit(pos, owner != null? owner.getX() + owner.getWidth() - 8: Integer.MAX_VALUE); + andConditionEditor.edit(getAndConditionText(), "Table", "A", table, null, null, null, false, true); + } + }; + + final Runnable createConditionEditor = new Runnable() { + @Override + public void run() { + createConditionEditor(); + } + + public void createConditionEditor() { + if (andConditionEditor == null) { + andConditionEditor = new DBConditionEditor(parentFrame, dataModel) { + @Override + protected void consume(String cond) { + if (cond != null) { + if (!getAndConditionText().equals((cond))) { + setAndCondition((cond), true); + loadButton.grabFocus(); + reloadRows(); + } + } + openEditorButton.setSelected(false); + } + }; + if (andCondition.getEditor().getEditorComponent() instanceof JTextField) { + andConditionEditor.observe((JTextField) andCondition.getEditor().getEditorComponent(), openConditionEditor); + } + } + } + }; + + openEditorButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + loadButton.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + createConditionEditor.run(); + openConditionEditor.run(); + } + }); + } + }); + if (andCondition.getEditor().getEditorComponent() instanceof JTextField) { + DBConditionEditor.initialObserve((JTextField) andCondition.getEditor().getEditorComponent(), new Runnable() { + @Override + public void run() { + createConditionEditor.run(); + andConditionEditor.doCompletion((JTextField) andCondition.getEditor().getEditorComponent(), openConditionEditor); + } + }); + } + relatedRowsLabel.setIcon(UIUtil.scaleIcon(this, relatedRowsIcon)); + relatedRowsLabel.setFont(relatedRowsLabel.getFont().deriveFont(relatedRowsLabel.getFont().getSize() * 1.1f)); + if (createPopupMenu(null, -1, 0, 0, false).getComponentCount() == 0) { + relatedRowsLabel.setEnabled(false); + } else { + relatedRowsPanel.addMouseListener(new java.awt.event.MouseAdapter() { + private JPopupMenu popup; + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + loadButton.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + popup = createPopupMenu(null, -1, 0, 0, false); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2, false); + popup.addPropertyChangeListener("visible", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.FALSE.equals(evt.getNewValue())) { + popup = null; + updateBorder(); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); + } + } + }); + UIUtil.showPopup(relatedRowsPanel, 0, relatedRowsPanel.getHeight(), popup); + } + }); + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + in = true; + updateBorder(); + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + relatedRowsPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED + : javax.swing.border.BevelBorder.RAISED)); + } + }); + } + sqlPanel.addMouseListener(new java.awt.event.MouseAdapter() { + private JPopupMenu popup; + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + loadButton.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + Point loc = sqlPanel.getLocationOnScreen(); + popup = createSqlPopupMenu(0, (int) loc.getX(), (int) loc.getY(), false, BrowserContentPane.this); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-2, false); + popup.addPropertyChangeListener("visible", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.FALSE.equals(evt.getNewValue())) { + popup = null; + updateBorder(); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); + } + } + }); + UIUtil.showPopup(sqlPanel, 0, sqlPanel.getHeight(), popup); + } + }); + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + in = true; + updateBorder(); + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + sqlPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED + : javax.swing.border.BevelBorder.RAISED)); + } + }); + if (selectDistinct != null) { + selectDistinctCheckBox.setSelected(selectDistinct); + } + sortColumnsPanel.addMouseListener(new java.awt.event.MouseAdapter() { + private JPopupMenu popup; + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + loadButton.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + popup = new JPopupMenu(); + JCheckBoxMenuItem natural = new JCheckBoxMenuItem("Natural column order "); + natural.setSelected(!sortColumnsCheckBox.isSelected()); + natural.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + sortColumnsCheckBox.setSelected(false); + sortColumnsCheckBoxActionPerformed(null); + sortColumnsLabel.setText("Natural column order"); + } + }); + popup.add(natural); + JCheckBoxMenuItem sorted = new JCheckBoxMenuItem("Alphabetical column order "); + sorted.setSelected(sortColumnsCheckBox.isSelected()); + sorted.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + sortColumnsCheckBox.setSelected(true); + sortColumnsCheckBoxActionPerformed(null); + sortColumnsLabel.setText("A-Z column order"); + } + }); + popup.add(sorted); + popup.addSeparator(); + JMenuItem changeOrder = new JMenuItem("Change natural column order "); + changeOrder.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + sortColumnsCheckBox.setSelected(false); + sortColumnsCheckBoxActionPerformed(null); + sortColumnsLabel.setText("Natural column order"); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + changeColumnOrder(table); + } + }); + } + }); + popup.add(changeOrder); + popup.addPropertyChangeListener("visible", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.FALSE.equals(evt.getNewValue())) { + popup = null; + updateBorder(); + } + } + }); + UIUtil.showPopup(sortColumnsPanel, 0, sortColumnsPanel.getHeight(), popup); + } + }); + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + in = true; + updateBorder(); + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + sortColumnsPanel.setBorder(new javax.swing.border.SoftBevelBorder((in || popup != null) ? javax.swing.border.BevelBorder.LOWERED + : javax.swing.border.BevelBorder.RAISED)); + } + }); + updateTableModel(0, false, false); + + suppressReload = false; + if (reload) { + reloadRows(); + } + } + + private void registerAccelerator(KeyStroke ks, AbstractAction a) { + registerAccelerator(ks, a, this); + registerAccelerator(ks, a, rowsTable); + registerAccelerator(ks, a, loadButton); + registerAccelerator(ks, a, sqlLabel1); + registerAccelerator(ks, a, relatedRowsLabel); + registerAccelerator(ks, a, andCondition); + Component editor = andCondition.getEditor().getEditorComponent(); + if (editor instanceof JComponent) { + registerAccelerator(ks, a, (JComponent) editor); + } + } + + private void registerAccelerator(KeyStroke ks, AbstractAction a, JComponent comp) { + InputMap im = comp.getInputMap(); + im.put(ks, a); + ActionMap am = comp.getActionMap(); + am.put(a, a); + } + + protected abstract boolean renderRowAsPK(Row theRow); + + boolean isPending = false; + + void setPendingState(boolean pending, boolean propagate) { + isPending = pending; + ((CardLayout) pendingNonpendingPanel.getLayout()).show(pendingNonpendingPanel, "nonpending"); + if (pending) { + updateMode("pending", null); + } + if (propagate) { + for (RowBrowser child: getChildBrowsers()) { + child.browserContentPane.setPendingState(pending, propagate); + } + } + } + + protected void historizeAndCondition(Object item) { + if (item == null || (item.toString().trim().isEmpty() && !item.toString().isEmpty())) { + return; + } + for (int i = 0; i < andCondModel.getSize(); ++i) { + if (item.equals(andCondModel.getElementAt(i))) { + return; + } + } + andCondModel.insertElementAt(item, 1); + } + + private boolean suppessReloadOnAndConditionAction = false; + + void setAndCondition(String cond, boolean historize) { + try { + suppessReloadOnAndConditionAction = true; + andCondition.setSelectedItem(cond); + if (historize) { + historizeAndCondition(cond); + } + } finally { + suppessReloadOnAndConditionAction = false; + } + } + + String getAndConditionText() { + if (andCondition.getEditor() != null && (andCondition.getEditor().getEditorComponent() instanceof JTextField)) { + JTextField f = ((JTextField) andCondition.getEditor().getEditorComponent()); + return f.getText(); + } + Object sel = andCondition.getSelectedItem(); + if (sel == null) { + return ""; + } + return sel.toString().trim(); + } + + private void adjustGui() { + if (this.association == null) { + joinPanel.setVisible(false); + onPanel.setVisible(false); + + jLabel1.setText(" "); + jLabel4.setText(" "); + + jLabel6.setVisible(false); + java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 8; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridheight = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + } else { + join.setText(this.dataModel.getDisplayName(this.association.source)); + on.setText(!this.association.reversed ? SqlUtil.reversRestrictionCondition(this.association.getUnrestrictedJoinCondition()) : this.association + .getUnrestrictedJoinCondition()); + updateWhereField(); + join.setToolTipText(join.getText()); + on.setToolTipText(assocToolTip(on.getText(), this.association)); + } + } + + private static String assocToolTip(String condition, Association assoc) { + return "" + UIUtil.toHTMLFragment(condition, 0) + "

FK: " + + UIUtil.toHTML(assoc.reversed? assoc.reversalAssociation.getName() : assoc.getName(), 0) + ""; + } + + private class AllNonEmptyItem extends JMenuItem { + int todo; + int done; + private List todoList = new ArrayList(); + private final String initText = "Counting rows... "; + + AllNonEmptyItem() { + setEnabled(false); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Component parent = SwingUtilities.getWindowAncestor(BrowserContentPane.this); + if (parent == null) { + parent = BrowserContentPane.this; + } + UIUtil.setWaitCursor(parent); + try { + Desktop.noArrangeLayoutOnNewTableBrowser = true; + Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = todoList.size() > 1; + Desktop.resetLastArrangeLayoutOnNewTableBrowser(); + for (int i = 0; i < todoList.size(); ++i) { + if (i == todoList.size() - 1) { + Desktop.noArrangeLayoutOnNewTableBrowser = false; + } + todoList.get(i).actionPerformed(e); + } + } finally { + Desktop.noArrangeLayoutOnNewTableBrowser = false; + Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = false; + UIUtil.resetWaitCursor(parent); + } + } + }); + } + + public void rowsCounted(long count, ActionListener itemAction) { + ++done; + if (count != 0) { + todoList.add(itemAction); + } + int p = todo > 0? (100 * done) / todo : 0; + if (done < todo) { + setText(initText + p + "%"); + } else { + setText("All non-empty (" + todoList.size() + ")"); + setEnabled(true); + } + } + + public void setInitialText() { + if (todoList.isEmpty()) { + setText("All non-empty (0)"); + } else { + setText(initText + "100%"); + } + } + + }; + + private String currentSelectedRowCondition = ""; + + /** + * Creates popup menu for navigation. + * @param navigateFromAllRows + * @param copyTCB + * @param runnable + * @param runnable + */ + public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows) { + return createPopupMenu(row, rowIndex, x, y, navigateFromAllRows, null, null); + } + + /** + * Creates popup menu for navigation. + * @param navigateFromAllRows + * @param runnable + */ + public JPopupMenu createPopupMenu(final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint) { + return createPopupMenu(rowsTable, row, rowIndex, x, y, navigateFromAllRows, altCopyTCB, repaint, true); + } + + /** + * Creates popup menu for navigation. + * @param navigateFromAllRows + * @param runnable + */ + public JPopupMenu createPopupMenu(final JTable contextJTable, final Row row, final int rowIndex, final int x, final int y, boolean navigateFromAllRows, JMenuItem altCopyTCB, final Runnable repaint, final boolean withKeyStroke) { + JMenuItem tableFilter = new JCheckBoxMenuItem("Table Filter"); + if (withKeyStroke) { + tableFilter.setAccelerator(KS_FILTER); + } else { + tableFilter.setVisible(false); + } + tableFilter.setSelected(isTableFilterEnabled); + if (isLimitExceeded) { + tableFilter.setForeground(Color.red); + tableFilter.setToolTipText("Row limit exceeded. Filtering may be incomplete."); + } + tableFilter.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Component parent = null; + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = null; + parent = SwingUtilities.getWindowAncestor(contextJTable); + UIUtil.setWaitCursor(parent); + isTableFilterEnabled = !isTableFilterEnabled; + updateTableModel(); + } finally { + UIUtil.resetWaitCursor(parent); + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } + }); + JMenuItem copyTCB; + if (altCopyTCB != null) { + copyTCB = altCopyTCB; + } else { + copyTCB = null; +// if (getQueryBuilderDialog() != null) { // !SQL Console +// copyTCB = null; +// } else { +// copyTCB = new JMenuItem("Copy to Clipboard"); +// if (withKeyStroke) { +// copyTCB.setAccelerator(KS_COPY_TO_CLIPBOARD); +// } +// copyTCB.setEnabled(rowsTable.getSelectedColumnCount() > 0); +// copyTCB.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent e) { +// UIUtil.copyToClipboard(rowsTable, true); +// } +// }); +// } + } + + if (table instanceof SqlStatementTable && resultSetType == null) { + JPopupMenu jPopupMenu = new JPopupMenu(); + if (row != null) { + JMenuItem det = new JMenuItem("Details"); + if (withKeyStroke) { + det.setAccelerator(KS_DETAILS); + } + jPopupMenu.add(det); + jPopupMenu.add(new JSeparator()); + det.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openDetailsView(rowIndex, x, y); + } + }); + } + JMenu script = new JMenu("Create SQL"); + script.setEnabled(false); + jPopupMenu.add(script); + jPopupMenu.addSeparator(); + if (copyTCB != null) { + jPopupMenu.add(copyTCB); + jPopupMenu.addSeparator(); + } + jPopupMenu.add(tableFilter); + JMenuItem editMode = new JMenuItem("Edit Mode"); + if (withKeyStroke) { + editMode.setAccelerator(KS_EDIT); + } + jPopupMenu.add(editMode); + editMode.setEnabled(false); + return jPopupMenu; + } + + List assList = new ArrayList(); + Map assMap = new HashMap(); + for (Association a : table.associations) { + int n = 0; + for (Association a2 : table.associations) { + if (a.destination == a2.destination) { + ++n; + } + } + char c = ' '; + if (a.isIgnored()) { + c = '4'; + } else if (a.isInsertDestinationBeforeSource()) { + c = '1'; + } else if (a.isInsertSourceBeforeDestination()) { + c = '2'; + } else { + c = '3'; + } + String name = c + a.getDataModel().getDisplayName(a.destination) + (n > 1 ? " (" + (a.reversed? a.reversalAssociation.getName() : a.getName()) + ")": ""); + assList.add(name); + assMap.put(name, a); + } + Collections.sort(assList); + + final Object context = new Object(); + AllNonEmptyItem allNonEmpty = new AllNonEmptyItem(); + + JPopupMenu popup = new JPopupMenu(); + popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Parents", "1", navigateFromAllRows, 80, allNonEmpty, context); + popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Children", "2", navigateFromAllRows, 60, allNonEmpty, context); + popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Associated Rows", "3", navigateFromAllRows, 40, allNonEmpty, context); + popup = createNavigationMenu(popup, row, rowIndex, assList, assMap, "Detached Rows", "4", navigateFromAllRows, 40, allNonEmpty, context); + + popup.addPopupMenuListener(new PopupMenuListener() { + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + cancel(); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + cancel(); + } + + private void cancel() { + CancellationHandler.cancelSilently(context); + getRunnableQueue().add(new RunnableWithPriority() { + + @Override + public void run() { + CancellationHandler.reset(context); + } + + @Override + public int getPriority() { + return 0; + } + }); + } + }); + + if (!isPending && !rows.isEmpty()) { + popup.add(allNonEmpty); + allNonEmpty.setInitialText(); + } + + if (row != null) { + JMenuItem det = new JMenuItem("Details"); + if (withKeyStroke) { + det.setAccelerator(KS_DETAILS); + } + popup.insert(det, 0); + popup.insert(new JSeparator(), 1); + det.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openDetailsView(rowIndex, x, y); + } + }); + + if (!(table instanceof SqlStatementTable) || resultSetType != null) { + if (popup.getComponentCount() > 0) { + popup.add(new JSeparator()); + } + + JMenuItem qb = new JMenuItem("Query Builder"); + qb.setAccelerator(KS_QUERYBUILDER); + popup.add(qb); + qb.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openQueryBuilder(false, SqlUtil.replaceAliases(row.rowId, "A", "A")); + } + }); + + JMenuItem sqlConsole = new JMenuItem("SQL Console"); + sqlConsole.setAccelerator(KS_SQLCONSOLE); + popup.add(sqlConsole); + sqlConsole.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openQueryBuilder(true, SqlUtil.replaceAliases(row.rowId, "A", "A")); + } + }); + + final List toSelect = new ArrayList(); + if (!row.nonEmptyRowId.isEmpty()) { + for (Row r: rows) { + if (!r.nonEmptyRowId.isEmpty() && rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId)) { + toSelect.add(r); + } + } + } + if (!toSelect.contains(row)) { + toSelect.clear(); + toSelect.add(row); + } + if (!currentSelectedRowCondition.equals("") && + (rows.size() == 1 || toSelect.size() == rows.size())) { + JMenuItem sr = new JMenuItem(rows.size() == 1? "Deselect Row" : ("Deselect Rows (" + rows.size() + ")")); + popup.insert(sr, 0); + sr.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + andCondition.setSelectedItem(""); + } + }); + } else { + JMenuItem sr = new JMenuItem(toSelect.size() <= 1? "Select Row" : ("Select Rows (" + toSelect.size() + ")")); + sr.setEnabled(rows.size() > 1 && !row.rowId.isEmpty()); + popup.insert(sr, 0); + sr.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + selectRow(toSelect); + } + }); + } + + JMenu sql = new JMenu("Create SQL"); + final String rowName = !(table instanceof SqlStatementTable)? dataModel.getDisplayName(table) + "(" + SqlUtil.replaceAliases(row.rowId, null, null) + ")" : ""; + JMenuItem update = new JMenuItem("Update"); + sql.add(update); + update.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Update Row " + rowName, x, y, SQLDMLBuilder.buildUpdate(table, toSelect, true, session)); + } + }); + JMenuItem insert = new JMenuItem("Insert"); + sql.add(insert); + insert.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Insert Row " + rowName, x, y, SQLDMLBuilder.buildInsert(table, toSelect, true, session)); + } + }); + JMenuItem insertNewRow = createInsertChildMenu(toSelect, x, y); + sql.add(insertNewRow); + JMenuItem delete = new JMenuItem("Delete"); + sql.add(delete); + delete.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Delete Row " + rowName, x, y, SQLDMLBuilder.buildDelete(table, toSelect, true, session)); + } + }); + insert.setEnabled(resultSetType == null); + update.setEnabled(resultSetType == null); + delete.setEnabled(resultSetType == null); + if (getQueryBuilderDialog() == null) { + popup.removeAll(); + popup.add(det); + popup.addSeparator(); + JMenu script = new JMenu("Create SQL"); + popup.add(script); + if (table.getName() == null) { + script.setEnabled(false); + } else { + final String tableName = dataModel.getDisplayName(table); + script.add(update); + script.add(insert); + script.add(insertNewRow); + script.add(delete); + script.addSeparator(); + JMenuItem updates = new JMenuItem("Updates (all rows)"); + script.add(updates); + updates.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Update " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildUpdate(table, sortedAndFiltered(rows), false, session); }}); + } + }); + JMenuItem inserts = new JMenuItem("Inserts (all rows)"); + script.add(inserts); + inserts.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Insert Into " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildInsert(table, sortedAndFiltered(rows), false, session); }}); + } + }); + JMenuItem deletes = new JMenuItem("Deletes (all rows)"); + script.add(deletes); + deletes.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Delete from " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildDelete(table, sortedAndFiltered(rows), false, session); } + }); + } + }); + boolean hasPK = !rowIdSupport.getPrimaryKey(table).getColumns().isEmpty(); + if (!hasPK) { + delete.setEnabled(false); + } + inserts.setEnabled(rows.size() > 0); + updates.setEnabled(hasPK && rows.size() > 0); + deletes.setEnabled(hasPK && rows.size() > 0); + } + } else { + popup.add(sql); + } + } + popup.addSeparator(); + if (copyTCB != null) { + popup.add(copyTCB); + popup.addSeparator(); + } + popup.add(createFindColumnMenuItem(x, y, contextJTable)); + popup.add(new JSeparator()); + popup.add(tableFilter); + JCheckBoxMenuItem editMode = new JCheckBoxMenuItem("Edit Mode"); + editMode.setEnabled(isTableEditable(table)); + if (withKeyStroke) { + editMode.setAccelerator(KS_EDIT); + } + editMode.setSelected(isEditMode); + editMode.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = null; + setEditMode(!isEditMode); + updateTableModel(); + if (repaint != null) { + UIUtil.invokeLater(repaint); + } + } finally { + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } + }); + popup.add(editMode); + } + + return popup; + } + + private JMenuItem createFindColumnMenuItem(final int x, final int y, final JTable contextJTable) { + final JMenuItem menuItem = new JMenuItem("Find Column..."); + menuItem.setEnabled(singleRowDetailsView == null); + menuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + findColumns(x, y, contextJTable); + } + }); + return menuItem; + } + + /** + * Creates popup menu for SQL. + * @param forNavTree + * @param browserContentPane + */ + public JPopupMenu createSqlPopupMenu(final int rowIndex, final int x, final int y, boolean forNavTree, final Component parentComponent) { + JPopupMenu popup = new JPopupMenu(); + + JMenuItem rebase = new JMenuItem("Start Navigation here"); + popup.add(rebase); + rebase.setEnabled(getParentBrowser() != null); + rebase.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + rebase(); + } + }); + popup.addSeparator(); + JMenuItem qb = new JMenuItem("Query Builder"); + qb.setAccelerator(KS_QUERYBUILDER); + popup.add(qb); + qb.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openQueryBuilder(false); + } + }); + JMenuItem sqlConsole = new JMenuItem("SQL Console"); + sqlConsole.setAccelerator(KS_SQLCONSOLE); + popup.add(sqlConsole); + sqlConsole.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openQueryBuilder(true); + } + }); + JMenu sqlDml = new JMenu("Create SQL"); + popup.add(sqlDml); + final String tableName = dataModel.getDisplayName(table); + JMenuItem update = new JMenuItem("Updates"); + sqlDml.add(update); + update.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Update " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildUpdate(table, sortedAndFiltered(rows), false, session); }}); + } + }); + JMenuItem insert = new JMenuItem("Inserts"); + sqlDml.add(insert); + insert.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Insert Into " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildInsert(table, sortedAndFiltered(rows), false, session); }}); + } + }); + JMenuItem insertNewRow = createInsertChildMenu(sortedAndFiltered(rows), x, y); + sqlDml.add(insertNewRow); + JMenuItem delete = new JMenuItem("Deletes"); + sqlDml.add(delete); + delete.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Delete from " + tableName, x, y, new Object() { @Override + public String toString() { return SQLDMLBuilder.buildDelete(table, sortedAndFiltered(rows), false, session); }}); + } + }); + boolean hasPK = !rowIdSupport.getPrimaryKey(table).getColumns().isEmpty(); + insert.setEnabled(rows.size() > 0); + update.setEnabled(hasPK && rows.size() > 0); + delete.setEnabled(hasPK && rows.size() > 0); + + popup.add(new JSeparator()); + JMenuItem exportData = new JMenuItem("Export Data"); + popup.add(exportData); + exportData.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openExtractionModelEditor(true); + } + }); + + JMenuItem extractionModel = new JMenuItem("Create Extraction Model"); + popup.add(extractionModel); + extractionModel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openExtractionModelEditor(false); + } + }); + + popup.add(new JSeparator()); + + if (!forNavTree) { + JMenuItem det = new JMenuItem("Details"); + det.setAccelerator(KS_DETAILS); + popup.add(det); + det.setEnabled(rows.size() > 0); + det.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openDetails(x, y); + } + }); + } +// popup.add(new JSeparator()); + JMenuItem snw = new JMenuItem("Show in New Window"); + popup.add(snw); + snw.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showInNewWindow(); + } + }); + +// JMenuItem al = new JMenuItem("Append Layout..."); +// popup.add(al); +// al.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent e) { +// appendLayout(); +// } +// }); +// +// popup.addSeparator(); + + JMenuItem m = new JMenuItem("Hide (Minimize)"); + popup.add(m); + m.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + onHide(); + } + }); + m = new JMenuItem("Close"); + popup.add(m); + m.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + closeWithChildren(parentComponent); + } + }); + popup.add(new JSeparator()); + if (!forNavTree) { + popup.add(createFindColumnMenuItem(x, y, rowsTable)); + popup.add(new JSeparator()); + } + JMenuItem tableFilter = new JCheckBoxMenuItem("Table Filter"); + tableFilter.setAccelerator(KS_FILTER); + tableFilter.setSelected(isTableFilterEnabled); + if (isLimitExceeded) { + tableFilter.setForeground(Color.red); + tableFilter.setToolTipText("Row limit exceeded. Filtering may be incomplete."); + } + tableFilter.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Component parent = null; + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = null; + parent = SwingUtilities.getWindowAncestor(parentComponent); + UIUtil.setWaitCursor(parent); + isTableFilterEnabled = !isTableFilterEnabled; + updateTableModel(); + } finally { + UIUtil.resetWaitCursor(parent); + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } + }); + popup.add(tableFilter); + JCheckBoxMenuItem editMode = new JCheckBoxMenuItem("Edit Mode"); + editMode.setEnabled(isTableEditable(table)); + editMode.setAccelerator(KS_EDIT); + editMode.setSelected(isEditMode); + editMode.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = null; + setEditMode(!isEditMode); + updateTableModel(); + } finally { + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } + }); + popup.add(editMode); + return popup; + } + + protected boolean isTableEditable(Table theTable) { + return resultSetType != null || !rowIdSupport.getPrimaryKey(theTable).getColumns().isEmpty(); + } + + public boolean closeWithChildren(Component parentComponent) { + int count = countSubNodes(this); + Component parent = SwingUtilities.getWindowAncestor(this); + if (parent == null) { + parent = BrowserContentPane.this; + } + boolean closeThisToo = true; + if (count > 1) { + int o = JOptionPane.showOptionDialog(parentComponent, "Which tables do you want to close?", "Close", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, + new Object[] { + "Only this table", + "This and related tables (" + (count) + ")", + "Related tables (" + (count - 1) + ")" + }, + null); + if (o == 0) { + UIUtil.setWaitCursor(parent); + try { + close(); + } finally { + UIUtil.resetWaitCursor(parent); + } + return true; + } + if (o == 1) { + closeThisToo = true; + } else if (o == 2) { + closeThisToo = false; + } else { + return false; + } + } + UIUtil.setWaitCursor(parent); + try { + closeSubTree(BrowserContentPane.this, closeThisToo); + } finally { + UIUtil.resetWaitCursor(parent); + } + return true; + } + + private int countSubNodes(BrowserContentPane cp) { + int count = 0; + for (RowBrowser c: cp.getChildBrowsers()) { + count += countSubNodes(c.browserContentPane); + } + return count + 1; + } + + protected void closeSubTree(BrowserContentPane cp, boolean closeThisToo) { + for (RowBrowser c: cp.getChildBrowsers()) { + closeSubTree(c.browserContentPane, true); + } + if (closeThisToo) { + cp.close(); + } + } + + private JMenu createInsertChildMenu(List parents, final int x, final int y) { + JScrollMenu insertNewRow = new JScrollMenu("Insert Child"); + if (parents == null || parents.isEmpty() || parents.size() > 1 || table == null || table.getName() == null) { + insertNewRow.setEnabled(false); + return insertNewRow; + } + List tableAssociations = table.associations; + + if (tableAssociations == null || tableAssociations.isEmpty()) { + // artificial table from SQL Console? + Table t = dataModel.getTable(table.getName()); + if (t == null) { + insertNewRow.setEnabled(false); + return insertNewRow; + } + tableAssociations = t.associations; + } + + List assocs = new ArrayList(); + Map> children = new HashMap>(); + + if (tableAssociations != null) { + for (Association association: tableAssociations) { + List child = createNewRow(parents, table, association); + if (child != null && !child.isEmpty()) { + assocs.add(association); + children.put(association, child); + } + } + } + Collections.sort(assocs, new Comparator() { + @Override + public int compare(Association a, Association b) { + String dNameA = dataModel.getDisplayName(a.destination); + String dNameB = dataModel.getDisplayName(b.destination); + return dNameA.compareTo(dNameB); + } + }); + for (int i = 0; i < assocs.size(); ++i) { + final Association association = assocs.get(i); + Association pred = i > 0? assocs.get(i - 1) : null; + Association succ = i < assocs.size() - 1? assocs.get(i + 1) : null; + final String dName = dataModel.getDisplayName(association.destination); + JMenuItem item; + if (pred != null && pred.destination == association.destination || succ != null && succ.destination == association.destination) { + item = new JMenuItem(dName + " on " + association.getName()); + } else { + item = new JMenuItem(dName); + } + final List child = children.get(association); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openSQLDialog("Insert Child into " + dName, x, y, SQLDMLBuilder.buildInsert(association.destination, child, true, session)); + } + }); + insertNewRow.add(item); + } + + insertNewRow.setEnabled(!assocs.isEmpty()); + return insertNewRow; + } + + void openExtractionModelEditor(boolean doExport) { + Component parent = SwingUtilities.getWindowAncestor(this); + if (parent == null) { + parent = this; + } + UIUtil.setWaitCursor(parent); + try { + String file; + String ts = new SimpleDateFormat("HH-mm-ss-SSS", Locale.ENGLISH).format(new Date()); + + Table stable = table; + String subjectCondition; + + QueryBuilderDialog.Relationship root = createQBRelations(false); + Collection restrictedAssociations = new HashSet(); + Collection restrictedDependencies = new HashSet(); + Collection restrictedDependencyDefinitions = new HashSet(); + List restrictionDefinitions = createRestrictions(root, stable, restrictedAssociations, restrictedDependencies, restrictedDependencyDefinitions); + +// if (!restrictedDependencies.isEmpty()) { + Set parents = new TreeSet(); + for (Association association: restrictedDependencies) { + parents.add(dataModel.getDisplayName(association.destination)); + } +// String pList = ""; +// int i = 0; +// for (String p: parents) { +// pList += p + "\n"; +// if (++i > 20) { +// break; +// } +// } + + final SbEDialog sbEDialog = new SbEDialog(SwingUtilities.getWindowAncestor(this), + (doExport? "Export rows and related rows from \"" : "Create Extraction Model for Subject \"") + dataModel.getDisplayName(stable) + "\".", (parents.isEmpty()? "" : ("\n\n" + parents.size() + " disregarded parent tables."))); + if (doExport) { + sbEDialog.setTitle("Export Data"); + } + sbEDialog.regardButton.setVisible(!parents.isEmpty()); + sbEDialog.dispose(); + DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + Component result = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof DefaultMutableTreeNode) { + if (!(((DefaultMutableTreeNode) value).getUserObject() instanceof String)) { + if (result instanceof JLabel) { + ((JLabel) result).setForeground(Color.red); + } else { + ((JLabel) result).setForeground(Color.black); + } + } + } + return result; + } + + }; + renderer.setOpenIcon(null); + renderer.setLeafIcon(null); + renderer.setClosedIcon(null); + sbEDialog.browserTree.setCellRenderer(renderer); + int[] count = new int[] { 0 }; + DefaultTreeModel treeModel = new DefaultTreeModel(addChildNodes(this, restrictedDependencies, count)); + sbEDialog.browserTree.setModel(treeModel); + for (int i = 0; i < count[0]; ++i) { + sbEDialog.browserTree.expandRow(i); + } + sbEDialog.browserTree.scrollRowToVisible(0); + sbEDialog.browserTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + sbEDialog.browserTree.getSelectionModel().clearSelection(); + } + }); + sbEDialog.grabFocus(); + sbEDialog.setVisible(true); + + if (!sbEDialog.ok) { + return; + } + if (sbEDialog.regardButton.isSelected()) { + restrictionDefinitions.removeAll(restrictedDependencyDefinitions); + for (Association a: restrictedDependencies) { + disableDisregardedNonParentsOfDestination(a, restrictedAssociations, restrictionDefinitions); + } + } + +// int option = JOptionPane.showOptionDialog(parent, "Disregarded parent tables:\n\n" + pList + "\n", "Disregarded parent tables", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "regard parent tables", "Ok" }, "regard parent tables"); +// switch (option) { +// case 0: +// restrictionDefinitions.removeAll(restrictedDependencyDefinitions); +// for (Association a: restrictedDependencies) { +// disableDisregardedNonParentsOfDestination(a, restrictedAssociations, restrictionDefinitions); +// } +// break; +// case 1: +// break; +// default: return; +// } +// } + + subjectCondition = root.whereClause; + if (doExport && (getParentBrowser() != null /* || isLimitExceeded */)) { + subjectCondition = root.whereClause; + if (subjectCondition != null) { + subjectCondition = subjectCondition.replace('\r', ' ').replace('\n', ' '); + } + StringBuilder sb = new StringBuilder(); + boolean f = true; + for (Row row: rows) { + if (f) { + f = false; + } else { + sb.append(" or "); + } + sb.append("(" + row.rowId + ")"); + } + + if (subjectCondition != null && subjectCondition.trim().length() > 0) { + subjectCondition = "(" + subjectCondition + ") and (" + sb + ")"; + } else { + subjectCondition = sb.toString(); + } + } + if (subjectCondition == null) { + subjectCondition = ""; + } +// if (doExport && isLimitExceeded && rows != null && !rows.isEmpty()) { +// StringBuilder sb = new StringBuilder(); +// boolean f = true; +// for (Row row: rows) { +// if (f) { +// f = false; +// } else { +// sb.append(" or "); +// } +// sb.append("(" + row.rowId + ")"); +// } +// subjectCondition = sb.toString(); +// } + subjectCondition = SqlUtil.replaceAliases(subjectCondition, "T", "T"); + + if (!doExport) { + for (int i = 1; ; ++i) { + file = Environment.newFile("extractionmodel" + File.separator + "by-example").getPath(); + File newFile = new File(file); + newFile.mkdirs(); + file += File.separator + "SbE-" + (dataModel.getDisplayName(stable).replaceAll("['`\"/\\\\\\~]+", "")) + "-" + ts + (i > 1? "-" + Integer.toString(i) : "") + ".jm"; + newFile = new File(file); + if (!newFile.exists()) { + break; + } + } + } else { + file = Configuration.getInstance().createTempFile().getPath(); + } + + Map> positions = new TreeMap>(); + collectPositions(positions); + String currentModelSubfolder = DataModelManager.getCurrentModelSubfolder(executionContext); + dataModel.save(file, stable, new SubjectLimitDefinition(null, null), subjectCondition, ScriptFormat.SQL, restrictionDefinitions, positions, new ArrayList(), currentModelSubfolder); + + final ExtractionModelFrame extractionModelFrame = ExtractionModelFrame.createFrame(file, false, !doExport, null, executionContext); + extractionModelFrame.setDbConnectionDialogClone(getDbConnectionDialog()); + if (doExport) { + extractionModelFrame.openExportDialog(false, + new Runnable() { + @Override + public void run() { + try { + reloadDataModel(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }, + new Runnable() { + @Override + public void run() { + extractionModelFrame.dispose(); + } + }); + } else { + extractionModelFrame.markDirty(); + extractionModelFrame.expandAll(); + } + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } finally { + UIUtil.resetWaitCursor(parent); + } + } + + private DefaultMutableTreeNode addChildNodes(BrowserContentPane browserContentPane, Collection restrictedDependencies, int[] count) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(dataModel.getDisplayName(browserContentPane.table)); + count[0]++; + Set
regardedChildren = new HashSet
(); + for (RowBrowser rb: browserContentPane.getChildBrowsers()) { + DefaultMutableTreeNode childNode = addChildNodes(rb.browserContentPane, restrictedDependencies, count); + node.add(childNode); + regardedChildren.add(rb.browserContentPane.table); + } + for (final Association dep: restrictedDependencies) { + if (dep.source == browserContentPane.table && !regardedChildren.contains(dep.destination)) { + node.add(new DefaultMutableTreeNode(new Object() { + String item = dataModel.getDisplayName(dep.destination); + @Override + public String toString() { + return item; + } + })); + count[0]++; + } + } + return node; + } + + private void disableDisregardedNonParentsOfDestination(Association a, + Collection regardedAssociations, + List restrictionDefinitions) { + for (Association npa: a.destination.associations) { + if (!regardedAssociations.contains(npa)) { + regardedAssociations.add(npa); + if (npa.isInsertDestinationBeforeSource()) { + disableDisregardedNonParentsOfDestination(npa, regardedAssociations, restrictionDefinitions); + } else { + RestrictionDefinition rest = new RestrictionDefinition(npa.source, npa.destination, npa.getName(), null, true); + restrictionDefinitions.add(rest); + } + } + } + } + + private static class RestrictionLiteral { + public String condition; + public int distanceFromRoot; + public boolean isIgnored; + public boolean isIgnoredIfReversalIsRestricted = false; + @Override + public String toString() { + return "Cond:" + condition + " Dist: " + distanceFromRoot + " isIgnored: " + isIgnored + " isIgnoredIfReversalIsRestricted: " + isIgnoredIfReversalIsRestricted; + } + } + + /** + * Creates restriction according to the given {@link Relationship} tree. + * + * @param root root of tree + * @return restrictions + */ + private List createRestrictions(Relationship root, Table subject, Collection regardedAssociations, Collection restrictedDependencies, Collection restrictedDependencyDefinitions) { + List restrictionDefinitions = new ArrayList(); + + Map> restrictionLiterals = new HashMap>(); + collectRestrictionLiterals(restrictionLiterals, root, subject, 0); + + for (Association association: restrictionLiterals.keySet()) { + RestrictionDefinition rest = createRestrictionDefinition(association, restrictionLiterals, true); + + regardedAssociations.add(association); + if (rest.isIgnored || (rest.condition != null && rest.condition.trim().length() != 0)) { + restrictionDefinitions.add(rest); + if (association.isInsertDestinationBeforeSource() && rest.isIgnored) { + restrictedDependencies.add(association); + restrictedDependencyDefinitions.add(rest); + } + } + } + + return restrictionDefinitions; + } + + private RestrictionDefinition createRestrictionDefinition(Association association, Map> restrictionLiterals, boolean checkReversal) { + List lits = restrictionLiterals.get(association); + boolean useDistance = false; + boolean hasTrue = false; + boolean hasNotTrue = false; + boolean hasNotFalse = false; + Integer lastDist = null; + for (RestrictionLiteral l: lits) { + + if (l.isIgnoredIfReversalIsRestricted) { + + if (checkReversal) { + RestrictionDefinition revRest = createRestrictionDefinition(association.reversalAssociation, restrictionLiterals, false); + if (revRest.isIgnored || (revRest.condition != null && revRest.condition.trim().length() > 0)) { + l.isIgnored = true; + } else { + l.isIgnored = false; + l.condition = null; + } + l.isIgnoredIfReversalIsRestricted = false; + } else { + l.isIgnored = true; + l.isIgnoredIfReversalIsRestricted = false; + } + } + + // disabled since 5.0 + +// if (lastDist != null && lastDist != l.distanceFromRoot) { +// useDistance = true; +// } +// lastDist = l.distanceFromRoot; + + if (!l.isIgnored) { + hasNotFalse = true; + if (l.condition == null || l.condition.trim().length() == 0) { + hasTrue = true; + } else { + hasNotTrue = true; + } + } else { + hasNotTrue = true; + } + } + + boolean isIgnored; + String condition = null; + + if (!hasNotFalse) { + isIgnored = true; + } else if (!hasNotTrue) { + isIgnored = false; + } else if (hasTrue && !useDistance) { + isIgnored = false; + } else { + for (RestrictionLiteral l: lits) { + if (!l.isIgnored) { + String c = null; + if (useDistance) { + c = l.distanceFromRoot == 0? "A.$IS_SUBJECT" : ("A.$DISTANCE=" + l.distanceFromRoot); + } + if (l.condition != null && l.condition.trim().length() > 0) { + if (c == null) { + c = l.condition; + } else { + c = c + " and (" + l.condition + ")"; + } + } + if (condition == null) { + condition = c; + } else { + condition += " or " + c; + } + } + } + isIgnored = false; + } + RestrictionDefinition rest = new RestrictionDefinition(association.source, association.destination, association.getName(), condition, isIgnored); + return rest; + } + + /** + * Collects restriction literals per association according to a given {@link Relationship} tree. + * + * @param restrictionLiterals to put literals into + * @param root root of tree + * @param distanceFromRoot distance + */ + private void collectRestrictionLiterals(Map> restrictionLiterals, Relationship root, Table subject, int distanceFromRoot) { + for (Association association: subject.associations) { + List children = new ArrayList(); + for (Relationship r: root.children) { + if (r.association == association) { + children.add(r); + } + } + if (children.isEmpty()) { + children.add(null); + } + for (Relationship child: children) { + RestrictionLiteral restrictionLiteral = new RestrictionLiteral(); + restrictionLiteral.distanceFromRoot = distanceFromRoot; + restrictionLiteral.isIgnored = false; + if (child == null) { + restrictionLiteral.isIgnored = true; +// if (association.isInsertDestinationBeforeSource()) { + if (root.association != null && association == root.association.reversalAssociation) { + if (association.getCardinality() == Cardinality.MANY_TO_ONE + || + association.getCardinality() == Cardinality.ONE_TO_ONE) { + restrictionLiteral.isIgnoredIfReversalIsRestricted = true; + } + } +// } + } else { + restrictionLiteral.condition = child.whereClause == null? "" : SqlUtil.replaceAliases(child.whereClause, "B", "A"); + collectRestrictionLiterals(restrictionLiterals, child, association.destination, distanceFromRoot + 1); + } + List literals = restrictionLiterals.get(association); + if (literals == null) { + literals = new ArrayList(); + restrictionLiterals.put(association, literals); + } + literals.add(restrictionLiteral); + } + } + } + + private void openSQLDialog(String titel, int x, int y, Object sql) { + UIUtil.setWaitCursor(this); + JDialog d; + try { + String LF = System.getProperty("line.separator", "\n"); + String sqlString = sql.toString().trim() + LF; + if (sqlString.length() > 10L*1024L*1024L) { + int o = JOptionPane.showOptionDialog(this, "SQL Script is large (" + (sqlString.length() / 1024) + " KB)", "SQL Script is large", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Open", "Cancel", "Save Script" }, "Save Script"); + if (o == 2) { + String fn = UIUtil.choseFile(null, ".", "Save SQL Script", ".sql", this, false, false, false); + if (fn != null) { + try { + PrintWriter out = new PrintWriter(new FileWriter(fn)); + out.print(sqlString); + out.close(); + } catch (Throwable e) { + UIUtil.showException(this, "Error saving script", e, UIUtil.EXCEPTION_CONTEXT_USER_ERROR); + } + } + } + if (o != 0) { + return; + } + } + d = new JDialog(getOwner(), "Create SQL - " + titel, true); + d.getContentPane().add(new SQLDMLPanel(sqlString, getSqlConsole(false), session, getMetaDataSource(), + new Runnable() { + @Override + public void run() { + reloadRows(); + } + }, + new Runnable() { + @Override + public void run() { + getSqlConsole(true); + } + }, + d, executionContext)); + d.pack(); + d.setLocation(x - 50, y - 100); + d.setSize(700, Math.max(d.getHeight() + 20, 400)); + d.setLocation(getOwner().getX() + (getOwner().getWidth() - d.getWidth()) / 2, Math.max(0, getOwner().getY() + (getOwner().getHeight() - d.getHeight()) / 2)); + UIUtil.fit(d); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e); + return; + } finally { + UIUtil.resetWaitCursor(this); + } + d.setVisible(true); + } + + protected abstract SQLConsole getSqlConsole(boolean switchToConsole); + + private void appendClosure() { + if (getParentBrowser() != null) { + if (rowsClosure.currentClosureRootPane == this) { + List selectedRows = new ArrayList(); + RowSorter rowSorter = rowsTable.getRowSorter(); + for (int i = rows.size() - 1; i >= 0; --i) { + if (rowsClosure.currentClosureRootID.contains(rows.get(i).nonEmptyRowId)) { + int vi = rowSorter.convertRowIndexToView(i); + if (vi >= 0) { + selectedRows.add(vi); + } + } + } + resetCurrentRowSelection(); + for (int si: selectedRows ) { + setCurrentRowSelection(si, true); + } + setCurrentRowSelection(-1, true); + } else { + BrowserContentPane parentContentPane = getParentBrowser().browserContentPane; + + Set> newElements = new HashSet>(); + synchronized (getMonitorForFindClosure()) { + FindClosureContext findClosureContext = new FindClosureContext(); + for (Pair e: rowsClosure.currentClosure) { + if (e.a == parentContentPane) { + parentContentPane.findClosure(e.b, newElements, true, findClosureContext); + } + } + } + rowsClosure.currentClosure.addAll(newElements); + rowsClosure.currentClosureRowIDs.clear(); + for (Pair r: rowsClosure.currentClosure) { + rowsClosure.currentClosureRowIDs.add(new Pair(r.a, r.b.nonEmptyRowId)); + } + rowsTable.repaint(); + adjustClosure(null, this); + } + } + } + + protected void setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(int i, boolean append) { + setCurrentRowSelection(i, append); + if (i >= 0) { + reloadChildrenIfLimitIsExceeded(); + } + } + + protected void setCurrentRowSelection(int i, boolean append) { + currentRowSelection = i; + if (i >= 0) { + int mi = rowsTable.getRowSorter().convertRowIndexToModel(i); + if (mi >= 0 && mi < rows.size()) { + Row row = rows.get(mi); + if (!append) { + for (Pair e: rowsClosure.currentClosure) { + e.a.currentRowSelection = -1; + } + rowsClosure.currentClosure.clear(); + rowsClosure.parentPath.clear(); + rowsClosure.currentClosureRootID.clear(); + } + rowsClosure.currentClosureRootID.add(row.nonEmptyRowId); + rowsClosure.currentClosureRootPane = this; + findClosure(row); + Rectangle visibleRect = rowsTable.getVisibleRect(); + Rectangle pos = rowsTable.getCellRect(i, 0, false); + rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, pos.y, 1, pos.height)); + } + } + rowsClosure.currentClosureRowIDs.clear(); + for (Pair r: rowsClosure.currentClosure) { + rowsClosure.currentClosureRowIDs.add(new Pair(r.a, r.b.nonEmptyRowId)); + } + rowsTable.repaint(); + adjustClosure(this, null); + } + + private void resetCurrentRowSelection() { + currentRowSelection = -1; + rowsClosure.currentClosure.clear(); + rowsClosure.parentPath.clear(); + rowsClosure.currentClosureRootID.clear(); + rowsTable.repaint(); + adjustClosure(this, null); + } + + private void reloadChildrenIfLimitIsExceeded() { + for (RowBrowser ch: getChildBrowsers()) { + if (ch.browserContentPane != null) { + if (ch.browserContentPane.isLimitExceeded) { + Boolean oldForceAdjustRows = Desktop.forceAdjustRows; + try { + Desktop.forceAdjustRows = true; + ch.browserContentPane.reloadRows("because rows limit is exceeded"); + } finally { + Desktop.forceAdjustRows = oldForceAdjustRows; + } + } else { + ch.browserContentPane.reloadChildrenIfLimitIsExceeded(); + } + } + } + } + + private JPopupMenu createNavigationMenu(JPopupMenu popup, final Row row, final int rowIndex, List assList, Map assMap, + String title, String prefix, final boolean navigateFromAllRows, final int rowCountPriority, final AllNonEmptyItem allNonEmptyItem, final Object context) { + JScrollC2Menu nav = new JScrollC2Menu(title); + + if (prefix.equals("1")) { + nav.setIcon(UIUtil.scaleIcon(this, redDotIcon)); + } + if (prefix.equals("2")) { + nav.setIcon(UIUtil.scaleIcon(this, greenDotIcon)); + } + if (prefix.equals("3")) { + nav.setIcon(UIUtil.scaleIcon(this, blueDotIcon)); + } + if (prefix.equals("4")) { + nav.setIcon(UIUtil.scaleIcon(this, greyDotIcon)); + } + JMenu current = nav; + + final List pRows; + if (row == null) { + pRows = Collections.emptyList(); + } else { + pRows = getSelectedRows(row); + } + String countCondition = toCondition(pRows); + + int l = 0; + for (String name : assList) { + if (!name.startsWith(prefix)) { + continue; + } + + final Association association = assMap.get(name); + + ++l; + + final JMenuItem item = new JMenuItem(" " + (name.substring(1)) + " "); + item.setToolTipText(assocToolTip(association.getUnrestrictedJoinCondition(), association)); + final JLabel countLabel = new JLabel(". >99999 ") { + @Override + public void paint(Graphics g) { + if (!getText().startsWith(".")) { + super.paint(g); + } + } + }; + + boolean excludeFromANEmpty = false; + for (RowBrowser child: getChildBrowsers()) { + if (association == child.association && + (child.browserContentPane.getAndConditionText().trim().length() == 0 + || child.browserContentPane.getAndConditionText().trim().equals(countCondition))) { + item.setFont(new Font(item.getFont().getName(), item.getFont().getStyle() | Font.ITALIC, item.getFont().getSize())); + excludeFromANEmpty = true; + break; + } + } + + if (association.reversalAssociation == this.association) { + excludeFromANEmpty = true; + } + + final ActionListener itemAction = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (navigateFromAllRows) { + navigateTo(association, null); + } else { + navigateTo(association, pRows); + } + } + }; + item.addActionListener(itemAction); + if (!excludeFromANEmpty) { + allNonEmptyItem.todo++; + } + final boolean fExcludeFromANEmpty = excludeFromANEmpty; + + if (!isPending && !rows.isEmpty()) { + getRunnableQueue().add(new RunnableWithPriority() { + + final int MAX_RC = 1000; + + String andConditionText = getAndConditionText(); + + @Override + public int getPriority() { + return rowCountPriority; + } + + @Override + public void run() { + List r; + Pair key; + if (rowIndex < 0) { + r = rows; + key = new Pair("", association); + } else { + r = pRows; + key = new Pair(row.nonEmptyRowId, association); + } + + Pair cachedCount = rowCountCache.get(key); + RowCount rowCount; + + if (cachedCount != null && cachedCount.b > System.currentTimeMillis()) { + rowCount = cachedCount.a; + } else { + RowCounter rc = new RowCounter(table, association, r, session, rowIdSupport); + try { + rowCount = rc.countRows(andConditionText, context, MAX_RC + 1, false); + } catch (SQLException e) { + rowCount = new RowCount(-1, true); + } + rowCountCache.put(key, new Pair(rowCount, System.currentTimeMillis() + MAX_ROWCOUNTCACHE_RETENTION_TIME)); + } + + final RowCount count = rowCount; + + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + String cs = " " + (count.count < 0? "?" : (count.count > MAX_RC)? (">" + MAX_RC) : count.isExact? count.count : (">" + count.count)) + " "; + countLabel.setText(cs); + if (count.count == 0) { + countLabel.setForeground(Color.lightGray); + } + if (!fExcludeFromANEmpty) { + allNonEmptyItem.rowsCounted(count.count, itemAction); + } + } + }); + } + }); + } + + if (current != null) { + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = l; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + current.getPopupMenu().add(item, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = l; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + current.getPopupMenu().add(countLabel, gridBagConstraints); + } else { + popup.add(item); + } + } + if (l > 0) { + popup.add(nav); + } + return popup; + } + + private long lastReloadTS = 0; + + /** + * Reloads rows. + */ + public void reloadRows() { + reloadRows(null); + } + + boolean loadedRowsAreRestricted = false; + + /** + * Reloads rows. + */ + public void reloadRows(String cause) { + if (!suppressReload) { + lastReloadTS = System.currentTimeMillis(); + cancelLoadJob(true); + setPendingState(true, true); + rows.clear(); + updateMode("loading", cause); + setPendingState(false, false); + int limit = getReloadLimit(); + LoadJob reloadJob; + loadedRowsAreRestricted = false; + if (statementForReloading != null) { + reloadJob = new LoadJob(limit, statementForReloading, getParentBrowser(), false); + } else { + loadedRowsAreRestricted = !(table instanceof SqlStatementTable) && !getAndConditionText().trim().isEmpty(); + reloadJob = new LoadJob(limit, (table instanceof SqlStatementTable)? "" : getAndConditionText(), getParentBrowser(), selectDistinctCheckBox.isSelected()); + currentSelectedRowCondition = getAndConditionText(); + } + synchronized (this) { + currentLoadJob = reloadJob; + } + getRunnableQueue().add(reloadJob); + } + } + + /** + * Reload rows from {@link #table}. + * + * @param rows + * to put the rows into + * @param loadJob + * cancellation context + * @param limit + * row number limit + */ + private void reloadRows(ResultSet inputResultSet, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct) throws SQLException { + try { + session.setSilent(true); + reloadRows(inputResultSet, andCond, rows, loadJob, limit, selectDistinct, null); + return; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another strategy (" + e.getMessage() + ")"); + } finally { + session.setSilent(false); + } + Set existingColumnsLowerCase = null; + if (!(table instanceof SqlStatementTable) && statementForReloading == null) { + existingColumnsLowerCase = findColumnsLowerCase(table, session); + } + reloadRows(inputResultSet, andCond, rows, loadJob, limit, selectDistinct, existingColumnsLowerCase); + } + + /** + * Finds the columns of a given {@link Table}. + * + * @param table the table + * @param session the statement executor for executing SQL-statements + */ + private Set findColumnsLowerCase(Table table, Session session) { + try { + Set columns = new HashSet(); + DatabaseMetaData metaData = session.getMetaData(); + Quoting quoting = Quoting.getQuoting(session); + String defaultSchema = JDBCMetaDataBasedModelElementFinder.getDefaultSchema(session, session.getSchema()); + String schema = quoting.unquote(table.getOriginalSchema(defaultSchema)); + String tableName = quoting.unquote(table.getUnqualifiedName()); + ResultSet resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, false, null); + while (resultSet.next()) { + String colName = resultSet.getString(4).toLowerCase(Locale.ENGLISH); + columns.add(colName); + } + resultSet.close(); + if (columns.isEmpty()) { + if (session.getMetaData().storesUpperCaseIdentifiers()) { + schema = schema.toUpperCase(Locale.ENGLISH); + tableName = tableName.toUpperCase(Locale.ENGLISH); + } else { + schema = schema.toLowerCase(Locale.ENGLISH); + tableName = tableName.toLowerCase(Locale.ENGLISH); + } + resultSet = JDBCMetaDataBasedModelElementFinder.getColumns(session, metaData, schema, tableName, "%", false, false, null); + while (resultSet.next()) { + String colName = resultSet.getString(4).toLowerCase(Locale.ENGLISH); + columns.add(colName); + } + } + if (columns.isEmpty()) { + return null; + } + return columns; + } catch (Exception e) { + return null; + } + } + + /** + * Reload rows from {@link #table}. + * + * @param rows + * to put the rows into + * @param loadJob + * cancellation context + * @param limit + * row number limit + */ + private void reloadRows(ResultSet inputResultSet, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct, Set existingColumnsLowerCase) throws SQLException { + if (table instanceof SqlStatementTable || statementForReloading != null) { + try { + session.setSilent(true); + Map> rowsMap = new HashMap>(); + reloadRows(inputResultSet, null, andCond, null, rowsMap, loadJob, limit, false, null, existingColumnsLowerCase); + if (rowsMap.get("") != null) { + rows.addAll(rowsMap.get("")); + } + } finally { + session.setSilent(false); + } + return; + } + + List pRows = parentRows; + if (pRows == null) { + pRows = Collections.singletonList(null); + } else { + pRows = new ArrayList(pRows); + } + Map rowSet = new HashMap(); + loadJob.checkCancellation(); + if (parentRows != null) { + beforeReload(); + } + noNonDistinctRows = 0; + noDistinctRows = 0; + + if (association != null && rowIdSupport.getPrimaryKey(association.source, session).getColumns().isEmpty()) { + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 1, existingColumnsLowerCase); + } else { + if (useInlineViewForResolvingAssociation(session)) { + try { + InlineViewStyle inlineViewStyle = session.getInlineViewStyle(); + if (inlineViewStyle != null) { + loadRowBlocks(inputResultSet, inlineViewStyle, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 510, existingColumnsLowerCase); + return; + } + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); + } + } + try { + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 510, existingColumnsLowerCase); + return; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); + } + try { + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 300, existingColumnsLowerCase); + return; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); + } + try { + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 100, existingColumnsLowerCase); + return; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); + } + try { + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 40, existingColumnsLowerCase); + return; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another blocking-size (" + e.getMessage() + ")"); + } + } + + loadRowBlocks(inputResultSet, null, andCond, rows, loadJob, limit, selectDistinct, pRows, rowSet, 1, existingColumnsLowerCase); + } + + static boolean useInlineViewForResolvingAssociation(Session session) { + return session.dbms.isUseInlineViewsInDataBrowser(); + } + + private void loadRowBlocks(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List rows, LoadJob loadJob, int limit, boolean selectDistinct, List pRows, + Map rowSet, int NUM_PARENTS, Set existingColumnsLowerCase) throws SQLException { + List> parentBlocks = new ArrayList>(); + List currentBlock = new ArrayList(); + Set regPRows = new HashSet(); + Map parentRowIndex = new IdentityHashMap(); + for (int i = 0; i < pRows.size(); ++i) { + parentRowIndex.put(pRows.get(i), i); + } + parentBlocks.add(currentBlock); + BrowserContentPane parentPane = null; + if (getParentBrowser() != null) { + parentPane = getParentBrowser().browserContentPane; + } + for (boolean inClosure: new boolean[] { true, false }) { + boolean firstNonClosure = false; + for (Row pRow : pRows) { + if (parentPane != null) { + if (rowsClosure.currentClosure.contains(new Pair(parentPane, pRow))) { + if (!inClosure) { + continue; + } + } else { + if (inClosure) { + continue; + } + } + } else if (!inClosure) { + break; + } + if (currentBlock.size() >= NUM_PARENTS || (!inClosure && !firstNonClosure)) { + if (!currentBlock.isEmpty()) { + currentBlock = new ArrayList(); + parentBlocks.add(currentBlock); + } + if (!inClosure) { + firstNonClosure = true; + } + } + currentBlock.add(pRow); + } + } + int parentIndex = 0; + + if (!pRows.isEmpty()) for (List pRowBlockI : parentBlocks) { + List pRowBlock = pRowBlockI; + Map> newBlockRows = new HashMap>(); + boolean loaded = false; + + if (pRowBlock.size() == 1 && pRowBlock.get(0) == null) { + pRowBlock = null; + } + + if (session.dbms.getSqlLimitSuffix() != null) { + try { + session.setSilent(true); + reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, false, session.dbms.getSqlLimitSuffix(), existingColumnsLowerCase); + loaded = true; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another limit-strategy (" + e.getMessage() + ")"); + } finally { + session.setSilent(false); + } + } + if (!loaded) { + try { + session.setSilent(true); + reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, true, null, existingColumnsLowerCase); + loaded = true; + } catch (Throwable e) { // embedded DBMS may throw non-SQLException + Session._log.warn("failed, try another limit-strategy (" + e.getMessage() + ")"); + } finally { + session.setSilent(false); + } + if (!loaded) { + try { + session.setSilent(true); + reloadRows(inputResultSet, inlineViewStyle, andCond, pRowBlock, newBlockRows, loadJob, limit, false, null, existingColumnsLowerCase); + } finally { + session.setSilent(false); + } + } + } + if (pRowBlock == null) { + pRowBlock = new ArrayList(); + pRowBlock.add(null); + } + for (Row pRow: pRowBlock) { + loadJob.checkCancellation(); + boolean dupParent = false; + if (pRow != null) { + if (regPRows.contains(pRow.nonEmptyRowId)) { + dupParent = true; + } + regPRows.add(pRow.nonEmptyRowId); + } + List newRows = new ArrayList(); + String rId = pRow == null? "" : pRow.nonEmptyRowId; + if (newBlockRows.get(rId) != null) { + newRows.addAll(newBlockRows.get(rId)); + } + sortNewRows(newRows); + if (parentRows != null) { + if (!newRows.isEmpty()) { + Integer i = parentRowIndex.get(pRow); + for (Row r: newRows) { + r.setParentModelIndex(i != null? i : parentIndex); + } + } + ++parentIndex; + for (Row row : newRows) { + Row exRow = rowSet.get(row.nonEmptyRowId); + if (!dupParent) { + if (exRow != null) { + ++noNonDistinctRows; + } else { + ++noDistinctRows; + } + } + if (exRow != null && (selectDistinct || dupParent)) { + addRowToRowLink(pRow, exRow); + } else { + rows.add(row); + addRowToRowLink(pRow, row); + rowSet.put(row.nonEmptyRowId, row); + --limit; + } + } + } else { + rows.addAll(newRows); + limit -= newRows.size(); + } + if (limit <= 0) { + if (parentPane != null) { + if (rowsClosure.currentClosure.contains(new Pair(parentPane, pRow))) { + loadJob.closureLimitExceeded = true; + } + } + break; + } + } + if (limit <= 0) { + break; + } + } + } + + private void sortNewRows(List newRows) { + if (rowsTable != null && rowsTable.getRowSorter() != null) { + List sk = rowsTable.getRowSorter().getSortKeys(); + final int col; + final boolean asc; + if (!sk.isEmpty()) { + col = sk.get(0).getColumn(); + asc = sk.get(0).getSortOrder() == SortOrder.ASCENDING; + } else { + col = getDefaultSortColumn(); + asc = true; + } + if (col >= 0) { + Collections.sort(newRows, new Comparator() { + @Override + public int compare(Row a, Row b) { + Object va = null; + if (a != null && a.values != null && a.values.length > col) { + va = a.values[col]; + } + Object vb = null; + if (b != null && b.values != null && b.values.length > col) { + vb = b.values[col]; + } + if (va == null && vb == null) { + return 0; + } + if (va == null) { + return -1; + } + if (vb == null) { + return 1; + } + if (va.getClass().equals(vb.getClass())) { + if (va instanceof Comparable) { + int cmp = ((Comparable) va).compareTo(vb); + return asc? cmp : -cmp; + } + return 0; + } + int cmp = va.getClass().getName().compareTo(vb.getClass().getName()); + return asc? cmp : -cmp; + } + }); + } + } + } + + /** + * Reload rows from {@link #table}. + * + * @param rows + * to put the rows into + * @param context + * cancellation context + * @param rowCache + * @param allPRows + */ + private void reloadRows(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List parentRows, final Map> rows, LoadJob loadJob, int limit, boolean useOLAPLimitation, + String sqlLimitSuffix, Set existingColumnsLowerCase) throws SQLException { + reloadRows0(inputResultSet, inlineViewStyle, andCond, parentRows, rows, loadJob, parentRows == null? limit : Math.max(5000, limit), useOLAPLimitation, sqlLimitSuffix, existingColumnsLowerCase); + } + + /** + * Gets qualified table name. + * + * @param t the table + * @return qualified name of t + */ + private String qualifiedTableName(Table t, Quoting quoting) { + String schema = t.getSchema(""); + if (schema.length() == 0) { + return quoting.requote(t.getUnqualifiedName()); + } + return quoting.requote(schema) + "." + quoting.requote(t.getUnqualifiedName()); + } + + /** + * Reload rows from {@link #table}. + * + * @param rows + * to put the rows into + * @param loadJob + * cancellation context + */ + private void reloadRows0(ResultSet inputResultSet, InlineViewStyle inlineViewStyle, String andCond, final List parentRows, final Map> rows, LoadJob loadJob, int limit, boolean useOLAPLimitation, + String sqlLimitSuffix, Set existingColumnsLowerCase) throws SQLException { + String sql = "Select "; + final Quoting quoting = Quoting.getQuoting(session); + final Set pkColumnNames = new HashSet(); + final Set parentPkColumnNames = new HashSet(); + final boolean selectParentPK = association != null && parentRows != null && parentRows.size() > 1; + final Set unknownColumnIndexes = new HashSet(); + int numParentPKColumns = 0; + + if (table instanceof SqlStatementTable || statementForReloading != null) { + sql = andCond; + if (!(table instanceof SqlStatementTable)) { + for (Column pk: rowIdSupport.getPrimaryKey(table, session).getColumns()) { + pkColumnNames.add(quoting.requote(pk.name)); + } + } else { + table.setColumns(new ArrayList()); + } + } else { + String olapPrefix = "Select "; + String olapSuffix = ") S Where S." + ROWNUMBERALIAS + " <= " + limit; + boolean limitSuffixInSelectClause = sqlLimitSuffix != null && + (sqlLimitSuffix.toLowerCase(Locale.ENGLISH).startsWith("top ") || sqlLimitSuffix.toLowerCase(Locale.ENGLISH).startsWith("first ")); + if (sqlLimitSuffix != null && limitSuffixInSelectClause) { + sql += (sqlLimitSuffix.replace("%s", Integer.toString(limit))) + " "; + } + int colI = 1; + boolean f = true; + if (selectParentPK) { + int i = 0; + for (Column column: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { + String name = quoting.requote(column.name); + sql += (!f ? ", " : "") + "B." + name + " AS B" + i; + olapPrefix += (!f ? ", " : "") + "S.B" + i; + ++numParentPKColumns; + ++i; + ++colI; + f = false; + } + } + int i = 0; + + for (Column column : rowIdSupport.getColumns(table, session)) { + String name = quoting.requote(column.name); + if (existingColumnsLowerCase != null && !rowIdSupport.isRowIdColumn(column) && !existingColumnsLowerCase.contains(quoting.unquote(name).toLowerCase(Locale.ENGLISH))) { + sql += (!f ? ", " : "") + "'?' AS A" + i; + unknownColumnIndexes.add(colI); + } else { + sql += (!f ? ", " : "") + "A." + name + " AS A" + i; + } + olapPrefix += (!f ? ", " : "") + "S.A" + i; + ++i; + ++colI; + f = false; + } + f = true; + if (selectParentPK) { + int j = 0; + for (Column pk: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { + parentPkColumnNames.add(quoting.requote(pk.name)); + ++j; + f = false; + } + } + int j = 0; + for (Column pk: rowIdSupport.getPrimaryKey(table, session).getColumns()) { + pkColumnNames.add(quoting.requote(pk.name)); + ++j; + f = false; + } + if (useOLAPLimitation) { + sql += ", row_number() over("; + if (useOLAPLimitation) { + sql += "order by -1"; // + orderBy; + } + sql += ") as " + ROWNUMBERALIAS + ""; + } + sql += " From "; + if (association != null) { + sql += qualifiedTableName(association.source, quoting) + " B join "; + } + sql += qualifiedTableName(table, quoting) + " A"; + if (association != null) { + if (association.reversed) { + sql += " on " + association.getUnrestrictedJoinCondition(); + } else { + sql += " on " + SqlUtil.reversRestrictionCondition(association.getUnrestrictedJoinCondition()); + } + } + + boolean whereExists = false; + if (parentRows != null && !parentRows.isEmpty()) { + if (association != null && parentRows.get(0).rowId.length() == 0) { + throw new SqlException("Missing primary key for table: \"" + Quoting.staticUnquote(association.source.getName()) + "\"\n" + + "Resolution: define the primary key manually using the data model editor.", "", null); + } + if (parentRows.size() == 1) { + sql += " Where (" + parentRows.get(0).rowId + ")"; + } else { + StringBuilder sb = new StringBuilder(); + if (inlineViewStyle != null && association != null) { + sb.append(" join "); + List columnNames = new ArrayList(); + for (Column pkColumn: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { + columnNames.add(pkColumn.name); + } + String[] columnNamesAsArray = columnNames.toArray(new String[columnNames.size()]); + sb.append(inlineViewStyle.head(columnNamesAsArray)); + int rowNumber = 0; + for (Row parentRow: parentRows) { + if (rowNumber > 0) { + sb.append(inlineViewStyle.separator()); + } + sb.append(inlineViewStyle.item(parentRow.primaryKey, columnNamesAsArray, rowNumber)); + ++rowNumber; + } + sb.append(inlineViewStyle.terminator("C", columnNamesAsArray)); + sb.append(" on ("); + boolean f2 = true; + for (String pkColumnName: columnNames) { + if (!f2) { + sb.append(" and "); + } + sb.append("B." + pkColumnName + " = " + "C." + pkColumnName); + f2 = false; + } + sb.append(")"); + } else { + for (Row parentRow: parentRows) { + if (sb.length() == 0) { + sb.append(" Where (("); + } else { + sb.append(" or ("); + } + sb.append(parentRow.rowId).append(")"); + } + sb.append(")"); + } + sql += sb.toString(); + } + whereExists = true; + } + if (andCond.trim().length() > 0) { + sql += (whereExists ? " and" : " Where") + " (" + (andCond) + ")"; + } + olapPrefix += " From ("; + if (useOLAPLimitation) { + sql = olapPrefix + sql + olapSuffix; + } + if (sqlLimitSuffix != null && !limitSuffixInSelectClause) { + sql += " " + (sqlLimitSuffix.replace("%s", Integer.toString(limit))); + } + } + + if (sql.length() > 0 || inputResultSet != null) { + final Map pkPosToColumnPos = new HashMap(); + if (!(table instanceof SqlStatementTable) && statementForReloading == null) { + List pks = rowIdSupport.getPrimaryKey(table, session).getColumns(); + List columns = rowIdSupport.getColumns(table, session); + for (int i = 0; i < columns.size(); ++i) { + Column column = columns.get(i); + for (int j = 0; j < pks.size(); ++j) { + if (column.name.equals(pks.get(j).name)) { + pkPosToColumnPos.put(j, i); + break; + } + } + } + } + final int finalNumParentPKColumns = numParentPKColumns; + AbstractResultSetReader reader = new AbstractResultSetReader() { + Map typeCache = new HashMap(); + int rowNr = 0; + + @Override + public void init(ResultSet resultSet) throws SQLException { + ResultSetMetaData metaData = getMetaData(resultSet); + int columnCount = metaData.getColumnCount(); + if (table instanceof SqlStatementTable) { + for (int ci = 1; ci <= columnCount; ++ci) { + table.getColumns().add(new Column(metaData.getColumnLabel(ci), metaData.getColumnTypeName(ci), -1, -1)); + } + } + int[] columnTypes = new int[columnCount]; + String[] columnTypeNames = new String[columnCount]; + for (int ci = 1 + finalNumParentPKColumns; ci <= columnCount; ++ci) { + if (metaData instanceof MemorizedResultSetMetaData) { + columnTypes[ci - 1 - finalNumParentPKColumns] = ((MemorizedResultSetMetaData) metaData).types[ci - 1]; + columnTypeNames[ci - 1 - finalNumParentPKColumns] = ((MemorizedResultSetMetaData) metaData).typeNames[ci - 1]; + } else { + columnTypes[ci - 1 - finalNumParentPKColumns] = metaData.getColumnType(ci); + columnTypeNames[ci - 1 - finalNumParentPKColumns] = metaData.getColumnTypeName(ci); + } + } + browserContentCellEditor = new BrowserContentCellEditor(columnTypes, columnTypeNames, session); + } + + @Override + public void readCurrentRow(ResultSet resultSet) throws SQLException { + int i = 1, vi = 0; + String parentRowId = ""; + if (selectParentPK) { + Object v[] = new Object[rowIdSupport.getPrimaryKey(association.source, session).getColumns().size()]; + for (Column column: rowIdSupport.getPrimaryKey(association.source, session).getColumns()) { + parentRowId = readRowFromResultSet(parentPkColumnNames, resultSet, i, vi, parentRowId, v, column, null, null, unknownColumnIndexes); + ++i; + ++vi; + } + } else { + if (parentRows != null && parentRows.size() == 1) { + parentRowId = parentRows.get(0).rowId; + } + } + + Map pkColumn = new HashMap(); + Map pkColumnValue = new HashMap(); + + Object v[] = new Object[rowIdSupport.getColumns(table, session).size()]; + vi = 0; + for (Column column: rowIdSupport.getColumns(table, session)) { + readRowFromResultSet(pkColumnNames, resultSet, i, vi, "", v, column, pkColumn, pkColumnValue, unknownColumnIndexes); + ++i; + ++vi; + } + + String rowId = ""; + String[] primaryKey = null; + PrimaryKey primaryKeys = rowIdSupport.getPrimaryKey(table, session); + if (primaryKeys != null && resultSetType == null) { + int pkPos = 0; + primaryKey = new String[primaryKeys.getColumns().size()]; + for (Column column : primaryKeys.getColumns()) { + if (rowId.length() > 0) { + rowId += " and "; + } + rowId += pkColumn.get(column.name); + Integer colPos = pkPosToColumnPos.get(pkPos); + if (colPos != null) { + primaryKey[pkPos] = pkColumnValue.get(column.name); + } + ++pkPos; + } + } else { + rowId = Integer.toString(++rowNr); + } + + List cRows = rows.get(parentRowId); + if (cRows == null) { + cRows = new ArrayList(); + rows.put(parentRowId, cRows); + } + cRows.add(new Row(rowId, primaryKey, v)); + } + + private String readRowFromResultSet(final Set pkColumnNames, ResultSet resultSet, int i, int vi, String rowId, Object[] v, Column column, Map pkColumn, Map pkColumnValue, Set unknownColumnIndexes) + throws SQLException { + Object value = ""; + if (unknownColumnIndexes.contains(i)) { + value = new UnknownValue() { + @Override + public String toString() { + return "?"; + } + }; + } else { + int type = SqlUtil.getColumnType(resultSet, getMetaData(resultSet), i, typeCache); + Object lob = null; + if (type == 0) { + lob = resultSet.getObject(i); + } + if (type == Types.BLOB || type == Types.CLOB || type == Types.NCLOB || type == Types.SQLXML + || (type == 0 && + (lob instanceof Blob || lob instanceof Clob || lob instanceof SQLXML) + )) { + Object object = resultSet.getObject(i); + if (object == null || resultSet.wasNull()) { + value = null; + } else { + Object lobValue = toLobRender(object); + if (lobValue != null) { + value = lobValue; + } + } + } else { + CellContentConverter cellContentConverter = getCellContentConverter(resultSet, session, session.dbms); + Object o; + try { + o = cellContentConverter.getObject(resultSet, i); + if (o instanceof byte[]) { + final long length = ((byte[]) o).length; + StringBuilder sb = new StringBuilder(); + int j; + for (j = 0; j < length && j < 16; ++j) { + byte b = ((byte[]) o)[j]; + sb.append(" "); + sb.append(CellContentConverter.hexChar[(b >> 4) & 15]); + sb.append(CellContentConverter.hexChar[b & 15]); + } + if (j < length) { + sb.append("... " + length + " bytes"); + } + final String content = sb.toString(); + final byte[] finalO = (byte[]) o; + o = new BinValue() { + @Override + public String toString() { + return "" + content; + } + + @Override + public byte[] getContent() { + return finalO; + } + }; + } + } catch (Throwable e) { + o = "ERROR: " + e.getClass().getName() + ": " + e.getMessage(); + } + boolean isPK = false; + if (pkColumnNames.isEmpty()) { + isPK = type != Types.BLOB && type != Types.CLOB && type != Types.DATALINK && type != Types.JAVA_OBJECT && type != Types.NCLOB + && type != Types.NULL && type != Types.OTHER && type != Types.REF && type != Types.SQLXML && type != Types.STRUCT; + } + if (pkColumnNames.contains(quoting.requote(column.name)) || isPK) { + String cVal = cellContentConverter.toSql(o instanceof BinValue? ((BinValue) o).getContent() : o); + String pkValue = "B." + quoting.requote(column.name) + ("null".equalsIgnoreCase(cVal)? " is null" : ("=" + cVal)); + if (pkColumn != null) { + pkColumn.put(column.name, pkValue); + } + if (pkColumnValue != null) { + pkColumnValue.put(column.name, cVal); + } + rowId += (rowId.length() == 0 ? "" : " and ") + pkValue; + } + if (o == null || resultSet.wasNull()) { + value = null; + } + if (o != null) { + value = o; + } + } + } + v[vi] = value; + return rowId; + } + }; + if (inputResultSet != null) { + reader.init(inputResultSet); + while (inputResultSet.next()) { + reader.readCurrentRow(inputResultSet); + } + inputResultSet.close(); + } + else { + session.executeQuery(sql, reader, null, loadJob, limit); + } + } + } + + /** + * True if row-limit is exceeded. + */ + private boolean isLimitExceeded = false; + private boolean isClosureLimitExceeded = false; + + /** + * Show single row in special view? + */ + protected boolean noSingleRowDetailsView = false; + protected String singleRowDetailsViewTitel = "Single Row Details"; + + /** + * Parent having row-limit exceeded. + */ + private RowBrowser parentWithExceededLimit() { + RowBrowser parent = getParentBrowser(); + + while (parent != null) { + if (parent.browserContentPane.isLimitExceeded) { + return parent; + } + parent = parent.browserContentPane.getParentBrowser(); + } + + return null; + } + + public static class TableModelItem { + public final int blockNr; + public final double inheritedBlockNumber; + public final Object value; + private String valueAsString = null; + + public TableModelItem(int blockNr, double inheritedBlockNumber, Object value) { + this.blockNr = blockNr; + this.inheritedBlockNumber = inheritedBlockNumber; + this.value = value; + } + + @Override + public String toString() { + if (valueAsString == null) { + if (value instanceof Double) { + valueAsString = SqlUtil.toString((Double) value); + } else if (value instanceof BigDecimal) { + valueAsString = SqlUtil.toString((BigDecimal) value); + } else { + valueAsString = String.valueOf(value); + } + } + return valueAsString; + } + } + + private int lastLimit; + private boolean lastLimitExceeded; + private boolean lastClosureLimitExceeded; + private boolean isUpdatingTableModel; + private Set foundColumn = new HashSet(); + + /** + * Updates the model of the {@link #rowsTable}. + * + * @param limit + * row limit + * @param limitExceeded + */ + private void updateTableModel() { + updateTableModel(lastLimit, lastLimitExceeded, lastClosureLimitExceeded); + } + + /** + * Updates the model of the {@link #rowsTable}. + * + * @param limit + * row limit + * @param limitExceeded + */ + private void updateTableModel(int limit, boolean limitExceeded, boolean closureLimitExceeded) { + try { + isUpdatingTableModel = true; + doUpdateTableModel(limit, limitExceeded, closureLimitExceeded); + } finally { + isUpdatingTableModel = false; + } + } + + private boolean dontPaintSortIcon = false; + + private void doUpdateTableModel(int limit, boolean limitExceeded, boolean closureLimitExceeded) { + lastLimit = limit; + lastLimitExceeded = limitExceeded; + lastClosureLimitExceeded = closureLimitExceeded; + pkColumns.clear(); + List columns = rowIdSupport.getColumns(table, session); + String[] columnNames = new String[columns.size()]; + final Set pkColumnNames = new HashSet(); + if (rowIdSupport.getPrimaryKey(table, session) != null) { + for (Column pk : rowIdSupport.getPrimaryKey(table, session).getColumns()) { + pkColumnNames.add(pk.name); + } + } + for (int i = 0; i < columnNames.length; ++i) { + columnNames[i] = columns.get(i).name; + if ("".equals(columnNames[i])) { + columnNames[i] = " "; + } + if (pkColumnNames.contains(columnNames[i])) { + pkColumns.add(i); + } + if (columnNames[i] == null) { + if (alternativeColumnLabels != null && i < alternativeColumnLabels.length) { + columnNames[i] = alternativeColumnLabels[i]; + } + } + } + + fkColumns.clear(); + final Set fkColumnNames = new HashSet(); + for (Association a: table.associations) { + if (a.isInsertDestinationBeforeSource()) { + Map m = a.createSourceToDestinationKeyMapping(); + for (Column fkColumn: m.keySet()) { + fkColumnNames.add(fkColumn.name); + } + } + } + if (rowIdSupport.getPrimaryKey(table, session) != null) { + for (Column pk : rowIdSupport.getPrimaryKey(table, session).getColumns()) { + pkColumnNames.add(pk.name); + } + } + for (int i = 0; i < columnNames.length; ++i) { + if (fkColumnNames.contains(columnNames[i])) { + fkColumns.add(i); + } + } + + DefaultTableModel dtm; + findColumnsLabel.setEnabled(true); + singleRowDetailsView = null; + singleRowViewScrollPaneContainer.setVisible(false); + rowsTableContainerPanel.setVisible(true); + boolean noFilter = true; + int rn = 0; + if (rows.size() != 1 || isEditMode || noSingleRowDetailsView) { + noFilter = false; + Map columnNameMap = new HashMap(); + for (int i = 0; i < columns.size(); ++i) { + columnNameMap.put(columnNames[i], i); + } + String[] uqColumnNames = new String[columnNames.length]; + for (int i = 0; i < uqColumnNames.length; ++i) { + if (columnNames[i] != null) { + uqColumnNames[i] = Quoting.staticUnquote(columnNames[i]); + } + } + dtm = new DefaultTableModel(uqColumnNames, 0) { + @Override + public boolean isCellEditable(int row, int column) { + Row r = null; + if (row < rows.size()) { + r = rows.get(row); + } + Table type = getResultSetTypeForColumn(column); + if (isEditMode && r != null && (r.rowId != null && !r.rowId.isEmpty()) && browserContentCellEditor.isEditable(type, row, column, r.values[column]) && isPKComplete(type, r)) { + return !rowIdSupport.getPrimaryKey(type, session).getColumns().isEmpty(); + } + return false; + } + + @Override + public void setValueAt(Object aValue, int row, int column) { + String text = aValue.toString(); + Row theRow = null; + if (row < rows.size()) { + theRow = rows.get(row); + Object content = browserContentCellEditor.textToContent(row, column, text, theRow.values[column]); + if (content != BrowserContentCellEditor.INVALID) { + if (!browserContentCellEditor.cellContentToText(row, column, theRow.values[column]).equals(text)) { + Table type = getResultSetTypeForColumn(column); + if (resultSetType != null) { + theRow = createRowWithNewID(theRow, type); + } + Object oldContent = theRow.values[column]; + theRow.values[column] = content; + final String updateStatement = SQLDMLBuilder.buildUpdate(type, theRow, false, column, session); + theRow.values[column] = oldContent; + updateMode("updating", null); + + getRunnableQueue().add(new RunnableWithPriority() { + private Exception exception; + + @Override + public void run() { + final Object context = new Object(); + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CancellationHandler.cancel(context); + } + }; + cancelLoadButton.addActionListener(listener); + try { + session.execute(updateStatement, context, false); + } catch (Exception e) { + exception = e; + } finally { + CancellationHandler.reset(context); + cancelLoadButton.removeActionListener(listener); + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + if (exception != null && !(exception instanceof CancellationException)) { + UIUtil.showException(BrowserContentPane.this, "Error", exception); + updateMode("table", null); + } else { + reloadRows(); + } + } + }); + } + + @Override + public int getPriority() { + return 50; + } + }); + } + } + } + } + }; + + boolean stripHour[] = new boolean[columns.size()]; + final String HOUR = " 00:00:00.0"; + for (int i = 0; i < columns.size(); ++i) { + stripHour[i] = true; + for (Row row : rows) { + Object value = row.values[i]; + if (value == null) { + continue; + } + if (!(value instanceof java.sql.Date) && !(value instanceof java.sql.Timestamp)) { + stripHour[i] = false; + break; + } + String asString = value.toString(); + if (asString.endsWith(HOUR)) { + continue; + } + stripHour[i] = false; + break; + } + } + + for (Row row : rows) { + Object[] rowData = new Object[columns.size()]; + for (int i = 0; i < columns.size(); ++i) { + rowData[i] = row.values[i]; + if (rowData[i] instanceof PObjectWrapper) { + rowData[i] = ((PObjectWrapper) rowData[i]).getValue(); + } + if (rowData[i] == null) { + rowData[i] = UIUtil.NULL; + } else if (rowData[i] instanceof UnknownValue) { + rowData[i] = UNKNOWN; + } + if (stripHour[i] && (rowData[i] instanceof java.sql.Date || rowData[i] instanceof java.sql.Timestamp)) { + String asString = rowData[i].toString(); + rowData[i] = asString.substring(0, asString.length() - HOUR.length()); + } + } + if (tableContentViewFilter != null) { + tableContentViewFilter.filter(rowData, columnNameMap); + } + for (int i = 0; i < columns.size(); ++i) { + TableModelItem item = new TableModelItem(row.getParentModelIndex(), row.getInheritedParentModelIndex(), rowData[i]); + rowData[i] = item; + } + dtm.addRow(rowData); + if (++rn >= limit) { + break; + } + } + + //set the editor as default on every column + JTextField textField = new JTextField(); + textField.setBorder(new LineBorder(Color.black)); + DefaultCellEditor anEditor = new DefaultCellEditor(textField) { + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (table != rowsTable) { + column = table.convertColumnIndexToModel(column); + if (column == 0) { + return null; + } + int h = row; + row = column - 1; + column = h; + } + if (row < rows.size()) { + Row r = rows.get(rowsTable.getRowSorter().convertRowIndexToModel(row)); + int convertedColumnIndex = rowsTable.convertColumnIndexToModel(column); + if (r != null) { + value = browserContentCellEditor.cellContentToText(row, convertedColumnIndex, r.values[convertedColumnIndex]); + } + } + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + }; + anEditor.setClickCountToStart(1); + for (int i = 0; i < rowsTable.getColumnCount(); i++) { + rowsTable.setDefaultEditor(rowsTable.getColumnClass(i), anEditor); + } + + List sortKeys = new ArrayList(rowsTable.getRowSorter().getSortKeys()); + List filterContent = new ArrayList(); + if (filterHeader != null) { + try { + for (int i = 0; i < rowsTable.getColumnCount(); ++i) { + filterContent.add(filterHeader.getFilterEditor(i).getContent()); + } + } catch (Exception e) { + // ignore + } + } + + rowsTable.setModel(dtm); + rowsTable.getSelectionModel().clearSelection(); + rowsTable.setRowHeight(initialRowHeight); + + noRowsFoundPanel.setVisible(dtm.getRowCount() == 0 && getAndConditionText().length() > 0); + + final int defaultSortColumn = getDefaultSortColumn(); + + TableRowSorter sorter = new TableRowSorter(dtm) { + @Override + protected boolean useToString(int column) { + return false; + } + + @Override + public List getSortKeys() { + if (dontPaintSortIcon) { + return new ArrayList(); + } + return super.getSortKeys(); + } + + @Override + public void toggleSortOrder(int column) { + if (association != null && association.isInsertDestinationBeforeSource()) { + if (!useInheritedBlockNumbers) { + return; + } + } + ignoreSortKey = false; + boolean toggled = false; + List sortKeys = getSortKeys(); + if (sortKeys.size() > 0) { + if (sortKeys.get(0).getColumn() == column && sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING) { + List sk = new ArrayList(); + if (defaultSortColumn >= 0) { + sk.add(new SortKey(defaultSortColumn, SortOrder.ASCENDING)); + } + setSortKeys(sk); + toggled = true; + } + } + if (!toggled) { + super.toggleSortOrder(column); + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + sortChildren(); + } + }); + } + + @Override + public Comparator getComparator(int n) { + List sortKeys = super.getSortKeys(); + final boolean desc = sortKeys.size() > 0 && sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING; + + return new Comparator() { + @SuppressWarnings("unchecked") + @Override + public int compare(Object o1, Object o2) { + RowSorter pSorter = null; + RowSorter ppSorter = null; + RowBrowser pb = getParentBrowser(); + if (pb != null) { + if (pb.browserContentPane != null) { + if (pb.browserContentPane.rowsTable != null) { + pSorter = pb.browserContentPane.rowsTable.getRowSorter(); + if (pb.browserContentPane.getParentBrowser() != null) { + if (pb.browserContentPane.getParentBrowser().browserContentPane != null) { + if (pb.browserContentPane.getParentBrowser().browserContentPane.rowsTable != null) { + ppSorter = pb.browserContentPane.getParentBrowser().browserContentPane.rowsTable.getRowSorter(); + } + } + } + } + } + } + if (o1 instanceof TableModelItem && o2 instanceof TableModelItem) { + if (useInheritedBlockNumbers && !ignoreSortKey) { + double b1 = ((TableModelItem) o1).inheritedBlockNumber; + double b2 = ((TableModelItem) o2).inheritedBlockNumber; + + if (ppSorter != null) { + double b; + b = b1 < ppSorter.getModelRowCount()? ppSorter.convertRowIndexToView((int) b1) : -1; + if (b < 0) { + b = b1 + Integer.MAX_VALUE / 2; + } + b1 = b; + b = b2 < ppSorter.getModelRowCount()? ppSorter.convertRowIndexToView((int) b2) : -1; + if (b < 0) { + b = b2 + Integer.MAX_VALUE / 2; + } + b2 = b; + } + if (b1 != b2) { + return (int) ((b1 - b2) * (desc? -1 : 1)); + } + } else { + int b1 = ((TableModelItem) o1).blockNr; + int b2 = ((TableModelItem) o2).blockNr; + + if (pSorter != null) { + int b; + b = b1 < pSorter.getModelRowCount()? pSorter.convertRowIndexToView(b1) : -1; + if (b < 0) { + b = b1 + Integer.MAX_VALUE / 2; + } + b1 = b; + b = b2 < pSorter.getModelRowCount()? pSorter.convertRowIndexToView(b2) : -1; + if (b < 0) { + b = b2 + Integer.MAX_VALUE / 2; + } + b2 = b; + } + if (b1 != b2) { + return (b1 - b2) * (desc? -1 : 1); + } + } + } + + if (ignoreSortKey) { + return 0; + } + + if (o1 instanceof TableModelItem) { + o1 = ((TableModelItem) o1).value; + } + if (o2 instanceof TableModelItem) { + o2 = ((TableModelItem) o2).value; + } + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + if (o1.getClass().equals(o2.getClass())) { + if (o1 instanceof Comparable) { + return ((Comparable) o1).compareTo(o2); + } + return 0; + } + return o1.getClass().getName().compareTo(o2.getClass().getName()); + } + }; + } + }; + sorter.addRowSorterListener(new RowSorterListener() { + @Override + public void sorterChanged(RowSorterEvent e) { + if (e.getType() == RowSorterEvent.Type.SORTED) { + List chBrs = getChildBrowsers(); + if (chBrs != null) { + for (RowBrowser chBr: chBrs) { + if (chBr.browserContentPane != null) { + if (chBr.browserContentPane.rowsTable != null) { + final RowSorter chSorter = chBr.browserContentPane.rowsTable.getRowSorter(); + if (chSorter instanceof TableRowSorter) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + ((TableRowSorter) chSorter).sort(); + } + }); + } + } + } + } + } + } + } + }); + rowsTable.setRowSorter(sorter); + try { + if (!sortKeys.isEmpty()) { + rowsTable.getRowSorter().setSortKeys(sortKeys); + } else { + List sk = new ArrayList(); + if (defaultSortColumn >= 0) { + sk.add(new SortKey(defaultSortColumn, SortOrder.ASCENDING)); + } + rowsTable.getRowSorter().setSortKeys(sk); + } + if (filterHeader != null) { + for (int i = 0; i < rowsTable.getColumnCount(); ++i) { + filterHeader.getFilterEditor(i).setContent(filterContent.get(i)); + } + } + } catch (Exception e) { + // ignore + } + } else { + final boolean deselect = !getAndConditionText().equals("") + && rows.size() == 1; + singleRowDetailsView = new DetailsView(Collections.singletonList(rows.get(0)), 1, dataModel, BrowserContentPane.this.table, 0, null, false, false, rowIdSupport, deselect, session) { + @Override + protected void onRowChanged(int row) { + } + @Override + protected void onClose() { + } + @Override + protected void onSelectRow(Row row) { + } + }; + singleRowDetailsView.setSortColumns(sortColumnsCheckBox.isSelected()); + dtm = new DefaultTableModel(new String[] { singleRowDetailsViewTitel }, 0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + findColumnsLabel.setEnabled(false); + + for (Row row : rows) { + dtm.addRow(new Object[] { row }); + if (++rn >= limit) { + break; + } + } + rowsTable.setModel(dtm); + + JPanel detailsPanel = new JPanel(new java.awt.BorderLayout(0, 0)) { + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + if (!(graphics instanceof Graphics2D)) { + return; + } + if (rows.size() == 1 && BrowserContentPane.this.rowsClosure.tempClosure.size() > 1 && BrowserContentPane.this.rowsClosure.tempClosure.contains(rows.get(0))) { + Rectangle visRect = singleRowViewContainterPanel.getVisibleRect(); + + Graphics2D g2d = (Graphics2D) graphics; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(1)); + + int width = (int) (visRect.width * 1.4); + + g2d.setColor(new Color(255, 0, 0, 20)); + int[] x = new int[2]; + int[] y = new int[2]; + x[0] = (int) visRect.getMinX(); + y[0] = (int) visRect.getMinY(); + x[1] = (int) visRect.getMinX() + width; + y[1] = (int) visRect.getMaxY(); + GradientPaint paint = new GradientPaint( + x[0], y[0], new Color(255, 0, 0, 20), + x[0] + width, y[1], new Color(255, 0, 0, 0)); + g2d.setPaint(paint); + g2d.fillRect(x[0], y[0], x[1] - x[0], y[1] - y[0]); + g2d.setPaint(null); + } + } + }; + detailsPanel.add(singleRowDetailsView.getDetailsPanel(), java.awt.BorderLayout.CENTER); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + singleRowViewContainterPanel.removeAll(); + singleRowViewContainterPanel.add(detailsPanel, gridBagConstraints); + + singleRowViewScrollPaneContainer.setVisible(true); + rowsTableContainerPanel.setVisible(false); + deselectButton.setVisible(deselect); + } + + adjustRowTableColumnsWidth(); + + if (sortColumnsCheckBox.isSelected()) { + TableColumnModel cm = rowsTable.getColumnModel(); + for (int a = 0; a < rowsTable.getColumnCount(); ++a) { + for (int b = a + 1; b < rowsTable.getColumnCount(); ++b) { + if (cm.getColumn(a).getHeaderValue().toString().compareToIgnoreCase(cm.getColumn(b).getHeaderValue().toString()) > 0) { + cm.moveColumn(b, a); + } + } + } + } + + rowsTable.setIntercellSpacing(new Dimension(0, 0)); + Set browserInClosure = new HashSet(); + for (Pair rid: rowsClosure.currentClosure) { + browserInClosure.add(rid.a); + } + updateRowsCountLabel(browserInClosure); + + final TableCellRenderer origRenderer = rowsTable.getTableHeader().getDefaultRenderer(); + rowsTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() { + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + try { + dontPaintSortIcon = ignoreSortKey; + return origRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } finally { + dontPaintSortIcon = false; + } + } + }); + + int nndr = noNonDistinctRows; + if (noDistinctRows + noNonDistinctRows >= limit) { + --nndr; + } + selectDistinctCheckBox.setVisible(nndr > 0); + selectDistinctCheckBox.setText("select distinct (-" + nndr + ")"); + if (getParentBrowser() != null) { + BrowserContentPane pBrowser = getParentBrowser().browserContentPane; + if (pBrowser.selectDistinctCheckBox.isVisible() && !pBrowser.selectDistinctCheckBox.isSelected()) { + if (selectDistinctCheckBox.isSelected()) { + selectDistinctCheckBox.setVisible(false); + } + } + } + + if (filterHeader != null) { + if (rowsTable.getRowSorter() != null && rowsTable.getRowSorter().getViewRowCount() == 0) { + filterHeader.setTable(null); + filterHeader = null; + adjustRowTableColumnsWidth(); + } + } + + if (isTableFilterEnabled && !noFilter) { + if (filterHeader == null) { + filterHeader = new TableFilterHeader(); + filterHeader.setRowHeightDelta(2); + filterHeader.setAutoChoices(AutoChoices.ENABLED); + filterHeader.setTable(rowsTable); + filterHeader.setMaxVisibleRows(20); + try { + for (int i = 0; i < rowsTable.getColumnCount(); ++i) { + filterHeader.getFilterEditor(i).setChoicesComparator(new Comparator() { + @SuppressWarnings("unchecked") + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof TableModelItem) { + o1 = ((TableModelItem) o1).value; + } + if (o2 instanceof TableModelItem) { + o2 = ((TableModelItem) o2).value; + } + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + if (o1.getClass().equals(o2.getClass())) { + if (o1 instanceof Comparable) { + return ((Comparable) o1).compareTo(o2); + } + return 0; + } + return o1.getClass().getName().compareTo(o2.getClass().getName()); + } + }); + } + } + catch (Exception e) { + // ignore + } + } + } else { + if (filterHeader != null) { + filterHeader.setTable(null); + filterHeader = null; + } + } + + isLimitExceeded = limitExceeded; + isClosureLimitExceeded = closureLimitExceeded; + appendClosure(); + } + + public void updateRowsCountLabel(Set browserInClosure) { + int limit = lastLimit; + boolean limitExceeded = lastLimitExceeded; + boolean closureLimitExceeded = lastClosureLimitExceeded; + + int size = rows.size(); + if (size > limit) { + size = limit; + } + rowsCount.setText((limitExceeded ? " more than " : " ") + size + " row" + (size != 1 ? "s" : "")); + RowBrowser theParentWithExceededLimit = parentWithExceededLimit(); + boolean cle = closureLimitExceeded; + boolean cleRelevant = true; +// if (theParentWithExceededLimit != null && theParentWithExceededLimit.browserContentPane.isClosureLimitExceeded) { +// cle = true; +// } + if (rowsClosure.parentPath.contains(this) || rowsClosure.currentClosureRowIDs.isEmpty()) { + cleRelevant = false; + } else if (getParentBrowser() != null) { + BrowserContentPane parent = getParentBrowser().browserContentPane; + if (!browserInClosure.contains(parent)) { + cleRelevant = false; + } + } + boolean bold = false; + if (limitExceeded || theParentWithExceededLimit != null) { + if (cle || !cleRelevant) { + rowsCount.setForeground(Color.RED); + bold = true; + } else { + rowsCount.setForeground(new Color(140, 0, 0)); + } + } else { + rowsCount.setForeground(new JLabel().getForeground()); + } + if (bold) { + rowsCount.setFont(rowsCount.getFont().deriveFont(rowsCount.getFont().getStyle() | Font.BOLD)); + } else { + rowsCount.setFont(rowsCount.getFont().deriveFont(rowsCount.getFont().getStyle() & ~Font.BOLD)); + } + + if (cle && cleRelevant) { + rowsCount.setToolTipText("row selection incomplete"); + } else if (!limitExceeded && theParentWithExceededLimit != null) { + rowsCount.setToolTipText("potentially incomplete because " + theParentWithExceededLimit.internalFrame.getTitle() + " exceeded row limit"); + } else { + rowsCount.setToolTipText(null); + } + } + + private int getDefaultSortColumn() { + if (table == null || table instanceof SqlStatementTable || getQueryBuilderDialog() == null /* SQL Console */) { + return -1; + } + if (association != null && association.isInsertDestinationBeforeSource()) { + return -1; + } + if (table.primaryKey.getColumns() != null && table.primaryKey.getColumns().size() > 0) { + Column pk = table.primaryKey.getColumns().get(0); + for (int i = 0; i < table.getColumns().size(); ++i) { + if (table.getColumns().get(i).equals(pk)) { + return i; + } + } + } + return 0; + } + + private TableFilterHeader filterHeader; + + protected Row createRowWithNewID(Row theRow, Table type) { + CellContentConverter cellContentConverter = new CellContentConverter(null, session, session.dbms); + String rowId = ""; + PrimaryKey primaryKeys = type.primaryKey; + for (Column pkColumn : primaryKeys.getColumns()) { + List cols = type.getColumns(); + int colSize = cols.size(); + for (int i = 0; i < colSize; ++i) { + Column column = cols.get(i); + if (column != null && pkColumn.name.equals(column.name)) { + if (rowId.length() > 0) { + rowId += " and "; + } + rowId += pkColumn.name + "=" + cellContentConverter.toSql(theRow.values[i]); + break; + } + } + } + return new Row(rowId, theRow.primaryKey, theRow.values); + } + + public void adjustRowTableColumnsWidth() { + DefaultTableModel dtm = (DefaultTableModel) rowsTable.getModel(); + int MAXLINES = 400; + if (rowsTable.getColumnCount() > 0) { + MAXLINES = Math.max(10 * MAXLINES / rowsTable.getColumnCount(), 10); + } + DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer(); + int minTotalWidth = (int) (Desktop.BROWSERTABLE_DEFAULT_WIDTH * getLayoutFactor()) - 18; + int totalWidth = 0; + final int maxColumnWidth = 300; + + for (int i = 0; i < rowsTable.getColumnCount(); i++) { + TableColumn column = rowsTable.getColumnModel().getColumn(i); + int width = minTotalWidth / rowsTable.getColumnCount(); + + Component comp = defaultTableCellRenderer.getTableCellRendererComponent(rowsTable, column.getHeaderValue(), false, false, 0, i); + int pw = comp.getPreferredSize().width; + if (pw < 100) { + pw = (pw * 110) / 100 + 2; + } + width = Math.min(Math.max(width, pw), 150); + + int line = 0; + for (; line < rowsTable.getRowCount(); ++line) { + comp = rowsTable.getCellRenderer(line, i).getTableCellRendererComponent(rowsTable, dtm.getValueAt(line, i), false, false, line, i); + width = Math.max(width, comp.getPreferredSize().width + 24); + if (line > MAXLINES) { + break; + } + } + Object maxValue = null; + int maxValueLength = 0; + for (; line < rowsTable.getRowCount(); ++line) { + Object value = dtm.getValueAt(line, i); + if (value != null) { + int valueLength = value.toString().length(); + if (maxValue == null || maxValueLength < valueLength) { + maxValue = value; + maxValueLength = valueLength; + } + } + if (line > 4 * MAXLINES) { + break; + } + } + if (maxValue != null) { + comp = rowsTable.getCellRenderer(line, i).getTableCellRendererComponent(rowsTable, maxValue, false, false, line, i); + int maxValueWidth = comp.getPreferredSize().width + 16; + if (maxValueWidth > width) { + width = maxValueWidth; + } + } + + column.setPreferredWidth(width); + totalWidth += width; + if (i == rowsTable.getColumnCount() - 1) { + if (totalWidth < minTotalWidth) { + width = width + minTotalWidth - totalWidth; + } + } + column.setPreferredWidth(Math.min(maxColumnWidth, width)); + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + andCondition = new javax.swing.JComboBox(); + openEditorLabel = new javax.swing.JLabel(); + pendingNonpendingPanel = new javax.swing.JPanel(); + cardPanel = new javax.swing.JPanel(); + tablePanel = new javax.swing.JPanel(); + jLayeredPane1 = new javax.swing.JLayeredPane(); + statusPanel = new javax.swing.JPanel(); + sortColumnsCheckBox = new javax.swing.JCheckBox(); + rowsCount = new javax.swing.JLabel(); + selectDistinctCheckBox = new javax.swing.JCheckBox(); + sortColumnsPanel = new javax.swing.JPanel(); + sortColumnsLabel = new javax.swing.JLabel(); + findColumnsPanel = new javax.swing.JPanel(); + findColumnsLabel = new javax.swing.JLabel(); + loadingPanel = new javax.swing.JPanel(); + jPanel1 = new javax.swing.JPanel(); + cancelLoadButton = new javax.swing.JButton(); + jLabel2 = new javax.swing.JLabel(); + jPanel13 = new javax.swing.JPanel(); + loadingCauseLabel = new javax.swing.JLabel(); + loadingLabel = new javax.swing.JLabel(); + jPanel2 = new javax.swing.JPanel(); + rowsTableContainerPanel = new javax.swing.JPanel(); + jLayeredPane2 = new javax.swing.JLayeredPane(); + rowsTableScrollPane = new javax.swing.JScrollPane(); + rowsTable = new javax.swing.JTable(); + noRowsFoundPanel = new javax.swing.JPanel(); + jLabel9 = new javax.swing.JLabel(); + removeConditionButton = new javax.swing.JButton(); + singleRowViewScrollPaneContainer = new javax.swing.JPanel(); + singleRowViewScrollPane = new javax.swing.JScrollPane(); + singleRowViewScrollContentPanel = new javax.swing.JPanel(); + singleRowViewContainterPanel = new javax.swing.JPanel(); + jPanel12 = new javax.swing.JPanel(); + jPanel11 = new javax.swing.JPanel(); + jLabel7 = new javax.swing.JLabel(); + deselectButton = new javax.swing.JButton(); + jPanel5 = new javax.swing.JPanel(); + errorLabel = new javax.swing.JLabel(); + errorDetailsButton = new javax.swing.JButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + errorMessageTextArea = new javax.swing.JTextArea(); + jPanel4 = new javax.swing.JPanel(); + jLabel8 = new javax.swing.JLabel(); + jPanel8 = new javax.swing.JPanel(); + jLabel11 = new javax.swing.JLabel(); + menuPanel = new javax.swing.JPanel(); + jPanel7 = new javax.swing.JPanel(); + loadButton = new javax.swing.JButton(); + openEditorButton = new javax.swing.JToggleButton(); + onPanel = new javax.swing.JPanel(); + on = new javax.swing.JLabel(); + joinPanel = new javax.swing.JPanel(); + join = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jPanel10 = new javax.swing.JPanel(); + from = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + jLabel1 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + rrPanel = new javax.swing.JPanel(); + relatedRowsPanel = new javax.swing.JPanel(); + relatedRowsLabel = new javax.swing.JLabel(); + sqlPanel = new javax.swing.JPanel(); + sqlLabel1 = new javax.swing.JLabel(); + jPanel9 = new javax.swing.JPanel(); + jPanel14 = new javax.swing.JPanel(); + wherejLabel = new javax.swing.JLabel(); + + andCondition.setEditable(true); + andCondition.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + + openEditorLabel.setText(" And "); + + setLayout(new java.awt.GridBagLayout()); + + pendingNonpendingPanel.setLayout(new java.awt.CardLayout()); + + cardPanel.setLayout(new java.awt.CardLayout()); + + tablePanel.setLayout(new java.awt.GridBagLayout()); + + jLayeredPane1.setLayout(new java.awt.GridBagLayout()); + + statusPanel.setLayout(new java.awt.GridBagLayout()); + + sortColumnsCheckBox.setText("sort columns "); + sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + sortColumnsCheckBoxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 1; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); + statusPanel.add(sortColumnsCheckBox, gridBagConstraints); + + rowsCount.setText("jLabel3"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + statusPanel.add(rowsCount, gridBagConstraints); + + selectDistinctCheckBox.setSelected(true); + selectDistinctCheckBox.setText("select distinct (-100 rows)"); + selectDistinctCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + selectDistinctCheckBoxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); + statusPanel.add(selectDistinctCheckBox, gridBagConstraints); + + sortColumnsPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + sortColumnsPanel.setLayout(new javax.swing.BoxLayout(sortColumnsPanel, javax.swing.BoxLayout.LINE_AXIS)); + + sortColumnsLabel.setText("Natural column order "); + sortColumnsPanel.add(sortColumnsLabel); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + statusPanel.add(sortColumnsPanel, gridBagConstraints); + + findColumnsPanel.setLayout(new java.awt.GridBagLayout()); + + findColumnsLabel.setText("Find Columns"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 6); + findColumnsPanel.add(findColumnsLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + statusPanel.add(findColumnsPanel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + jLayeredPane1.add(statusPanel, gridBagConstraints); + + loadingPanel.setOpaque(false); + loadingPanel.setLayout(new java.awt.GridBagLayout()); + + jPanel1.setBackground(new Color(255,255,255,150)); + jPanel1.setLayout(new java.awt.GridBagLayout()); + + cancelLoadButton.setText("Cancel"); + cancelLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelLoadButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel1.add(cancelLoadButton, gridBagConstraints); + + jLabel2.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.weightx = 1.0; + jPanel1.add(jLabel2, gridBagConstraints); + + jPanel13.setOpaque(false); + jPanel13.setLayout(new java.awt.GridBagLayout()); + + loadingCauseLabel.setFont(loadingCauseLabel.getFont().deriveFont(loadingCauseLabel.getFont().getSize()+3f)); + loadingCauseLabel.setForeground(new java.awt.Color(141, 16, 16)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel13.add(loadingCauseLabel, gridBagConstraints); + + loadingLabel.setFont(loadingLabel.getFont().deriveFont(loadingLabel.getFont().getStyle() | java.awt.Font.BOLD, loadingLabel.getFont().getSize()+3)); + loadingLabel.setForeground(new java.awt.Color(141, 16, 16)); + loadingLabel.setText("loading... "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel13.add(loadingLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8); + jPanel1.add(jPanel13, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(4, 4, 2, 4); + loadingPanel.add(jPanel1, gridBagConstraints); + + jLayeredPane1.setLayer(loadingPanel, javax.swing.JLayeredPane.MODAL_LAYER); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridheight = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + jLayeredPane1.add(loadingPanel, gridBagConstraints); + + jPanel2.setLayout(new java.awt.GridBagLayout()); + + rowsTableContainerPanel.setLayout(new java.awt.GridBagLayout()); + + jLayeredPane2.setLayout(new java.awt.GridBagLayout()); + + rowsTableScrollPane.setWheelScrollingEnabled(false); + + rowsTable.setAutoCreateRowSorter(true); + rowsTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null} + }, + new String [] { + "Title 1", "Title 2", "Title 3", "Title 4" + } + )); + rowsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); + rowsTableScrollPane.setViewportView(rowsTable); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jLayeredPane2.add(rowsTableScrollPane, gridBagConstraints); + + noRowsFoundPanel.setOpaque(false); + noRowsFoundPanel.setLayout(new java.awt.GridBagLayout()); + + jLabel9.setText("No rows found."); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + gridBagConstraints.weighty = 1.0; + noRowsFoundPanel.add(jLabel9, gridBagConstraints); + + removeConditionButton.setText("Remove condition"); + removeConditionButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + removeConditionButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + gridBagConstraints.weighty = 1.0; + noRowsFoundPanel.add(removeConditionButton, gridBagConstraints); + + jLayeredPane2.setLayer(noRowsFoundPanel, javax.swing.JLayeredPane.PALETTE_LAYER); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jLayeredPane2.add(noRowsFoundPanel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + rowsTableContainerPanel.add(jLayeredPane2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel2.add(rowsTableContainerPanel, gridBagConstraints); + + singleRowViewScrollPaneContainer.setLayout(new java.awt.GridBagLayout()); + + singleRowViewScrollPane.setWheelScrollingEnabled(false); + + singleRowViewScrollContentPanel.setLayout(new java.awt.GridBagLayout()); + + singleRowViewContainterPanel.setBackground(java.awt.Color.white); + singleRowViewContainterPanel.setBorder(new javax.swing.border.LineBorder(java.awt.Color.gray, 1, true)); + singleRowViewContainterPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + gridBagConstraints.weightx = 1.0; + singleRowViewScrollContentPanel.add(singleRowViewContainterPanel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + gridBagConstraints.weighty = 1.0; + singleRowViewScrollContentPanel.add(jPanel12, gridBagConstraints); + + singleRowViewScrollPane.setViewportView(singleRowViewScrollContentPanel); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + singleRowViewScrollPaneContainer.add(singleRowViewScrollPane, gridBagConstraints); + + jPanel11.setBackground(new java.awt.Color(228, 228, 232)); + jPanel11.setLayout(new java.awt.GridBagLayout()); + + jLabel7.setBackground(new java.awt.Color(200, 200, 200)); + jLabel7.setForeground(new java.awt.Color(1, 0, 0)); + jLabel7.setText(" Single Row Details "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(2, 2, 0, 2); + jPanel11.add(jLabel7, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + singleRowViewScrollPaneContainer.add(jPanel11, gridBagConstraints); + + deselectButton.setText("Deselect Row"); + deselectButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + deselectButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + singleRowViewScrollPaneContainer.add(deselectButton, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel2.add(singleRowViewScrollPaneContainer, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jLayeredPane1.add(jPanel2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + tablePanel.add(jLayeredPane1, gridBagConstraints); + + cardPanel.add(tablePanel, "table"); + + jPanel5.setLayout(new java.awt.GridBagLayout()); + + errorLabel.setForeground(new java.awt.Color(141, 16, 16)); + errorLabel.setText("Error"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8); + jPanel5.add(errorLabel, gridBagConstraints); + + errorDetailsButton.setText("Details..."); + errorDetailsButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + errorDetailsButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + jPanel5.add(errorDetailsButton, gridBagConstraints); + + jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + errorMessageTextArea.setEditable(false); + errorMessageTextArea.setColumns(20); + errorMessageTextArea.setLineWrap(true); + errorMessageTextArea.setWrapStyleWord(true); + jScrollPane2.setViewportView(errorMessageTextArea); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + jPanel5.add(jScrollPane2, gridBagConstraints); + + cardPanel.add(jPanel5, "error"); + + jPanel4.setLayout(new java.awt.GridBagLayout()); + + jLabel8.setFont(jLabel8.getFont().deriveFont(jLabel8.getFont().getStyle() | java.awt.Font.BOLD, jLabel8.getFont().getSize()+3)); + jLabel8.setForeground(new java.awt.Color(141, 16, 16)); + jLabel8.setText("Cancelled"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); + jPanel4.add(jLabel8, gridBagConstraints); + + cardPanel.add(jPanel4, "cancelled"); + + pendingNonpendingPanel.add(cardPanel, "nonpending"); + + jPanel8.setLayout(new java.awt.GridBagLayout()); + + jLabel11.setFont(jLabel11.getFont().deriveFont(jLabel11.getFont().getStyle() | java.awt.Font.BOLD, jLabel11.getFont().getSize()+3)); + jLabel11.setForeground(new java.awt.Color(141, 16, 16)); + jLabel11.setText("pending..."); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); + jPanel8.add(jLabel11, gridBagConstraints); + + pendingNonpendingPanel.add(jPanel8, "pending"); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(pendingNonpendingPanel, gridBagConstraints); + + menuPanel.setLayout(new java.awt.GridBagLayout()); + + jPanel7.setLayout(new java.awt.GridBagLayout()); + + loadButton.setText("Reload"); + loadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + loadButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + jPanel7.add(loadButton, gridBagConstraints); + + openEditorButton.setText("Where"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + jPanel7.add(openEditorButton, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 8; + gridBagConstraints.gridwidth = 6; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + menuPanel.add(jPanel7, gridBagConstraints); + + onPanel.setMinimumSize(new java.awt.Dimension(66, 17)); + onPanel.setLayout(new java.awt.BorderLayout()); + + on.setFont(on.getFont().deriveFont(on.getFont().getStyle() | java.awt.Font.BOLD)); + on.setText("jLabel3"); + onPanel.add(on, java.awt.BorderLayout.CENTER); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + menuPanel.add(onPanel, gridBagConstraints); + + joinPanel.setMinimumSize(new java.awt.Dimension(66, 17)); + joinPanel.setLayout(new java.awt.GridBagLayout()); + + join.setFont(join.getFont().deriveFont(join.getFont().getStyle() | java.awt.Font.BOLD)); + join.setText("jLabel3"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + joinPanel.add(join, gridBagConstraints); + + jLabel6.setText(" as B "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + joinPanel.add(jLabel6, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + menuPanel.add(joinPanel, gridBagConstraints); + + jPanel10.setMinimumSize(new java.awt.Dimension(66, 17)); + jPanel10.setLayout(new java.awt.GridBagLayout()); + + from.setFont(from.getFont().deriveFont(from.getFont().getStyle() | java.awt.Font.BOLD)); + from.setText("jLabel3"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + jPanel10.add(from, gridBagConstraints); + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + jLabel5.setText(" as A"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + jPanel10.add(jLabel5, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + menuPanel.add(jPanel10, gridBagConstraints); + + jLabel1.setText(" Join "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weighty = 1.0; + menuPanel.add(jLabel1, gridBagConstraints); + + jLabel4.setText(" On "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weighty = 1.0; + menuPanel.add(jLabel4, gridBagConstraints); + + jLabel3.setText(" From "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 4; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weighty = 1.0; + menuPanel.add(jLabel3, gridBagConstraints); + + rrPanel.setLayout(new java.awt.GridBagLayout()); + + relatedRowsPanel.setBackground(new java.awt.Color(224, 240, 255)); + relatedRowsPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + relatedRowsPanel.setLayout(new java.awt.GridBagLayout()); + + relatedRowsLabel.setBackground(new java.awt.Color(224, 240, 255)); + relatedRowsLabel.setText(" Related Rows "); + relatedRowsLabel.setOpaque(true); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3); + relatedRowsPanel.add(relatedRowsLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 7; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0); + rrPanel.add(relatedRowsPanel, gridBagConstraints); + + sqlPanel.setBackground(new java.awt.Color(255, 243, 218)); + sqlPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + sqlPanel.setLayout(new java.awt.GridBagLayout()); + + sqlLabel1.setForeground(new java.awt.Color(1, 0, 0)); + sqlLabel1.setText(" Menu "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3); + sqlPanel.add(sqlLabel1, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 8; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); + rrPanel.add(sqlPanel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 7; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.gridheight = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + menuPanel.add(rrPanel, gridBagConstraints); + + jPanel9.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + menuPanel.add(jPanel9, gridBagConstraints); + + jPanel14.setLayout(new java.awt.GridBagLayout()); + + wherejLabel.setText(" Where "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + jPanel14.add(wherejLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 8; + menuPanel.add(jPanel14, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + add(menuPanel, gridBagConstraints); + }// //GEN-END:initComponents + + private void cancelLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelLoadButtonActionPerformed + cancelLoadJob(false); + updateMode("cancelled", null); + }//GEN-LAST:event_cancelLoadButtonActionPerformed + + private void selectDistinctCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectDistinctCheckBoxActionPerformed + reloadRows(); + }//GEN-LAST:event_selectDistinctCheckBoxActionPerformed + + private void sortColumnsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortColumnsCheckBoxActionPerformed + updateTableModel(); + }//GEN-LAST:event_sortColumnsCheckBoxActionPerformed + + private void deselectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectButtonActionPerformed + andCondition.setSelectedItem(""); + }//GEN-LAST:event_deselectButtonActionPerformed + + private void removeConditionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeConditionButtonActionPerformed + andCondition.setSelectedItem(""); + }//GEN-LAST:event_removeConditionButtonActionPerformed + + private void errorDetailsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_errorDetailsButtonActionPerformed + UIUtil.showException(this, "Error", currentErrorDetail); + }//GEN-LAST:event_errorDetailsButtonActionPerformed + + private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_loadButtonActionPerformed + if (System.currentTimeMillis() - lastReloadTS > 200) { + reloadRows(); + } + }// GEN-LAST:event_loadButtonActionPerformed + + private void limitBoxItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_limitBoxItemStateChanged + if (evt.getStateChange() == ItemEvent.SELECTED) { + reloadRows(); + } + }// GEN-LAST:event_limitBoxItemStateChanged + + void openQueryBuilder(boolean openSQLConsole) { + openQueryBuilder(openSQLConsole, null); + } + + void openQueryBuilder(boolean openSQLConsole, String alternativeWhere) { + QueryBuilderDialog.Relationship root = createQBRelations(true); + if (root != null) { + if (alternativeWhere != null) { + root.whereClause = alternativeWhere; + } + root.selectColumns = true; + getQueryBuilderDialog().buildQuery(table, root, dataModel, session, getMetaDataSource(), openSQLConsole); + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + javax.swing.JComboBox andCondition; + private javax.swing.JButton cancelLoadButton; + private javax.swing.JPanel cardPanel; + private javax.swing.JButton deselectButton; + private javax.swing.JButton errorDetailsButton; + private javax.swing.JLabel errorLabel; + private javax.swing.JTextArea errorMessageTextArea; + private javax.swing.JLabel findColumnsLabel; + public javax.swing.JPanel findColumnsPanel; + private javax.swing.JLabel from; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JLayeredPane jLayeredPane1; + private javax.swing.JLayeredPane jLayeredPane2; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel10; + private javax.swing.JPanel jPanel11; + private javax.swing.JPanel jPanel12; + private javax.swing.JPanel jPanel13; + private javax.swing.JPanel jPanel14; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel7; + private javax.swing.JPanel jPanel8; + private javax.swing.JPanel jPanel9; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JLabel join; + private javax.swing.JPanel joinPanel; + public javax.swing.JButton loadButton; + private javax.swing.JLabel loadingCauseLabel; + private javax.swing.JLabel loadingLabel; + private javax.swing.JPanel loadingPanel; + javax.swing.JPanel menuPanel; + private javax.swing.JPanel noRowsFoundPanel; + private javax.swing.JLabel on; + private javax.swing.JPanel onPanel; + private javax.swing.JToggleButton openEditorButton; + private javax.swing.JLabel openEditorLabel; + private javax.swing.JPanel pendingNonpendingPanel; + private javax.swing.JLabel relatedRowsLabel; + javax.swing.JPanel relatedRowsPanel; + private javax.swing.JButton removeConditionButton; + public javax.swing.JLabel rowsCount; + public javax.swing.JTable rowsTable; + private javax.swing.JPanel rowsTableContainerPanel; + protected javax.swing.JScrollPane rowsTableScrollPane; + private javax.swing.JPanel rrPanel; + javax.swing.JCheckBox selectDistinctCheckBox; + protected javax.swing.JPanel singleRowViewContainterPanel; + private javax.swing.JPanel singleRowViewScrollContentPanel; + javax.swing.JScrollPane singleRowViewScrollPane; + private javax.swing.JPanel singleRowViewScrollPaneContainer; + public javax.swing.JCheckBox sortColumnsCheckBox; + private javax.swing.JLabel sortColumnsLabel; + public javax.swing.JPanel sortColumnsPanel; + private javax.swing.JLabel sqlLabel1; + javax.swing.JPanel sqlPanel; + protected javax.swing.JPanel statusPanel; + private javax.swing.JPanel tablePanel; + private javax.swing.JLabel wherejLabel; + // End of variables declaration//GEN-END:variables + + JPanel thumbnail; + private DBConditionEditor andConditionEditor; + private ImageIcon conditionEditorIcon; + { + // load images + conditionEditorIcon = UIUtil.readImage("/edit.png"); + } + + /** + * Cancels current load job. + * @param propagate + * @return + */ + public void cancelLoadJob(boolean propagate) { + LoadJob cLoadJob; + synchronized (this) { + cLoadJob = currentLoadJob; + } + if (cLoadJob != null) { + cLoadJob.cancel(); + } + if (propagate) { + for (RowBrowser child: getChildBrowsers()) { + child.browserContentPane.cancelLoadJob(propagate); + } + } + } + + private void updateMode(String mode, String cause) { + String suffix; + if (cause != null) { + suffix = cause; + } else { + suffix = ""; + } + loadingCauseLabel.setVisible(false); + if ("table".equals(mode)) { + loadingPanel.setVisible(false); + rowsTable.setEnabled(true); + } else if ("loading".equals(mode)) { + mode = "table"; + loadingPanel.setVisible(true); + loadingLabel.setText("loading..."); + loadingCauseLabel.setText(suffix); + loadingCauseLabel.setVisible(true); + cancelLoadButton.setVisible(true); + rowsTable.setEnabled(false); + } else if ("pending".equals(mode)) { + mode = "table"; + loadingPanel.setVisible(true); + loadingLabel.setText("pending..."); + cancelLoadButton.setVisible(false); + rowsTable.setEnabled(false); + } else if ("updating".equals(mode)) { + mode = "table"; + loadingPanel.setVisible(true); + loadingLabel.setText("updating..."); + cancelLoadButton.setVisible(true); + rowsTable.setEnabled(false); + } + errorDetailsButton.setVisible(false); + ((CardLayout) cardPanel.getLayout()).show(cardPanel, mode); + } + + /** + * Creates new row. Fills in foreign key. + * + * @param parents rows holding the primary key + * @param table the table of the new row + * @return new row of table + */ + private List createNewRow(List parents, Table table, Association association) { + List children = new ArrayList(); + try { + if (parents != null && association != null && !association.isInsertDestinationBeforeSource()) { + for (Row par: parents) { + Map sToDMap = association.createSourceToDestinationKeyMapping(); + if (!sToDMap.isEmpty()) { + Row row = new Row("", null, new Object[association.destination.getColumns().size()]); + for (Map.Entry e: sToDMap.entrySet()) { + int iS = -1; + for (int i = 0; i < table.getColumns().size(); ++i) { + if (Quoting.equalsIgnoreQuotingAndCase(e.getKey().name, table.getColumns().get(i).name)) { + iS = i; + break; + } + } + int iD = -1; + for (int i = 0; i < association.destination.getColumns().size(); ++i) { + if (Quoting.equalsIgnoreQuotingAndCase(e.getValue().name, association.destination.getColumns().get(i).name)) { + iD = i; + break; + } + } + if (iS >= 0 && iD >= 0) { + row.values[iD] = par.values[iS]; + } else { + break; + } + } + children.add(row); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return children; + } + + protected abstract RowBrowser navigateTo(Association association, List pRows); + + protected abstract void onContentChange(List rows, boolean reloadChildren); + + protected abstract void onRedraw(); + protected abstract void onHide(); + + protected abstract void beforeReload(); + protected void afterReload() {} + + protected abstract QueryBuilderDialog.Relationship createQBRelations(boolean withParents); + protected abstract List createQBChildrenRelations(RowBrowser tabu, boolean all); + + protected abstract void addRowToRowLink(Row pRow, Row exRow); + + protected abstract JFrame getOwner(); + + protected abstract void findClosure(Row row); + protected Object getMonitorForFindClosure() { + return ""; + } + protected void findTempClosure(Row row) {}; + protected abstract void findClosure(Row row, Set> closure, boolean forward, FindClosureContext findClosureContext); + + protected abstract QueryBuilderDialog getQueryBuilderDialog(); + + protected abstract void openSchemaMappingDialog(); + protected abstract void openSchemaAnalyzer(); + protected abstract DbConnectionDialog getDbConnectionDialog(); + protected abstract double getLayoutFactor(); + protected abstract List getChildBrowsers(); + protected abstract RowBrowser getParentBrowser(); + protected abstract List getTableBrowser(); + protected abstract void unhide(); + protected abstract void close(); + protected abstract void showInNewWindow(); + protected abstract void appendLayout(); + protected abstract void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne); + protected abstract void reloadDataModel() throws Exception; + protected abstract MetaDataSource getMetaDataSource(); + protected abstract void deselectChildrenIfNeededWithoutReload(); + protected abstract int getReloadLimit(); + protected void changeColumnOrder(Table table) { + } + protected void rebase() { + } + protected RowBrowser copy(RowBrowser tableBrowser, Association association, Row parentRow, RowBrowser childToIgnore, boolean newParent) { + return null; + } + protected RowBrowser getRowBrowser() { + return null; + }; + protected boolean shouldShowLoadErrors() { + return true; + } + + public interface RunnableWithPriority extends Runnable { + int getPriority(); + }; + + protected abstract PriorityBlockingQueue getRunnableQueue(); + + /** + * Collect layout of tables in a extraction model. + * + * @param positions to put positions into + */ + protected abstract void collectPositions(Map> positions); + + + private void openDetails(final int x, final int y) { + final JDialog d = new JDialog(getOwner(), (table instanceof SqlStatementTable)? "" : dataModel.getDisplayName(table), true); + final boolean deselect = !currentSelectedRowCondition.equals("") + && currentSelectedRowCondition.equals(getAndConditionText()) + && rows.size() == 1; + d.getContentPane().add(new DetailsView(rows, rowsTable.getRowCount(), dataModel, table, 0, rowsTable.getRowSorter(), true, getQueryBuilderDialog() != null, rowIdSupport, deselect, session) { + @Override + protected void onRowChanged(int row) { + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(row, false); + } + @Override + protected void onClose() { + d.setVisible(false); + } + @Override + protected void onSelectRow(Row row) { + d.setVisible(false); + if (deselect) { + andCondition.setSelectedItem(""); + } else { + List rowList = new ArrayList(); + rowList.add(row); + selectRow(rowList); + } + } + }); + d.pack(); + d.setLocation(x, y); + d.setSize(400, d.getHeight() + 20); + UIUtil.fit(d); + Window p = SwingUtilities.getWindowAncestor(this); + if (p != null) { + int maxX = p.getX() + p.getWidth() - d.getWidth(); + d.setLocation(Math.max(0, Math.min(maxX, d.getX())), d.getY()); + int maxY = p.getY() + p.getHeight() - d.getHeight(); + if (maxY < d.getY()) { + int deltaH = Math.min(d.getY() - maxY, (int) (0.30 * d.getHeight())); + maxY += deltaH; + d.setSize(d.getWidth(), d.getHeight() - deltaH); + d.setLocation(d.getX(), Math.max(0, maxY)); + } + } + d.setVisible(true); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); + onRedraw(); + } + + private void updateWhereField() { + if (association != null) { + if (parentRows != null && parentRows.size() > 0) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < parentRows.size(); ++i) { + if (i > 0) { + sb.append(" or\n"); + } + sb.append(parentRows.get(i).rowId); + if (i > 50) { + sb.append("\n..."); + break; + } + } + String currentCond = getAndConditionText().trim(); + String toolTip; + if (currentCond.length() > 0) { + toolTip = currentCond + "\nand (\n" + sb + ")"; + } else { + toolTip = sb.toString(); + } + wherejLabel.setToolTipText(UIUtil.toHTML(toolTip, 0)); + } else { + wherejLabel.setToolTipText(null); + } + } else { + wherejLabel.setToolTipText(null); + } + } + + public void convertToRoot() { + association = null; + parentRows = null; + rowsClosure.currentClosureRowIDs.clear(); + adjustGui(); + reloadRows(); + } + + public void openDetailsView(int rowIndex, int x, int y) { + final JDialog d = new JDialog(getOwner(), (table instanceof SqlStatementTable)? "" : dataModel.getDisplayName(table), true); + final boolean deselect = !currentSelectedRowCondition.equals("") + && currentSelectedRowCondition.equals(getAndConditionText()) + && rows.size() == 1; + d.getContentPane().add(new DetailsView(rows, rowsTable.getRowCount(), dataModel, table, rowIndex, rowsTable.getRowSorter(), true, getQueryBuilderDialog() != null, rowIdSupport, deselect, session) { + @Override + protected void onRowChanged(int row) { + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(row, false); + } + @Override + protected void onClose() { + d.setVisible(false); + } + @Override + protected void onSelectRow(Row row) { + d.setVisible(false); + if (deselect) { + andCondition.setSelectedItem(""); + } else { + List rowList = new ArrayList(); + rowList.add(row); + selectRow(rowList); + } + } + }); + d.pack(); + d.setLocation(x, y); + d.setSize(400, d.getHeight() + 20); + int h = d.getHeight(); + UIUtil.fit(d); + if (d.getHeight() < h) { + y = Math.max(y - Math.min(h - d.getHeight(), Math.max(400 - d.getHeight(), 0)), 20); + d.pack(); + d.setLocation(x, y); + d.setSize(400, d.getHeight() + 20); + UIUtil.fit(d); + } + Window p = SwingUtilities.getWindowAncestor(this); + if (p != null) { + int maxX = p.getX() + p.getWidth() - d.getWidth(); + d.setLocation(Math.max(0, Math.min(maxX, d.getX())), d.getY()); + int maxY = p.getY() + p.getHeight() - d.getHeight(); + if (maxY < d.getY()) { + int deltaH = Math.min(d.getY() - maxY, (int) (0.30 * d.getHeight())); + maxY += deltaH; + d.setSize(d.getWidth(), d.getHeight() - deltaH); + d.setLocation(d.getX(), Math.max(0, maxY)); + } + } + d.setVisible(true); + setCurrentRowSelectionAndReloadChildrenIfLimitIsExceeded(-1, false); + onRedraw(); + } + + public void updateSingleRowDetailsView() { + if (singleRowDetailsView != null) { + if (rowsClosure != null && rowsClosure.currentClosureRowIDs != null) { + singleRowDetailsView.updateInClosureState(rows.size() == 1 && rowsClosure.currentClosureRowIDs.contains(new Pair(this, rows.get(0).nonEmptyRowId))); + } + } + } + + private static TableContentViewFilter tableContentViewFilter = TableContentViewFilter.create(); + + private Icon dropDownIcon; + private ImageIcon relatedRowsIcon; + private ImageIcon redDotIcon; + private ImageIcon blueDotIcon; + private ImageIcon greenDotIcon; + private ImageIcon greyDotIcon; + { + // load images + dropDownIcon = UIUtil.readImage("/dropdown.png"); + relatedRowsIcon = UIUtil.readImage("/right.png"); + redDotIcon = UIUtil.readImage("/reddot.gif"); + blueDotIcon = UIUtil.readImage("/bluedot.gif"); + greenDotIcon = UIUtil.readImage("/greendot.gif"); + greyDotIcon = UIUtil.readImage("/greydot.gif"); + } + + public void resetRowsTableContainer() { + cardPanel.setVisible(true); + } + + public JComponent getRowsTableContainer() { + return cardPanel; + } + + public JTable getRowsTable() { + return rowsTable; + } + + public LoadJob newLoadJob(ResultSet resultSet, Integer limit) { + return new LoadJob(resultSet, limit == null? Integer.MAX_VALUE : limit); + } + + public boolean isEditMode() { + return isEditMode; + } + + public void setEditMode(boolean isEditMode) { + this.isEditMode = isEditMode; + } + + private String statementForReloading; + + public synchronized void setStatementForReloading(String statementForReloading) { + this.statementForReloading = statementForReloading; + } + + /** + * Type of result set for in-place editing of query result. + */ + private List
resultSetType; + + /** + * Sets type of result set for in-place editing of query result. + * + * @param resultSetType the type + */ + public void setResultSetType(List
resultSetType) { + this.resultSetType = resultSetType; + } + + /** + * Gets a table from {@link #resultSetType} where a given column is defined. + * + * @param column the column + * @return suitable table for column or {@link #table} + */ + private Table getResultSetTypeForColumn(int column) { + if (resultSetType == null) { + return table; + } + if (typePerColumn.containsKey(column)) { + return typePerColumn.get(column); + } + for (Table type: resultSetType) { + if (type.getColumns().size() > column) { + Column col = type.getColumns().get(column); + if (col != null && col.name != null) { + typePerColumn.put(column, type); + return type; + } + } + } + typePerColumn.put(column, table); + return table; + } + + private boolean isPKComplete(Table type, Row r) { + if (type.primaryKey == null) { + return false; + } + int[] indexes = pkColumnIndexes.get(type); + if (indexes == null) { + indexes = new int[type.primaryKey.getColumns().size()]; + int ii = 0; + for (Column pk: type.primaryKey.getColumns()) { + Integer index = null; + int i = 0; + for (Column c: type.getColumns()) { + if (c.name != null && c.name.equals(pk.name)) { + index = i; + break; + } + ++i; + } + if (index == null) { + return false; + } + indexes[ii++] = index; + } + pkColumnIndexes.put(type, indexes); + } + for (int i: indexes) { + if (i >= r.values.length) { + return false; + } + Object content = r.values[i]; + if (/*content == null || */ content instanceof TableModelItem && (((TableModelItem) content).value == UIUtil.NULL || ((TableModelItem) content).value == null)) { + return false; + } + } + return true; + } + + private static boolean showingLoadErrorNow = false; + + private Map typePerColumn = new HashMap(); + private Map pkColumnIndexes = new HashMap(); + + private String[] alternativeColumnLabels; + + public void setAlternativeColumnLabels(String[] columnLabels) { + this.alternativeColumnLabels = columnLabels; + } + + private void selectRow(final List toSelect) { + StringBuilder conds = new StringBuilder(); + int numConds = 0; + boolean append = false; + for (int i = 0; i < rows.size(); ++i) { + String rowId = rows.get(i).rowId; + for (Row r: toSelect) { + if (!r.rowId.isEmpty()) { + if (r.rowId.equals(rowId)) { + int vi = rowsTable.getRowSorter().convertRowIndexToView(i); + if (vi >= 0) { + setCurrentRowSelection(vi, append); + append = true; + } + currentRowSelection = -1; + String cond = SqlUtil.replaceAliases(rowId, "A", "A"); + if (numConds == 1) { + conds = new StringBuilder("(" + conds + ")"); + } + if (conds.length() != 0) { + conds.append(" or "); + } + if (numConds > 0) { + conds.append("("); + } + conds.append(cond); + if (numConds > 0) { + conds.append(")"); + } + ++numConds; + break; + } + } + } + } + deselectChildrenIfNeededWithoutReload(); +// String currentCond = getAndConditionText().trim(); + String cond = conds.toString(); +// if (currentCond.length() > 0) { +// cond = "(" + cond + ") and (" + currentCond + ")"; +// } + andCondition.setSelectedItem(cond); + } + + protected void deselectIfNeededWithoutReload() { + if (rows.size() == 1) { + String rowId = rows.get(0).rowId; + if (rowId != null && !rowId.isEmpty()) { + String cond = SqlUtil.replaceAliases(rowId, "A", "A"); + String currentCond = getAndConditionText().trim(); + if (cond.equals(currentCond)) { + boolean isSingleRowNotInClosure = false; + if (rowsClosure != null && rowsClosure.currentClosureRowIDs != null) { + isSingleRowNotInClosure = !rowsClosure.currentClosureRowIDs.contains(new Pair(this, rowId)); + } + if (isSingleRowNotInClosure) { + try { + suppessReloadOnAndConditionAction = true; + andCondition.setSelectedItem(""); + } finally { + suppessReloadOnAndConditionAction = false; + } + } + } + } + } + } + + private static String readCharacterStream(final Reader reader) + throws IOException { + final StringBuilder sb = new StringBuilder(); + final BufferedReader br = new BufferedReader(reader); + + int b; + while(-1 != (b = br.read())) + { + sb.append((char)b); + if (sb.length() > MAXLOBLENGTH) { + sb.append("..."); + break; + } + } + br.close(); + return sb.toString(); + } + + private List sortedAndFiltered(List rows) { + RowSorter sorter = rowsTable.getRowSorter(); + if (sorter != null && !rows.isEmpty()) { + List result = new ArrayList(); + for (int i = 0; i < sorter.getViewRowCount(); ++i) { + result.add(rows.get(sorter.convertRowIndexToModel(i))); + } + return result; + } + return rows; + } + + private void sortChildren() { + try { + if (rowsTable.getRowSorter().getSortKeys().isEmpty()) { + List sk = new ArrayList(); + sk.add(new SortKey(rowsTable.getColumnCount() - 1, SortOrder.ASCENDING)); + rowsTable.getRowSorter().setSortKeys(sk); + ignoreSortKey = true; + } + adjustClosure(null, BrowserContentPane.this); + } catch (Exception e) { + // ignore + } + ((TableRowSorter) rowsTable.getRowSorter()).sort(); + for (RowBrowser ch: getChildBrowsers()) { + if (ch.browserContentPane != null) { + ch.browserContentPane.sortChildren(); + } + } + } + + private static String readClob(Clob clob) throws SQLException, IOException { + return readCharacterStream(clob.getCharacterStream()); + } + + private static String readSQLXML(SQLXML xml) throws SQLException, IOException { + return readCharacterStream(xml.getCharacterStream()); + } + + public static Object toLobRender(Object object) { + Object value = null; + if (object instanceof Blob) { + try { + final long length = ((Blob) object).length(); + value = new LobValue() { + @Override + public String toString() { + return " " + length + " bytes"; + } + }; + } catch (Exception e) { + value = new LobValue() { + @Override + public String toString() { + return ""; + } + }; + } + } + if (object instanceof Clob) { + try { + final String content = readClob((Clob) object); + value = new LobValue() { + @Override + public String toString() { + return content; + } + }; + } catch (Exception e) { + value = new LobValue() { + @Override + public String toString() { + return ""; + } + };e.printStackTrace(); + } + } + if (object instanceof SQLXML) { + try { + final String content = readSQLXML((SQLXML) object); + value = new LobValue() { + @Override + public String toString() { + return content; + } + }; + } catch (Exception e) { + value = new LobValue() { + @Override + public String toString() { + return ""; + } + }; + e.printStackTrace(); + } + } + return value; + } + + public List getSelectedRows(Row additionalRow) { + final List toSelect = new ArrayList(); + if (rowsClosure.currentClosureRootID.contains(additionalRow.nonEmptyRowId)) { + for (Row r: rows) { + if (!r.nonEmptyRowId.isEmpty() && + (rowsClosure.currentClosureRootID.contains(r.nonEmptyRowId) || additionalRow == r)) { + toSelect.add(r); + } + } + } else { + toSelect.add(additionalRow); + } + return toSelect; + } + + public String toCondition(List r) { + if (r == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + int neCount = 0; + for (Row row: r) { + if (row.rowId != null) { + neCount++; + } + } + for (Row row: r) { + if (row.rowId != null) { + if (sb.length() > 0) { + sb.append(" or "); + } + if (neCount > 1) { + sb.append("("); + } + sb.append(row.rowId); + if (neCount > 1) { + sb.append(")"); + } + } + } + return sb.toString(); + } + + private Reference currentRowsTableReference = null; + + public void setCurrentRowsTable(Reference reference) { + currentRowsTableReference = reference; + } + + private void findColumns(final int x, final int y, final JTable contextJTable) { + TableColumnModel columnModel = rowsTable.getColumnModel(); + List columNames = new ArrayList(); + Map columNamesCount = new HashMap(); + for (int i = 0; i < columnModel.getColumnCount(); ++i) { + Object nameObj = columnModel.getColumn(i).getHeaderValue(); + if (nameObj != null) { + String name = nameObj.toString(); + if (columNamesCount.containsKey(name)) { + columNamesCount.put(name, columNamesCount.get(name) + 1); + } else { + columNames.add(name); + columNamesCount.put(name, 1); + } + } + } + Collections.sort(columNames, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + }); + + final Window owner = SwingUtilities.getWindowAncestor(contextJTable); + + final JComboBox combobox = new JComboBox(); + combobox.setModel(new DefaultComboBoxModel(columNames.toArray())); + StringSearchPanel searchPanel = new StringSearchPanel(null, combobox, null, null, null, new Runnable() { + @Override + public void run() { + Object selected = combobox.getSelectedItem(); + if (selected != null) { + TableColumnModel columnModel = rowsTable.getColumnModel(); + foundColumn.clear(); + boolean scrolled = false; + for (int i = 0; i < columnModel.getColumnCount(); ++i) { + Object name = columnModel.getColumn(i).getHeaderValue(); + if (name != null && name.equals(selected)) { + int mi = i; + if (!scrolled) { + if (contextJTable != null && contextJTable != rowsTable) { + Rectangle visibleRect = contextJTable.getVisibleRect(); + Rectangle cellRect = contextJTable.getCellRect(mi, 0, true); + contextJTable.scrollRectToVisible( + new Rectangle( + visibleRect.x + visibleRect.width / 2, + cellRect.y - 16, + 1, cellRect.width + 16)); + contextJTable.repaint(); + } else { + Rectangle visibleRect = rowsTable.getVisibleRect(); + Rectangle cellRect = rowsTable.getCellRect(0, mi, true); + rowsTable.scrollRectToVisible( + new Rectangle( + cellRect.x - 32, visibleRect.y + visibleRect.height / 2, + cellRect.width + 64, 1)); + rowsTable.repaint(); + } + scrolled = true; + } + foundColumn.add(columnModel.getColumn(i).getModelIndex()); + } + } + } + } + }) { + @Override + protected Integer preferredWidth() { + return 260; + } + @Override + protected Integer maxX() { + if (owner != null) { + return owner.getX() + owner.getWidth() - preferredWidth(); + } else { + return null; + } + } + @Override + protected Integer maxY(int height) { + if (owner != null) { + return owner.getY() + owner.getHeight() - height - 8; + } else { + return null; + } + } + }; + + searchPanel.setStringCount(columNamesCount); + searchPanel.find(owner, "Find Column", x, y, true); + } + + /** + * Calculates temporary closure when mouse cursor is on new row. + */ + private class TempClosureListener implements MouseListener, MouseMotionListener { + Row currentRow = null; + + private Row rowAt(Point point) { + int ri = rowsTable.rowAtPoint(point); + if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { + int i = rowsTable.getRowSorter().convertRowIndexToModel(ri); + if (i >= 0 && i < rows.size()) { + return rows.get(i); + } + } + return null; + } + + private void updateClosure(Row row) { + if (currentRow != row) { + currentRow = row; + rowsClosure.tempClosure.clear(); + if (currentRow != null) { + findTempClosure(currentRow); + } + onRedraw(); + } + } + + @Override + public void mouseMoved(MouseEvent e) { + Row row = null; + if (e.getSource() == rowsTable) { + row = rowAt(e.getPoint()); + } else if (e.getSource() == singleRowViewContainterPanel && rows.size() == 1) { + row = rows.get(0); + } + updateClosure(row); + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + updateClosure(null); + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(e); + } + @Override + public void mouseClicked(MouseEvent e) { + } + @Override + public void mousePressed(MouseEvent e) { + } + @Override + public void mouseReleased(MouseEvent e) { + } + } +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/DataBrowser.java b/src/main/gui/net/sf/jailer/ui/databrowser/DataBrowser.java index a73e12a39..80acff260 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/DataBrowser.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/DataBrowser.java @@ -1,4281 +1,4281 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser; - -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.beans.PropertyVetoException; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URI; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; -import java.util.Vector; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.ButtonGroup; -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.InputMap; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JLabel; -import javax.swing.JLayeredPane; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JToggleButton; -import javax.swing.JTree; -import javax.swing.JViewport; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UIManager.LookAndFeelInfo; -import javax.swing.WindowConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.MouseInputAdapter; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.database.BasicDataSource; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.PrimaryKeyFactory; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; -import net.sf.jailer.modelbuilder.ModelBuilder; -import net.sf.jailer.ui.About; -import net.sf.jailer.ui.AnalyseOptionsDialog; -import net.sf.jailer.ui.AssociationListUI; -import net.sf.jailer.ui.AssociationListUI.AssociationModel; -import net.sf.jailer.ui.AssociationListUI.DefaultAssociationModel; -import net.sf.jailer.ui.AutoCompletion; -import net.sf.jailer.ui.BrowserLauncher; -import net.sf.jailer.ui.CLIPanel; -import net.sf.jailer.ui.ColumnOrderEditor; -import net.sf.jailer.ui.DataModelEditor; -import net.sf.jailer.ui.DataModelManager; -import net.sf.jailer.ui.DataModelManagerDialog; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.DbConnectionDialog.ConnectionInfo; -import net.sf.jailer.ui.Environment; -import net.sf.jailer.ui.ExtractionModelFrame; -import net.sf.jailer.ui.ImportDialog; -import net.sf.jailer.ui.JComboBox; -import net.sf.jailer.ui.PrivilegedSessionProviderDialog; -import net.sf.jailer.ui.SessionForUI; -import net.sf.jailer.ui.StringSearchPanel; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.UIUtil.ResultConsumer; -import net.sf.jailer.ui.associationproposer.AssociationProposerView; -import net.sf.jailer.ui.commandline.CommandLineInstance; -import net.sf.jailer.ui.constraintcheck.ConstraintChecker; -import net.sf.jailer.ui.databrowser.BookmarksPanel.BookmarkId; -import net.sf.jailer.ui.databrowser.BrowserContentPane.SqlStatementTable; -import net.sf.jailer.ui.databrowser.Desktop.LayoutMode; -import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; -import net.sf.jailer.ui.databrowser.metadata.MDGeneric; -import net.sf.jailer.ui.databrowser.metadata.MDSchema; -import net.sf.jailer.ui.databrowser.metadata.MDTable; -import net.sf.jailer.ui.databrowser.metadata.MetaDataDetailsPanel; -import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel; -import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel.OutlineInfo; -import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; -import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; -import net.sf.jailer.ui.syntaxtextarea.BasicFormatterImpl; -import net.sf.jailer.ui.util.AnimationController; -import net.sf.jailer.ui.util.SmallButton; -import net.sf.jailer.ui.util.UISettings; -import net.sf.jailer.ui.util.UpdateInfoManager; -import net.sf.jailer.util.CancellationHandler; -import net.sf.jailer.util.Quoting; - -/** - * Data Browser Frame. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public class DataBrowser extends javax.swing.JFrame { - - /** - * The desktop. - */ - Desktop desktop; - - /** - * Icon for the frame. - */ - private ImageIcon jailerIcon = null; - - /** - * The {@link DataModel}. - */ - private final Reference datamodel; - - /** - * The DB connection dialog. - */ - private DbConnectionDialog dbConnectionDialog; - - /** - * Session. - */ - private Session session; - - /** - * The border browser. - */ - private final AssociationListUI borderBrowser; - - /** - * The execution context. - */ - private final ExecutionContext executionContext; - - private final JComboBox tablesComboBox; - private boolean initialized = false; - - /** - * Allowed row limits. - */ - public static final Integer[] ROW_LIMITS = new Integer[] { 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 70000, 100000 }; - public static final int ROW_LIMIT_DEFAULT = 500; - - /** - * Constructor. - * - * @param datamodel - * the {@link DataModel} - * @param root - * table to start browsing with - * @param condition - * initial condition - * @param dbConnectionDialog - * DB-connection dialog - */ - public DataBrowser(final DataModel datamodel, final Table root, String condition, DbConnectionDialog dbConnectionDialog, Map schemaMapping, boolean embedded, final ExecutionContext executionContext) throws Exception { - this.executionContext = executionContext; - this.datamodel = new Reference(datamodel); - this.dbConnectionDialog = dbConnectionDialog != null ? new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext) : null; - this.borderBrowser = new AssociationListUI("Resolve", "Resolve selected Associations", true) { - @Override - protected void applyAction(Collection selection) { - resolveSelection(selection); - } - }; - if (embedded) { - DataBrowserContext.setSupportsDataModelUpdates(false); - } - initComponents(); - initMenu(); - - UpdateInfoManager.checkUpdateAvailability(updateInfoPanel, updateInfoLabel, downloadMenuItem, "B"); - UIUtil.initPLAFMenuItem(nativeLAFCheckBoxMenuItem, this); - if (datamodel != null) { - UISettings.dmStats(datamodel); - } - initRowLimitButtons(); - workbenchTabbedPane.setTabComponentAt(0, new JLabel("Desktop", desktopIcon, JLabel.LEFT)); - workbenchTabbedPane.setTabComponentAt(1, new JLabel("SQL Console ", sqlConsoleIcon, JLabel.LEFT)); - workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.getTabCount() - 1, new JLabel(addSqlConsoleIcon)); - - tableTreesTabbedPane.setTabComponentAt(0, new JLabel("Navigation", navigationIcon, JLabel.LEFT)); - tableTreesTabbedPane.setTabComponentAt(1, new JLabel("Database", databaseIcon, JLabel.LEFT)); - - tableTreesTabbedPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (createMetaDataPanel != null && tableTreesTabbedPane.getSelectedComponent() == tablesCardPanel) { - UIUtil.invokeLater(10, new Runnable() { - @Override - public void run() { - if (createMetaDataPanel != null) { - createMetaDataPanel.run(); - } - } - }); - } - } - }); - - initialized = true; - - tablesComboBox = new JComboBox() { - @Override - public Dimension getMinimumSize() { - return new Dimension(40, super.getMinimumSize().height); - } - }; - tablesComboBox.setMaximumRowCount(20); - updateNavigationCombobox(); - AutoCompletion.enable(tablesComboBox); - - tablesComboBox.grabFocus(); - - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1; - navigationPanel.add(tablesComboBox, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - searchButton = StringSearchPanel.createSearchButton(this, tablesComboBox, "Open Table Browser", new Runnable() { - @Override - public void run() { - openTableButtonActionPerformed(null); - } - }); - navigationPanel.add(searchButton, gridBagConstraints); - - tablesComboBox.setVisible(false); - openTableButton.setVisible(false); - searchButton.setText("Open Table"); - - detailsAndBorderBrowserTabbedPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - updateBorderBrowser(); - updateDataModelView(null); - showDataModelMenuItem.setSelected(detailsAndBorderBrowserTabbedPane.getSelectedComponent() == dataModelPanel); - } - }); - - metaDataDetailsPanel = createMetaDataDetailsPanel(executionContext); - metaDataViewPanel.add(metaDataDetailsPanel); - - jLayeredPane1.removeAll(); - jLayeredPane1.setLayout(null); - jLayeredPane1.setLayer(layeredPaneContent, JLayeredPane.PALETTE_LAYER); - jLayeredPane1.setLayer(dummy, JLayeredPane.DEFAULT_LAYER); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 1; - jLayeredPane1.add(layeredPaneContent /*, gridBagConstraints */); - layeredPaneContent.setLocation(0, 0); -// jLayeredPane1.add(dummy /*, gridBagConstraints */); - - addComponentListener(new ComponentListener() { - @Override - public void componentShown(ComponentEvent e) { - layeredPaneContent.setSize(jLayeredPane1.getSize()); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - desktopSplitPane.setDividerLocation(0.75); - } - }); - } - @Override - public void componentResized(ComponentEvent e) { - } - @Override - public void componentMoved(ComponentEvent e) { - } - @Override - public void componentHidden(ComponentEvent e) { - } - }); - - jLayeredPane1.addComponentListener(new ComponentListener() { - @Override - public void componentShown(ComponentEvent e) { - layeredPaneContent.setSize(jLayeredPane1.getSize()); - } - @Override - public void componentResized(ComponentEvent e) { - layeredPaneContent.setSize(jLayeredPane1.getSize()); - jLayeredPane1.validate(); - } - @Override - public void componentMoved(ComponentEvent e) { - layeredPaneContent.setSize(jLayeredPane1.getSize()); - } - @Override - public void componentHidden(ComponentEvent e) { - } - }); - - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 1; - JPanel anchorPanel = new JPanel(null); - anchorPanel.setOpaque(false); - jLayeredPane1.setLayer(anchorPanel, JLayeredPane.POPUP_LAYER); - jLayeredPane1.add(anchorPanel/* , gridBagConstraints */); - - anchorManager = new DesktopAnchorManager(anchorPanel) { - @Override - protected void layout(RowBrowser anchor) { - try { - anchor.internalFrame.setSelected(true); - } catch (PropertyVetoException e) { - // ignore - } - arrangeLayout(true, anchor); - } - @Override - protected boolean isApplicable(RowBrowser tableBrowser) { - if (tableBrowser.parent == null) { - return false; - } - if (desktop.desktopAnimation != null && desktop.desktopAnimation.isActive()) { - return false; - } - RowBrowser ancestor = tableBrowser.parent; - while (ancestor != null) { - if (ancestor.internalFrame.isVisible() && Math.abs(tableBrowser.internalFrame.getY() - ancestor.internalFrame.getY()) > 2) { - return true; - } - ancestor = ancestor.parent; - } - return false; - } - }; - - if (jScrollPane1.getVerticalScrollBar() != null) { - jScrollPane1.getVerticalScrollBar().setUnitIncrement(16); - jScrollPane1.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - anchorManager.reset(); - } - }); - } - if (jScrollPane1.getHorizontalScrollBar() != null) { - jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16); - jScrollPane1.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() { - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - anchorManager.reset(); - } - }); - } - - hiddenPanel.setVisible(false); - borderBrowserPanel.add(borderBrowser, java.awt.BorderLayout.CENTER); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - gridBagConstraints.weighty = 0; -// jPanel4.add(new JPanel() { -// @Override -// public Dimension getMinimumSize() { -// return new Dimension(1, 300); -// } -// -// private static final long serialVersionUID = -947582621664272477L; -// }, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - gridBagConstraints.weighty = 0; -// borderBrowserTitledPanel.add(new JPanel() { -// @Override -// public Dimension getMinimumSize() { -// return new Dimension(1, 180); -// } -// -// private static final long serialVersionUID = -947582621664272477L; -// }, gridBagConstraints); - - DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, - boolean leaf, int row, boolean hasFocus) { - Component render = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - if (render instanceof JLabel) { - ImageIcon icon = null; - if (value instanceof DefaultMutableTreeNode && ((DefaultMutableTreeNode) value).getUserObject() instanceof TreeNodeForRowBrowser) { - TreeNodeForRowBrowser node = (TreeNodeForRowBrowser) ((DefaultMutableTreeNode) value).getUserObject(); - if (node.rowBrowser.association != null) { - if (node.rowBrowser.association.isInsertDestinationBeforeSource()) { - icon = redIcon; - } else if (node.rowBrowser.association.isInsertSourceBeforeDestination()) { - icon = greenIcon; - } else { - icon = blueIcon; - } - } else { - icon = tableIcon; - } - } else { - if (((JLabel) render).getText().trim().length() > 0) { - icon = navigationIcon; - } - } - ((JLabel) render).setIcon(icon); - } - return render; - } - }; - renderer.setOpenIcon(null); - renderer.setLeafIcon(null); - renderer.setClosedIcon(null); - navigationTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(""))); - - navigationTree.setCellRenderer(renderer); - - ButtonGroup buttonGroup = new ButtonGroup(); - - buttonGroup.add(thumbnailLayoutRadioButtonMenuItem); - buttonGroup.add(tinyLayoutRadioButtonMenuItem); - buttonGroup.add(smallLayoutRadioButtonMenuItem); - buttonGroup.add(mediumLayoutRadioButtonMenuItem); - buttonGroup.add(largeLayoutRadioButtonMenuItem); - - mediumLayoutRadioButtonMenuItem.setSelected(true); - - setTitle(DataBrowserContext.getAppName(false)); - if (embedded) { - analyseMenuItem.setEnabled(false); - dataModelEditorjMenuItem.setEnabled(false); - analyseSQLMenuItem1.setEnabled(false); - } - - // L&F can no longer be changed - jSeparator6.setVisible(false); - view.setVisible(false); - - try { - for (final LookAndFeelInfo lfInfo : UIManager.getInstalledLookAndFeels()) { - JMenuItem mItem = new JMenuItem(); - mItem.setText(lfInfo.getName()); - view.add(mItem); - mItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent arg0) { - setPLAF(lfInfo.getClassName()); - } - }); - } - } catch (Throwable t) { - } - - try { - setIconImage((jailerIcon = UIUtil.readImage("/jailerlight.png")).getImage()); - } catch (Throwable t) { - try { - setIconImage((jailerIcon = UIUtil.readImage("/jailer.gif")).getImage()); - } catch (Throwable t2) { - } - } - - jailerIcon.setImage(UIUtil.scaleIcon(jailerIcon, 16, 16).getImage()); - - if (dbConnectionDialog != null) { - createSession(dbConnectionDialog); - if (session == null) { - return; - } - } - desktop = new Desktop(this.datamodel, jailerIcon, session, this, dbConnectionDialog, schemaMapping == null? new HashMap() : schemaMapping, anchorManager, executionContext) { - @Override - public void openSchemaAnalyzer() { - updateDataModel(); - } - - protected void updateMenu(boolean hasTableBrowser, boolean hasIFrame) { - storeSessionItem.setEnabled(hasIFrame); - closeAllMenuItem.setEnabled(hasIFrame); - addBookmarkMenuItem.setEnabled(hasTableBrowser); - exportDataMenuItem.setEnabled(hasTableBrowser); - createExtractionModelMenuItem.setEnabled(hasTableBrowser); - updateIFramesBar(); - super.updateMenu(hasTableBrowser, hasIFrame); - } - - @Override - protected void updateMenu(LayoutMode layoutMode) { - zoomInMenuItem.setEnabled(layoutMode != Desktop.LayoutMode.LARGE); - zoomOutMenuItem.setEnabled(layoutMode != Desktop.LayoutMode.THUMBNAIL); - tinyLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.TINY); - smallLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.SMALL); - mediumLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.MEDIUM); - largeLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.LARGE); - thumbnailLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.THUMBNAIL); - } - - @Override - protected DataBrowser openNewDataBrowser() { - try { - return DataBrowser.openNewDataBrowser(DataBrowser.this.datamodel.get(), dbConnectionDialog, false, executionContext, null); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - return null; - } - } - - @Override - public void onNewDataModel() { - onNewSession(session); - } - - @Override - protected SQLConsole getSqlConsole(boolean switchToConsole) { - if (switchToConsole) { - workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); - } - return getCurrentSQLConsole(); - } - - @Override - public void onLayoutChanged(boolean isLayouted, boolean scrollToCenter) { - if (!isLayouted) { - arrangeLayout(scrollToCenter); - } - } - - @Override - protected int getRowLimit() { - for (Entry e: rowLimitButtonToLimit.entrySet()) { - if (e.getKey().isSelected()) { - return e.getValue(); - } - } - return ROW_LIMIT_DEFAULT; - } - - @Override - protected boolean isDesktopVisible() { - return workbenchTabbedPane.getSelectedComponent() == desktopSplitPane; - } - - @Override - protected void checkAnchorRetension() { - if (anchorManager != null) { - anchorManager.checkRetention(); - } - } - - @Override - public void updateBookmarksMenu() { - new BookmarksPanel(DataBrowser.this, bookmarkMenu, desktop, executionContext).updateBookmarksMenu(); - } - - @Override - protected void changeColumnOrder(Table table) { - openColumnOrderEditor(table); - } - - @Override - protected void onRowSelect(Table table, Row row) { - if (metaDataDetailsPanel != null) { - MetaDataSource metaDataSource = getMetaDataSource(session); - boolean passTable = metaDataSource.isInitialized() && metaDataSource.getDefaultSchema() != null && metaDataSource.getDefaultSchema().isLoaded(); - if (passTable) { - MDSchema schema = metaDataSource.getSchemaOfTable(table); - if (schema != null && schema != metaDataSource.getDefaultSchema()) { - if (!schema.isLoaded()) { - passTable = false; - schema.loadTables(true, null, null); - } - } - } - metaDataDetailsPanel.showMetaDataDetails(passTable? metaDataSource.toMDTable(table): null, table, row, true, datamodel); - } - } - }; - - desktop.addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseMoved(MouseEvent e) { - double buttonWidth = anchorManager.getButtonWidth() * 1.4; - double minDist = Double.MAX_VALUE; - RowBrowser nearest = null; - for (RowBrowser br : desktop.getBrowsers()) { - if (br.internalFrame != null && br.internalFrame.isVisible()) { - if (e.getX() - buttonWidth <= br.internalFrame.getX()) { - double dx = e.getX() - br.internalFrame.getX(); - double dy = e.getY() - br.internalFrame.getY(); - double dist2 = dx * dx + dy * dy; - if (nearest == null || dist2 < minDist) { - nearest = br; - minDist = dist2; - } - } - } - } - if (nearest != null) { - anchorManager.onTableBrowserNeared(nearest); - } - } - - @Override - public void mouseDragged(MouseEvent e) { - } - }); - - new BookmarksPanel(this, bookmarkMenu, desktop, executionContext).updateBookmarksMenu(); - - jScrollPane1.setViewportView(desktop); - addWindowListener(new WindowListener() { - @Override - public void windowOpened(WindowEvent e) { - } - - @Override - public void windowIconified(WindowEvent e) { - } - - @Override - public void windowDeiconified(WindowEvent e) { - } - - @Override - public void windowDeactivated(WindowEvent e) { - } - - @Override - public void windowClosing(WindowEvent e) { - if (closeAllSQLConsoles()) { - DataBrowser.this.dispose(); - } - } - - @Override - public void windowClosed(WindowEvent e) { - storeLastSession(); - desktop.stop(); - UIUtil.checkTermination(); - } - - @Override - public void windowActivated(WindowEvent e) { - } - }); - - MouseInputAdapter mia = new MouseInputAdapter() { - int m_XDifference, m_YDifference; - Container c; - - @Override - public void mouseDragged(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON3) { - return; - } - c = desktop.getParent(); - if (c instanceof JViewport) { - JViewport jv = (JViewport) c; - Point p = jv.getViewPosition(); - int newX = p.x - (e.getX() - m_XDifference); - int newY = p.y - (e.getY() - m_YDifference); - int maxX = desktop.getWidth() - jv.getWidth(); - int maxY = desktop.getHeight() - jv.getHeight(); - if (newX < 0) - newX = 0; - if (newX > maxX) - newX = maxX; - if (newY < 0) - newY = 0; - if (newY > maxY) - newY = maxY; - jv.setViewPosition(new Point(newX, newY)); - DesktopAnimation.stopScrolling = true; - } - } - - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON3) { - return; - } - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - m_XDifference = e.getX(); - m_YDifference = e.getY(); - DesktopAnimation.stopScrolling = true; - } - - @Override - public void mouseReleased(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON3) { - return; - } - setCursor(null); - } - - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON3) { - return; - } - JPopupMenu popup = new JPopupMenu(); - JMenuItem i = new JMenuItem("Arrange Layout"); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - layoutMenuItemActionPerformed(e); - } - }); - ButtonGroup group = new ButtonGroup(); - popup.add(new JSeparator()); - i = new JRadioButtonMenuItem("Thumbnail Layout"); - i.setSelected(desktop.layoutMode == LayoutMode.THUMBNAIL); - group.add(i); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - thumbnailLayoutRadioButtonMenuItemActionPerformed(e); - } - }); - i = new JRadioButtonMenuItem("Tiny Layout"); - i.setSelected(desktop.layoutMode == LayoutMode.TINY); - group.add(i); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tinyLayoutRadioButtonMenuItemActionPerformed(e); - } - }); - i = new JRadioButtonMenuItem("Small Layout"); - i.setSelected(desktop.layoutMode == LayoutMode.SMALL); - group.add(i); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - smallLayoutRadioButtonMenuItemActionPerformed(e); - } - }); - i = new JRadioButtonMenuItem("Medium Layout"); - i.setSelected(desktop.layoutMode == LayoutMode.MEDIUM); - group.add(i); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - mediumLayoutRadioButtonMenuItemActionPerformed(e); - } - }); - i = new JRadioButtonMenuItem("Large Layout"); - i.setSelected(desktop.layoutMode == LayoutMode.LARGE); - group.add(i); - popup.add(i); - i.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - largeLayoutRadioButtonMenuItemActionPerformed(e); - } - }); - UIUtil.showPopup(desktop, e.getX(), e.getY(), popup); - } - }; - - desktop.addMouseMotionListener(mia); - desktop.addMouseListener(mia); - - AnimationController.registerWindow(this, new AnimationController.AnimationControl() { - @Override - public void setEnabled(boolean enabled) { - desktop.setAnimationEnabled(enabled); - } - }); - - int c = 0; - for (Frame frame: Frame.getFrames()) { - if (frame instanceof DataBrowser && frame.isVisible()) { - c = (c + 1) % 10; - } - } - - setLocation(40 + c * 32, 40 + c * 32); - setSize(980, 640); - - UIUtil.fit(this); - - if (root != null) { - final RowBrowser rb = desktop.addTableBrowser(null, null, root, null, condition, null, null, true); - if (rb != null && rb.internalFrame != null) { - UIUtil.invokeLater(10, new Runnable() { - @Override - public void run() { - try { - rb.internalFrame.setSelected(true); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(rb.internalFrame); - } catch (PropertyVetoException e) { - // ignore - } - } - }); - } - } - schemaNamePanel.addMouseListener(new java.awt.event.MouseAdapter() { - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - desktop.openSchemaMappingDialog(false); - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - in = true; - updateBorder(); - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - schemaNamePanel.setBorder(new javax.swing.border.SoftBevelBorder(in ? javax.swing.border.BevelBorder.LOWERED - : javax.swing.border.BevelBorder.RAISED)); - } - }); - updateStatusBar(); - updateClosureBrowser(null); - - TreeSelectionListener treeListener = new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - if (e.getNewLeadSelectionPath() != null) { - Object lastPathComponent = e.getNewLeadSelectionPath().getLastPathComponent(); - if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); - if (userObject instanceof TreeNodeForRowBrowser) { - updateDataModelView(null); - updateClosureBrowser(((TreeNodeForRowBrowser) userObject).rowBrowser); - if (metaDataPanel != null) { - if (((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane != null) { - if (!(((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table instanceof SqlStatementTable)) { - metaDataPanel.select(((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table); - } - } - } - return; - } - } - } else { - updateClosureBrowser(null); - } - } - }; - - navigationTree.getSelectionModel().addTreeSelectionListener(treeListener); - initDnD(this); - } - - private Map rowLimitButtonToLimit = new HashMap(); - - private void initRowLimitButtons() { - ButtonGroup group = new ButtonGroup(); - JRadioButtonMenuItem def = null; - for (final Integer limit: ROW_LIMITS) { - JRadioButtonMenuItem item = new JRadioButtonMenuItem(limit.toString()); - group.add(item); - rowLimitMenu.add(item); - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent arg0) { - try { - Component sc = workbenchTabbedPane.getSelectedComponent(); - if (sc instanceof SQLConsole) { - SQLConsole sqlConsole = (SQLConsole) sc; - sqlConsole.setRowLimit(limit); - } - desktop.reloadRoots(); - } catch (Exception e) { - UIUtil.showException(DataBrowser.this, "Error", e); - } - } - }); - rowLimitButtonToLimit.put(item, limit); - if (limit == ROW_LIMIT_DEFAULT) { - def = item; - } - } - if (def != null) { - def.setSelected(true); - } - } - - @SuppressWarnings("unchecked") - public void updateNavigationCombobox() { - List tables = new ArrayList(); - - for (Table table: datamodel.get().getTables()) { - tables.add(datamodel.get().getDisplayName(table)); - } - Collections.sort(tables); - @SuppressWarnings({ "rawtypes" }) - ComboBoxModel model = new DefaultComboBoxModel(new Vector(tables)); - - tablesComboBox.setModel(model); - } - - private MetaDataDetailsPanel createMetaDataDetailsPanel(final ExecutionContext executionContext) { - return new MetaDataDetailsPanel(this.datamodel, session, this, executionContext) { - @Override - protected void analyseSchema(String schemaName, boolean withViews, boolean withSynonyms) { - updateDataModel(schemaName, withViews, withSynonyms); - } - }; - } - - private void createSession(DbConnectionDialog dbConnectionDialog) throws Exception { - ConnectionInfo connection = dbConnectionDialog.currentConnection; - BasicDataSource dataSource = UIUtil.createBasicDataSource(this, connection.driverClass, connection.url, connection.user, connection.password, 0, dbConnectionDialog.currentJarURLs()); - SessionForUI newSession = SessionForUI.createSession(dataSource, dataSource.dbms, executionContext.getIsolationLevel(), false, this); - if (newSession != null) { - if (session != null) { - try { - session.shutDown(); - session = null; - } catch (Exception e) { - // ignore - } - } - session = newSession; - List args = new ArrayList(); - dbConnectionDialog.addDbArgs(args); - session.setCliArguments(args); - session.setPassword(dbConnectionDialog.getPassword()); - onNewSession(session); - } - } - - protected void setConnection(DbConnectionDialog dbConnectionDialog) throws Exception { - if (dbConnectionDialog != null) { - dbConnectionDialog = new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); - } - this.dbConnectionDialog = dbConnectionDialog; - desktop.dbConnectionDialog = dbConnectionDialog; - if (dbConnectionDialog != null) { - ConnectionInfo connection = dbConnectionDialog.currentConnection; - if (connection != null) { - createSession(dbConnectionDialog); - if (session != null) { - desktop.session = session; - onNewSession(session); - desktop.openSchemaMappingDialog(true); - updateStatusBar(); - if (desktop != null) { - desktop.updateMenu(); - for (RowBrowser rb : desktop.getBrowsers()) { - rb.browserContentPane.session = session; - rb.browserContentPane.rows.clear(); - } - for (RowBrowser rb : desktop.getRootBrowsers(false)) { - rb.browserContentPane.reloadRows(); - } - } - } - } - } - } - - public void updateStatusBar() { - final int MAX_LENGTH = 50; - ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; - String dburl = connection != null ? (connection.url) : " "; - connectivityState.setToolTipText(dburl); - dburl = connection != null ? (connection.user + "@" + connection.alias) : " "; - if (dburl.length() > MAX_LENGTH) { - dburl = dburl.substring(0, MAX_LENGTH - 3) + "..."; - } - connectivityState.setText(dburl); - DataModel dataModel = datamodel != null ? datamodel.get() : null; - String modelname = "Data Model \"" + (dataModel == null ? DataModel.DEFAULT_NAME : dataModel.getName()) + "\""; - String lastMod = dataModel == null ? "" : dataModel.getLastModifiedAsString(); - if (lastMod.length() > 0) { - lastMod = " (" + lastMod + ")"; - } - modelName.setText(modelname); - modelName.setToolTipText(modelname + lastMod); - - String modelpath = executionContext.getQualifiedDatamodelFolder(); - try { - modelpath = new File(modelpath).getAbsolutePath(); - } catch (Throwable t) { - // use default modelpath - } - modelpath += File.separator; - modelPath.setToolTipText(modelpath); - if (modelpath.length() > MAX_LENGTH + 4) { - modelpath = modelpath.substring(0, MAX_LENGTH / 2) + "..." + modelpath.substring(modelpath.length() - MAX_LENGTH / 2); - } - modelPath.setText(modelpath); - - String nonDefaultSchema = null; - if (desktop.schemaMapping != null) { - for (Map.Entry e : desktop.schemaMapping.entrySet()) { - if (!e.getKey().equalsIgnoreCase(e.getValue())) { - nonDefaultSchema = e.getValue(); - break; - } - } - } - schemaNamePanel.setVisible(nonDefaultSchema != null); - if (nonDefaultSchema != null) { - if (nonDefaultSchema.equals("")) { - schemaName.setText("Default Schema"); - } else { - schemaName.setText("Schema " + nonDefaultSchema + ""); - } - // schemaName.setToolTipText(schemaName.getText()); - } - } - - @SuppressWarnings("deprecation") - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - dummy = new javax.swing.JPanel(); - jScrollPane3 = new javax.swing.JScrollPane(); - jTable1 = new javax.swing.JTable(); - jLayeredPane2 = new javax.swing.JLayeredPane(); - jPanel1 = new javax.swing.JPanel(); - jPanel11 = new javax.swing.JPanel(); - legende1 = new javax.swing.JPanel(); - modelName = new javax.swing.JLabel(); - modelPath = new javax.swing.JLabel(); - legende = new javax.swing.JPanel(); - dependsOn = new javax.swing.JLabel(); - hasDependent = new javax.swing.JLabel(); - associatedWith = new javax.swing.JLabel(); - ignored = new javax.swing.JLabel(); - schemaNamePanel = new javax.swing.JPanel(); - schemaName = new javax.swing.JLabel(); - legende2 = new javax.swing.JPanel(); - connectivityState = new javax.swing.JLabel(); - jPanel2 = new javax.swing.JPanel(); - jSplitPane1 = new javax.swing.JSplitPane(); - jPanel3 = new javax.swing.JPanel(); - jPanel5 = new javax.swing.JPanel(); - workbenchTabbedPane = new javax.swing.JTabbedPane(); - desktopSplitPane = new javax.swing.JSplitPane(); - jLayeredPane1 = new javax.swing.JLayeredPane(); - layeredPaneContent = new javax.swing.JPanel(); - jScrollPane1 = new javax.swing.JScrollPane(); - jInternalFrame1 = new javax.swing.JInternalFrame(); - hiddenPanel = new javax.swing.JPanel(); - closurePanel = new javax.swing.JPanel(); - consoleDummyPanel = new javax.swing.JPanel(); - addSQLConsoleTab = new javax.swing.JPanel(); - jPanel4 = new javax.swing.JPanel(); - jSplitPane4 = new javax.swing.JSplitPane(); - tableTreesTabbedPane = new javax.swing.JTabbedPane(); - navigationPanel = new javax.swing.JPanel(); - navigationTreeScrollPane = new javax.swing.JScrollPane(); - navigationTree = new javax.swing.JTree(); - openTableButton = new javax.swing.JButton(); - tablesCardPanel = new javax.swing.JPanel(); - tablesPanel = new javax.swing.JPanel(); - jPanel6 = new javax.swing.JPanel(); - jScrollPane2 = new javax.swing.JScrollPane(); - jTree1 = new javax.swing.JTree(); - refreshButton = new javax.swing.JButton(); - detailsAndBorderBrowserTabbedPane = new javax.swing.JTabbedPane(); - jPanel7 = new javax.swing.JPanel(); - metaDataViewPanel = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); - jLabel5 = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); - jLabel7 = new javax.swing.JLabel(); - jLabel8 = new javax.swing.JLabel(); - jLabel9 = new javax.swing.JLabel(); - jLabel10 = new javax.swing.JLabel(); - jLabel11 = new javax.swing.JLabel(); - jLabel12 = new javax.swing.JLabel(); - jLabel13 = new javax.swing.JLabel(); - jLabel14 = new javax.swing.JLabel(); - jLabel19 = new javax.swing.JLabel(); - jLabel20 = new javax.swing.JLabel(); - jLabel21 = new javax.swing.JLabel(); - jLabel22 = new javax.swing.JLabel(); - borderBrowserTabPane = new javax.swing.JPanel(); - borderBrowserPanel = new javax.swing.JPanel(); - titleLabel = new javax.swing.JLabel(); - dataModelPanel = new javax.swing.JPanel(); - jLabel26 = new javax.swing.JLabel(); - updateInfoPanel = new javax.swing.JPanel(); - updateInfoLabel = new javax.swing.JLabel(); - downloadButton = new javax.swing.JButton(); - jButton1 = new javax.swing.JButton(); - menuBar = new javax.swing.JMenuBar(); - jMenu1 = new javax.swing.JMenu(); - jMenuItem3 = new javax.swing.JMenuItem(); - closeAllMenuItem = new javax.swing.JMenuItem(); - jSeparator4 = new javax.swing.JPopupMenu.Separator(); - loadScriptMenuItem = new javax.swing.JMenuItem(); - saveScriptMenuItem = new javax.swing.JMenuItem(); - saveScriptAsMenuItem = new javax.swing.JMenuItem(); - jSeparator9 = new javax.swing.JPopupMenu.Separator(); - storeSessionItem = new javax.swing.JMenuItem(); - restoreSessionItem = new javax.swing.JMenuItem(); - jSeparator7 = new javax.swing.JPopupMenu.Separator(); - reconnectMenuItem = new javax.swing.JMenuItem(); - newBrowserjMenuItem = new javax.swing.JMenuItem(); - jSeparator12 = new javax.swing.JPopupMenu.Separator(); - exitMenuItem = new javax.swing.JMenuItem(); - menuTools = new javax.swing.JMenu(); - analyseMenuItem = new javax.swing.JMenuItem(); - dataModelEditorjMenuItem = new javax.swing.JMenuItem(); - schemaMappingMenuItem = new javax.swing.JMenuItem(); - jSeparator2 = new javax.swing.JPopupMenu.Separator(); - columnOrderItem = new javax.swing.JMenuItem(); - jSeparator11 = new javax.swing.JPopupMenu.Separator(); - analyseSQLMenuItem1 = new javax.swing.JMenuItem(); - jSeparator10 = new javax.swing.JPopupMenu.Separator(); - showDataModelMenuItem = new javax.swing.JCheckBoxMenuItem(); - checkPKMenuItem = new javax.swing.JMenuItem(); - consistencyCheckMenuItem1 = new javax.swing.JMenuItem(); - jviewMenu = new javax.swing.JMenu(); - rowLimitMenu = new javax.swing.JMenu(); - bookmarkMenu = new javax.swing.JMenu(); - addBookmarkMenuItem = new javax.swing.JMenuItem(); - editBookmarkMenuItem = new javax.swing.JMenuItem(); - jSeparator13 = new javax.swing.JPopupMenu.Separator(); - jMenu2 = new javax.swing.JMenu(); - exportDataMenuItem = new javax.swing.JMenuItem(); - dataImport = new javax.swing.JMenuItem(); - jSeparator8 = new javax.swing.JPopupMenu.Separator(); - createExtractionModelMenuItem = new javax.swing.JMenuItem(); - consistencyCheckMenuItem = new javax.swing.JMenuItem(); - createCLIItem = new javax.swing.JMenuItem(); - menuWindow = new javax.swing.JMenu(); - layoutMenuItem = new javax.swing.JMenuItem(); - jSeparator5 = new javax.swing.JPopupMenu.Separator(); - zoomInMenuItem = new javax.swing.JMenuItem(); - zoomOutMenuItem = new javax.swing.JMenuItem(); - jSeparator15 = new javax.swing.JPopupMenu.Separator(); - thumbnailLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); - tinyLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); - smallLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); - mediumLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); - largeLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); - jSeparator1 = new javax.swing.JPopupMenu.Separator(); - newWindowMenuItem = new javax.swing.JMenuItem(); - jSeparator6 = new javax.swing.JPopupMenu.Separator(); - view = new javax.swing.JMenu(); - jMenu3 = new javax.swing.JMenu(); - nativeLAFCheckBoxMenuItem = new javax.swing.JCheckBoxMenuItem(); - helpMenu = new javax.swing.JMenu(); - jMenuItem4 = new javax.swing.JMenuItem(); - helpForum = new javax.swing.JMenuItem(); - downloadMenuItem = new javax.swing.JMenuItem(); - jSeparator14 = new javax.swing.JPopupMenu.Separator(); - aboutMenuItem = new javax.swing.JMenuItem(); - - jTable1.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null}, - {null, null, null, null} - }, - new String [] { - "Title 1", "Title 2", "Title 3", "Title 4" - } - )); - jScrollPane3.setViewportView(jTable1); - - dummy.add(jScrollPane3); - - jLayeredPane2.setLayout(new java.awt.GridBagLayout()); - - jPanel1.setLayout(new java.awt.GridBagLayout()); - - jPanel11.setLayout(new java.awt.GridBagLayout()); - - legende1.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - legende1.setLayout(new java.awt.GridBagLayout()); - - modelName.setFont(modelName.getFont().deriveFont(modelName.getFont().getSize()+1f)); - modelName.setText("Data Model \"Demo\""); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 12); - legende1.add(modelName, gridBagConstraints); - - modelPath.setFont(modelPath.getFont().deriveFont(modelPath.getFont().getSize()+1f)); - modelPath.setForeground(java.awt.Color.gray); - modelPath.setText("/home/jailer/datamodel/"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - legende1.add(modelPath, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - jPanel11.add(legende1, gridBagConstraints); - - legende.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - legende.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 0)); - - dependsOn.setFont(dependsOn.getFont().deriveFont(dependsOn.getFont().getSize()+1f)); - dependsOn.setForeground(new java.awt.Color(170, 0, 0)); - dependsOn.setText(" depends on (has parent) "); - legende.add(dependsOn); - - hasDependent.setFont(hasDependent.getFont().deriveFont(hasDependent.getFont().getSize()+1f)); - hasDependent.setForeground(new java.awt.Color(0, 112, 0)); - hasDependent.setText(" has dependent (has child) "); - legende.add(hasDependent); - - associatedWith.setFont(associatedWith.getFont().deriveFont(associatedWith.getFont().getSize()+1f)); - associatedWith.setForeground(new java.awt.Color(0, 100, 255)); - associatedWith.setText(" associated with"); - legende.add(associatedWith); - - ignored.setFont(ignored.getFont().deriveFont(ignored.getFont().getSize()+1f)); - ignored.setForeground(new java.awt.Color(153, 153, 153)); - ignored.setText(" disabled "); - legende.add(ignored); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - jPanel11.add(legende, gridBagConstraints); - - schemaNamePanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - schemaNamePanel.setLayout(new java.awt.GridBagLayout()); - - schemaName.setFont(schemaName.getFont().deriveFont(schemaName.getFont().getSize()+1f)); - schemaName.setText("Schema"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 12); - schemaNamePanel.add(schemaName, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - jPanel11.add(schemaNamePanel, gridBagConstraints); - - legende2.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); - legende2.setLayout(new java.awt.GridBagLayout()); - - connectivityState.setFont(connectivityState.getFont().deriveFont(connectivityState.getFont().getSize()+1f)); - connectivityState.setText("offline"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 6); - legende2.add(connectivityState, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); - jPanel11.add(legende2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - jPanel1.add(jPanel11, gridBagConstraints); - - jPanel2.setLayout(new java.awt.GridBagLayout()); - - jSplitPane1.setDividerLocation(340); - jSplitPane1.setContinuousLayout(true); - jSplitPane1.setOneTouchExpandable(true); - - jPanel3.setLayout(new java.awt.GridBagLayout()); - jSplitPane1.setLeftComponent(jPanel3); - - jPanel5.setLayout(new java.awt.GridBagLayout()); - - workbenchTabbedPane.addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent evt) { - workbenchTabbedPaneStateChanged(evt); - } - }); - - desktopSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - desktopSplitPane.setResizeWeight(0.95); - desktopSplitPane.setContinuousLayout(true); - desktopSplitPane.setOneTouchExpandable(true); - - layeredPaneContent.setLayout(new java.awt.GridBagLayout()); - - jScrollPane1.setAutoscrolls(true); - jScrollPane1.setWheelScrollingEnabled(false); - jScrollPane1.addMouseWheelListener(new java.awt.event.MouseWheelListener() { - public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { - jScrollPane1MouseWheelMoved(evt); - } - }); - - jInternalFrame1.setVisible(true); - jScrollPane1.setViewportView(jInternalFrame1); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - layeredPaneContent.add(jScrollPane1, gridBagConstraints); - - hiddenPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - layeredPaneContent.add(hiddenPanel, gridBagConstraints); - - jLayeredPane1.setLayer(layeredPaneContent, javax.swing.JLayeredPane.PALETTE_LAYER); - jLayeredPane1.add(layeredPaneContent); - layeredPaneContent.setBounds(0, 0, 24, 42); - - desktopSplitPane.setLeftComponent(jLayeredPane1); - - closurePanel.setLayout(new java.awt.GridBagLayout()); - desktopSplitPane.setRightComponent(closurePanel); - - workbenchTabbedPane.addTab("Desktop", desktopSplitPane); - workbenchTabbedPane.addTab("SQL Console", consoleDummyPanel); - workbenchTabbedPane.addTab("+", addSQLConsoleTab); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(1, 0, 0, 0); - jPanel5.add(workbenchTabbedPane, gridBagConstraints); - - jSplitPane1.setRightComponent(jPanel5); - - jPanel4.setLayout(new java.awt.GridBagLayout()); - - jSplitPane4.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - jSplitPane4.setResizeWeight(1.0); - jSplitPane4.setContinuousLayout(true); - jSplitPane4.setOneTouchExpandable(true); - - navigationPanel.setLayout(new java.awt.GridBagLayout()); - - navigationTree.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - navigationTreeMouseClicked(evt); - } - }); - navigationTreeScrollPane.setViewportView(navigationTree); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - navigationPanel.add(navigationTreeScrollPane, gridBagConstraints); - - openTableButton.setText("Open"); - openTableButton.setToolTipText("Open table browser for the selected table"); - openTableButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - openTableButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); - navigationPanel.add(openTableButton, gridBagConstraints); - - tableTreesTabbedPane.addTab("Navigation", navigationPanel); - - tablesCardPanel.setLayout(new java.awt.CardLayout()); - - tablesPanel.setLayout(new java.awt.BorderLayout()); - tablesCardPanel.add(tablesPanel, "tables"); - - jPanel6.setLayout(new java.awt.GridBagLayout()); - - javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("loading database meta data..."); - jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); - jTree1.setSelectionModel(null); - jScrollPane2.setViewportView(jTree1); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel6.add(jScrollPane2, gridBagConstraints); - - refreshButton.setText("Refresh"); - refreshButton.setToolTipText("Refresh Database Meta Data Cache"); - refreshButton.setEnabled(false); - refreshButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - refreshButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - jPanel6.add(refreshButton, gridBagConstraints); - - tablesCardPanel.add(jPanel6, "loading"); - - tableTreesTabbedPane.addTab("Database", tablesCardPanel); - - jSplitPane4.setLeftComponent(tableTreesTabbedPane); - - jPanel7.setLayout(new java.awt.GridBagLayout()); - - metaDataViewPanel.setLayout(new javax.swing.BoxLayout(metaDataViewPanel, javax.swing.BoxLayout.LINE_AXIS)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridheight = 30; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel7.add(metaDataViewPanel, gridBagConstraints); - - jLabel1.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - jPanel7.add(jLabel1, gridBagConstraints); - - jLabel3.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - jPanel7.add(jLabel3, gridBagConstraints); - - jLabel4.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - jPanel7.add(jLabel4, gridBagConstraints); - - jLabel5.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 4; - jPanel7.add(jLabel5, gridBagConstraints); - - jLabel6.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 5; - jPanel7.add(jLabel6, gridBagConstraints); - - jLabel7.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 6; - jPanel7.add(jLabel7, gridBagConstraints); - - jLabel8.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 7; - jPanel7.add(jLabel8, gridBagConstraints); - - jLabel9.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 8; - jPanel7.add(jLabel9, gridBagConstraints); - - jLabel10.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 10; - jPanel7.add(jLabel10, gridBagConstraints); - - jLabel11.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 11; - jPanel7.add(jLabel11, gridBagConstraints); - - jLabel12.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 12; - jPanel7.add(jLabel12, gridBagConstraints); - - jLabel13.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 13; - jPanel7.add(jLabel13, gridBagConstraints); - - jLabel14.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 14; - jPanel7.add(jLabel14, gridBagConstraints); - - jLabel19.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 19; - jPanel7.add(jLabel19, gridBagConstraints); - - jLabel20.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 20; - jPanel7.add(jLabel20, gridBagConstraints); - - jLabel21.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 21; - jPanel7.add(jLabel21, gridBagConstraints); - - jLabel22.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 22; - jPanel7.add(jLabel22, gridBagConstraints); - - detailsAndBorderBrowserTabbedPane.addTab("Details", jPanel7); - - borderBrowserTabPane.setLayout(new java.awt.GridBagLayout()); - - borderBrowserPanel.setLayout(new java.awt.BorderLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - borderBrowserTabPane.add(borderBrowserPanel, gridBagConstraints); - - titleLabel.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0); - borderBrowserTabPane.add(titleLabel, gridBagConstraints); - - detailsAndBorderBrowserTabbedPane.addTab("Closure Border", borderBrowserTabPane); - - dataModelPanel.setLayout(new java.awt.BorderLayout()); - - jLabel26.setText(" Loading..."); - dataModelPanel.add(jLabel26, java.awt.BorderLayout.CENTER); - - detailsAndBorderBrowserTabbedPane.addTab("Data Model", dataModelPanel); - - jSplitPane4.setRightComponent(detailsAndBorderBrowserTabbedPane); - detailsAndBorderBrowserTabbedPane.getAccessibleContext().setAccessibleName("Closure Border"); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel4.add(jSplitPane4, gridBagConstraints); - - jSplitPane1.setLeftComponent(jPanel4); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel2.add(jSplitPane1, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jPanel2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jLayeredPane2.add(jPanel1, gridBagConstraints); - - updateInfoPanel.setBackground(new java.awt.Color(255, 255, 236)); - updateInfoPanel.setLayout(new java.awt.GridBagLayout()); - - updateInfoLabel.setText("Release x available"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); - updateInfoPanel.add(updateInfoLabel, gridBagConstraints); - - downloadButton.setText("Download"); - downloadButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - downloadButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 0); - updateInfoPanel.add(downloadButton, gridBagConstraints); - - jButton1.setText("Close"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 2; - gridBagConstraints.insets = new java.awt.Insets(0, 2, 4, 4); - updateInfoPanel.add(jButton1, gridBagConstraints); - - jLayeredPane2.setLayer(updateInfoPanel, javax.swing.JLayeredPane.MODAL_LAYER); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 72, 24); - jLayeredPane2.add(updateInfoPanel, gridBagConstraints); - - getContentPane().add(jLayeredPane2, java.awt.BorderLayout.CENTER); - - jMenu1.setText("File"); - - jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, java.awt.event.InputEvent.CTRL_MASK)); - jMenuItem3.setText("Open Table"); - jMenuItem3.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jMenuItem3ActionPerformed(evt); - } - }); - jMenu1.add(jMenuItem3); - - closeAllMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)); - closeAllMenuItem.setText("Close All Tables"); - closeAllMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - closeAllMenuItemActionPerformed(evt); - } - }); - jMenu1.add(closeAllMenuItem); - jMenu1.add(jSeparator4); - - loadScriptMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK)); - loadScriptMenuItem.setText("Open SQL Script..."); - loadScriptMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - loadScriptMenuItemActionPerformed(evt); - } - }); - jMenu1.add(loadScriptMenuItem); - - saveScriptMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK)); - saveScriptMenuItem.setText("Save"); - saveScriptMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - saveScriptMenuItemActionPerformed(evt); - } - }); - jMenu1.add(saveScriptMenuItem); - - saveScriptAsMenuItem.setText("Save as..."); - saveScriptAsMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - saveScriptAsMenuItemActionPerformed(evt); - } - }); - jMenu1.add(saveScriptAsMenuItem); - jMenu1.add(jSeparator9); - - storeSessionItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK)); - storeSessionItem.setText("Store Layout"); - storeSessionItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - storeSessionItemActionPerformed(evt); - } - }); - jMenu1.add(storeSessionItem); - - restoreSessionItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK)); - restoreSessionItem.setText("Restore Layout"); - restoreSessionItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - restoreSessionItemActionPerformed(evt); - } - }); - jMenu1.add(restoreSessionItem); - jMenu1.add(jSeparator7); - - reconnectMenuItem.setText("Reconnect..."); - reconnectMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - reconnectMenuItemActionPerformed(evt); - } - }); - jMenu1.add(reconnectMenuItem); - - newBrowserjMenuItem.setText("New Data Browser"); - newBrowserjMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - newBrowserjMenuItemActionPerformed(evt); - } - }); - jMenu1.add(newBrowserjMenuItem); - jMenu1.add(jSeparator12); - - exitMenuItem.setText("Exit"); - exitMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - exitMenuItemActionPerformed(evt); - } - }); - jMenu1.add(exitMenuItem); - - menuBar.add(jMenu1); - - menuTools.setText("Model"); - - analyseMenuItem.setText("Analyse Database"); - analyseMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - analyseMenuItemActionPerformed(evt); - } - }); - menuTools.add(analyseMenuItem); - - dataModelEditorjMenuItem.setText("Data Model Editor"); - dataModelEditorjMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - dataModelEditorjMenuItemActionPerformed(evt); - } - }); - menuTools.add(dataModelEditorjMenuItem); - - schemaMappingMenuItem.setText("Schema Mapping"); - schemaMappingMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - schemaMappingMenuItemActionPerformed(evt); - } - }); - menuTools.add(schemaMappingMenuItem); - menuTools.add(jSeparator2); - - columnOrderItem.setText("Column Ordering"); - columnOrderItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - columnOrderItemActionPerformed(evt); - } - }); - menuTools.add(columnOrderItem); - menuTools.add(jSeparator11); - - analyseSQLMenuItem1.setText("Analyze SQL Script"); - analyseSQLMenuItem1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - analyseSQLMenuItem1ActionPerformed(evt); - } - }); - menuTools.add(analyseSQLMenuItem1); - menuTools.add(jSeparator10); - - showDataModelMenuItem.setText("Show Data Model"); - showDataModelMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - showDataModelMenuItemActionPerformed(evt); - } - }); - menuTools.add(showDataModelMenuItem); - - checkPKMenuItem.setText("Check Primary Keys"); - checkPKMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - checkPKMenuItemActionPerformed(evt); - } - }); - menuTools.add(checkPKMenuItem); - - consistencyCheckMenuItem1.setText("Check referential Consistency"); - consistencyCheckMenuItem1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - consistencyCheckMenuItem1ActionPerformed(evt); - } - }); - menuTools.add(consistencyCheckMenuItem1); - - menuBar.add(menuTools); - - jviewMenu.setText("View"); - - rowLimitMenu.setText("Row Limit"); - rowLimitMenu.setToolTipText("Desktop Row Limit"); - jviewMenu.add(rowLimitMenu); - - menuBar.add(jviewMenu); - - bookmarkMenu.setText("Bookmark"); - - addBookmarkMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_B, java.awt.event.InputEvent.CTRL_MASK)); - addBookmarkMenuItem.setText("Add Bookmark"); - addBookmarkMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - addBookmarkMenuItemActionPerformed(evt); - } - }); - bookmarkMenu.add(addBookmarkMenuItem); - - editBookmarkMenuItem.setText("Edit Bookmarks"); - editBookmarkMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - editBookmarkMenuItemActionPerformed(evt); - } - }); - bookmarkMenu.add(editBookmarkMenuItem); - bookmarkMenu.add(jSeparator13); - - menuBar.add(bookmarkMenu); - - jMenu2.setText("Tools"); - - exportDataMenuItem.setText("Export Data"); - exportDataMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - exportDataMenuItemActionPerformed(evt); - } - }); - jMenu2.add(exportDataMenuItem); - - dataImport.setLabel("Import SQL Data"); - dataImport.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - dataImportActionPerformed(evt); - } - }); - jMenu2.add(dataImport); - jMenu2.add(jSeparator8); - - createExtractionModelMenuItem.setText("Create Extraction Model"); - createExtractionModelMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - createExtractionModelMenuItemActionPerformed(evt); - } - }); - jMenu2.add(createExtractionModelMenuItem); - - consistencyCheckMenuItem.setText("Referential Consistency Check"); - consistencyCheckMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - consistencyCheckMenuItemActionPerformed(evt); - } - }); - jMenu2.add(consistencyCheckMenuItem); - - createCLIItem.setText("Show Command Line"); - createCLIItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - createCLIItemActionPerformed(evt); - } - }); - jMenu2.add(createCLIItem); - - menuBar.add(jMenu2); - - menuWindow.setText("Window"); - - layoutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, java.awt.event.InputEvent.CTRL_MASK)); - layoutMenuItem.setText("Arrange Layout"); - layoutMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - layoutMenuItemActionPerformed(evt); - } - }); - menuWindow.add(layoutMenuItem); - menuWindow.add(jSeparator5); - - zoomInMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_PLUS, java.awt.event.InputEvent.CTRL_MASK)); - zoomInMenuItem.setText("Zoom In (Mouse Wheel Up)"); - zoomInMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - zoomInMenuItemActionPerformed(evt); - } - }); - menuWindow.add(zoomInMenuItem); - - zoomOutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_MINUS, java.awt.event.InputEvent.CTRL_MASK)); - zoomOutMenuItem.setText("Zoom Out (Mouse Wheel Down)"); - zoomOutMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - zoomOutMenuItemActionPerformed(evt); - } - }); - menuWindow.add(zoomOutMenuItem); - menuWindow.add(jSeparator15); - - thumbnailLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_0, java.awt.event.InputEvent.CTRL_MASK)); - thumbnailLayoutRadioButtonMenuItem.setText("Thumbnail Layout"); - thumbnailLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - thumbnailLayoutRadioButtonMenuItemActionPerformed(evt); - } - }); - menuWindow.add(thumbnailLayoutRadioButtonMenuItem); - - tinyLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_1, java.awt.event.InputEvent.CTRL_MASK)); - tinyLayoutRadioButtonMenuItem.setText("Tiny Layout"); - tinyLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - tinyLayoutRadioButtonMenuItemActionPerformed(evt); - } - }); - menuWindow.add(tinyLayoutRadioButtonMenuItem); - - smallLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_2, java.awt.event.InputEvent.CTRL_MASK)); - smallLayoutRadioButtonMenuItem.setText("Small Layout"); - smallLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - smallLayoutRadioButtonMenuItemActionPerformed(evt); - } - }); - menuWindow.add(smallLayoutRadioButtonMenuItem); - - mediumLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_3, java.awt.event.InputEvent.CTRL_MASK)); - mediumLayoutRadioButtonMenuItem.setText("Medium Layout"); - mediumLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - mediumLayoutRadioButtonMenuItemActionPerformed(evt); - } - }); - menuWindow.add(mediumLayoutRadioButtonMenuItem); - - largeLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_4, java.awt.event.InputEvent.CTRL_MASK)); - largeLayoutRadioButtonMenuItem.setText("Large Layout"); - largeLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - largeLayoutRadioButtonMenuItemActionPerformed(evt); - } - }); - menuWindow.add(largeLayoutRadioButtonMenuItem); - menuWindow.add(jSeparator1); - - newWindowMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK)); - newWindowMenuItem.setText("New Window"); - newWindowMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - newWindowMenuItemActionPerformed(evt); - } - }); - menuWindow.add(newWindowMenuItem); - menuWindow.add(jSeparator6); - - view.setText("Look&Feel"); - menuWindow.add(view); - - menuBar.add(menuWindow); - - jMenu3.setText("Settings"); - - nativeLAFCheckBoxMenuItem.setText("Native Look&Feel"); - nativeLAFCheckBoxMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - nativeLAFCheckBoxMenuItemActionPerformed(evt); - } - }); - jMenu3.add(nativeLAFCheckBoxMenuItem); - - menuBar.add(jMenu3); - - helpMenu.setText("Help"); - - jMenuItem4.setText("Manual"); - jMenuItem4.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jMenuItem4ActionPerformed(evt); - } - }); - helpMenu.add(jMenuItem4); - - helpForum.setText("Forum"); - helpForum.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - helpForumActionPerformed(evt); - } - }); - helpMenu.add(helpForum); - - downloadMenuItem.setText("Download Latest Version"); - downloadMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - downloadMenuItemActionPerformed(evt); - } - }); - helpMenu.add(downloadMenuItem); - helpMenu.add(jSeparator14); - - aboutMenuItem.setText("About Jailer"); - aboutMenuItem.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - aboutMenuItemActionPerformed(evt); - } - }); - helpMenu.add(aboutMenuItem); - - menuBar.add(helpMenu); - - setJMenuBar(menuBar); - - pack(); - }// //GEN-END:initComponents - - private void exportDataMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportDataMenuItemActionPerformed - desktop.createExtractionModel(true); - }//GEN-LAST:event_exportDataMenuItemActionPerformed - - private void dataImportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataImportActionPerformed - if (!UIUtil.canRunJailer()) { - return; - } - try { - String sqlFile = UIUtil.choseFile(null, ".", "Data Import", ".sql", this, false, true); - if (sqlFile != null) { - DbConnectionDialog dcd = new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); - if (dcd.connect("Data Import")) { - List args = new ArrayList(); - args.add("import"); - args.add(sqlFile); - dcd.addDbArgs(args); - ImportDialog importDialog = new ImportDialog(this, sqlFile, args, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), true); - if (importDialog.isOk) { - importDialog.fillCLIArgs(args); - ResultConsumer consumer = new ResultConsumer() { - @Override - public void consume(boolean result, Throwable t) { - } - public void cleanUp() { - try { - if (desktop != null) { - desktop.updateMenu(); - for (RowBrowser rb : desktop.getBrowsers()) { - rb.browserContentPane.session = session; - rb.browserContentPane.rows.clear(); - } - for (RowBrowser rb : desktop.getRootBrowsers(false)) { - rb.browserContentPane.reloadRows(); - } - } - } catch (Exception e) { - UIUtil.showException(DataBrowser.this, "Error", e, session); - } - } - }; - UIUtil.runJailer(this, args, false, true, false, - false, null, dcd.getUser(), dcd.getPassword(), null, null, false, - true, false, false, false, consumer, executionContext); - } - } - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - }//GEN-LAST:event_dataImportActionPerformed - - private void newBrowserjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newBrowserjMenuItemActionPerformed - createFrame(); - }//GEN-LAST:event_newBrowserjMenuItemActionPerformed - - private void openTableButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openTableButtonActionPerformed - if (tablesComboBox.getSelectedItem() != null) { - String tableName = tablesComboBox.getSelectedItem().toString(); - desktop.addTableBrowser(null, null, datamodel.get().getTableByDisplayName(tableName), null, "", null, null, true); - switchToDesktop(); - } - }//GEN-LAST:event_openTableButtonActionPerformed - - private boolean ignoreTabChangeEvent = false; - - private void workbenchTabbedPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_workbenchTabbedPaneStateChanged - if (initialized) { - if (workbenchTabbedPane.getSelectedComponent() == addSQLConsoleTab) { - if (!ignoreTabChangeEvent) { - try { - createNewSQLConsole(getMetaDataSource(session)); - } catch (SQLException e) { - UIUtil.showException(this, "Error", e); - } - } - } else if (!(workbenchTabbedPane.getSelectedComponent() instanceof SQLConsole)) { - for (SQLConsole sqlConsole: sqlConsoles) { - if (sqlConsole.getDataHasChanged()) { - try { - desktop.reloadRoots(); - } catch (Exception e) { - UIUtil.showException(this, "Error", e); - } - sqlConsole.setDataHasChanged(false); - } - } - tableTreesTabbedPane.setSelectedComponent(navigationPanel); - } else { - SQLConsole sqlConsole = getCurrentSQLConsole(); - if (sqlConsole != null) { - tableTreesTabbedPane.setSelectedComponent(tablesCardPanel); - sqlConsole.grabFocus(); - sqlConsole.update(); - } - } - updateLoadSaveScriptMenuItemsState(); - } - }//GEN-LAST:event_workbenchTabbedPaneStateChanged - - private void showDataModelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showDataModelMenuItemActionPerformed - detailsAndBorderBrowserTabbedPane.setSelectedComponent(dataModelPanel); - }//GEN-LAST:event_showDataModelMenuItemActionPerformed - - private void consistencyCheckMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_consistencyCheckMenuItemActionPerformed - new ConstraintChecker(this, datamodel.get(), true, session) { - @Override - protected void openTableBrowser(Table source, String where) { - workbenchTabbedPane.setSelectedComponent(desktopSplitPane); - desktop.addTableBrowser(null, null, source, null, UIUtil.toSingleLineSQL(new BasicFormatterImpl().format(where)), null, null, true); - } - }; - }//GEN-LAST:event_consistencyCheckMenuItemActionPerformed - - private void newWindowMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_newWindowMenuItemActionPerformed - try { - openNewDataBrowser(datamodel.get(), dbConnectionDialog, false, executionContext, null); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - }// GEN-LAST:event_newWindowMenuItemActionPerformed - - private void reconnectMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_reconnectMenuItemActionPerformed - synchronized (this) { - if (dbConnectionDialog.connect("Reconnect", true)) { - try { - setConnection(dbConnectionDialog); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - } - } - }// GEN-LAST:event_reconnectMenuItemActionPerformed - - private void thumbnailLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_thumbnailLayoutRadioButtonMenuItemActionPerformed - desktop.rescaleLayout(Desktop.LayoutMode.THUMBNAIL, null); - wheelzoomTip(); - }// GEN-LAST:event_thumbnailLayoutRadioButtonMenuItemActionPerformed - - private void jMenuItem3ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem1ActionPerformed - openNewTableBrowser(false); - }// GEN-LAST:event_jMenuItem1ActionPerformed - - private void closeAllMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cloaseAllMenuItemActionPerformed - desktop.closeAll(); - }// GEN-LAST:event_cloaseAllMenuItemActionPerformed - - private void schemaMappingMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_schemaMappingMenuItemActionPerformed - desktop.openSchemaMappingDialog(false); - }// GEN-LAST:event_schemaMappingMenuItemActionPerformed - - private void jMenuItem4ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem4ActionPerformed - try { - BrowserLauncher.openURL(new URI("http://jailer.sourceforge.net/data-browsing.html"), this); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - }// GEN-LAST:event_jMenuItem4ActionPerformed - - private void createExtractionModelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_createExtractionModelMenuItemActionPerformed - desktop.createExtractionModel(false); - }// GEN-LAST:event_createExtractionModelMenuItemActionPerformed - - private void storeSessionItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_storeSessionItemActionPerformed - desktop.storeSession((BookmarksPanel) null); - }// GEN-LAST:event_storeSessionItemActionPerformed - - private void restoreSessionItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_restoreSessionItemActionPerformed - UISettings.s6 += 10000000; - desktop.restoreSession(null, null); - }// GEN-LAST:event_restoreSessionItemActionPerformed - - private void tinyLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tinyLayoutRadioButtonMenuItemActionPerformed - desktop.rescaleLayout(Desktop.LayoutMode.TINY, null); - wheelzoomTip(); - }// GEN-LAST:event_tinyLayoutRadioButtonMenuItemActionPerformed - - private void wheelzoomTip() { - TipDialog.showTip(this, "WHEELZOOM", "You can use the mouse-wheel to zoom in or out."); - } - - private void smallLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_smallLayoutRadioButtonMenuItemActionPerformed - desktop.rescaleLayout(Desktop.LayoutMode.SMALL, null); - wheelzoomTip(); - }// GEN-LAST:event_smallLayoutRadioButtonMenuItemActionPerformed - - private void mediumLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_mediumLayoutRadioButtonMenuItemActionPerformed - desktop.rescaleLayout(Desktop.LayoutMode.MEDIUM, null); - wheelzoomTip(); - }// GEN-LAST:event_mediumLayoutRadioButtonMenuItemActionPerformed - - private void largeLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_largeLayoutRadioButtonMenuItemActionPerformed - desktop.rescaleLayout(Desktop.LayoutMode.LARGE, null); - wheelzoomTip(); - }// GEN-LAST:event_largeLayoutRadioButtonMenuItemActionPerformed - - private void navigationTreeMouseClicked(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_navigationTreeMouseClicked - TreePath node = navigationTree.getPathForLocation(evt.getX(), evt.getY()); - if (node == null) { - for (int x = navigationTree.getWidth(); x > 0; x -= 32) { - node = navigationTree.getPathForLocation(x, evt.getY()); - if (node != null) { - break; - } - } - } - Object sel = null; - Object selNode = null; - RowBrowser rowBrowser = null; - int row = 0; - if (node != null) { - sel = node.getLastPathComponent(); - if (sel instanceof DefaultMutableTreeNode) { - selNode = ((DefaultMutableTreeNode) sel).getUserObject(); - if (selNode instanceof TreeNodeForRowBrowser) { - rowBrowser = ((TreeNodeForRowBrowser) selNode).rowBrowser; - row = ((TreeNodeForRowBrowser) selNode).rowIndex; - } - } - } - if (evt.getButton() == MouseEvent.BUTTON1) { - if (rowBrowser != null) { - desktop.scrollToCenter(rowBrowser.internalFrame); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(rowBrowser.internalFrame); - navigationTree.setSelectionPath(node); - } - } - if (evt.getButton() == MouseEvent.BUTTON3) { - if (evt.getClickCount() == 1) { - if (rowBrowser != null) { - navigationTree.setSelectionRow(row); - JPopupMenu popup = rowBrowser.browserContentPane.createPopupMenu(null, -1, 0, 0, false); - if (popup != null) { - JPopupMenu popup2 = rowBrowser.browserContentPane.createSqlPopupMenu(-1, 0, 0, true, navigationTreeScrollPane); - if (popup2.getComponentCount() > 0 && popup.getComponentCount() > 0) { - popup.add(new JSeparator()); - } - for (Component c : popup2.getComponents()) { - popup.add(c); - } - UIUtil.fit(popup); - UIUtil.showPopup(evt.getComponent(), evt.getX(), evt.getY(), popup); - } - } - } - } - }// GEN-LAST:event_navigationTreeMouseClicked - - private void layoutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_layoutMenuItemActionPerformed - arrangeLayout(true); - }// GEN-LAST:event_layoutMenuItemActionPerformed - - public void arrangeLayout(boolean scrollToCenter) { - arrangeLayout(scrollToCenter, Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor? null : anchorManager.getNewestBrowser()); - anchorManager.setNewestBrowser(null); - } - - public void arrangeLayout(boolean scrollToCenter, RowBrowser anchor) { - UIUtil.setWaitCursor(this); - try { - desktop.layoutBrowser(null, scrollToCenter, anchor); - } finally { - UIUtil.resetWaitCursor(this); - } - } - - private void jScrollPane1MouseWheelMoved(java.awt.event.MouseWheelEvent evt) {// GEN-FIRST:event_jScrollPane1MouseWheelMoved - long currentTime = System.currentTimeMillis(); - desktop.startRescaleMode(currentTime, evt); - desktop.onMouseWheelMoved(evt, currentTime); - desktop.onMouseWheelMoved(evt, jScrollPane1, currentTime); - }// GEN-LAST:event_jScrollPane1MouseWheelMoved - - private void openNewTableBrowser(boolean offerAlternatives) { - new NewTableBrowser(this, datamodel.get(), offerAlternatives) { - @Override - void openTableBrowser(String tableName) { - desktop.addTableBrowser(null, null, datamodel.get().getTableByDisplayName(tableName), null, "", null, null, true); - switchToDesktop(); - } - - @Override - void openDatabaseAnalyzer() { - updateDataModel(); - } - - @Override - void restoreSession() { - desktop.restoreSession(null, null); - } - }; - } - - private void helpForumActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_helpForumActionPerformed - try { - BrowserLauncher.openURL(new URI("https://sourceforge.net/p/jailer/discussion/"), this); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - }// GEN-LAST:event_helpForumActionPerformed - - private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem4ActionPerformed - About about = new About(this, true); - about.setTitle(DataBrowserContext.getAppName(false)); - about.pack(); - about.setLocation(getLocation().x + (getSize().width - about.getPreferredSize().width) / 2, - getLocation().y + (getSize().height - about.getPreferredSize().height) / 2); - about.setVisible(true); - }// GEN-LAST:event_jMenuItem4ActionPerformed - - private void analyseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_analyseMenuItemActionPerformed - updateDataModel(); - }// GEN-LAST:event_analyseMenuItemActionPerformed - - private void dataModelEditorjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_dataModelEditorjMenuItemActionPerformed - openDataModelEditor(false); - }// GEN-LAST:event_dataModelEditorjMenuItemActionPerformed - - /** - * File in which plaf-setting is stored. - */ - private static final String PLAFSETTING = ".plaf2.ui"; - - /** - * @param args the command line arguments - */ - public static void main(String args[]) { - try { - start(args); - } catch (Throwable t) { - t.printStackTrace(); - UIUtil.showException(null, "Error", t); - } - } - - /** - * @param args - * the command line arguments - */ - private static void start(final String args[]) { - try { - Environment.init(); - } catch (Throwable e) { - e.printStackTrace(); - UIUtil.showException(null, "Error", e); - return; - } - - // turn off logging for prefuse library - try { - Logger.getLogger("prefuse").setLevel(Level.OFF); - } catch (Exception e1) { - e1.printStackTrace(); - } - try { - CommandLineInstance.init(args); - } catch (Exception e) { - e.printStackTrace(); - UIUtil.showException(null, "Illegal arguments", e); - return; - } - try { - System.setProperty("db2.jcc.charsetDecoderEncoder", "3"); - } catch (Exception e) { - } - try { - // create initial data-model files - if (CommandLineInstance.getInstance().datamodelFolder == null) { - File file = new File(DataModel.getDatamodelFolder(new ExecutionContext())); - if (!file.exists()) { - file.mkdir(); - } - } - } catch (Exception e) { - } - java.awt.EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - try { - if (!Boolean.TRUE.equals(UISettings.restore(UISettings.USE_NATIVE_PLAF))) { - try { - for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - if ("Nimbus".equals(info.getName())) { - UIManager.setLookAndFeel(info.getClassName()); - Environment.nimbus = true; - break; - } - } - ((InputMap) UIManager.get("Button.focusInputMap")).put(KeyStroke.getKeyStroke("pressed ENTER"), "pressed"); - ((InputMap) UIManager.get("Button.focusInputMap")).put(KeyStroke.getKeyStroke("released ENTER"), "released"); - Object dSize = UIManager.get("SplitPane.dividerSize"); - if (Integer.valueOf(10).equals(dSize)) { - UIManager.put("SplitPane.dividerSize", Integer.valueOf(14)); - } - - if (UIManager.get("InternalFrame:InternalFrameTitlePane[Enabled].textForeground") instanceof Color) { - UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE); - } - - // UIUtil.prepareUI(); - } catch (Exception x) { - UIUtil.showException(null, "Error", x); - } - } - createFrame(); - } catch (Exception e) { - UIUtil.showException(null, "Error", e); - } - } - }); - } - - private static DataBrowser openNewDataBrowser(DataModel datamodel, DbConnectionDialog dbConnectionDialog, boolean maximize, ExecutionContext executionContext, DataBrowser theDataBrowser) throws Exception { - final DataBrowser dataBrowser = theDataBrowser != null? theDataBrowser : new DataBrowser(datamodel, null, "", null, ExecutionContext.getSchemaMapping(CommandLineInstance.getInstance().rawschemamapping), false, executionContext); - dataBrowser.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - dataBrowser.setVisible(true); - dataBrowser.setExtendedState(Frame.MAXIMIZED_BOTH); - - if (dbConnectionDialog == null) { - dbConnectionDialog = new DbConnectionDialog(dataBrowser, DataBrowserContext.getAppName(), null, executionContext); - } else { - dbConnectionDialog = new DbConnectionDialog(dataBrowser, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); - } - dbConnectionDialog.autoConnect(); - if (dbConnectionDialog.isConnected || dbConnectionDialog.connect(DataBrowserContext.getAppName(true))) { - dataBrowser.setConnection(dbConnectionDialog); - if (dataBrowser.session != null) { - dataBrowser.askForDataModel(); - dataBrowser.desktop.openSchemaMappingDialog(true); - dataBrowser.updateStatusBar(); - } - } else { - if (dbConnectionDialog.isConnected) { - dataBrowser.setConnection(dbConnectionDialog); - } else { - dataBrowser.dbConnectionDialog = dbConnectionDialog; - } - dataBrowser.dispose(); - return dataBrowser; - } - String bmName = CommandLineInstance.getInstance().bookmark; - final File bmFile; - final boolean restoreLastSession; - if ("".equals(bmName)) { - bmFile = null; - restoreLastSession = true; - } else { - bmFile = BookmarksPanel.getBookmarksFile(bmName, dataBrowser.executionContext); - restoreLastSession = false; - } - UIUtil.invokeLater(3, new Runnable() { - @Override - public void run() { - dataBrowser.toFront(); - if (restoreLastSession) { - dataBrowser.desktop.restoreSession(null, Environment.newFile(LAST_SESSION_FILE)); - } else if (bmFile != null) { - dataBrowser.desktop.restoreSession(null, bmFile); - BookmarksPanel.setLastUsedBookmark(bmFile.getName(), dataBrowser.executionContext); - bmFile.setLastModified(System.currentTimeMillis()); - new BookmarksPanel(dataBrowser, dataBrowser.bookmarkMenu, dataBrowser.desktop, dataBrowser.executionContext).updateBookmarksMenu(); - } - } - }); - return dataBrowser; - } - - private static void createFrame() { - DataModelManagerDialog dataModelManagerDialog = new DataModelManagerDialog(DataBrowserContext.getAppName(true) - + " - Relational Data Browser", false, "B") { - @Override - protected void onSelect(final DbConnectionDialog connectionDialog, final ExecutionContext executionContext) { - try { - final DataModel datamodel; - Map schemaMapping = ExecutionContext.getSchemaMapping(CommandLineInstance.getInstance().rawschemamapping); - datamodel = new DataModel(null, null, schemaMapping, null, new PrimaryKeyFactory(executionContext), executionContext, true, null); - final DataBrowser databrowser = new DataBrowser(datamodel, null, "", null, schemaMapping, false, executionContext); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - try { - openNewDataBrowser(datamodel, connectionDialog, true, executionContext, databrowser); - CommandLineInstance.clear(); - } catch (Exception e) { - UIUtil.showException(null, "Error", e); - } - } - }); - } catch (Exception e) { - UIUtil.showException(null, "Error", e); - UIUtil.checkTermination(); - } - } - @Override - protected void onLoadExtractionmodel(String modelFile, ExecutionContext executionContext2) { - // nothing to do - } - private static final long serialVersionUID = 1L; - }; - dataModelManagerDialog.start(); - } - - /** - * Opens the data model editor. - */ - private void openDataModelEditor(boolean merge) { - try { - UIUtil.setWaitCursor(this); - String modelname = datamodel == null || datamodel.get() == null ? DataModel.DEFAULT_NAME : datamodel.get().getName(); - DataModelEditor dataModelEditor = new DataModelEditor(this, merge, false, null, null, null, modelname, null, dbConnectionDialog, executionContext); - dataModelEditor.setVisible(true); - removeMetaDataSource(session); - desktop.reloadDataModel(desktop.schemaMapping); - dataModelViewFrame = null; - updateDataModelView(null); - updateStatusBar(); - askForDataModel(); - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } finally { - UIUtil.resetWaitCursor(this); - } - } - - private void updateDataModel() { - updateDataModel(null, false, false); - } - - private void updateDataModel(String schemaName, boolean withViews, boolean withSynonyms) { - if (!UIUtil.canRunJailer()) { - return; - } - try { - JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(this); - - List args = new ArrayList(); - args.add("build-model-wo-merge"); - dbConnectionDialog.addDbArgs(args); - - AnalyseOptionsDialog analyseOptionsDialog = new AnalyseOptionsDialog(this, datamodel == null ? null : datamodel.get(), executionContext); - analyseOptionsDialog.setInitiallyWithViews(withViews); - analyseOptionsDialog.setInitiallyWithSynonyms(withSynonyms); - boolean[] isDefaultSchema = new boolean[1]; - if (analyseOptionsDialog.edit(dbConnectionDialog, schemaName == null? null : Quoting.staticUnquote(schemaName), isDefaultSchema, dbConnectionDialog.currentConnection.user)) { - String schema = analyseOptionsDialog.getSelectedSchema(); - if (schema != null) { - args.add("-schema"); - args.add(schema); - } - if (!isDefaultSchema[0]) { - args.add("-qualifyNames"); - } - analyseOptionsDialog.appendAnalyseCLIOptions(args); - ModelBuilder.assocFilter = analyseOptionsDialog.getAssociationLineFilter(); - if (UIUtil.runJailer(this, args, false, true, false, true, null, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), null, null, false, true, false, executionContext)) { - ModelBuilder.assocFilter = null; - String modelname = datamodel == null || datamodel.get() == null ? DataModel.DEFAULT_NAME : datamodel.get().getName(); - DataModelEditor dataModelEditor = new DataModelEditor(this, true, analyseOptionsDialog.isRemoving(), null, - analyseOptionsDialog.getTableLineFilter(), analyseOptionsDialog.getAssociationLineFilter(), modelname, - schema == null? dbConnectionDialog.getName() : schema, dbConnectionDialog, executionContext); - if (dataModelEditor.dataModelHasChanged()) { - dataModelEditor.setVisible(true); - } - removeMetaDataSource(session); - desktop.reloadDataModel(desktop.schemaMapping); - dataModelViewFrame = null; - updateDataModelView(null); - updateStatusBar(); - askForDataModel(); - } - } else { - askForDataModel(); - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } finally { - ModelBuilder.assocFilter = null; - JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null; - } - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JMenuItem aboutMenuItem; - private javax.swing.JMenuItem addBookmarkMenuItem; - private javax.swing.JPanel addSQLConsoleTab; - private javax.swing.JMenuItem analyseMenuItem; - private javax.swing.JMenuItem analyseSQLMenuItem1; - private javax.swing.JLabel associatedWith; - private javax.swing.JMenu bookmarkMenu; - private javax.swing.JPanel borderBrowserPanel; - private javax.swing.JPanel borderBrowserTabPane; - javax.swing.JMenuItem checkPKMenuItem; - private javax.swing.JMenuItem closeAllMenuItem; - private javax.swing.JPanel closurePanel; - private javax.swing.JMenuItem columnOrderItem; - public javax.swing.JLabel connectivityState; - private javax.swing.JMenuItem consistencyCheckMenuItem; - private javax.swing.JMenuItem consistencyCheckMenuItem1; - private javax.swing.JPanel consoleDummyPanel; - private javax.swing.JMenuItem createCLIItem; - private javax.swing.JMenuItem createExtractionModelMenuItem; - private javax.swing.JMenuItem dataImport; - private javax.swing.JMenuItem dataModelEditorjMenuItem; - private javax.swing.JPanel dataModelPanel; - private javax.swing.JLabel dependsOn; - private javax.swing.JSplitPane desktopSplitPane; - private javax.swing.JTabbedPane detailsAndBorderBrowserTabbedPane; - private javax.swing.JButton downloadButton; - private javax.swing.JMenuItem downloadMenuItem; - private javax.swing.JPanel dummy; - private javax.swing.JMenuItem editBookmarkMenuItem; - private javax.swing.JMenuItem exitMenuItem; - private javax.swing.JMenuItem exportDataMenuItem; - private javax.swing.JLabel hasDependent; - private javax.swing.JMenuItem helpForum; - private javax.swing.JMenu helpMenu; - private javax.swing.JPanel hiddenPanel; - private javax.swing.JLabel ignored; - private javax.swing.JButton jButton1; - private javax.swing.JInternalFrame jInternalFrame1; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel10; - private javax.swing.JLabel jLabel11; - private javax.swing.JLabel jLabel12; - private javax.swing.JLabel jLabel13; - private javax.swing.JLabel jLabel14; - private javax.swing.JLabel jLabel19; - private javax.swing.JLabel jLabel20; - private javax.swing.JLabel jLabel21; - private javax.swing.JLabel jLabel22; - private javax.swing.JLabel jLabel26; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; - private javax.swing.JLabel jLabel7; - private javax.swing.JLabel jLabel8; - private javax.swing.JLabel jLabel9; - private javax.swing.JLayeredPane jLayeredPane1; - private javax.swing.JLayeredPane jLayeredPane2; - private javax.swing.JMenu jMenu1; - private javax.swing.JMenu jMenu2; - private javax.swing.JMenu jMenu3; - private javax.swing.JMenuItem jMenuItem3; - private javax.swing.JMenuItem jMenuItem4; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel11; - private javax.swing.JPanel jPanel2; - private javax.swing.JPanel jPanel3; - private javax.swing.JPanel jPanel4; - private javax.swing.JPanel jPanel5; - private javax.swing.JPanel jPanel6; - private javax.swing.JPanel jPanel7; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JScrollPane jScrollPane3; - private javax.swing.JPopupMenu.Separator jSeparator1; - private javax.swing.JPopupMenu.Separator jSeparator10; - private javax.swing.JPopupMenu.Separator jSeparator11; - private javax.swing.JPopupMenu.Separator jSeparator12; - private javax.swing.JPopupMenu.Separator jSeparator13; - private javax.swing.JPopupMenu.Separator jSeparator14; - private javax.swing.JPopupMenu.Separator jSeparator15; - private javax.swing.JPopupMenu.Separator jSeparator2; - private javax.swing.JPopupMenu.Separator jSeparator4; - private javax.swing.JPopupMenu.Separator jSeparator5; - private javax.swing.JPopupMenu.Separator jSeparator6; - private javax.swing.JPopupMenu.Separator jSeparator7; - private javax.swing.JPopupMenu.Separator jSeparator8; - private javax.swing.JPopupMenu.Separator jSeparator9; - private javax.swing.JSplitPane jSplitPane1; - private javax.swing.JSplitPane jSplitPane4; - private javax.swing.JTable jTable1; - private javax.swing.JTree jTree1; - private javax.swing.JMenu jviewMenu; - private javax.swing.JRadioButtonMenuItem largeLayoutRadioButtonMenuItem; - private javax.swing.JPanel layeredPaneContent; - private javax.swing.JMenuItem layoutMenuItem; - private javax.swing.JPanel legende; - private javax.swing.JPanel legende1; - private javax.swing.JPanel legende2; - private javax.swing.JMenuItem loadScriptMenuItem; - private javax.swing.JRadioButtonMenuItem mediumLayoutRadioButtonMenuItem; - private javax.swing.JMenuBar menuBar; - private javax.swing.JMenu menuTools; - private javax.swing.JMenu menuWindow; - private javax.swing.JPanel metaDataViewPanel; - private javax.swing.JLabel modelName; - private javax.swing.JLabel modelPath; - private javax.swing.JCheckBoxMenuItem nativeLAFCheckBoxMenuItem; - private javax.swing.JPanel navigationPanel; - private javax.swing.JTree navigationTree; - private javax.swing.JScrollPane navigationTreeScrollPane; - private javax.swing.JMenuItem newBrowserjMenuItem; - private javax.swing.JMenuItem newWindowMenuItem; - private javax.swing.JButton openTableButton; - private javax.swing.JMenuItem reconnectMenuItem; - private javax.swing.JButton refreshButton; - private javax.swing.JMenuItem restoreSessionItem; - private javax.swing.JMenu rowLimitMenu; - private javax.swing.JMenuItem saveScriptAsMenuItem; - private javax.swing.JMenuItem saveScriptMenuItem; - private javax.swing.JMenuItem schemaMappingMenuItem; - private javax.swing.JLabel schemaName; - private javax.swing.JPanel schemaNamePanel; - private javax.swing.JCheckBoxMenuItem showDataModelMenuItem; - private javax.swing.JRadioButtonMenuItem smallLayoutRadioButtonMenuItem; - private javax.swing.JMenuItem storeSessionItem; - private javax.swing.JTabbedPane tableTreesTabbedPane; - private javax.swing.JPanel tablesCardPanel; - private javax.swing.JPanel tablesPanel; - private javax.swing.JRadioButtonMenuItem thumbnailLayoutRadioButtonMenuItem; - private javax.swing.JRadioButtonMenuItem tinyLayoutRadioButtonMenuItem; - private javax.swing.JLabel titleLabel; - private javax.swing.JLabel updateInfoLabel; - private javax.swing.JPanel updateInfoPanel; - private javax.swing.JMenu view; - private javax.swing.JTabbedPane workbenchTabbedPane; - private javax.swing.JMenuItem zoomInMenuItem; - private javax.swing.JMenuItem zoomOutMenuItem; - // End of variables declaration//GEN-END:variables - - private JToggleButton searchButton; - - /** - * Sets Look&Feel. - * - * @param plaf - * the l&f - */ - private void setPLAF(String plaf) { - try { - UIManager.setLookAndFeel(plaf); - SwingUtilities.updateComponentTreeUI(this); - try { - File file = new File(PLAFSETTING); - file.delete(); - } catch (Exception e) { - } - try { - File plafSetting = new File(PLAFSETTING); - PrintWriter out = new PrintWriter(plafSetting); - out.println(plaf); - out.close(); - } catch (Exception x) { - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e); - } - } - - private void askForDataModel() { - try { - if (datamodel.get().getTables().isEmpty()) { - switch (JOptionPane.showOptionDialog(this, "Data model \"" + DataModelManager.getModelDetails(DataModelManager.getCurrentModelSubfolder(executionContext), executionContext).a - + "\" is empty.", DataBrowserContext.getAppName(true), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { - "Analyze Database", "Data Model Editor" }, null)) { - case 0: - updateDataModel(); - break; - case 1: - openDataModelEditor(false); - break; - } - } else if (!new File(DataModel.getColumnsFile(executionContext)).exists()) { - switch (JOptionPane.showOptionDialog(this, "No column definition found.", DataBrowserContext.getAppName(true), JOptionPane.YES_NO_OPTION, - JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Analyze Database", "Data Model Editor" }, null)) { - case 0: - updateDataModel(); - break; - case 1: - openDataModelEditor(false); - break; - } - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - } - - private void updateIFramesBar() { - updateNavigationTree(); - updateBorderBrowser(); - updateHiddenPanel(); - - // iFramesPanel is obsolete - return; - } - - private void updateHiddenPanel() { - if (desktop == null) { - return; - } - - hiddenPanel.removeAll(); - hiddenPanel.setVisible(false); - - int num = desktop.getAllFrames().length; - if (num == 0) { - jPanel1.revalidate(); - return; - } - int COLUMNS = 7; - int y = 1; - - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = y; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.weightx = 1; - JPanel iFramesRowPanel = new JPanel(); - iFramesRowPanel.setLayout(new GridBagLayout()); - hiddenPanel.add(iFramesRowPanel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = COLUMNS + 2; - gridBagConstraints.gridy = y; - gridBagConstraints.weightx = 1; - iFramesRowPanel.add(new JLabel(" "), gridBagConstraints); - - int x = 1; - boolean visible = false; - for (final RowBrowser rb : desktop.getBrowsers()) { - if (!rb.isHidden()) { - continue; - } - visible = true; - if (++x > COLUMNS) { - x = 1; - ++y; - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = y; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.weightx = 1; - iFramesRowPanel = new JPanel(); - iFramesRowPanel.setLayout(new GridBagLayout()); - hiddenPanel.add(iFramesRowPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = COLUMNS + 2; - gridBagConstraints.gridy = y; - gridBagConstraints.weightx = 1; - iFramesRowPanel.add(new JLabel(" "), gridBagConstraints); - } - - final JToggleButton toggleButton = new JToggleButton(); - toggleButton.setText(rb.internalFrame.getTitle()); - toggleButton.setIcon(UIUtil.readImage("/jailerlight.png")); - toggleButton.setSelected(false); - - toggleButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - toggleButton.setSelected(true); - rb.setHidden(false); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = x; - gridBagConstraints.gridy = y; - iFramesRowPanel.add(toggleButton, gridBagConstraints); - - hiddenPanel.setVisible(visible); - } - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new Insets(0, 0, 4, 0); - - jPanel1.revalidate(); - } - - private static final class BrowserAssociationModel extends DefaultAssociationModel { - private final RowBrowser rowBrowser; - - public BrowserAssociationModel(RowBrowser rowBrowser, Association association) { - super(association); - this.rowBrowser = rowBrowser; - } - - @Override - public String getSourceName() { - return rowBrowser.internalFrame.getTitle(); - } - - @Override - public boolean equals(Object other) { - if (other == null) { - return false; - } - if (other.getClass().equals(getClass())) { - BrowserAssociationModel otherModel = (BrowserAssociationModel) other; - return rowBrowser == otherModel.rowBrowser && association == otherModel.association; - } - return false; - } - - @Override - public int hashCode() { - return rowBrowser.hashCode() + 3 * association.hashCode(); - } - - public RowBrowser getRowBrowser() { - return rowBrowser; - } - - public Association getAssociation() { - return association; - } - } - - private boolean disableBorderBrowserUpdates = false; - - private void updateBorderBrowser() { - if (disableBorderBrowserUpdates || detailsAndBorderBrowserTabbedPane.getSelectedComponent() != borderBrowserTabPane) { - return; - } - try { - UIUtil.setWaitCursor(this); - - Collection model = new ArrayList(); - if (desktop != null) { - titleLabel.setText(" Related Rows"); - List allChildren = new ArrayList(); - for (RowBrowser rb : desktop.getBrowsers()) { - if (rb.internalFrame == desktop.getSelectedFrame() && !rb.isHidden()) { - allChildren.add(rb); - allChildren.addAll(collectChildren(rb)); - titleLabel.setText(" Related Rows of Subtree " + rb.internalFrame.getTitle()); - break; - } - } - for (RowBrowser rb : allChildren) { - if (rb.browserContentPane.table != null) { - Set associations = new HashSet(rb.browserContentPane.table.associations); - for (RowBrowser c : desktop.getChildBrowsers(rb, false)) { - if (c.browserContentPane.association != null) { - associations.remove(c.browserContentPane.association); - } - } - if (rb.browserContentPane.association != null && rb.parent != null) { - if (allChildren.contains(rb.parent)) { - associations.remove(rb.browserContentPane.association.reversalAssociation); - } - } - for (Association association : associations) { - model.add(new BrowserAssociationModel(rb, association)); - } - } - } - } - - borderBrowser.setModel(model); - } finally { - UIUtil.resetWaitCursor(this); - } - } - - private ExtractionModelFrame dataModelViewFrame; - private Table lastFocusTable = null; - private Table currentTableInDMV = null; - - private void updateDataModelView(final Table table) { - if (table != null) { - lastFocusTable = table; - } - if (detailsAndBorderBrowserTabbedPane.getSelectedComponent() != dataModelPanel) { - return; - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - try { - UIUtil.setWaitCursor(DataBrowser.this); - if (dataModelViewFrame == null) { - dataModelViewFrame = ExtractionModelFrame.createFrame(null, false, false, null, executionContext); - JComponent graphViewContainer = dataModelViewFrame.tearOutGraphViewContainer(DataBrowser.this); - dataModelPanel.removeAll(); - dataModelPanel.add(graphViewContainer); - } - if (table != null) { - dataModelViewFrame.select(table); - } else { - Table toSelect = null; - if (lastFocusTable != null && tableTreesTabbedPane.getSelectedComponent() == tablesCardPanel) { - toSelect = datamodel.get().getTable(lastFocusTable.getName()); - } - if (toSelect == null) { - TreePath selectionPath = navigationTree.getSelectionPath(); - toSelect = datamodel.get().getTables().isEmpty()? null : datamodel.get().getTables().iterator().next(); - if (selectionPath != null) { - Object lastPathComponent = selectionPath.getLastPathComponent(); - if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); - if (userObject instanceof TreeNodeForRowBrowser) { - Table table = ((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table; - if (!(table instanceof SqlStatementTable)) { - toSelect = table; - } - } - } - } - } - if (toSelect != null && currentTableInDMV != toSelect) { - dataModelViewFrame.select(toSelect); - currentTableInDMV = toSelect; - } - } - } catch (IOException e) { - UIUtil.showException(DataBrowser.this, "Error", e); - } finally { - UIUtil.resetWaitCursor(DataBrowser.this); - } - } - }); - } - - protected void resolveSelection(Collection selection) { - try { - UIUtil.setWaitCursor(this); - - disableBorderBrowserUpdates = true; - JInternalFrame currentSelection = desktop.getSelectedFrame(); - for (AssociationModel a : selection) { - BrowserAssociationModel associationModel = (BrowserAssociationModel) a; - desktop.addTableBrowser(associationModel.getRowBrowser(), associationModel.getRowBrowser(), associationModel.getAssociation().destination, associationModel.getAssociation(), - "", null, null, true); - } - if (currentSelection != null) { - try { - currentSelection.setSelected(true); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(currentSelection); - } catch (PropertyVetoException e) { - // ignore - } - } - } finally { - UIUtil.resetWaitCursor(this); - disableBorderBrowserUpdates = false; - updateBorderBrowser(); - } - } - - private List collectChildren(RowBrowser rb) { - List result = new ArrayList(); - for (RowBrowser c : desktop.getChildBrowsers(rb, true)) { - result.add(c); - } - for (RowBrowser c : desktop.getChildBrowsers(rb, true)) { - result.addAll(collectChildren(c)); - } - return result; - } - - private Map treeNodeByIFrame = new HashMap(); - private TreeSelectionListener navigationTreeListener = null; - - private class TreeNodeForRowBrowser { - public final RowBrowser rowBrowser; - public final int rowIndex; - private final String title; - - public TreeNodeForRowBrowser(RowBrowser rowBrowser, int rowIndex) { - this.rowBrowser = rowBrowser; - this.rowIndex = rowIndex; - this.title = " " + rowBrowser.internalFrame.getTitle() + " "; - treeNodeByIFrame.put(rowBrowser.internalFrame, this); - } - - @Override - public String toString() { - return title; - } - } - - private void updateNavigationTree() { - if (navigationTreeListener != null) { - navigationTree.getSelectionModel().removeTreeSelectionListener(navigationTreeListener); - } - - ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; - DefaultMutableTreeNode root = new DefaultMutableTreeNode(connection != null ? connection.alias : " "); - - treeNodeByIFrame.clear(); - - int[] count = new int[1]; - count[0] = 1; - if (desktop != null) { - for (RowBrowser rb : desktop.getRootBrowsers(true)) { - DefaultMutableTreeNode node = new DefaultMutableTreeNode(new TreeNodeForRowBrowser(rb, count[0]++)); - root.add(node); - addChildNodes(node, rb, count); - } - } - DefaultTreeModel treeModel = new DefaultTreeModel(root); - navigationTree.setModel(treeModel); - for (int i = 0; i < count[0]; ++i) { - navigationTree.expandRow(i); - } - JInternalFrame activeFrame = desktop != null ? desktop.getSelectedFrame() : null; - if (activeFrame != null) { - TreeNodeForRowBrowser node = treeNodeByIFrame.get(activeFrame); - if (node != null) { - navigationTree.setSelectionRow(node.rowIndex); - Rectangle bounds = navigationTree.getRowBounds(node.rowIndex); - navigationTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height)); - for (RowBrowser rb : desktop.getRootBrowsers(true)) { - if (rb.internalFrame == activeFrame) { - if (rb.getMDTable() != null && metaDataPanel != null) { - metaDataPanel.select(rb.getMDTable()); - } - break; - } - } - } - } - - navigationTreeListener = new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - if (e.getPath() != null) { - Object lastPathComponent = e.getPath().getLastPathComponent(); - if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); - if (userObject instanceof TreeNodeForRowBrowser) { - try { - JInternalFrame iFrame = ((TreeNodeForRowBrowser) userObject).rowBrowser.internalFrame; - desktop.scrollToCenter(iFrame); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame); - iFrame.setSelected(true); - iFrame.grabFocus(); - } catch (PropertyVetoException e1) { - // ignore - } - return; - } else { - searchButton.doClick(1); - } - } - } - updateNavigationTree(); - } - }; - - navigationTree.getSelectionModel().addTreeSelectionListener(navigationTreeListener); - } - - private void addChildNodes(DefaultMutableTreeNode node, RowBrowser browser, int[] count) { - for (RowBrowser rb : desktop.getChildBrowsers(browser, true)) { - DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(new TreeNodeForRowBrowser(rb, count[0]++)); - node.add(childNode); - addChildNodes(childNode, rb, count); - } - } - - public JScrollPane getDesktopScrollPane() { - return jScrollPane1; - } - - private DBClosureView closureView; - private boolean suppressUpdateClosureBrowser = false; - - protected void updateClosureBrowser(final RowBrowser rowBrowser) { - if (suppressUpdateClosureBrowser) { - return; - } - if (rowBrowser != null) { - if (rowBrowser.browserContentPane.table instanceof SqlStatementTable) { - updateClosureBrowser(null); - return; - } - } - closureView = new DBClosureView(this) { - private RowBrowser closureRoot = rowBrowser; - - @Override - protected DataModel getDataModel() { - return DataBrowser.this.datamodel.get(); - } - - @Override - protected Table getRootTable() { - if (rowBrowser != null) { - return rowBrowser.browserContentPane.table; - } - return null; - } - - private Map visibleTables = null; - private Map levels = null; - - @Override - protected Map getVisibleTables() { - if (visibleTables == null) { - visibleTables = new HashMap(); - levels = new HashMap(); - if (rowBrowser != null) { - collectVisibleTables(rowBrowser, 1); - } - } - return visibleTables; - } - - private void collectVisibleTables(RowBrowser rowBrowser, int level) { - Integer prevLevel = levels.get(rowBrowser.browserContentPane.table); - if (prevLevel == null || prevLevel > level) { - visibleTables.put(rowBrowser.browserContentPane.table, rowBrowser); - levels.put(rowBrowser.browserContentPane.table, level); - } - for (RowBrowser cb: rowBrowser.browserContentPane.getChildBrowsers()) { - collectVisibleTables(cb, level + 1); - } - } - - @Override - protected void scrollToTable(Table table) { - RowBrowser rb = visibleTables.get(table); - if (rb != null) { - desktop.scrollToCenter(rb.internalFrame); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(rb.internalFrame); - } - } - - @Override - protected void repaintClosureView() { - desktopSplitPane.repaint(); - desktopSplitPane.setDividerLocation(desktopSplitPane.getDividerLocation() - 1); - desktopSplitPane.setDividerLocation(desktopSplitPane.getDividerLocation() + 1); - } - - @Override - protected void expandTablePath(List
path) { - int i; - i = path.size() - 1; - while (i >= 0) { - if (!getVisibleTables().containsKey(path.get(i))) { - ++i; - break; - } - --i; - } - Association[] associations = openAssociationPathPanel(path.subList(0, i + 1)); - if (associations != null) { - try { - Desktop.noArrangeLayoutOnNewTableBrowser = true; - desktop.getiFrameStateChangeRenderer().startAtomic(); - disableBorderBrowserUpdates = true; - suppressUpdateClosureBrowser = true; - RowBrowser nextRb = null; - while (i > 0) { - Table table = path.get(i); - RowBrowser rb; - if (nextRb != null && nextRb.association != null && nextRb.association.destination.equals(table)) { - rb = nextRb; - } else { - rb = getVisibleTables().get(table); - } - Association association = associations[i - 1]; - if (association != null) { - nextRb = rb.browserContentPane.navigateTo(association, null); - visibleTables = null; - } else { - break; - } - --i; - } - suppressUpdateClosureBrowser = false; - - closureRoot.internalFrame.setSelected(true); - } catch (Exception e) { - // ignore - } finally { - Desktop.noArrangeLayoutOnNewTableBrowser = false; - disableBorderBrowserUpdates = false; - suppressUpdateClosureBrowser = false; - desktop.getiFrameStateChangeRenderer().endAtomic(); - desktop.catchUpLastArrangeLayoutOnNewTableBrowser(); - } - closureView.find(getDataModel().getDisplayName(path.get(0))); - } - } - - @Override - protected void select(String selectedTable) { - try { - if (selectedTable != null) { - RowBrowser rb = getVisibleTables().get(datamodel.get().getTableByDisplayName(selectedTable)); - if (rb != null) { - JInternalFrame iFrame = rb.internalFrame; - desktop.scrollToCenter(iFrame); - iFrame.setSelected(true); - iFrame.grabFocus(); - desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame); - } - } - } catch (PropertyVetoException e1) { - // ignore - } - } - - private Association[] openAssociationPathPanel(List
path) { - if (path.isEmpty()) { - return null; - } - final AssociationPathPanel assocPanel = new AssociationPathPanel(getDataModel(), path, dependsOn.getForeground(), hasDependent.getForeground(), associatedWith.getForeground(), ignored.getForeground()); - if (!assocPanel.needToAsk) { - return assocPanel.selectedAssociations; - } - final JDialog d = new JDialog(DataBrowser.this, "Open Path", true); - assocPanel.okButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - assocPanel.ok = true; - d.setVisible(false); - } - }); - assocPanel.cancelButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - assocPanel.ok = false; - d.setVisible(false); - } - }); - d.getContentPane().add(assocPanel); - d.pack(); - d.setSize(600, Math.max(d.getHeight() + 20, 400)); - d.setLocation(DataBrowser.this.getX() + (DataBrowser.this.getWidth() - d.getWidth()) / 2, Math.max(0, DataBrowser.this.getY() + (DataBrowser.this.getHeight() - d.getHeight()) / 2)); - UIUtil.fit(d); - assocPanel.okButton.grabFocus(); - d.setVisible(true); - if (assocPanel.ok) { - return assocPanel.selectedAssociations; - } - return null; - } - }; - Container cVContentPane = closureView.tablePanel; - closureView.dispose(); - closurePanel.removeAll(); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 1; - closurePanel.add(cVContentPane, gridBagConstraints); - closureView.refresh(); - } - - private MetaDataSource getMetaDataSource(Session session) { - return (MetaDataSource) session.getSessionProperty(DataBrowser.class, "MetaDataSource"); - } - - private void removeMetaDataSource(Session session) { - session.setSessionProperty(DataBrowser.class, "removeMetaDataSource", Boolean.TRUE); - } - - private MetaDataPanel metaDataPanel; - private Runnable createMetaDataPanel; - - private void onNewSession(Session newSession) { - if (newSession == null) { - return; - } - - ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; - String alias = connection != null ? " " + connection.alias : " "; - - UIUtil.setWaitCursor(this); - CancellationHandler.reset(null); - try { - updateNavigationCombobox(); - - tablesPanel.removeAll(); - metaDataPanel = (MetaDataPanel) session.getSessionProperty(getClass(), "metaDataPanel"); - MetaDataSource metaDataSource; - try { - metaDataSource = getMetaDataSource(newSession); - if (metaDataSource == null || Boolean.TRUE.equals(session.getSessionProperty(DataBrowser.class, "removeMetaDataSource"))) { - metaDataSource = new MetaDataSource(newSession, datamodel.get(), alias, executionContext); - final MetaDataSource finalMetaDataSource = metaDataSource; - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - Session.setThreadSharesConnection(); - final MDSchema defaultSchema = finalMetaDataSource.getDefaultSchema(); - if (defaultSchema != null) { - // trigger reading meta data asynchronously - defaultSchema.loadTables(true, null, new Runnable() { - @Override - public void run() { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - if (createMetaDataPanel != null) { - createMetaDataPanel.run(); - } - if (metaDataPanel != null) { - metaDataPanel.refresh(); - } - } - }); - } - }); - } else { - if (createMetaDataPanel != null) { - createMetaDataPanel.run(); - } - if (metaDataPanel != null) { - metaDataPanel.refresh(); - } - } - } - }); - thread.setDaemon(true); - thread.start(); - metaDataPanel = null; - } - session.setSessionProperty(DataBrowser.class, "removeMetaDataSource", null); - newSession.setSessionProperty(DataBrowser.class, "MetaDataSource", metaDataSource); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - metaDataViewPanel.remove(metaDataDetailsPanel); - metaDataDetailsPanel = createMetaDataDetailsPanel(executionContext); - metaDataViewPanel.add(metaDataDetailsPanel); - - try { - if (sqlConsoles.isEmpty()) { - createNewSQLConsole(metaDataSource); - workbenchTabbedPane.setSelectedComponent(desktopSplitPane); - } else { - for (SQLConsole sqlConsole: sqlConsoles) { - sqlConsole.reset(session, metaDataSource); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - - ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, "loading"); - - final MetaDataSource fMetaDataSource = metaDataSource; - final Runnable createMetaDataPanelImmediately = new Runnable() { - @Override - public void run() { - if (metaDataPanel == null) { - metaDataPanel = new MetaDataPanel(DataBrowser.this, fMetaDataSource, metaDataDetailsPanel, datamodel.get(), executionContext) { - @Override - protected void open(Table table) { - if (!selectNavTreeNode(navigationTree.getModel().getRoot(), table)) { - if (workbenchTabbedPane.getSelectedComponent() != getCurrentSQLConsole()) { - desktop.addTableBrowser(null, null, table, null, "", null, null, true); - } - } - try { - String sql; - Quoting quoting = Quoting.getQuoting(session); - MDTable mdTable = getMetaDataSource(session).toMDTable(table); - String tableName; - String schemaName; - if (mdTable != null) { - tableName = mdTable.getName(); - schemaName = mdTable.getSchema().isDefaultSchema? "": mdTable.getSchema().getName(); - } else { - tableName = table.getUnqualifiedName(); - schemaName = table.getSchema(""); - } - sql = "Select * From " + (schemaName == null || schemaName.length() == 0? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName); - if (workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) { - workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); - getCurrentSQLConsole().grabFocus(); - getCurrentSQLConsole().appendStatement(sql, true); - } - } catch (SQLException e) { - UIUtil.showException(this, "Error", e); - } - } - - private boolean selectNavTreeNode(Object root, Table table) { - if (root instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); - if (userObject instanceof TreeNodeForRowBrowser) { - RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser; - if (table.equals(rowBrowser.browserContentPane.table)) { - navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath())); - return true; - } - } - int cc = ((DefaultMutableTreeNode) root).getChildCount(); - for (int i = 0; i < cc; ++i) { - if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), table)) { - return true; - } - } - } - return false; - } - - private boolean selectNavTreeNode(Object root, MDTable mdTable) { - if (root instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); - if (userObject instanceof TreeNodeForRowBrowser) { - RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser; - if (mdTable.equals(rowBrowser.getMDTable())) { - navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath())); - return true; - } - } - int cc = ((DefaultMutableTreeNode) root).getChildCount(); - for (int i = 0; i < cc; ++i) { - if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), mdTable)) { - return true; - } - } - } - return false; - } - - @Override - protected void analyseSchema(String schemaName) { - updateDataModel(schemaName, false, false); - } - - @Override - protected void open(MDTable mdTable) { - String schemaName = mdTable.getSchema().isDefaultSchema? null : mdTable.getSchema().getName(); - String tableName = mdTable.getName(); - try { - Quoting quoting = Quoting.getQuoting(session); - String sql = "Select * From " + (schemaName == null? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName); - if (!selectNavTreeNode(navigationTree.getModel().getRoot(), mdTable) - || workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) { - workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); - getCurrentSQLConsole().grabFocus(); - getCurrentSQLConsole().appendStatement(sql, true); - } - } catch (SQLException e) { - UIUtil.showException(this, "Error", e); - } - } - - @Override - protected void appendScript(String script, boolean execute) { - try { - workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); - getCurrentSQLConsole().grabFocus(); - getCurrentSQLConsole().appendStatement(script, execute); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e); - } - } - - @Override - protected void onTableSelect(MDTable mdTable) { - metaDataDetailsPanel - .showMetaDataDetails(mdTable, getMetaDataSource(session).toTable(mdTable), null, false, datamodel.get()); - } - - @Override - protected void onRowSelect(Table table, Row row) { - metaDataDetailsPanel - .showMetaDataDetails(null, table, row, true, datamodel.get()); - } - - @Override - protected void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext) { - metaDataDetailsPanel - .showMetaDataDetails(mdOther, executionContext); - } - - @Override - protected void onSchemaSelect(MDSchema mdSchema) { - metaDataDetailsPanel.clear(); - } - - @Override - protected void openNewTableBrowser() { - DataBrowser.this.openNewTableBrowser(false); - } - - @Override - protected void updateDataModelView(Table table) { - DataBrowser.this.updateDataModelView(table); - } - - @Override - protected void setCaretPosition(int position) { - getCurrentSQLConsole().setCaretPosition(position); - } - - @Override - protected void setOrResetWaitState(boolean set) { - ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, set? "loading" : "tables"); - } - }; - } - session.setSessionProperty(getClass(), "metaDataPanel", metaDataPanel); - tablesPanel.add(metaDataPanel, java.awt.BorderLayout.CENTER); - ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, "tables"); - } - }; - createMetaDataPanel = new Runnable() { - @Override - public void run() { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - Session.setThreadSharesConnection(); - - // trigger loading meta data - fMetaDataSource.getSchemas(); - - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - createMetaDataPanelImmediately.run(); - } - }); - } - }); - thread.setDaemon(true); - thread.start(); - createMetaDataPanel = null; - } - }; - if (tableTreesTabbedPane.getSelectedComponent() == tablesPanel) { - createMetaDataPanel.run(); - } - } - finally { - UIUtil.resetWaitCursor(this); - } - } - - private final class SQLConsoleWithTitle extends SQLConsole { - private final String initialTitle; - private final JLabel titleLbl; - private String title; - - private SQLConsoleWithTitle(Session session, MetaDataSource metaDataSource, Reference datamodel, - ExecutionContext executionContext, String title, JLabel titleLbl) throws SQLException { - super(session, metaDataSource, datamodel, executionContext); - this.initialTitle = title; - this.titleLbl = titleLbl; - } - - @Override - protected void refreshMetaData() { - if (metaDataPanel != null) { - metaDataPanel.reset(); - } - } - - @Override - protected void selectTable(MDTable mdTable) { - if (metaDataPanel != null) { - metaDataPanel.select(mdTable); - } - } - - @Override - protected void setOutlineTables(List outlineTables, int indexOfInfoAtCaret) { - if (metaDataPanel != null) { - metaDataPanel.setOutline(outlineTables, indexOfInfoAtCaret); - } - } - - @Override - protected void onContentStateChange(File file, boolean dirty) { - if (file == null) { - title = initialTitle; - } else { - title = file.getName(); - } - if (dirty && file != null) { - titleLbl.setText("* " + title); - } else { - titleLbl.setText(title); - } - updateLoadSaveScriptMenuItemsState(); - } - - public String getTitle() { - return title; - } - - @Override - protected JFrame getOwner() { - return DataBrowser.this; - } - - @Override - protected void openDataModelEditor(boolean merge) { - DataBrowser.this.openDataModelEditor(merge); - } - } - - private int sqlConsoleNr = 0; - - private SQLConsole createNewSQLConsole(MetaDataSource metaDataSource) throws SQLException { - final JLabel titleLbl = new JLabel(sqlConsoleIcon); - String tabName = "SQL Console"; - ++sqlConsoleNr; - String title = tabName + (sqlConsoleNr > 1? " (" + sqlConsoleNr + ")" : "") + " "; - - final SQLConsoleWithTitle sqlConsole = new SQLConsoleWithTitle(session, metaDataSource, datamodel, executionContext, title, titleLbl); - initDnD(sqlConsole.getEditorPane()); - sqlConsoles.add(sqlConsole); - - try { - ignoreTabChangeEvent = true; - for (int i = 0; i < workbenchTabbedPane.getTabCount(); ++i) { - if (workbenchTabbedPane.getComponentAt(i) == consoleDummyPanel) { - workbenchTabbedPane.removeTabAt(i); - break; - } - } - workbenchTabbedPane.insertTab(title, null, sqlConsole, null, sqlConsoles.size()); - JPanel titelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); - titelPanel.setOpaque(false); - titleLbl.setText(title); - // titleLbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - titelPanel.add(titleLbl); - SmallButton closeButton = new SmallButton(closeIcon) { - @Override - protected void onClick() { - if (closeSQLConsole(sqlConsole, true)) { - workbenchTabbedPane.setSelectedComponent(desktopSplitPane); - } - } - }; - titelPanel.add(closeButton); - if (sqlConsoles.size() > 1) { - workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.indexOfComponent(sqlConsole), titelPanel); - } else { - workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.indexOfComponent(sqlConsole), titleLbl); - } - } finally { - ignoreTabChangeEvent = false; - } - workbenchTabbedPane.setSelectedComponent(sqlConsole); - return sqlConsole; - } - - private boolean closeAllSQLConsoles() { - List toClose = new ArrayList(sqlConsoles); - for (SQLConsoleWithTitle sqlConsole: toClose) { - workbenchTabbedPane.setSelectedComponent(sqlConsole); - if (sqlConsole.getFile() != null && sqlConsole.isDirty()) { - if (!closeSQLConsole(sqlConsole, true)) { - return false; - } - } - } - toClose = new ArrayList(sqlConsoles); - for (SQLConsoleWithTitle sqlConsole: toClose) { - workbenchTabbedPane.setSelectedComponent(sqlConsole); - if (!closeSQLConsole(sqlConsole, false)) { - return false; - } - } - return true; - } - - private boolean closeSQLConsole(SQLConsoleWithTitle sqlConsole, boolean ask) { - if (ask) { - if (!sqlConsole.isEmpty() && !(sqlConsole.getFile() != null && !sqlConsole.isDirty())) { - if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(DataBrowser.this, "Close \"" + sqlConsole.getTitle() + "\"" + (sqlConsole.getFile() == null? "?" : " without saving?"), "Close Console", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)) { - return false; - } - } - } - try { - sqlConsole.close(); - ignoreTabChangeEvent = true; - workbenchTabbedPane.remove(sqlConsole); - sqlConsoles.remove(sqlConsole); - } finally { - ignoreTabChangeEvent = false; - } - return true; - } - - private void updateLoadSaveScriptMenuItemsState() { - SQLConsole sqlConsole = null; - Component sc = workbenchTabbedPane.getSelectedComponent(); - if (sc instanceof SQLConsole) { - sqlConsole = (SQLConsole) sc; - } - saveScriptMenuItem.setEnabled(sqlConsole != null && sqlConsole.isDirty()); - saveScriptAsMenuItem.setEnabled(sqlConsole != null && !sqlConsole.isEmpty()); - } - - private void loadScriptMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadScriptMenuItemActionPerformed - String fName = UIUtil.choseFile(null, ".", "Load SQL Script", "", this, false, true); - if (fName != null) { - File file = new File(fName); - loadSQLScriptFile(file); - } - }//GEN-LAST:event_loadScriptMenuItemActionPerformed - - private void loadSQLScriptFile(File file) { - for (SQLConsole sqlConsole: sqlConsoles) { - if (file.equals(sqlConsole.getFile())) { - workbenchTabbedPane.setSelectedComponent(sqlConsole); - return; - } - } - try { - UIUtil.setWaitCursor(this); - createNewSQLConsole(getMetaDataSource()).loadFromFile(file); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } finally { - UIUtil.resetWaitCursor(this); - } - } - - private void saveScriptMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveScriptMenuItemActionPerformed - SQLConsole sqlConsole = getCurrentSQLConsole(); - if (sqlConsole != null) { - if (sqlConsole.getFile() == null) { - saveScriptAsMenuItemActionPerformed(evt); - } else { - try { - UIUtil.setWaitCursor(this); - sqlConsole.storeToFile(null); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } finally { - UIUtil.resetWaitCursor(this); - } - } - } - }//GEN-LAST:event_saveScriptMenuItemActionPerformed - - private void initMenu() { - int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - if (mask != InputEvent.CTRL_MASK) { - for (int i = 0; i < menuBar.getMenuCount(); ++i) { - JMenu menu = menuBar.getMenu(i); - for (int j = 0; j < menu.getItemCount(); ++j) { - JMenuItem item = menu.getItem(j); - if (item != null) { - KeyStroke accelerator = item.getAccelerator(); - if (accelerator != null) { - item.setAccelerator(KeyStroke.getKeyStroke(accelerator.getKeyCode(), mask, accelerator.isOnKeyRelease())); - } - } - } - } - } - } - - private void saveScriptAsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveScriptAsMenuItemActionPerformed - SQLConsole sqlConsole = getCurrentSQLConsole(); - if (sqlConsole != null) { - String fName = UIUtil.choseFile(null, ".", "Save SQL Script", "", this, false, false); - if (fName != null) { - File file = new File(fName); - try { - UIUtil.setWaitCursor(this); - sqlConsole.storeToFile(file); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } finally { - UIUtil.resetWaitCursor(this); - } - } - } - }//GEN-LAST:event_saveScriptAsMenuItemActionPerformed - - private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed - if (closeAllSQLConsoles()) { - DataBrowser.this.dispose(); - } - }//GEN-LAST:event_exitMenuItemActionPerformed - - private void analyseSQLMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analyseSQLMenuItem1ActionPerformed - AssociationProposerView assocProposerView = new AssociationProposerView(this, datamodel.get(), null, executionContext); - if (assocProposerView.isAccepted()) { - openDataModelEditor(true); - } - }//GEN-LAST:event_analyseSQLMenuItem1ActionPerformed - - private void columnOrderItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_columnOrderItemActionPerformed - openColumnOrderEditor(null); - }//GEN-LAST:event_columnOrderItemActionPerformed - - private void openColumnOrderEditor(Table table) { - try { - if (new ColumnOrderEditor(this, table, datamodel.get(), executionContext).wasOk()) { - removeMetaDataSource(session); - desktop.reloadDataModel(desktop.schemaMapping); - dataModelViewFrame = null; - updateDataModelView(null); - updateStatusBar(); - askForDataModel(); - } - } catch (Throwable e) { - UIUtil.showException(this, "Error", e); - } - } - - private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - updateInfoPanel.setVisible(false); - }//GEN-LAST:event_jButton1ActionPerformed - - private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed - updateInfoPanel.setVisible(false); - UpdateInfoManager.download(); - }//GEN-LAST:event_downloadButtonActionPerformed - - private void nativeLAFCheckBoxMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nativeLAFCheckBoxMenuItemActionPerformed - - }//GEN-LAST:event_nativeLAFCheckBoxMenuItemActionPerformed - - private void addBookmarkMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addBookmarkMenuItemActionPerformed - desktop.storeSession(new BookmarksPanel(this, bookmarkMenu, desktop, executionContext)); - }//GEN-LAST:event_addBookmarkMenuItemActionPerformed - - private void editBookmarkMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editBookmarkMenuItemActionPerformed - new BookmarksPanel(this, bookmarkMenu, desktop, executionContext).editBookmarks(); - desktop.updateAllBookmarkMenues(); - }//GEN-LAST:event_editBookmarkMenuItemActionPerformed - - private void downloadMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadMenuItemActionPerformed - UpdateInfoManager.download(); - }//GEN-LAST:event_downloadMenuItemActionPerformed - - private void zoomInMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomInMenuItemActionPerformed - desktop.zoom(1); - }//GEN-LAST:event_zoomInMenuItemActionPerformed - - private void zoomOutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomOutMenuItemActionPerformed - desktop.zoom(-1); - }//GEN-LAST:event_zoomOutMenuItemActionPerformed - - private void checkPKMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkPKMenuItemActionPerformed - try { - if (dbConnectionDialog.isConnected || dbConnectionDialog.connect("Check Primary Keys")) { - BasicDataSource dataSource = UIUtil.createBasicDataSource(this, dbConnectionDialog.currentConnection.driverClass, dbConnectionDialog.currentConnection.url, dbConnectionDialog.currentConnection.user, dbConnectionDialog.getPassword(), 0, dbConnectionDialog.currentJarURLs()); - UIUtil.validatePrimaryKeys(this, dataSource, new TreeSet
(datamodel.get().getTables())); - } - } catch (Exception e) { - // ignore - } - }//GEN-LAST:event_checkPKMenuItemActionPerformed - - private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed - }//GEN-LAST:event_refreshButtonActionPerformed - - private void createCLIItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createCLIItemActionPerformed - String mapping = desktop.getRawSchemaMapping(); - String bookmark = BookmarksPanel.getLastUsedBookmark(executionContext); - if (bookmark != null) { - bookmark = bookmarkName(bookmark); - } - List bookmarks = new ArrayList(); - for (StringBuilder sb: BookmarksPanel.loadBookmarks(executionContext)) { - bookmarks.add(bookmarkName(sb.toString())); - } - new CLIPanel(dbConnectionDialog, true, null, mapping, bookmarks, bookmark, executionContext).open(this); - }//GEN-LAST:event_createCLIItemActionPerformed - - private void consistencyCheckMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_consistencyCheckMenuItem1ActionPerformed - consistencyCheckMenuItemActionPerformed(evt); - }//GEN-LAST:event_consistencyCheckMenuItem1ActionPerformed - - private String bookmarkName(String bookmarkFileName) { - if (bookmarkFileName.endsWith(BookmarksPanel.BOOKMARKFILE_EXTENSION)) { - return bookmarkFileName.substring(0, bookmarkFileName.length() - BookmarksPanel.BOOKMARKFILE_EXTENSION.length()); - } else { - return bookmarkFileName; - } - } - - private MetaDataDetailsPanel metaDataDetailsPanel; - private List sqlConsoles = new ArrayList(); - - private SQLConsole getCurrentSQLConsole() { - Component sc = workbenchTabbedPane.getSelectedComponent(); - if (sc instanceof SQLConsole) { - return (SQLConsole) sc; - } - if (sqlConsoles.isEmpty()) { - return null; - } - for (int i = sqlConsoles.size() - 1; i >= 0; --i) { - if (sqlConsoles.get(i).getFile() == null) { - return sqlConsoles.get(i); - } - } - return sqlConsoles.get(sqlConsoles.size() - 1); - } - - public MetaDataSource getMetaDataSource() { - return getMetaDataSource(session); - } - - private void switchToDesktop() { - workbenchTabbedPane.setSelectedComponent(desktopSplitPane); - } - - private void initDnD(Component target) { - new DropTarget(target, new DropTargetListener() { - @Override - public void drop(DropTargetDropEvent dtde) { - try { - Transferable tr = dtde.getTransferable(); - DataFlavor[] flavors = tr.getTransferDataFlavors(); - for (int i = 0; i < flavors.length; i++) { - if (flavors[i].isFlavorJavaFileListType()) { - dtde.acceptDrop(dtde.getDropAction()); - @SuppressWarnings("unchecked") - java.util.List files = (java.util.List) tr.getTransferData(flavors[i]); - for (int k = 0; k < files.size(); k++) { - loadSQLScriptFile(files.get(k)); - } - - dtde.dropComplete(true); - } - } - return; - } catch (Throwable t) { - t.printStackTrace(); - } - dtde.rejectDrop(); - } - - @Override - public void dragEnter(DropTargetDragEvent dtde) { - } - - @Override - public void dragOver(DropTargetDragEvent dtde) { - } - - @Override - public void dropActionChanged(DropTargetDragEvent dtde) { - } - - @Override - public void dragExit(DropTargetEvent dte) { - } - - }); - } - - public boolean isReady() { - return session != null; - } - - public SQLConsole getSqlConsole(boolean switchToConsole) { - return desktop.getSqlConsole(switchToConsole); - } - - private static final String LAST_SESSION_FILE = ".lastsession"; - - private void storeLastSession() { - BookmarkId bookmark; - try { - desktop.storeSession(Environment.newFile(LAST_SESSION_FILE).getPath()); - bookmark = new BookmarkId(null, executionContext.getCurrentModelSubfolder(), executionContext.getCurrentConnectionAlias(), desktop.getRawSchemaMapping()); - } catch (IOException e) { - bookmark = null; - } - UISettings.storeLastSession(bookmark, "B"); - } - - public static Date getLastSessionDate() { - try { - long lastModified = Environment.newFile(LAST_SESSION_FILE).lastModified(); - if (lastModified == 0) { - return null; - } - return new Date(lastModified); - } catch (Exception e) { - return null; - } - } - - private DesktopAnchorManager anchorManager; - - private ImageIcon tableIcon; - private ImageIcon databaseIcon; - private ImageIcon redIcon; - private ImageIcon blueIcon; - private ImageIcon greenIcon; - private Icon closeIcon; - private ImageIcon sqlConsoleIcon; - private ImageIcon addSqlConsoleIcon; - private ImageIcon navigationIcon; - private ImageIcon desktopIcon; - { - // load images - tableIcon = UIUtil.readImage("/table.png"); - databaseIcon = UIUtil.readImage("/database.png"); - redIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/reddot.gif")); - blueIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/bluedot.gif")); - greenIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/greendot.gif")); - closeIcon = UIUtil.readImage("/Close-16-1.png"); - sqlConsoleIcon = UIUtil.readImage("/runall.png"); - desktopIcon = UIUtil.readImage("/tables.png"); - addSqlConsoleIcon = UIUtil.readImage("/add.png"); - navigationIcon = UIUtil.readImage("/navigation.png"); - } -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser; + +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.beans.PropertyVetoException; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URI; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.ButtonGroup; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JToggleButton; +import javax.swing.JTree; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.WindowConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.database.BasicDataSource; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.PrimaryKeyFactory; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; +import net.sf.jailer.modelbuilder.ModelBuilder; +import net.sf.jailer.ui.About; +import net.sf.jailer.ui.AnalyseOptionsDialog; +import net.sf.jailer.ui.AssociationListUI; +import net.sf.jailer.ui.AssociationListUI.AssociationModel; +import net.sf.jailer.ui.AssociationListUI.DefaultAssociationModel; +import net.sf.jailer.ui.AutoCompletion; +import net.sf.jailer.ui.BrowserLauncher; +import net.sf.jailer.ui.CLIPanel; +import net.sf.jailer.ui.ColumnOrderEditor; +import net.sf.jailer.ui.DataModelEditor; +import net.sf.jailer.ui.DataModelManager; +import net.sf.jailer.ui.DataModelManagerDialog; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.DbConnectionDialog.ConnectionInfo; +import net.sf.jailer.ui.Environment; +import net.sf.jailer.ui.ExtractionModelFrame; +import net.sf.jailer.ui.ImportDialog; +import net.sf.jailer.ui.JComboBox; +import net.sf.jailer.ui.PrivilegedSessionProviderDialog; +import net.sf.jailer.ui.SessionForUI; +import net.sf.jailer.ui.StringSearchPanel; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.UIUtil.ResultConsumer; +import net.sf.jailer.ui.associationproposer.AssociationProposerView; +import net.sf.jailer.ui.commandline.CommandLineInstance; +import net.sf.jailer.ui.constraintcheck.ConstraintChecker; +import net.sf.jailer.ui.databrowser.BookmarksPanel.BookmarkId; +import net.sf.jailer.ui.databrowser.BrowserContentPane.SqlStatementTable; +import net.sf.jailer.ui.databrowser.Desktop.LayoutMode; +import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; +import net.sf.jailer.ui.databrowser.metadata.MDGeneric; +import net.sf.jailer.ui.databrowser.metadata.MDSchema; +import net.sf.jailer.ui.databrowser.metadata.MDTable; +import net.sf.jailer.ui.databrowser.metadata.MetaDataDetailsPanel; +import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel; +import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel.OutlineInfo; +import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; +import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; +import net.sf.jailer.ui.syntaxtextarea.BasicFormatterImpl; +import net.sf.jailer.ui.util.AnimationController; +import net.sf.jailer.ui.util.SmallButton; +import net.sf.jailer.ui.util.UISettings; +import net.sf.jailer.ui.util.UpdateInfoManager; +import net.sf.jailer.util.CancellationHandler; +import net.sf.jailer.util.Quoting; + +/** + * Data Browser Frame. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public class DataBrowser extends javax.swing.JFrame { + + /** + * The desktop. + */ + Desktop desktop; + + /** + * Icon for the frame. + */ + private ImageIcon jailerIcon = null; + + /** + * The {@link DataModel}. + */ + private final Reference datamodel; + + /** + * The DB connection dialog. + */ + private DbConnectionDialog dbConnectionDialog; + + /** + * Session. + */ + private Session session; + + /** + * The border browser. + */ + private final AssociationListUI borderBrowser; + + /** + * The execution context. + */ + private final ExecutionContext executionContext; + + private final JComboBox tablesComboBox; + private boolean initialized = false; + + /** + * Allowed row limits. + */ + public static final Integer[] ROW_LIMITS = new Integer[] { 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 70000, 100000 }; + public static final int ROW_LIMIT_DEFAULT = 500; + + /** + * Constructor. + * + * @param datamodel + * the {@link DataModel} + * @param root + * table to start browsing with + * @param condition + * initial condition + * @param dbConnectionDialog + * DB-connection dialog + */ + public DataBrowser(final DataModel datamodel, final Table root, String condition, DbConnectionDialog dbConnectionDialog, Map schemaMapping, boolean embedded, final ExecutionContext executionContext) throws Exception { + this.executionContext = executionContext; + this.datamodel = new Reference(datamodel); + this.dbConnectionDialog = dbConnectionDialog != null ? new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext) : null; + this.borderBrowser = new AssociationListUI("Resolve", "Resolve selected Associations", true) { + @Override + protected void applyAction(Collection selection) { + resolveSelection(selection); + } + }; + if (embedded) { + DataBrowserContext.setSupportsDataModelUpdates(false); + } + initComponents(); + initMenu(); + + UpdateInfoManager.checkUpdateAvailability(updateInfoPanel, updateInfoLabel, downloadMenuItem, "B"); + UIUtil.initPLAFMenuItem(nativeLAFCheckBoxMenuItem, this); + if (datamodel != null) { + UISettings.dmStats(datamodel); + } + initRowLimitButtons(); + workbenchTabbedPane.setTabComponentAt(0, new JLabel("Desktop", desktopIcon, JLabel.LEFT)); + workbenchTabbedPane.setTabComponentAt(1, new JLabel("SQL Console ", sqlConsoleIcon, JLabel.LEFT)); + workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.getTabCount() - 1, new JLabel(addSqlConsoleIcon)); + + tableTreesTabbedPane.setTabComponentAt(0, new JLabel("Navigation", navigationIcon, JLabel.LEFT)); + tableTreesTabbedPane.setTabComponentAt(1, new JLabel("Database", databaseIcon, JLabel.LEFT)); + + tableTreesTabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (createMetaDataPanel != null && tableTreesTabbedPane.getSelectedComponent() == tablesCardPanel) { + UIUtil.invokeLater(10, new Runnable() { + @Override + public void run() { + if (createMetaDataPanel != null) { + createMetaDataPanel.run(); + } + } + }); + } + } + }); + + initialized = true; + + tablesComboBox = new JComboBox() { + @Override + public Dimension getMinimumSize() { + return new Dimension(40, super.getMinimumSize().height); + } + }; + tablesComboBox.setMaximumRowCount(20); + updateNavigationCombobox(); + AutoCompletion.enable(tablesComboBox); + + tablesComboBox.grabFocus(); + + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1; + navigationPanel.add(tablesComboBox, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + searchButton = StringSearchPanel.createSearchButton(this, tablesComboBox, "Open Table Browser", new Runnable() { + @Override + public void run() { + openTableButtonActionPerformed(null); + } + }); + navigationPanel.add(searchButton, gridBagConstraints); + + tablesComboBox.setVisible(false); + openTableButton.setVisible(false); + searchButton.setText("Open Table"); + + detailsAndBorderBrowserTabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updateBorderBrowser(); + updateDataModelView(null); + showDataModelMenuItem.setSelected(detailsAndBorderBrowserTabbedPane.getSelectedComponent() == dataModelPanel); + } + }); + + metaDataDetailsPanel = createMetaDataDetailsPanel(executionContext); + metaDataViewPanel.add(metaDataDetailsPanel); + + jLayeredPane1.removeAll(); + jLayeredPane1.setLayout(null); + jLayeredPane1.setLayer(layeredPaneContent, JLayeredPane.PALETTE_LAYER); + jLayeredPane1.setLayer(dummy, JLayeredPane.DEFAULT_LAYER); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 1; + jLayeredPane1.add(layeredPaneContent /*, gridBagConstraints */); + layeredPaneContent.setLocation(0, 0); +// jLayeredPane1.add(dummy /*, gridBagConstraints */); + + addComponentListener(new ComponentListener() { + @Override + public void componentShown(ComponentEvent e) { + layeredPaneContent.setSize(jLayeredPane1.getSize()); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + desktopSplitPane.setDividerLocation(0.75); + } + }); + } + @Override + public void componentResized(ComponentEvent e) { + } + @Override + public void componentMoved(ComponentEvent e) { + } + @Override + public void componentHidden(ComponentEvent e) { + } + }); + + jLayeredPane1.addComponentListener(new ComponentListener() { + @Override + public void componentShown(ComponentEvent e) { + layeredPaneContent.setSize(jLayeredPane1.getSize()); + } + @Override + public void componentResized(ComponentEvent e) { + layeredPaneContent.setSize(jLayeredPane1.getSize()); + jLayeredPane1.validate(); + } + @Override + public void componentMoved(ComponentEvent e) { + layeredPaneContent.setSize(jLayeredPane1.getSize()); + } + @Override + public void componentHidden(ComponentEvent e) { + } + }); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 1; + JPanel anchorPanel = new JPanel(null); + anchorPanel.setOpaque(false); + jLayeredPane1.setLayer(anchorPanel, JLayeredPane.POPUP_LAYER); + jLayeredPane1.add(anchorPanel/* , gridBagConstraints */); + + anchorManager = new DesktopAnchorManager(anchorPanel) { + @Override + protected void layout(RowBrowser anchor) { + try { + anchor.internalFrame.setSelected(true); + } catch (PropertyVetoException e) { + // ignore + } + arrangeLayout(true, anchor); + } + @Override + protected boolean isApplicable(RowBrowser tableBrowser) { + if (tableBrowser.parent == null) { + return false; + } + if (desktop.desktopAnimation != null && desktop.desktopAnimation.isActive()) { + return false; + } + RowBrowser ancestor = tableBrowser.parent; + while (ancestor != null) { + if (ancestor.internalFrame.isVisible() && Math.abs(tableBrowser.internalFrame.getY() - ancestor.internalFrame.getY()) > 2) { + return true; + } + ancestor = ancestor.parent; + } + return false; + } + }; + + if (jScrollPane1.getVerticalScrollBar() != null) { + jScrollPane1.getVerticalScrollBar().setUnitIncrement(16); + jScrollPane1.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + anchorManager.reset(); + } + }); + } + if (jScrollPane1.getHorizontalScrollBar() != null) { + jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16); + jScrollPane1.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + anchorManager.reset(); + } + }); + } + + hiddenPanel.setVisible(false); + borderBrowserPanel.add(borderBrowser, java.awt.BorderLayout.CENTER); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + gridBagConstraints.weighty = 0; +// jPanel4.add(new JPanel() { +// @Override +// public Dimension getMinimumSize() { +// return new Dimension(1, 300); +// } +// +// private static final long serialVersionUID = -947582621664272477L; +// }, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + gridBagConstraints.weighty = 0; +// borderBrowserTitledPanel.add(new JPanel() { +// @Override +// public Dimension getMinimumSize() { +// return new Dimension(1, 180); +// } +// +// private static final long serialVersionUID = -947582621664272477L; +// }, gridBagConstraints); + + DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + Component render = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (render instanceof JLabel) { + ImageIcon icon = null; + if (value instanceof DefaultMutableTreeNode && ((DefaultMutableTreeNode) value).getUserObject() instanceof TreeNodeForRowBrowser) { + TreeNodeForRowBrowser node = (TreeNodeForRowBrowser) ((DefaultMutableTreeNode) value).getUserObject(); + if (node.rowBrowser.association != null) { + if (node.rowBrowser.association.isInsertDestinationBeforeSource()) { + icon = redIcon; + } else if (node.rowBrowser.association.isInsertSourceBeforeDestination()) { + icon = greenIcon; + } else { + icon = blueIcon; + } + } else { + icon = tableIcon; + } + } else { + if (((JLabel) render).getText().trim().length() > 0) { + icon = navigationIcon; + } + } + ((JLabel) render).setIcon(icon); + } + return render; + } + }; + renderer.setOpenIcon(null); + renderer.setLeafIcon(null); + renderer.setClosedIcon(null); + navigationTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(""))); + + navigationTree.setCellRenderer(renderer); + + ButtonGroup buttonGroup = new ButtonGroup(); + + buttonGroup.add(thumbnailLayoutRadioButtonMenuItem); + buttonGroup.add(tinyLayoutRadioButtonMenuItem); + buttonGroup.add(smallLayoutRadioButtonMenuItem); + buttonGroup.add(mediumLayoutRadioButtonMenuItem); + buttonGroup.add(largeLayoutRadioButtonMenuItem); + + mediumLayoutRadioButtonMenuItem.setSelected(true); + + setTitle(DataBrowserContext.getAppName(false)); + if (embedded) { + analyseMenuItem.setEnabled(false); + dataModelEditorjMenuItem.setEnabled(false); + analyseSQLMenuItem1.setEnabled(false); + } + + // L&F can no longer be changed + jSeparator6.setVisible(false); + view.setVisible(false); + + try { + for (final LookAndFeelInfo lfInfo : UIManager.getInstalledLookAndFeels()) { + JMenuItem mItem = new JMenuItem(); + mItem.setText(lfInfo.getName()); + view.add(mItem); + mItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + setPLAF(lfInfo.getClassName()); + } + }); + } + } catch (Throwable t) { + } + + try { + setIconImage((jailerIcon = UIUtil.readImage("/jailerlight.png")).getImage()); + } catch (Throwable t) { + try { + setIconImage((jailerIcon = UIUtil.readImage("/jailer.gif")).getImage()); + } catch (Throwable t2) { + } + } + + jailerIcon.setImage(UIUtil.scaleIcon(jailerIcon, 16, 16).getImage()); + + if (dbConnectionDialog != null) { + createSession(dbConnectionDialog); + if (session == null) { + return; + } + } + desktop = new Desktop(this.datamodel, jailerIcon, session, this, dbConnectionDialog, schemaMapping == null? new HashMap() : schemaMapping, anchorManager, executionContext) { + @Override + public void openSchemaAnalyzer() { + updateDataModel(); + } + + protected void updateMenu(boolean hasTableBrowser, boolean hasIFrame) { + storeSessionItem.setEnabled(hasIFrame); + closeAllMenuItem.setEnabled(hasIFrame); + addBookmarkMenuItem.setEnabled(hasTableBrowser); + exportDataMenuItem.setEnabled(hasTableBrowser); + createExtractionModelMenuItem.setEnabled(hasTableBrowser); + updateIFramesBar(); + super.updateMenu(hasTableBrowser, hasIFrame); + } + + @Override + protected void updateMenu(LayoutMode layoutMode) { + zoomInMenuItem.setEnabled(layoutMode != Desktop.LayoutMode.LARGE); + zoomOutMenuItem.setEnabled(layoutMode != Desktop.LayoutMode.THUMBNAIL); + tinyLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.TINY); + smallLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.SMALL); + mediumLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.MEDIUM); + largeLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.LARGE); + thumbnailLayoutRadioButtonMenuItem.setSelected(layoutMode == Desktop.LayoutMode.THUMBNAIL); + } + + @Override + protected DataBrowser openNewDataBrowser() { + try { + return DataBrowser.openNewDataBrowser(DataBrowser.this.datamodel.get(), dbConnectionDialog, false, executionContext, null); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + return null; + } + } + + @Override + public void onNewDataModel() { + onNewSession(session); + } + + @Override + protected SQLConsole getSqlConsole(boolean switchToConsole) { + if (switchToConsole) { + workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); + } + return getCurrentSQLConsole(); + } + + @Override + public void onLayoutChanged(boolean isLayouted, boolean scrollToCenter) { + if (!isLayouted) { + arrangeLayout(scrollToCenter); + } + } + + @Override + protected int getRowLimit() { + for (Entry e: rowLimitButtonToLimit.entrySet()) { + if (e.getKey().isSelected()) { + return e.getValue(); + } + } + return ROW_LIMIT_DEFAULT; + } + + @Override + protected boolean isDesktopVisible() { + return workbenchTabbedPane.getSelectedComponent() == desktopSplitPane; + } + + @Override + protected void checkAnchorRetension() { + if (anchorManager != null) { + anchorManager.checkRetention(); + } + } + + @Override + public void updateBookmarksMenu() { + new BookmarksPanel(DataBrowser.this, bookmarkMenu, desktop, executionContext).updateBookmarksMenu(); + } + + @Override + protected void changeColumnOrder(Table table) { + openColumnOrderEditor(table); + } + + @Override + protected void onRowSelect(Table table, Row row) { + if (metaDataDetailsPanel != null) { + MetaDataSource metaDataSource = getMetaDataSource(session); + boolean passTable = metaDataSource.isInitialized() && metaDataSource.getDefaultSchema() != null && metaDataSource.getDefaultSchema().isLoaded(); + if (passTable) { + MDSchema schema = metaDataSource.getSchemaOfTable(table); + if (schema != null && schema != metaDataSource.getDefaultSchema()) { + if (!schema.isLoaded()) { + passTable = false; + schema.loadTables(true, null, null); + } + } + } + metaDataDetailsPanel.showMetaDataDetails(passTable? metaDataSource.toMDTable(table): null, table, row, true, datamodel); + } + } + }; + + desktop.addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseMoved(MouseEvent e) { + double buttonWidth = anchorManager.getButtonWidth() * 1.4; + double minDist = Double.MAX_VALUE; + RowBrowser nearest = null; + for (RowBrowser br : desktop.getBrowsers()) { + if (br.internalFrame != null && br.internalFrame.isVisible()) { + if (e.getX() - buttonWidth <= br.internalFrame.getX()) { + double dx = e.getX() - br.internalFrame.getX(); + double dy = e.getY() - br.internalFrame.getY(); + double dist2 = dx * dx + dy * dy; + if (nearest == null || dist2 < minDist) { + nearest = br; + minDist = dist2; + } + } + } + } + if (nearest != null) { + anchorManager.onTableBrowserNeared(nearest); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + } + }); + + new BookmarksPanel(this, bookmarkMenu, desktop, executionContext).updateBookmarksMenu(); + + jScrollPane1.setViewportView(desktop); + addWindowListener(new WindowListener() { + @Override + public void windowOpened(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + if (closeAllSQLConsoles()) { + DataBrowser.this.dispose(); + } + } + + @Override + public void windowClosed(WindowEvent e) { + storeLastSession(); + desktop.stop(); + UIUtil.checkTermination(); + } + + @Override + public void windowActivated(WindowEvent e) { + } + }); + + MouseInputAdapter mia = new MouseInputAdapter() { + int m_XDifference, m_YDifference; + Container c; + + @Override + public void mouseDragged(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + return; + } + c = desktop.getParent(); + if (c instanceof JViewport) { + JViewport jv = (JViewport) c; + Point p = jv.getViewPosition(); + int newX = p.x - (e.getX() - m_XDifference); + int newY = p.y - (e.getY() - m_YDifference); + int maxX = desktop.getWidth() - jv.getWidth(); + int maxY = desktop.getHeight() - jv.getHeight(); + if (newX < 0) + newX = 0; + if (newX > maxX) + newX = maxX; + if (newY < 0) + newY = 0; + if (newY > maxY) + newY = maxY; + jv.setViewPosition(new Point(newX, newY)); + DesktopAnimation.stopScrolling = true; + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + return; + } + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + m_XDifference = e.getX(); + m_YDifference = e.getY(); + DesktopAnimation.stopScrolling = true; + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + return; + } + setCursor(null); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON3) { + return; + } + JPopupMenu popup = new JPopupMenu(); + JMenuItem i = new JMenuItem("Arrange Layout"); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + layoutMenuItemActionPerformed(e); + } + }); + ButtonGroup group = new ButtonGroup(); + popup.add(new JSeparator()); + i = new JRadioButtonMenuItem("Thumbnail Layout"); + i.setSelected(desktop.layoutMode == LayoutMode.THUMBNAIL); + group.add(i); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + thumbnailLayoutRadioButtonMenuItemActionPerformed(e); + } + }); + i = new JRadioButtonMenuItem("Tiny Layout"); + i.setSelected(desktop.layoutMode == LayoutMode.TINY); + group.add(i); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tinyLayoutRadioButtonMenuItemActionPerformed(e); + } + }); + i = new JRadioButtonMenuItem("Small Layout"); + i.setSelected(desktop.layoutMode == LayoutMode.SMALL); + group.add(i); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + smallLayoutRadioButtonMenuItemActionPerformed(e); + } + }); + i = new JRadioButtonMenuItem("Medium Layout"); + i.setSelected(desktop.layoutMode == LayoutMode.MEDIUM); + group.add(i); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mediumLayoutRadioButtonMenuItemActionPerformed(e); + } + }); + i = new JRadioButtonMenuItem("Large Layout"); + i.setSelected(desktop.layoutMode == LayoutMode.LARGE); + group.add(i); + popup.add(i); + i.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + largeLayoutRadioButtonMenuItemActionPerformed(e); + } + }); + UIUtil.showPopup(desktop, e.getX(), e.getY(), popup); + } + }; + + desktop.addMouseMotionListener(mia); + desktop.addMouseListener(mia); + + AnimationController.registerWindow(this, new AnimationController.AnimationControl() { + @Override + public void setEnabled(boolean enabled) { + desktop.setAnimationEnabled(enabled); + } + }); + + int c = 0; + for (Frame frame: Frame.getFrames()) { + if (frame instanceof DataBrowser && frame.isVisible()) { + c = (c + 1) % 10; + } + } + + setLocation(40 + c * 32, 40 + c * 32); + setSize(980, 640); + + UIUtil.fit(this); + + if (root != null) { + final RowBrowser rb = desktop.addTableBrowser(null, null, root, null, condition, null, null, true); + if (rb != null && rb.internalFrame != null) { + UIUtil.invokeLater(10, new Runnable() { + @Override + public void run() { + try { + rb.internalFrame.setSelected(true); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(rb.internalFrame); + } catch (PropertyVetoException e) { + // ignore + } + } + }); + } + } + schemaNamePanel.addMouseListener(new java.awt.event.MouseAdapter() { + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + desktop.openSchemaMappingDialog(false); + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + in = true; + updateBorder(); + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + schemaNamePanel.setBorder(new javax.swing.border.SoftBevelBorder(in ? javax.swing.border.BevelBorder.LOWERED + : javax.swing.border.BevelBorder.RAISED)); + } + }); + updateStatusBar(); + updateClosureBrowser(null); + + TreeSelectionListener treeListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + if (e.getNewLeadSelectionPath() != null) { + Object lastPathComponent = e.getNewLeadSelectionPath().getLastPathComponent(); + if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); + if (userObject instanceof TreeNodeForRowBrowser) { + updateDataModelView(null); + updateClosureBrowser(((TreeNodeForRowBrowser) userObject).rowBrowser); + if (metaDataPanel != null) { + if (((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane != null) { + if (!(((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table instanceof SqlStatementTable)) { + metaDataPanel.select(((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table); + } + } + } + return; + } + } + } else { + updateClosureBrowser(null); + } + } + }; + + navigationTree.getSelectionModel().addTreeSelectionListener(treeListener); + initDnD(this); + } + + private Map rowLimitButtonToLimit = new HashMap(); + + private void initRowLimitButtons() { + ButtonGroup group = new ButtonGroup(); + JRadioButtonMenuItem def = null; + for (final Integer limit: ROW_LIMITS) { + JRadioButtonMenuItem item = new JRadioButtonMenuItem(limit.toString()); + group.add(item); + rowLimitMenu.add(item); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + try { + Component sc = workbenchTabbedPane.getSelectedComponent(); + if (sc instanceof SQLConsole) { + SQLConsole sqlConsole = (SQLConsole) sc; + sqlConsole.setRowLimit(limit); + } + desktop.reloadRoots(); + } catch (Exception e) { + UIUtil.showException(DataBrowser.this, "Error", e); + } + } + }); + rowLimitButtonToLimit.put(item, limit); + if (limit == ROW_LIMIT_DEFAULT) { + def = item; + } + } + if (def != null) { + def.setSelected(true); + } + } + + @SuppressWarnings("unchecked") + public void updateNavigationCombobox() { + List tables = new ArrayList(); + + for (Table table: datamodel.get().getTables()) { + tables.add(datamodel.get().getDisplayName(table)); + } + Collections.sort(tables); + @SuppressWarnings({ "rawtypes" }) + ComboBoxModel model = new DefaultComboBoxModel(new Vector(tables)); + + tablesComboBox.setModel(model); + } + + private MetaDataDetailsPanel createMetaDataDetailsPanel(final ExecutionContext executionContext) { + return new MetaDataDetailsPanel(this.datamodel, session, this, executionContext) { + @Override + protected void analyseSchema(String schemaName, boolean withViews, boolean withSynonyms) { + updateDataModel(schemaName, withViews, withSynonyms); + } + }; + } + + private void createSession(DbConnectionDialog dbConnectionDialog) throws Exception { + ConnectionInfo connection = dbConnectionDialog.currentConnection; + BasicDataSource dataSource = UIUtil.createBasicDataSource(this, connection.driverClass, connection.url, connection.user, connection.password, 0, dbConnectionDialog.currentJarURLs()); + SessionForUI newSession = SessionForUI.createSession(dataSource, dataSource.dbms, executionContext.getIsolationLevel(), false, this); + if (newSession != null) { + if (session != null) { + try { + session.shutDown(); + session = null; + } catch (Exception e) { + // ignore + } + } + session = newSession; + List args = new ArrayList(); + dbConnectionDialog.addDbArgs(args); + session.setCliArguments(args); + session.setPassword(dbConnectionDialog.getPassword()); + onNewSession(session); + } + } + + protected void setConnection(DbConnectionDialog dbConnectionDialog) throws Exception { + if (dbConnectionDialog != null) { + dbConnectionDialog = new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); + } + this.dbConnectionDialog = dbConnectionDialog; + desktop.dbConnectionDialog = dbConnectionDialog; + if (dbConnectionDialog != null) { + ConnectionInfo connection = dbConnectionDialog.currentConnection; + if (connection != null) { + createSession(dbConnectionDialog); + if (session != null) { + desktop.session = session; + onNewSession(session); + desktop.openSchemaMappingDialog(true); + updateStatusBar(); + if (desktop != null) { + desktop.updateMenu(); + for (RowBrowser rb : desktop.getBrowsers()) { + rb.browserContentPane.session = session; + rb.browserContentPane.rows.clear(); + } + for (RowBrowser rb : desktop.getRootBrowsers(false)) { + rb.browserContentPane.reloadRows(); + } + } + } + } + } + } + + public void updateStatusBar() { + final int MAX_LENGTH = 50; + ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; + String dburl = connection != null ? (connection.url) : " "; + connectivityState.setToolTipText(dburl); + dburl = connection != null ? (connection.user + "@" + connection.alias) : " "; + if (dburl.length() > MAX_LENGTH) { + dburl = dburl.substring(0, MAX_LENGTH - 3) + "..."; + } + connectivityState.setText(dburl); + DataModel dataModel = datamodel != null ? datamodel.get() : null; + String modelname = "Data Model \"" + (dataModel == null ? DataModel.DEFAULT_NAME : dataModel.getName()) + "\""; + String lastMod = dataModel == null ? "" : dataModel.getLastModifiedAsString(); + if (lastMod.length() > 0) { + lastMod = " (" + lastMod + ")"; + } + modelName.setText(modelname); + modelName.setToolTipText(modelname + lastMod); + + String modelpath = executionContext.getQualifiedDatamodelFolder(); + try { + modelpath = new File(modelpath).getAbsolutePath(); + } catch (Throwable t) { + // use default modelpath + } + modelpath += File.separator; + modelPath.setToolTipText(modelpath); + if (modelpath.length() > MAX_LENGTH + 4) { + modelpath = modelpath.substring(0, MAX_LENGTH / 2) + "..." + modelpath.substring(modelpath.length() - MAX_LENGTH / 2); + } + modelPath.setText(modelpath); + + String nonDefaultSchema = null; + if (desktop.schemaMapping != null) { + for (Map.Entry e : desktop.schemaMapping.entrySet()) { + if (!e.getKey().equalsIgnoreCase(e.getValue())) { + nonDefaultSchema = e.getValue(); + break; + } + } + } + schemaNamePanel.setVisible(nonDefaultSchema != null); + if (nonDefaultSchema != null) { + if (nonDefaultSchema.equals("")) { + schemaName.setText("Default Schema"); + } else { + schemaName.setText("Schema " + nonDefaultSchema + ""); + } + // schemaName.setToolTipText(schemaName.getText()); + } + } + + @SuppressWarnings("deprecation") + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + dummy = new javax.swing.JPanel(); + jScrollPane3 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); + jLayeredPane2 = new javax.swing.JLayeredPane(); + jPanel1 = new javax.swing.JPanel(); + jPanel11 = new javax.swing.JPanel(); + legende1 = new javax.swing.JPanel(); + modelName = new javax.swing.JLabel(); + modelPath = new javax.swing.JLabel(); + legende = new javax.swing.JPanel(); + dependsOn = new javax.swing.JLabel(); + hasDependent = new javax.swing.JLabel(); + associatedWith = new javax.swing.JLabel(); + ignored = new javax.swing.JLabel(); + schemaNamePanel = new javax.swing.JPanel(); + schemaName = new javax.swing.JLabel(); + legende2 = new javax.swing.JPanel(); + connectivityState = new javax.swing.JLabel(); + jPanel2 = new javax.swing.JPanel(); + jSplitPane1 = new javax.swing.JSplitPane(); + jPanel3 = new javax.swing.JPanel(); + jPanel5 = new javax.swing.JPanel(); + workbenchTabbedPane = new javax.swing.JTabbedPane(); + desktopSplitPane = new javax.swing.JSplitPane(); + jLayeredPane1 = new javax.swing.JLayeredPane(); + layeredPaneContent = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jInternalFrame1 = new javax.swing.JInternalFrame(); + hiddenPanel = new javax.swing.JPanel(); + closurePanel = new javax.swing.JPanel(); + consoleDummyPanel = new javax.swing.JPanel(); + addSQLConsoleTab = new javax.swing.JPanel(); + jPanel4 = new javax.swing.JPanel(); + jSplitPane4 = new javax.swing.JSplitPane(); + tableTreesTabbedPane = new javax.swing.JTabbedPane(); + navigationPanel = new javax.swing.JPanel(); + navigationTreeScrollPane = new javax.swing.JScrollPane(); + navigationTree = new javax.swing.JTree(); + openTableButton = new javax.swing.JButton(); + tablesCardPanel = new javax.swing.JPanel(); + tablesPanel = new javax.swing.JPanel(); + jPanel6 = new javax.swing.JPanel(); + jScrollPane2 = new javax.swing.JScrollPane(); + jTree1 = new javax.swing.JTree(); + refreshButton = new javax.swing.JButton(); + detailsAndBorderBrowserTabbedPane = new javax.swing.JTabbedPane(); + jPanel7 = new javax.swing.JPanel(); + metaDataViewPanel = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + jLabel9 = new javax.swing.JLabel(); + jLabel10 = new javax.swing.JLabel(); + jLabel11 = new javax.swing.JLabel(); + jLabel12 = new javax.swing.JLabel(); + jLabel13 = new javax.swing.JLabel(); + jLabel14 = new javax.swing.JLabel(); + jLabel19 = new javax.swing.JLabel(); + jLabel20 = new javax.swing.JLabel(); + jLabel21 = new javax.swing.JLabel(); + jLabel22 = new javax.swing.JLabel(); + borderBrowserTabPane = new javax.swing.JPanel(); + borderBrowserPanel = new javax.swing.JPanel(); + titleLabel = new javax.swing.JLabel(); + dataModelPanel = new javax.swing.JPanel(); + jLabel26 = new javax.swing.JLabel(); + updateInfoPanel = new javax.swing.JPanel(); + updateInfoLabel = new javax.swing.JLabel(); + downloadButton = new javax.swing.JButton(); + jButton1 = new javax.swing.JButton(); + menuBar = new javax.swing.JMenuBar(); + jMenu1 = new javax.swing.JMenu(); + jMenuItem3 = new javax.swing.JMenuItem(); + closeAllMenuItem = new javax.swing.JMenuItem(); + jSeparator4 = new javax.swing.JPopupMenu.Separator(); + loadScriptMenuItem = new javax.swing.JMenuItem(); + saveScriptMenuItem = new javax.swing.JMenuItem(); + saveScriptAsMenuItem = new javax.swing.JMenuItem(); + jSeparator9 = new javax.swing.JPopupMenu.Separator(); + storeSessionItem = new javax.swing.JMenuItem(); + restoreSessionItem = new javax.swing.JMenuItem(); + jSeparator7 = new javax.swing.JPopupMenu.Separator(); + reconnectMenuItem = new javax.swing.JMenuItem(); + newBrowserjMenuItem = new javax.swing.JMenuItem(); + jSeparator12 = new javax.swing.JPopupMenu.Separator(); + exitMenuItem = new javax.swing.JMenuItem(); + menuTools = new javax.swing.JMenu(); + analyseMenuItem = new javax.swing.JMenuItem(); + dataModelEditorjMenuItem = new javax.swing.JMenuItem(); + schemaMappingMenuItem = new javax.swing.JMenuItem(); + jSeparator2 = new javax.swing.JPopupMenu.Separator(); + columnOrderItem = new javax.swing.JMenuItem(); + jSeparator11 = new javax.swing.JPopupMenu.Separator(); + analyseSQLMenuItem1 = new javax.swing.JMenuItem(); + jSeparator10 = new javax.swing.JPopupMenu.Separator(); + showDataModelMenuItem = new javax.swing.JCheckBoxMenuItem(); + checkPKMenuItem = new javax.swing.JMenuItem(); + consistencyCheckMenuItem1 = new javax.swing.JMenuItem(); + jviewMenu = new javax.swing.JMenu(); + rowLimitMenu = new javax.swing.JMenu(); + bookmarkMenu = new javax.swing.JMenu(); + addBookmarkMenuItem = new javax.swing.JMenuItem(); + editBookmarkMenuItem = new javax.swing.JMenuItem(); + jSeparator13 = new javax.swing.JPopupMenu.Separator(); + jMenu2 = new javax.swing.JMenu(); + exportDataMenuItem = new javax.swing.JMenuItem(); + dataImport = new javax.swing.JMenuItem(); + jSeparator8 = new javax.swing.JPopupMenu.Separator(); + createExtractionModelMenuItem = new javax.swing.JMenuItem(); + consistencyCheckMenuItem = new javax.swing.JMenuItem(); + createCLIItem = new javax.swing.JMenuItem(); + menuWindow = new javax.swing.JMenu(); + layoutMenuItem = new javax.swing.JMenuItem(); + jSeparator5 = new javax.swing.JPopupMenu.Separator(); + zoomInMenuItem = new javax.swing.JMenuItem(); + zoomOutMenuItem = new javax.swing.JMenuItem(); + jSeparator15 = new javax.swing.JPopupMenu.Separator(); + thumbnailLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); + tinyLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); + smallLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); + mediumLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); + largeLayoutRadioButtonMenuItem = new javax.swing.JRadioButtonMenuItem(); + jSeparator1 = new javax.swing.JPopupMenu.Separator(); + newWindowMenuItem = new javax.swing.JMenuItem(); + jSeparator6 = new javax.swing.JPopupMenu.Separator(); + view = new javax.swing.JMenu(); + jMenu3 = new javax.swing.JMenu(); + nativeLAFCheckBoxMenuItem = new javax.swing.JCheckBoxMenuItem(); + helpMenu = new javax.swing.JMenu(); + jMenuItem4 = new javax.swing.JMenuItem(); + helpForum = new javax.swing.JMenuItem(); + downloadMenuItem = new javax.swing.JMenuItem(); + jSeparator14 = new javax.swing.JPopupMenu.Separator(); + aboutMenuItem = new javax.swing.JMenuItem(); + + jTable1.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null} + }, + new String [] { + "Title 1", "Title 2", "Title 3", "Title 4" + } + )); + jScrollPane3.setViewportView(jTable1); + + dummy.add(jScrollPane3); + + jLayeredPane2.setLayout(new java.awt.GridBagLayout()); + + jPanel1.setLayout(new java.awt.GridBagLayout()); + + jPanel11.setLayout(new java.awt.GridBagLayout()); + + legende1.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + legende1.setLayout(new java.awt.GridBagLayout()); + + modelName.setFont(modelName.getFont().deriveFont(modelName.getFont().getSize()+1f)); + modelName.setText("Data Model \"Demo\""); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 12); + legende1.add(modelName, gridBagConstraints); + + modelPath.setFont(modelPath.getFont().deriveFont(modelPath.getFont().getSize()+1f)); + modelPath.setForeground(java.awt.Color.gray); + modelPath.setText("/home/jailer/datamodel/"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + legende1.add(modelPath, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + jPanel11.add(legende1, gridBagConstraints); + + legende.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + legende.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 0)); + + dependsOn.setFont(dependsOn.getFont().deriveFont(dependsOn.getFont().getSize()+1f)); + dependsOn.setForeground(new java.awt.Color(170, 0, 0)); + dependsOn.setText(" depends on (has parent) "); + legende.add(dependsOn); + + hasDependent.setFont(hasDependent.getFont().deriveFont(hasDependent.getFont().getSize()+1f)); + hasDependent.setForeground(new java.awt.Color(0, 112, 0)); + hasDependent.setText(" has dependent (has child) "); + legende.add(hasDependent); + + associatedWith.setFont(associatedWith.getFont().deriveFont(associatedWith.getFont().getSize()+1f)); + associatedWith.setForeground(new java.awt.Color(0, 100, 255)); + associatedWith.setText(" associated with"); + legende.add(associatedWith); + + ignored.setFont(ignored.getFont().deriveFont(ignored.getFont().getSize()+1f)); + ignored.setForeground(new java.awt.Color(153, 153, 153)); + ignored.setText(" disabled "); + legende.add(ignored); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + jPanel11.add(legende, gridBagConstraints); + + schemaNamePanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + schemaNamePanel.setLayout(new java.awt.GridBagLayout()); + + schemaName.setFont(schemaName.getFont().deriveFont(schemaName.getFont().getSize()+1f)); + schemaName.setText("Schema"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 12); + schemaNamePanel.add(schemaName, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + jPanel11.add(schemaNamePanel, gridBagConstraints); + + legende2.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + legende2.setLayout(new java.awt.GridBagLayout()); + + connectivityState.setFont(connectivityState.getFont().deriveFont(connectivityState.getFont().getSize()+1f)); + connectivityState.setText("offline"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 6); + legende2.add(connectivityState, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); + jPanel11.add(legende2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + jPanel1.add(jPanel11, gridBagConstraints); + + jPanel2.setLayout(new java.awt.GridBagLayout()); + + jSplitPane1.setDividerLocation(340); + jSplitPane1.setContinuousLayout(true); + jSplitPane1.setOneTouchExpandable(true); + + jPanel3.setLayout(new java.awt.GridBagLayout()); + jSplitPane1.setLeftComponent(jPanel3); + + jPanel5.setLayout(new java.awt.GridBagLayout()); + + workbenchTabbedPane.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + workbenchTabbedPaneStateChanged(evt); + } + }); + + desktopSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + desktopSplitPane.setResizeWeight(0.95); + desktopSplitPane.setContinuousLayout(true); + desktopSplitPane.setOneTouchExpandable(true); + + layeredPaneContent.setLayout(new java.awt.GridBagLayout()); + + jScrollPane1.setAutoscrolls(true); + jScrollPane1.setWheelScrollingEnabled(false); + jScrollPane1.addMouseWheelListener(new java.awt.event.MouseWheelListener() { + public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { + jScrollPane1MouseWheelMoved(evt); + } + }); + + jInternalFrame1.setVisible(true); + jScrollPane1.setViewportView(jInternalFrame1); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + layeredPaneContent.add(jScrollPane1, gridBagConstraints); + + hiddenPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + layeredPaneContent.add(hiddenPanel, gridBagConstraints); + + jLayeredPane1.setLayer(layeredPaneContent, javax.swing.JLayeredPane.PALETTE_LAYER); + jLayeredPane1.add(layeredPaneContent); + layeredPaneContent.setBounds(0, 0, 24, 42); + + desktopSplitPane.setLeftComponent(jLayeredPane1); + + closurePanel.setLayout(new java.awt.GridBagLayout()); + desktopSplitPane.setRightComponent(closurePanel); + + workbenchTabbedPane.addTab("Desktop", desktopSplitPane); + workbenchTabbedPane.addTab("SQL Console", consoleDummyPanel); + workbenchTabbedPane.addTab("+", addSQLConsoleTab); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(1, 0, 0, 0); + jPanel5.add(workbenchTabbedPane, gridBagConstraints); + + jSplitPane1.setRightComponent(jPanel5); + + jPanel4.setLayout(new java.awt.GridBagLayout()); + + jSplitPane4.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane4.setResizeWeight(1.0); + jSplitPane4.setContinuousLayout(true); + jSplitPane4.setOneTouchExpandable(true); + + navigationPanel.setLayout(new java.awt.GridBagLayout()); + + navigationTree.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + navigationTreeMouseClicked(evt); + } + }); + navigationTreeScrollPane.setViewportView(navigationTree); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + navigationPanel.add(navigationTreeScrollPane, gridBagConstraints); + + openTableButton.setText("Open"); + openTableButton.setToolTipText("Open table browser for the selected table"); + openTableButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + openTableButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); + navigationPanel.add(openTableButton, gridBagConstraints); + + tableTreesTabbedPane.addTab("Navigation", navigationPanel); + + tablesCardPanel.setLayout(new java.awt.CardLayout()); + + tablesPanel.setLayout(new java.awt.BorderLayout()); + tablesCardPanel.add(tablesPanel, "tables"); + + jPanel6.setLayout(new java.awt.GridBagLayout()); + + javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("loading database meta data..."); + jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); + jTree1.setSelectionModel(null); + jScrollPane2.setViewportView(jTree1); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel6.add(jScrollPane2, gridBagConstraints); + + refreshButton.setText("Refresh"); + refreshButton.setToolTipText("Refresh Database Meta Data Cache"); + refreshButton.setEnabled(false); + refreshButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + refreshButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + jPanel6.add(refreshButton, gridBagConstraints); + + tablesCardPanel.add(jPanel6, "loading"); + + tableTreesTabbedPane.addTab("Database", tablesCardPanel); + + jSplitPane4.setLeftComponent(tableTreesTabbedPane); + + jPanel7.setLayout(new java.awt.GridBagLayout()); + + metaDataViewPanel.setLayout(new javax.swing.BoxLayout(metaDataViewPanel, javax.swing.BoxLayout.LINE_AXIS)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridheight = 30; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel7.add(metaDataViewPanel, gridBagConstraints); + + jLabel1.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + jPanel7.add(jLabel1, gridBagConstraints); + + jLabel3.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + jPanel7.add(jLabel3, gridBagConstraints); + + jLabel4.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + jPanel7.add(jLabel4, gridBagConstraints); + + jLabel5.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + jPanel7.add(jLabel5, gridBagConstraints); + + jLabel6.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 5; + jPanel7.add(jLabel6, gridBagConstraints); + + jLabel7.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 6; + jPanel7.add(jLabel7, gridBagConstraints); + + jLabel8.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 7; + jPanel7.add(jLabel8, gridBagConstraints); + + jLabel9.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 8; + jPanel7.add(jLabel9, gridBagConstraints); + + jLabel10.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 10; + jPanel7.add(jLabel10, gridBagConstraints); + + jLabel11.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 11; + jPanel7.add(jLabel11, gridBagConstraints); + + jLabel12.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 12; + jPanel7.add(jLabel12, gridBagConstraints); + + jLabel13.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 13; + jPanel7.add(jLabel13, gridBagConstraints); + + jLabel14.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 14; + jPanel7.add(jLabel14, gridBagConstraints); + + jLabel19.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 19; + jPanel7.add(jLabel19, gridBagConstraints); + + jLabel20.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 20; + jPanel7.add(jLabel20, gridBagConstraints); + + jLabel21.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 21; + jPanel7.add(jLabel21, gridBagConstraints); + + jLabel22.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 22; + jPanel7.add(jLabel22, gridBagConstraints); + + detailsAndBorderBrowserTabbedPane.addTab("Details", jPanel7); + + borderBrowserTabPane.setLayout(new java.awt.GridBagLayout()); + + borderBrowserPanel.setLayout(new java.awt.BorderLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + borderBrowserTabPane.add(borderBrowserPanel, gridBagConstraints); + + titleLabel.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0); + borderBrowserTabPane.add(titleLabel, gridBagConstraints); + + detailsAndBorderBrowserTabbedPane.addTab("Closure Border", borderBrowserTabPane); + + dataModelPanel.setLayout(new java.awt.BorderLayout()); + + jLabel26.setText(" Loading..."); + dataModelPanel.add(jLabel26, java.awt.BorderLayout.CENTER); + + detailsAndBorderBrowserTabbedPane.addTab("Data Model", dataModelPanel); + + jSplitPane4.setRightComponent(detailsAndBorderBrowserTabbedPane); + detailsAndBorderBrowserTabbedPane.getAccessibleContext().setAccessibleName("Closure Border"); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel4.add(jSplitPane4, gridBagConstraints); + + jSplitPane1.setLeftComponent(jPanel4); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel2.add(jSplitPane1, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel1.add(jPanel2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jLayeredPane2.add(jPanel1, gridBagConstraints); + + updateInfoPanel.setBackground(new java.awt.Color(255, 255, 236)); + updateInfoPanel.setLayout(new java.awt.GridBagLayout()); + + updateInfoLabel.setText("Release x available"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); + updateInfoPanel.add(updateInfoLabel, gridBagConstraints); + + downloadButton.setText("Download"); + downloadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + downloadButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 0); + updateInfoPanel.add(downloadButton, gridBagConstraints); + + jButton1.setText("Close"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 2, 4, 4); + updateInfoPanel.add(jButton1, gridBagConstraints); + + jLayeredPane2.setLayer(updateInfoPanel, javax.swing.JLayeredPane.MODAL_LAYER); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 72, 24); + jLayeredPane2.add(updateInfoPanel, gridBagConstraints); + + getContentPane().add(jLayeredPane2, java.awt.BorderLayout.CENTER); + + jMenu1.setText("File"); + + jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, java.awt.event.InputEvent.CTRL_MASK)); + jMenuItem3.setText("Open Table"); + jMenuItem3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jMenuItem3ActionPerformed(evt); + } + }); + jMenu1.add(jMenuItem3); + + closeAllMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)); + closeAllMenuItem.setText("Close All Tables"); + closeAllMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + closeAllMenuItemActionPerformed(evt); + } + }); + jMenu1.add(closeAllMenuItem); + jMenu1.add(jSeparator4); + + loadScriptMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK)); + loadScriptMenuItem.setText("Open SQL Script..."); + loadScriptMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + loadScriptMenuItemActionPerformed(evt); + } + }); + jMenu1.add(loadScriptMenuItem); + + saveScriptMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK)); + saveScriptMenuItem.setText("Save"); + saveScriptMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + saveScriptMenuItemActionPerformed(evt); + } + }); + jMenu1.add(saveScriptMenuItem); + + saveScriptAsMenuItem.setText("Save as..."); + saveScriptAsMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + saveScriptAsMenuItemActionPerformed(evt); + } + }); + jMenu1.add(saveScriptAsMenuItem); + jMenu1.add(jSeparator9); + + storeSessionItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK)); + storeSessionItem.setText("Store Layout"); + storeSessionItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + storeSessionItemActionPerformed(evt); + } + }); + jMenu1.add(storeSessionItem); + + restoreSessionItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK)); + restoreSessionItem.setText("Restore Layout"); + restoreSessionItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + restoreSessionItemActionPerformed(evt); + } + }); + jMenu1.add(restoreSessionItem); + jMenu1.add(jSeparator7); + + reconnectMenuItem.setText("Reconnect..."); + reconnectMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + reconnectMenuItemActionPerformed(evt); + } + }); + jMenu1.add(reconnectMenuItem); + + newBrowserjMenuItem.setText("New Data Browser"); + newBrowserjMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + newBrowserjMenuItemActionPerformed(evt); + } + }); + jMenu1.add(newBrowserjMenuItem); + jMenu1.add(jSeparator12); + + exitMenuItem.setText("Exit"); + exitMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + exitMenuItemActionPerformed(evt); + } + }); + jMenu1.add(exitMenuItem); + + menuBar.add(jMenu1); + + menuTools.setText("Model"); + + analyseMenuItem.setText("Analyse Database"); + analyseMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + analyseMenuItemActionPerformed(evt); + } + }); + menuTools.add(analyseMenuItem); + + dataModelEditorjMenuItem.setText("Data Model Editor"); + dataModelEditorjMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dataModelEditorjMenuItemActionPerformed(evt); + } + }); + menuTools.add(dataModelEditorjMenuItem); + + schemaMappingMenuItem.setText("Schema Mapping"); + schemaMappingMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + schemaMappingMenuItemActionPerformed(evt); + } + }); + menuTools.add(schemaMappingMenuItem); + menuTools.add(jSeparator2); + + columnOrderItem.setText("Column Ordering"); + columnOrderItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + columnOrderItemActionPerformed(evt); + } + }); + menuTools.add(columnOrderItem); + menuTools.add(jSeparator11); + + analyseSQLMenuItem1.setText("Analyze SQL Script"); + analyseSQLMenuItem1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + analyseSQLMenuItem1ActionPerformed(evt); + } + }); + menuTools.add(analyseSQLMenuItem1); + menuTools.add(jSeparator10); + + showDataModelMenuItem.setText("Show Data Model"); + showDataModelMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showDataModelMenuItemActionPerformed(evt); + } + }); + menuTools.add(showDataModelMenuItem); + + checkPKMenuItem.setText("Check Primary Keys"); + checkPKMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkPKMenuItemActionPerformed(evt); + } + }); + menuTools.add(checkPKMenuItem); + + consistencyCheckMenuItem1.setText("Check referential Consistency"); + consistencyCheckMenuItem1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + consistencyCheckMenuItem1ActionPerformed(evt); + } + }); + menuTools.add(consistencyCheckMenuItem1); + + menuBar.add(menuTools); + + jviewMenu.setText("View"); + + rowLimitMenu.setText("Row Limit"); + rowLimitMenu.setToolTipText("Desktop Row Limit"); + jviewMenu.add(rowLimitMenu); + + menuBar.add(jviewMenu); + + bookmarkMenu.setText("Bookmark"); + + addBookmarkMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_B, java.awt.event.InputEvent.CTRL_MASK)); + addBookmarkMenuItem.setText("Add Bookmark"); + addBookmarkMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + addBookmarkMenuItemActionPerformed(evt); + } + }); + bookmarkMenu.add(addBookmarkMenuItem); + + editBookmarkMenuItem.setText("Edit Bookmarks"); + editBookmarkMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + editBookmarkMenuItemActionPerformed(evt); + } + }); + bookmarkMenu.add(editBookmarkMenuItem); + bookmarkMenu.add(jSeparator13); + + menuBar.add(bookmarkMenu); + + jMenu2.setText("Tools"); + + exportDataMenuItem.setText("Export Data"); + exportDataMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + exportDataMenuItemActionPerformed(evt); + } + }); + jMenu2.add(exportDataMenuItem); + + dataImport.setLabel("Import SQL Data"); + dataImport.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dataImportActionPerformed(evt); + } + }); + jMenu2.add(dataImport); + jMenu2.add(jSeparator8); + + createExtractionModelMenuItem.setText("Create Extraction Model"); + createExtractionModelMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + createExtractionModelMenuItemActionPerformed(evt); + } + }); + jMenu2.add(createExtractionModelMenuItem); + + consistencyCheckMenuItem.setText("Referential Consistency Check"); + consistencyCheckMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + consistencyCheckMenuItemActionPerformed(evt); + } + }); + jMenu2.add(consistencyCheckMenuItem); + + createCLIItem.setText("Show Command Line"); + createCLIItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + createCLIItemActionPerformed(evt); + } + }); + jMenu2.add(createCLIItem); + + menuBar.add(jMenu2); + + menuWindow.setText("Window"); + + layoutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, java.awt.event.InputEvent.CTRL_MASK)); + layoutMenuItem.setText("Arrange Layout"); + layoutMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + layoutMenuItemActionPerformed(evt); + } + }); + menuWindow.add(layoutMenuItem); + menuWindow.add(jSeparator5); + + zoomInMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_PLUS, java.awt.event.InputEvent.CTRL_MASK)); + zoomInMenuItem.setText("Zoom In (Mouse Wheel Up)"); + zoomInMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + zoomInMenuItemActionPerformed(evt); + } + }); + menuWindow.add(zoomInMenuItem); + + zoomOutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_MINUS, java.awt.event.InputEvent.CTRL_MASK)); + zoomOutMenuItem.setText("Zoom Out (Mouse Wheel Down)"); + zoomOutMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + zoomOutMenuItemActionPerformed(evt); + } + }); + menuWindow.add(zoomOutMenuItem); + menuWindow.add(jSeparator15); + + thumbnailLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_0, java.awt.event.InputEvent.CTRL_MASK)); + thumbnailLayoutRadioButtonMenuItem.setText("Thumbnail Layout"); + thumbnailLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + thumbnailLayoutRadioButtonMenuItemActionPerformed(evt); + } + }); + menuWindow.add(thumbnailLayoutRadioButtonMenuItem); + + tinyLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_1, java.awt.event.InputEvent.CTRL_MASK)); + tinyLayoutRadioButtonMenuItem.setText("Tiny Layout"); + tinyLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tinyLayoutRadioButtonMenuItemActionPerformed(evt); + } + }); + menuWindow.add(tinyLayoutRadioButtonMenuItem); + + smallLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_2, java.awt.event.InputEvent.CTRL_MASK)); + smallLayoutRadioButtonMenuItem.setText("Small Layout"); + smallLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + smallLayoutRadioButtonMenuItemActionPerformed(evt); + } + }); + menuWindow.add(smallLayoutRadioButtonMenuItem); + + mediumLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_3, java.awt.event.InputEvent.CTRL_MASK)); + mediumLayoutRadioButtonMenuItem.setText("Medium Layout"); + mediumLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + mediumLayoutRadioButtonMenuItemActionPerformed(evt); + } + }); + menuWindow.add(mediumLayoutRadioButtonMenuItem); + + largeLayoutRadioButtonMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_4, java.awt.event.InputEvent.CTRL_MASK)); + largeLayoutRadioButtonMenuItem.setText("Large Layout"); + largeLayoutRadioButtonMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + largeLayoutRadioButtonMenuItemActionPerformed(evt); + } + }); + menuWindow.add(largeLayoutRadioButtonMenuItem); + menuWindow.add(jSeparator1); + + newWindowMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK)); + newWindowMenuItem.setText("New Window"); + newWindowMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + newWindowMenuItemActionPerformed(evt); + } + }); + menuWindow.add(newWindowMenuItem); + menuWindow.add(jSeparator6); + + view.setText("Look&Feel"); + menuWindow.add(view); + + menuBar.add(menuWindow); + + jMenu3.setText("Settings"); + + nativeLAFCheckBoxMenuItem.setText("Native Look&Feel"); + nativeLAFCheckBoxMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + nativeLAFCheckBoxMenuItemActionPerformed(evt); + } + }); + jMenu3.add(nativeLAFCheckBoxMenuItem); + + menuBar.add(jMenu3); + + helpMenu.setText("Help"); + + jMenuItem4.setText("Manual"); + jMenuItem4.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jMenuItem4ActionPerformed(evt); + } + }); + helpMenu.add(jMenuItem4); + + helpForum.setText("Forum"); + helpForum.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + helpForumActionPerformed(evt); + } + }); + helpMenu.add(helpForum); + + downloadMenuItem.setText("Download Latest Version"); + downloadMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + downloadMenuItemActionPerformed(evt); + } + }); + helpMenu.add(downloadMenuItem); + helpMenu.add(jSeparator14); + + aboutMenuItem.setText("About Jailer"); + aboutMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + aboutMenuItemActionPerformed(evt); + } + }); + helpMenu.add(aboutMenuItem); + + menuBar.add(helpMenu); + + setJMenuBar(menuBar); + + pack(); + }// //GEN-END:initComponents + + private void exportDataMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportDataMenuItemActionPerformed + desktop.createExtractionModel(true); + }//GEN-LAST:event_exportDataMenuItemActionPerformed + + private void dataImportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataImportActionPerformed + if (!UIUtil.canRunJailer()) { + return; + } + try { + String sqlFile = UIUtil.choseFile(null, ".", "Data Import", ".sql", this, false, true); + if (sqlFile != null) { + DbConnectionDialog dcd = new DbConnectionDialog(this, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); + if (dcd.connect("Data Import")) { + List args = new ArrayList(); + args.add("import"); + args.add(sqlFile); + dcd.addDbArgs(args); + ImportDialog importDialog = new ImportDialog(this, sqlFile, args, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), true); + if (importDialog.isOk) { + importDialog.fillCLIArgs(args); + ResultConsumer consumer = new ResultConsumer() { + @Override + public void consume(boolean result, Throwable t) { + } + public void cleanUp() { + try { + if (desktop != null) { + desktop.updateMenu(); + for (RowBrowser rb : desktop.getBrowsers()) { + rb.browserContentPane.session = session; + rb.browserContentPane.rows.clear(); + } + for (RowBrowser rb : desktop.getRootBrowsers(false)) { + rb.browserContentPane.reloadRows(); + } + } + } catch (Exception e) { + UIUtil.showException(DataBrowser.this, "Error", e, session); + } + } + }; + UIUtil.runJailer(this, args, false, true, false, + false, null, dcd.getUser(), dcd.getPassword(), null, null, false, + true, false, false, false, consumer, executionContext); + } + } + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + }//GEN-LAST:event_dataImportActionPerformed + + private void newBrowserjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newBrowserjMenuItemActionPerformed + createFrame(); + }//GEN-LAST:event_newBrowserjMenuItemActionPerformed + + private void openTableButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openTableButtonActionPerformed + if (tablesComboBox.getSelectedItem() != null) { + String tableName = tablesComboBox.getSelectedItem().toString(); + desktop.addTableBrowser(null, null, datamodel.get().getTableByDisplayName(tableName), null, "", null, null, true); + switchToDesktop(); + } + }//GEN-LAST:event_openTableButtonActionPerformed + + private boolean ignoreTabChangeEvent = false; + + private void workbenchTabbedPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_workbenchTabbedPaneStateChanged + if (initialized) { + if (workbenchTabbedPane.getSelectedComponent() == addSQLConsoleTab) { + if (!ignoreTabChangeEvent) { + try { + createNewSQLConsole(getMetaDataSource(session)); + } catch (SQLException e) { + UIUtil.showException(this, "Error", e); + } + } + } else if (!(workbenchTabbedPane.getSelectedComponent() instanceof SQLConsole)) { + for (SQLConsole sqlConsole: sqlConsoles) { + if (sqlConsole.getDataHasChanged()) { + try { + desktop.reloadRoots(); + } catch (Exception e) { + UIUtil.showException(this, "Error", e); + } + sqlConsole.setDataHasChanged(false); + } + } + tableTreesTabbedPane.setSelectedComponent(navigationPanel); + } else { + SQLConsole sqlConsole = getCurrentSQLConsole(); + if (sqlConsole != null) { + tableTreesTabbedPane.setSelectedComponent(tablesCardPanel); + sqlConsole.grabFocus(); + sqlConsole.update(); + } + } + updateLoadSaveScriptMenuItemsState(); + } + }//GEN-LAST:event_workbenchTabbedPaneStateChanged + + private void showDataModelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showDataModelMenuItemActionPerformed + detailsAndBorderBrowserTabbedPane.setSelectedComponent(dataModelPanel); + }//GEN-LAST:event_showDataModelMenuItemActionPerformed + + private void consistencyCheckMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_consistencyCheckMenuItemActionPerformed + new ConstraintChecker(this, datamodel.get(), true, session) { + @Override + protected void openTableBrowser(Table source, String where) { + workbenchTabbedPane.setSelectedComponent(desktopSplitPane); + desktop.addTableBrowser(null, null, source, null, UIUtil.toSingleLineSQL(new BasicFormatterImpl().format(where)), null, null, true); + } + }; + }//GEN-LAST:event_consistencyCheckMenuItemActionPerformed + + private void newWindowMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_newWindowMenuItemActionPerformed + try { + openNewDataBrowser(datamodel.get(), dbConnectionDialog, false, executionContext, null); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + }// GEN-LAST:event_newWindowMenuItemActionPerformed + + private void reconnectMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_reconnectMenuItemActionPerformed + synchronized (this) { + if (dbConnectionDialog.connect("Reconnect", true)) { + try { + setConnection(dbConnectionDialog); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + } + } + }// GEN-LAST:event_reconnectMenuItemActionPerformed + + private void thumbnailLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_thumbnailLayoutRadioButtonMenuItemActionPerformed + desktop.rescaleLayout(Desktop.LayoutMode.THUMBNAIL, null); + wheelzoomTip(); + }// GEN-LAST:event_thumbnailLayoutRadioButtonMenuItemActionPerformed + + private void jMenuItem3ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem1ActionPerformed + openNewTableBrowser(false); + }// GEN-LAST:event_jMenuItem1ActionPerformed + + private void closeAllMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cloaseAllMenuItemActionPerformed + desktop.closeAll(); + }// GEN-LAST:event_cloaseAllMenuItemActionPerformed + + private void schemaMappingMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_schemaMappingMenuItemActionPerformed + desktop.openSchemaMappingDialog(false); + }// GEN-LAST:event_schemaMappingMenuItemActionPerformed + + private void jMenuItem4ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem4ActionPerformed + try { + BrowserLauncher.openURL(new URI("http://jailer.sourceforge.net/data-browsing.html"), this); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + }// GEN-LAST:event_jMenuItem4ActionPerformed + + private void createExtractionModelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_createExtractionModelMenuItemActionPerformed + desktop.createExtractionModel(false); + }// GEN-LAST:event_createExtractionModelMenuItemActionPerformed + + private void storeSessionItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_storeSessionItemActionPerformed + desktop.storeSession((BookmarksPanel) null); + }// GEN-LAST:event_storeSessionItemActionPerformed + + private void restoreSessionItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_restoreSessionItemActionPerformed + UISettings.s6 += 10000000; + desktop.restoreSession(null, null); + }// GEN-LAST:event_restoreSessionItemActionPerformed + + private void tinyLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tinyLayoutRadioButtonMenuItemActionPerformed + desktop.rescaleLayout(Desktop.LayoutMode.TINY, null); + wheelzoomTip(); + }// GEN-LAST:event_tinyLayoutRadioButtonMenuItemActionPerformed + + private void wheelzoomTip() { + TipDialog.showTip(this, "WHEELZOOM", "You can use the mouse-wheel to zoom in or out."); + } + + private void smallLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_smallLayoutRadioButtonMenuItemActionPerformed + desktop.rescaleLayout(Desktop.LayoutMode.SMALL, null); + wheelzoomTip(); + }// GEN-LAST:event_smallLayoutRadioButtonMenuItemActionPerformed + + private void mediumLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_mediumLayoutRadioButtonMenuItemActionPerformed + desktop.rescaleLayout(Desktop.LayoutMode.MEDIUM, null); + wheelzoomTip(); + }// GEN-LAST:event_mediumLayoutRadioButtonMenuItemActionPerformed + + private void largeLayoutRadioButtonMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_largeLayoutRadioButtonMenuItemActionPerformed + desktop.rescaleLayout(Desktop.LayoutMode.LARGE, null); + wheelzoomTip(); + }// GEN-LAST:event_largeLayoutRadioButtonMenuItemActionPerformed + + private void navigationTreeMouseClicked(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_navigationTreeMouseClicked + TreePath node = navigationTree.getPathForLocation(evt.getX(), evt.getY()); + if (node == null) { + for (int x = navigationTree.getWidth(); x > 0; x -= 32) { + node = navigationTree.getPathForLocation(x, evt.getY()); + if (node != null) { + break; + } + } + } + Object sel = null; + Object selNode = null; + RowBrowser rowBrowser = null; + int row = 0; + if (node != null) { + sel = node.getLastPathComponent(); + if (sel instanceof DefaultMutableTreeNode) { + selNode = ((DefaultMutableTreeNode) sel).getUserObject(); + if (selNode instanceof TreeNodeForRowBrowser) { + rowBrowser = ((TreeNodeForRowBrowser) selNode).rowBrowser; + row = ((TreeNodeForRowBrowser) selNode).rowIndex; + } + } + } + if (evt.getButton() == MouseEvent.BUTTON1) { + if (rowBrowser != null) { + desktop.scrollToCenter(rowBrowser.internalFrame); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(rowBrowser.internalFrame); + navigationTree.setSelectionPath(node); + } + } + if (evt.getButton() == MouseEvent.BUTTON3) { + if (evt.getClickCount() == 1) { + if (rowBrowser != null) { + navigationTree.setSelectionRow(row); + JPopupMenu popup = rowBrowser.browserContentPane.createPopupMenu(null, -1, 0, 0, false); + if (popup != null) { + JPopupMenu popup2 = rowBrowser.browserContentPane.createSqlPopupMenu(-1, 0, 0, true, navigationTreeScrollPane); + if (popup2.getComponentCount() > 0 && popup.getComponentCount() > 0) { + popup.add(new JSeparator()); + } + for (Component c : popup2.getComponents()) { + popup.add(c); + } + UIUtil.fit(popup); + UIUtil.showPopup(evt.getComponent(), evt.getX(), evt.getY(), popup); + } + } + } + } + }// GEN-LAST:event_navigationTreeMouseClicked + + private void layoutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_layoutMenuItemActionPerformed + arrangeLayout(true); + }// GEN-LAST:event_layoutMenuItemActionPerformed + + public void arrangeLayout(boolean scrollToCenter) { + arrangeLayout(scrollToCenter, Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor? null : anchorManager.getNewestBrowser()); + anchorManager.setNewestBrowser(null); + } + + public void arrangeLayout(boolean scrollToCenter, RowBrowser anchor) { + UIUtil.setWaitCursor(this); + try { + desktop.layoutBrowser(null, scrollToCenter, anchor); + } finally { + UIUtil.resetWaitCursor(this); + } + } + + private void jScrollPane1MouseWheelMoved(java.awt.event.MouseWheelEvent evt) {// GEN-FIRST:event_jScrollPane1MouseWheelMoved + long currentTime = System.currentTimeMillis(); + desktop.startRescaleMode(currentTime, evt); + desktop.onMouseWheelMoved(evt, currentTime); + desktop.onMouseWheelMoved(evt, jScrollPane1, currentTime); + }// GEN-LAST:event_jScrollPane1MouseWheelMoved + + private void openNewTableBrowser(boolean offerAlternatives) { + new NewTableBrowser(this, datamodel.get(), offerAlternatives) { + @Override + void openTableBrowser(String tableName) { + desktop.addTableBrowser(null, null, datamodel.get().getTableByDisplayName(tableName), null, "", null, null, true); + switchToDesktop(); + } + + @Override + void openDatabaseAnalyzer() { + updateDataModel(); + } + + @Override + void restoreSession() { + desktop.restoreSession(null, null); + } + }; + } + + private void helpForumActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_helpForumActionPerformed + try { + BrowserLauncher.openURL(new URI("https://sourceforge.net/p/jailer/discussion/"), this); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + }// GEN-LAST:event_helpForumActionPerformed + + private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem4ActionPerformed + About about = new About(this, true); + about.setTitle(DataBrowserContext.getAppName(false)); + about.pack(); + about.setLocation(getLocation().x + (getSize().width - about.getPreferredSize().width) / 2, + getLocation().y + (getSize().height - about.getPreferredSize().height) / 2); + about.setVisible(true); + }// GEN-LAST:event_jMenuItem4ActionPerformed + + private void analyseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_analyseMenuItemActionPerformed + updateDataModel(); + }// GEN-LAST:event_analyseMenuItemActionPerformed + + private void dataModelEditorjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_dataModelEditorjMenuItemActionPerformed + openDataModelEditor(false); + }// GEN-LAST:event_dataModelEditorjMenuItemActionPerformed + + /** + * File in which plaf-setting is stored. + */ + private static final String PLAFSETTING = ".plaf2.ui"; + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + try { + start(args); + } catch (Throwable t) { + t.printStackTrace(); + UIUtil.showException(null, "Error", t); + } + } + + /** + * @param args + * the command line arguments + */ + private static void start(final String args[]) { + try { + Environment.init(); + } catch (Throwable e) { + e.printStackTrace(); + UIUtil.showException(null, "Error", e); + return; + } + + // turn off logging for prefuse library + try { + Logger.getLogger("prefuse").setLevel(Level.OFF); + } catch (Exception e1) { + e1.printStackTrace(); + } + try { + CommandLineInstance.init(args); + } catch (Exception e) { + e.printStackTrace(); + UIUtil.showException(null, "Illegal arguments", e); + return; + } + try { + System.setProperty("db2.jcc.charsetDecoderEncoder", "3"); + } catch (Exception e) { + } + try { + // create initial data-model files + if (CommandLineInstance.getInstance().datamodelFolder == null) { + File file = new File(DataModel.getDatamodelFolder(new ExecutionContext())); + if (!file.exists()) { + file.mkdir(); + } + } + } catch (Exception e) { + } + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + try { + if (!Boolean.TRUE.equals(UISettings.restore(UISettings.USE_NATIVE_PLAF))) { + try { + for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + UIManager.setLookAndFeel(info.getClassName()); + Environment.nimbus = true; + break; + } + } + ((InputMap) UIManager.get("Button.focusInputMap")).put(KeyStroke.getKeyStroke("pressed ENTER"), "pressed"); + ((InputMap) UIManager.get("Button.focusInputMap")).put(KeyStroke.getKeyStroke("released ENTER"), "released"); + Object dSize = UIManager.get("SplitPane.dividerSize"); + if (Integer.valueOf(10).equals(dSize)) { + UIManager.put("SplitPane.dividerSize", Integer.valueOf(14)); + } + + if (UIManager.get("InternalFrame:InternalFrameTitlePane[Enabled].textForeground") instanceof Color) { + UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.BLUE); + } + + // UIUtil.prepareUI(); + } catch (Exception x) { + UIUtil.showException(null, "Error", x); + } + } + createFrame(); + } catch (Exception e) { + UIUtil.showException(null, "Error", e); + } + } + }); + } + + private static DataBrowser openNewDataBrowser(DataModel datamodel, DbConnectionDialog dbConnectionDialog, boolean maximize, ExecutionContext executionContext, DataBrowser theDataBrowser) throws Exception { + final DataBrowser dataBrowser = theDataBrowser != null? theDataBrowser : new DataBrowser(datamodel, null, "", null, ExecutionContext.getSchemaMapping(CommandLineInstance.getInstance().rawschemamapping), false, executionContext); + dataBrowser.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + dataBrowser.setVisible(true); + dataBrowser.setExtendedState(Frame.MAXIMIZED_BOTH); + + if (dbConnectionDialog == null) { + dbConnectionDialog = new DbConnectionDialog(dataBrowser, DataBrowserContext.getAppName(), null, executionContext); + } else { + dbConnectionDialog = new DbConnectionDialog(dataBrowser, dbConnectionDialog, DataBrowserContext.getAppName(), executionContext); + } + dbConnectionDialog.autoConnect(); + if (dbConnectionDialog.isConnected || dbConnectionDialog.connect(DataBrowserContext.getAppName(true))) { + dataBrowser.setConnection(dbConnectionDialog); + if (dataBrowser.session != null) { + dataBrowser.askForDataModel(); + dataBrowser.desktop.openSchemaMappingDialog(true); + dataBrowser.updateStatusBar(); + } + } else { + if (dbConnectionDialog.isConnected) { + dataBrowser.setConnection(dbConnectionDialog); + } else { + dataBrowser.dbConnectionDialog = dbConnectionDialog; + } + dataBrowser.dispose(); + return dataBrowser; + } + String bmName = CommandLineInstance.getInstance().bookmark; + final File bmFile; + final boolean restoreLastSession; + if ("".equals(bmName)) { + bmFile = null; + restoreLastSession = true; + } else { + bmFile = BookmarksPanel.getBookmarksFile(bmName, dataBrowser.executionContext); + restoreLastSession = false; + } + UIUtil.invokeLater(3, new Runnable() { + @Override + public void run() { + dataBrowser.toFront(); + if (restoreLastSession) { + dataBrowser.desktop.restoreSession(null, Environment.newFile(LAST_SESSION_FILE)); + } else if (bmFile != null) { + dataBrowser.desktop.restoreSession(null, bmFile); + BookmarksPanel.setLastUsedBookmark(bmFile.getName(), dataBrowser.executionContext); + bmFile.setLastModified(System.currentTimeMillis()); + new BookmarksPanel(dataBrowser, dataBrowser.bookmarkMenu, dataBrowser.desktop, dataBrowser.executionContext).updateBookmarksMenu(); + } + } + }); + return dataBrowser; + } + + private static void createFrame() { + DataModelManagerDialog dataModelManagerDialog = new DataModelManagerDialog(DataBrowserContext.getAppName(true) + + " - Relational Data Browser", false, "B") { + @Override + protected void onSelect(final DbConnectionDialog connectionDialog, final ExecutionContext executionContext) { + try { + final DataModel datamodel; + Map schemaMapping = ExecutionContext.getSchemaMapping(CommandLineInstance.getInstance().rawschemamapping); + datamodel = new DataModel(null, null, schemaMapping, null, new PrimaryKeyFactory(executionContext), executionContext, true, null); + final DataBrowser databrowser = new DataBrowser(datamodel, null, "", null, schemaMapping, false, executionContext); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + try { + openNewDataBrowser(datamodel, connectionDialog, true, executionContext, databrowser); + CommandLineInstance.clear(); + } catch (Exception e) { + UIUtil.showException(null, "Error", e); + } + } + }); + } catch (Exception e) { + UIUtil.showException(null, "Error", e); + UIUtil.checkTermination(); + } + } + @Override + protected void onLoadExtractionmodel(String modelFile, ExecutionContext executionContext2) { + // nothing to do + } + private static final long serialVersionUID = 1L; + }; + dataModelManagerDialog.start(); + } + + /** + * Opens the data model editor. + */ + private void openDataModelEditor(boolean merge) { + try { + UIUtil.setWaitCursor(this); + String modelname = datamodel == null || datamodel.get() == null ? DataModel.DEFAULT_NAME : datamodel.get().getName(); + DataModelEditor dataModelEditor = new DataModelEditor(this, merge, false, null, null, null, modelname, null, dbConnectionDialog, executionContext); + dataModelEditor.setVisible(true); + removeMetaDataSource(session); + desktop.reloadDataModel(desktop.schemaMapping); + dataModelViewFrame = null; + updateDataModelView(null); + updateStatusBar(); + askForDataModel(); + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } finally { + UIUtil.resetWaitCursor(this); + } + } + + private void updateDataModel() { + updateDataModel(null, false, false); + } + + private void updateDataModel(String schemaName, boolean withViews, boolean withSynonyms) { + if (!UIUtil.canRunJailer()) { + return; + } + try { + JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = new PrivilegedSessionProviderDialog.Provider(this); + + List args = new ArrayList(); + args.add("build-model-wo-merge"); + dbConnectionDialog.addDbArgs(args); + + AnalyseOptionsDialog analyseOptionsDialog = new AnalyseOptionsDialog(this, datamodel == null ? null : datamodel.get(), executionContext); + analyseOptionsDialog.setInitiallyWithViews(withViews); + analyseOptionsDialog.setInitiallyWithSynonyms(withSynonyms); + boolean[] isDefaultSchema = new boolean[1]; + if (analyseOptionsDialog.edit(dbConnectionDialog, schemaName == null? null : Quoting.staticUnquote(schemaName), isDefaultSchema, dbConnectionDialog.currentConnection.user)) { + String schema = analyseOptionsDialog.getSelectedSchema(); + if (schema != null) { + args.add("-schema"); + args.add(schema); + } + if (!isDefaultSchema[0]) { + args.add("-qualifyNames"); + } + analyseOptionsDialog.appendAnalyseCLIOptions(args); + ModelBuilder.assocFilter = analyseOptionsDialog.getAssociationLineFilter(); + if (UIUtil.runJailer(this, args, false, true, false, true, null, dbConnectionDialog.getUser(), dbConnectionDialog.getPassword(), null, null, false, true, false, executionContext)) { + ModelBuilder.assocFilter = null; + String modelname = datamodel == null || datamodel.get() == null ? DataModel.DEFAULT_NAME : datamodel.get().getName(); + DataModelEditor dataModelEditor = new DataModelEditor(this, true, analyseOptionsDialog.isRemoving(), null, + analyseOptionsDialog.getTableLineFilter(), analyseOptionsDialog.getAssociationLineFilter(), modelname, + schema == null? dbConnectionDialog.getName() : schema, dbConnectionDialog, executionContext); + if (dataModelEditor.dataModelHasChanged()) { + dataModelEditor.setVisible(true); + } + removeMetaDataSource(session); + desktop.reloadDataModel(desktop.schemaMapping); + dataModelViewFrame = null; + updateDataModelView(null); + updateStatusBar(); + askForDataModel(); + } + } else { + askForDataModel(); + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } finally { + ModelBuilder.assocFilter = null; + JDBCMetaDataBasedModelElementFinder.privilegedSessionProvider = null; + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JMenuItem aboutMenuItem; + private javax.swing.JMenuItem addBookmarkMenuItem; + private javax.swing.JPanel addSQLConsoleTab; + private javax.swing.JMenuItem analyseMenuItem; + private javax.swing.JMenuItem analyseSQLMenuItem1; + private javax.swing.JLabel associatedWith; + private javax.swing.JMenu bookmarkMenu; + private javax.swing.JPanel borderBrowserPanel; + private javax.swing.JPanel borderBrowserTabPane; + javax.swing.JMenuItem checkPKMenuItem; + private javax.swing.JMenuItem closeAllMenuItem; + private javax.swing.JPanel closurePanel; + private javax.swing.JMenuItem columnOrderItem; + public javax.swing.JLabel connectivityState; + private javax.swing.JMenuItem consistencyCheckMenuItem; + private javax.swing.JMenuItem consistencyCheckMenuItem1; + private javax.swing.JPanel consoleDummyPanel; + private javax.swing.JMenuItem createCLIItem; + private javax.swing.JMenuItem createExtractionModelMenuItem; + private javax.swing.JMenuItem dataImport; + private javax.swing.JMenuItem dataModelEditorjMenuItem; + private javax.swing.JPanel dataModelPanel; + private javax.swing.JLabel dependsOn; + private javax.swing.JSplitPane desktopSplitPane; + private javax.swing.JTabbedPane detailsAndBorderBrowserTabbedPane; + private javax.swing.JButton downloadButton; + private javax.swing.JMenuItem downloadMenuItem; + private javax.swing.JPanel dummy; + private javax.swing.JMenuItem editBookmarkMenuItem; + private javax.swing.JMenuItem exitMenuItem; + private javax.swing.JMenuItem exportDataMenuItem; + private javax.swing.JLabel hasDependent; + private javax.swing.JMenuItem helpForum; + private javax.swing.JMenu helpMenu; + private javax.swing.JPanel hiddenPanel; + private javax.swing.JLabel ignored; + private javax.swing.JButton jButton1; + private javax.swing.JInternalFrame jInternalFrame1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel12; + private javax.swing.JLabel jLabel13; + private javax.swing.JLabel jLabel14; + private javax.swing.JLabel jLabel19; + private javax.swing.JLabel jLabel20; + private javax.swing.JLabel jLabel21; + private javax.swing.JLabel jLabel22; + private javax.swing.JLabel jLabel26; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JLayeredPane jLayeredPane1; + private javax.swing.JLayeredPane jLayeredPane2; + private javax.swing.JMenu jMenu1; + private javax.swing.JMenu jMenu2; + private javax.swing.JMenu jMenu3; + private javax.swing.JMenuItem jMenuItem3; + private javax.swing.JMenuItem jMenuItem4; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel11; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JPopupMenu.Separator jSeparator1; + private javax.swing.JPopupMenu.Separator jSeparator10; + private javax.swing.JPopupMenu.Separator jSeparator11; + private javax.swing.JPopupMenu.Separator jSeparator12; + private javax.swing.JPopupMenu.Separator jSeparator13; + private javax.swing.JPopupMenu.Separator jSeparator14; + private javax.swing.JPopupMenu.Separator jSeparator15; + private javax.swing.JPopupMenu.Separator jSeparator2; + private javax.swing.JPopupMenu.Separator jSeparator4; + private javax.swing.JPopupMenu.Separator jSeparator5; + private javax.swing.JPopupMenu.Separator jSeparator6; + private javax.swing.JPopupMenu.Separator jSeparator7; + private javax.swing.JPopupMenu.Separator jSeparator8; + private javax.swing.JPopupMenu.Separator jSeparator9; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JSplitPane jSplitPane4; + private javax.swing.JTable jTable1; + private javax.swing.JTree jTree1; + private javax.swing.JMenu jviewMenu; + private javax.swing.JRadioButtonMenuItem largeLayoutRadioButtonMenuItem; + private javax.swing.JPanel layeredPaneContent; + private javax.swing.JMenuItem layoutMenuItem; + private javax.swing.JPanel legende; + private javax.swing.JPanel legende1; + private javax.swing.JPanel legende2; + private javax.swing.JMenuItem loadScriptMenuItem; + private javax.swing.JRadioButtonMenuItem mediumLayoutRadioButtonMenuItem; + private javax.swing.JMenuBar menuBar; + private javax.swing.JMenu menuTools; + private javax.swing.JMenu menuWindow; + private javax.swing.JPanel metaDataViewPanel; + private javax.swing.JLabel modelName; + private javax.swing.JLabel modelPath; + private javax.swing.JCheckBoxMenuItem nativeLAFCheckBoxMenuItem; + private javax.swing.JPanel navigationPanel; + private javax.swing.JTree navigationTree; + private javax.swing.JScrollPane navigationTreeScrollPane; + private javax.swing.JMenuItem newBrowserjMenuItem; + private javax.swing.JMenuItem newWindowMenuItem; + private javax.swing.JButton openTableButton; + private javax.swing.JMenuItem reconnectMenuItem; + private javax.swing.JButton refreshButton; + private javax.swing.JMenuItem restoreSessionItem; + private javax.swing.JMenu rowLimitMenu; + private javax.swing.JMenuItem saveScriptAsMenuItem; + private javax.swing.JMenuItem saveScriptMenuItem; + private javax.swing.JMenuItem schemaMappingMenuItem; + private javax.swing.JLabel schemaName; + private javax.swing.JPanel schemaNamePanel; + private javax.swing.JCheckBoxMenuItem showDataModelMenuItem; + private javax.swing.JRadioButtonMenuItem smallLayoutRadioButtonMenuItem; + private javax.swing.JMenuItem storeSessionItem; + private javax.swing.JTabbedPane tableTreesTabbedPane; + private javax.swing.JPanel tablesCardPanel; + private javax.swing.JPanel tablesPanel; + private javax.swing.JRadioButtonMenuItem thumbnailLayoutRadioButtonMenuItem; + private javax.swing.JRadioButtonMenuItem tinyLayoutRadioButtonMenuItem; + private javax.swing.JLabel titleLabel; + private javax.swing.JLabel updateInfoLabel; + private javax.swing.JPanel updateInfoPanel; + private javax.swing.JMenu view; + private javax.swing.JTabbedPane workbenchTabbedPane; + private javax.swing.JMenuItem zoomInMenuItem; + private javax.swing.JMenuItem zoomOutMenuItem; + // End of variables declaration//GEN-END:variables + + private JToggleButton searchButton; + + /** + * Sets Look&Feel. + * + * @param plaf + * the l&f + */ + private void setPLAF(String plaf) { + try { + UIManager.setLookAndFeel(plaf); + SwingUtilities.updateComponentTreeUI(this); + try { + File file = new File(PLAFSETTING); + file.delete(); + } catch (Exception e) { + } + try { + File plafSetting = new File(PLAFSETTING); + PrintWriter out = new PrintWriter(plafSetting); + out.println(plaf); + out.close(); + } catch (Exception x) { + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e); + } + } + + private void askForDataModel() { + try { + if (datamodel.get().getTables().isEmpty()) { + switch (JOptionPane.showOptionDialog(this, "Data model \"" + DataModelManager.getModelDetails(DataModelManager.getCurrentModelSubfolder(executionContext), executionContext).a + + "\" is empty.", DataBrowserContext.getAppName(true), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { + "Analyze Database", "Data Model Editor" }, null)) { + case 0: + updateDataModel(); + break; + case 1: + openDataModelEditor(false); + break; + } + } else if (!new File(DataModel.getColumnsFile(executionContext)).exists()) { + switch (JOptionPane.showOptionDialog(this, "No column definition found.", DataBrowserContext.getAppName(true), JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Analyze Database", "Data Model Editor" }, null)) { + case 0: + updateDataModel(); + break; + case 1: + openDataModelEditor(false); + break; + } + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + } + + private void updateIFramesBar() { + updateNavigationTree(); + updateBorderBrowser(); + updateHiddenPanel(); + + // iFramesPanel is obsolete + return; + } + + private void updateHiddenPanel() { + if (desktop == null) { + return; + } + + hiddenPanel.removeAll(); + hiddenPanel.setVisible(false); + + int num = desktop.getAllFrames().length; + if (num == 0) { + jPanel1.revalidate(); + return; + } + int COLUMNS = 7; + int y = 1; + + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = y; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.weightx = 1; + JPanel iFramesRowPanel = new JPanel(); + iFramesRowPanel.setLayout(new GridBagLayout()); + hiddenPanel.add(iFramesRowPanel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = COLUMNS + 2; + gridBagConstraints.gridy = y; + gridBagConstraints.weightx = 1; + iFramesRowPanel.add(new JLabel(" "), gridBagConstraints); + + int x = 1; + boolean visible = false; + for (final RowBrowser rb : desktop.getBrowsers()) { + if (!rb.isHidden()) { + continue; + } + visible = true; + if (++x > COLUMNS) { + x = 1; + ++y; + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = y; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.weightx = 1; + iFramesRowPanel = new JPanel(); + iFramesRowPanel.setLayout(new GridBagLayout()); + hiddenPanel.add(iFramesRowPanel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = COLUMNS + 2; + gridBagConstraints.gridy = y; + gridBagConstraints.weightx = 1; + iFramesRowPanel.add(new JLabel(" "), gridBagConstraints); + } + + final JToggleButton toggleButton = new JToggleButton(); + toggleButton.setText(rb.internalFrame.getTitle()); + toggleButton.setIcon(UIUtil.readImage("/jailerlight.png")); + toggleButton.setSelected(false); + + toggleButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toggleButton.setSelected(true); + rb.setHidden(false); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = x; + gridBagConstraints.gridy = y; + iFramesRowPanel.add(toggleButton, gridBagConstraints); + + hiddenPanel.setVisible(visible); + } + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new Insets(0, 0, 4, 0); + + jPanel1.revalidate(); + } + + private static final class BrowserAssociationModel extends DefaultAssociationModel { + private final RowBrowser rowBrowser; + + public BrowserAssociationModel(RowBrowser rowBrowser, Association association) { + super(association); + this.rowBrowser = rowBrowser; + } + + @Override + public String getSourceName() { + return rowBrowser.internalFrame.getTitle(); + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + if (other.getClass().equals(getClass())) { + BrowserAssociationModel otherModel = (BrowserAssociationModel) other; + return rowBrowser == otherModel.rowBrowser && association == otherModel.association; + } + return false; + } + + @Override + public int hashCode() { + return rowBrowser.hashCode() + 3 * association.hashCode(); + } + + public RowBrowser getRowBrowser() { + return rowBrowser; + } + + public Association getAssociation() { + return association; + } + } + + private boolean disableBorderBrowserUpdates = false; + + private void updateBorderBrowser() { + if (disableBorderBrowserUpdates || detailsAndBorderBrowserTabbedPane.getSelectedComponent() != borderBrowserTabPane) { + return; + } + try { + UIUtil.setWaitCursor(this); + + Collection model = new ArrayList(); + if (desktop != null) { + titleLabel.setText(" Related Rows"); + List allChildren = new ArrayList(); + for (RowBrowser rb : desktop.getBrowsers()) { + if (rb.internalFrame == desktop.getSelectedFrame() && !rb.isHidden()) { + allChildren.add(rb); + allChildren.addAll(collectChildren(rb)); + titleLabel.setText(" Related Rows of Subtree " + rb.internalFrame.getTitle()); + break; + } + } + for (RowBrowser rb : allChildren) { + if (rb.browserContentPane.table != null) { + Set associations = new HashSet(rb.browserContentPane.table.associations); + for (RowBrowser c : desktop.getChildBrowsers(rb, false)) { + if (c.browserContentPane.association != null) { + associations.remove(c.browserContentPane.association); + } + } + if (rb.browserContentPane.association != null && rb.parent != null) { + if (allChildren.contains(rb.parent)) { + associations.remove(rb.browserContentPane.association.reversalAssociation); + } + } + for (Association association : associations) { + model.add(new BrowserAssociationModel(rb, association)); + } + } + } + } + + borderBrowser.setModel(model); + } finally { + UIUtil.resetWaitCursor(this); + } + } + + private ExtractionModelFrame dataModelViewFrame; + private Table lastFocusTable = null; + private Table currentTableInDMV = null; + + private void updateDataModelView(final Table table) { + if (table != null) { + lastFocusTable = table; + } + if (detailsAndBorderBrowserTabbedPane.getSelectedComponent() != dataModelPanel) { + return; + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + try { + UIUtil.setWaitCursor(DataBrowser.this); + if (dataModelViewFrame == null) { + dataModelViewFrame = ExtractionModelFrame.createFrame(null, false, false, null, executionContext); + JComponent graphViewContainer = dataModelViewFrame.tearOutGraphViewContainer(DataBrowser.this); + dataModelPanel.removeAll(); + dataModelPanel.add(graphViewContainer); + } + if (table != null) { + dataModelViewFrame.select(table); + } else { + Table toSelect = null; + if (lastFocusTable != null && tableTreesTabbedPane.getSelectedComponent() == tablesCardPanel) { + toSelect = datamodel.get().getTable(lastFocusTable.getName()); + } + if (toSelect == null) { + TreePath selectionPath = navigationTree.getSelectionPath(); + toSelect = datamodel.get().getTables().isEmpty()? null : datamodel.get().getTables().iterator().next(); + if (selectionPath != null) { + Object lastPathComponent = selectionPath.getLastPathComponent(); + if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); + if (userObject instanceof TreeNodeForRowBrowser) { + Table table = ((TreeNodeForRowBrowser) userObject).rowBrowser.browserContentPane.table; + if (!(table instanceof SqlStatementTable)) { + toSelect = table; + } + } + } + } + } + if (toSelect != null && currentTableInDMV != toSelect) { + dataModelViewFrame.select(toSelect); + currentTableInDMV = toSelect; + } + } + } catch (IOException e) { + UIUtil.showException(DataBrowser.this, "Error", e); + } finally { + UIUtil.resetWaitCursor(DataBrowser.this); + } + } + }); + } + + protected void resolveSelection(Collection selection) { + try { + UIUtil.setWaitCursor(this); + + disableBorderBrowserUpdates = true; + JInternalFrame currentSelection = desktop.getSelectedFrame(); + for (AssociationModel a : selection) { + BrowserAssociationModel associationModel = (BrowserAssociationModel) a; + desktop.addTableBrowser(associationModel.getRowBrowser(), associationModel.getRowBrowser(), associationModel.getAssociation().destination, associationModel.getAssociation(), + "", null, null, true); + } + if (currentSelection != null) { + try { + currentSelection.setSelected(true); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(currentSelection); + } catch (PropertyVetoException e) { + // ignore + } + } + } finally { + UIUtil.resetWaitCursor(this); + disableBorderBrowserUpdates = false; + updateBorderBrowser(); + } + } + + private List collectChildren(RowBrowser rb) { + List result = new ArrayList(); + for (RowBrowser c : desktop.getChildBrowsers(rb, true)) { + result.add(c); + } + for (RowBrowser c : desktop.getChildBrowsers(rb, true)) { + result.addAll(collectChildren(c)); + } + return result; + } + + private Map treeNodeByIFrame = new HashMap(); + private TreeSelectionListener navigationTreeListener = null; + + private class TreeNodeForRowBrowser { + public final RowBrowser rowBrowser; + public final int rowIndex; + private final String title; + + public TreeNodeForRowBrowser(RowBrowser rowBrowser, int rowIndex) { + this.rowBrowser = rowBrowser; + this.rowIndex = rowIndex; + this.title = " " + rowBrowser.internalFrame.getTitle() + " "; + treeNodeByIFrame.put(rowBrowser.internalFrame, this); + } + + @Override + public String toString() { + return title; + } + } + + private void updateNavigationTree() { + if (navigationTreeListener != null) { + navigationTree.getSelectionModel().removeTreeSelectionListener(navigationTreeListener); + } + + ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; + DefaultMutableTreeNode root = new DefaultMutableTreeNode(connection != null ? connection.alias : " "); + + treeNodeByIFrame.clear(); + + int[] count = new int[1]; + count[0] = 1; + if (desktop != null) { + for (RowBrowser rb : desktop.getRootBrowsers(true)) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(new TreeNodeForRowBrowser(rb, count[0]++)); + root.add(node); + addChildNodes(node, rb, count); + } + } + DefaultTreeModel treeModel = new DefaultTreeModel(root); + navigationTree.setModel(treeModel); + for (int i = 0; i < count[0]; ++i) { + navigationTree.expandRow(i); + } + JInternalFrame activeFrame = desktop != null ? desktop.getSelectedFrame() : null; + if (activeFrame != null) { + TreeNodeForRowBrowser node = treeNodeByIFrame.get(activeFrame); + if (node != null) { + navigationTree.setSelectionRow(node.rowIndex); + Rectangle bounds = navigationTree.getRowBounds(node.rowIndex); + navigationTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height)); + for (RowBrowser rb : desktop.getRootBrowsers(true)) { + if (rb.internalFrame == activeFrame) { + if (rb.getMDTable() != null && metaDataPanel != null) { + metaDataPanel.select(rb.getMDTable()); + } + break; + } + } + } + } + + navigationTreeListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + if (e.getPath() != null) { + Object lastPathComponent = e.getPath().getLastPathComponent(); + if (lastPathComponent != null && lastPathComponent instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) lastPathComponent).getUserObject(); + if (userObject instanceof TreeNodeForRowBrowser) { + try { + JInternalFrame iFrame = ((TreeNodeForRowBrowser) userObject).rowBrowser.internalFrame; + desktop.scrollToCenter(iFrame); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame); + iFrame.setSelected(true); + iFrame.grabFocus(); + } catch (PropertyVetoException e1) { + // ignore + } + return; + } else { + searchButton.doClick(1); + } + } + } + updateNavigationTree(); + } + }; + + navigationTree.getSelectionModel().addTreeSelectionListener(navigationTreeListener); + } + + private void addChildNodes(DefaultMutableTreeNode node, RowBrowser browser, int[] count) { + for (RowBrowser rb : desktop.getChildBrowsers(browser, true)) { + DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(new TreeNodeForRowBrowser(rb, count[0]++)); + node.add(childNode); + addChildNodes(childNode, rb, count); + } + } + + public JScrollPane getDesktopScrollPane() { + return jScrollPane1; + } + + private DBClosureView closureView; + private boolean suppressUpdateClosureBrowser = false; + + protected void updateClosureBrowser(final RowBrowser rowBrowser) { + if (suppressUpdateClosureBrowser) { + return; + } + if (rowBrowser != null) { + if (rowBrowser.browserContentPane.table instanceof SqlStatementTable) { + updateClosureBrowser(null); + return; + } + } + closureView = new DBClosureView(this) { + private RowBrowser closureRoot = rowBrowser; + + @Override + protected DataModel getDataModel() { + return DataBrowser.this.datamodel.get(); + } + + @Override + protected Table getRootTable() { + if (rowBrowser != null) { + return rowBrowser.browserContentPane.table; + } + return null; + } + + private Map visibleTables = null; + private Map levels = null; + + @Override + protected Map getVisibleTables() { + if (visibleTables == null) { + visibleTables = new HashMap(); + levels = new HashMap(); + if (rowBrowser != null) { + collectVisibleTables(rowBrowser, 1); + } + } + return visibleTables; + } + + private void collectVisibleTables(RowBrowser rowBrowser, int level) { + Integer prevLevel = levels.get(rowBrowser.browserContentPane.table); + if (prevLevel == null || prevLevel > level) { + visibleTables.put(rowBrowser.browserContentPane.table, rowBrowser); + levels.put(rowBrowser.browserContentPane.table, level); + } + for (RowBrowser cb: rowBrowser.browserContentPane.getChildBrowsers()) { + collectVisibleTables(cb, level + 1); + } + } + + @Override + protected void scrollToTable(Table table) { + RowBrowser rb = visibleTables.get(table); + if (rb != null) { + desktop.scrollToCenter(rb.internalFrame); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(rb.internalFrame); + } + } + + @Override + protected void repaintClosureView() { + desktopSplitPane.repaint(); + desktopSplitPane.setDividerLocation(desktopSplitPane.getDividerLocation() - 1); + desktopSplitPane.setDividerLocation(desktopSplitPane.getDividerLocation() + 1); + } + + @Override + protected void expandTablePath(List
path) { + int i; + i = path.size() - 1; + while (i >= 0) { + if (!getVisibleTables().containsKey(path.get(i))) { + ++i; + break; + } + --i; + } + Association[] associations = openAssociationPathPanel(path.subList(0, i + 1)); + if (associations != null) { + try { + Desktop.noArrangeLayoutOnNewTableBrowser = true; + desktop.getiFrameStateChangeRenderer().startAtomic(); + disableBorderBrowserUpdates = true; + suppressUpdateClosureBrowser = true; + RowBrowser nextRb = null; + while (i > 0) { + Table table = path.get(i); + RowBrowser rb; + if (nextRb != null && nextRb.association != null && nextRb.association.destination.equals(table)) { + rb = nextRb; + } else { + rb = getVisibleTables().get(table); + } + Association association = associations[i - 1]; + if (association != null) { + nextRb = rb.browserContentPane.navigateTo(association, null); + visibleTables = null; + } else { + break; + } + --i; + } + suppressUpdateClosureBrowser = false; + + closureRoot.internalFrame.setSelected(true); + } catch (Exception e) { + // ignore + } finally { + Desktop.noArrangeLayoutOnNewTableBrowser = false; + disableBorderBrowserUpdates = false; + suppressUpdateClosureBrowser = false; + desktop.getiFrameStateChangeRenderer().endAtomic(); + desktop.catchUpLastArrangeLayoutOnNewTableBrowser(); + } + closureView.find(getDataModel().getDisplayName(path.get(0))); + } + } + + @Override + protected void select(String selectedTable) { + try { + if (selectedTable != null) { + RowBrowser rb = getVisibleTables().get(datamodel.get().getTableByDisplayName(selectedTable)); + if (rb != null) { + JInternalFrame iFrame = rb.internalFrame; + desktop.scrollToCenter(iFrame); + iFrame.setSelected(true); + iFrame.grabFocus(); + desktop.getiFrameStateChangeRenderer().onIFrameSelected(iFrame); + } + } + } catch (PropertyVetoException e1) { + // ignore + } + } + + private Association[] openAssociationPathPanel(List
path) { + if (path.isEmpty()) { + return null; + } + final AssociationPathPanel assocPanel = new AssociationPathPanel(getDataModel(), path, dependsOn.getForeground(), hasDependent.getForeground(), associatedWith.getForeground(), ignored.getForeground()); + if (!assocPanel.needToAsk) { + return assocPanel.selectedAssociations; + } + final JDialog d = new JDialog(DataBrowser.this, "Open Path", true); + assocPanel.okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + assocPanel.ok = true; + d.setVisible(false); + } + }); + assocPanel.cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + assocPanel.ok = false; + d.setVisible(false); + } + }); + d.getContentPane().add(assocPanel); + d.pack(); + d.setSize(600, Math.max(d.getHeight() + 20, 400)); + d.setLocation(DataBrowser.this.getX() + (DataBrowser.this.getWidth() - d.getWidth()) / 2, Math.max(0, DataBrowser.this.getY() + (DataBrowser.this.getHeight() - d.getHeight()) / 2)); + UIUtil.fit(d); + assocPanel.okButton.grabFocus(); + d.setVisible(true); + if (assocPanel.ok) { + return assocPanel.selectedAssociations; + } + return null; + } + }; + Container cVContentPane = closureView.tablePanel; + closureView.dispose(); + closurePanel.removeAll(); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 1; + closurePanel.add(cVContentPane, gridBagConstraints); + closureView.refresh(); + } + + private MetaDataSource getMetaDataSource(Session session) { + return (MetaDataSource) session.getSessionProperty(DataBrowser.class, "MetaDataSource"); + } + + private void removeMetaDataSource(Session session) { + session.setSessionProperty(DataBrowser.class, "removeMetaDataSource", Boolean.TRUE); + } + + private MetaDataPanel metaDataPanel; + private Runnable createMetaDataPanel; + + private void onNewSession(Session newSession) { + if (newSession == null) { + return; + } + + ConnectionInfo connection = dbConnectionDialog != null ? dbConnectionDialog.currentConnection : null; + String alias = connection != null ? " " + connection.alias : " "; + + UIUtil.setWaitCursor(this); + CancellationHandler.reset(null); + try { + updateNavigationCombobox(); + + tablesPanel.removeAll(); + metaDataPanel = (MetaDataPanel) session.getSessionProperty(getClass(), "metaDataPanel"); + MetaDataSource metaDataSource; + try { + metaDataSource = getMetaDataSource(newSession); + if (metaDataSource == null || Boolean.TRUE.equals(session.getSessionProperty(DataBrowser.class, "removeMetaDataSource"))) { + metaDataSource = new MetaDataSource(newSession, datamodel.get(), alias, executionContext); + final MetaDataSource finalMetaDataSource = metaDataSource; + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + Session.setThreadSharesConnection(); + final MDSchema defaultSchema = finalMetaDataSource.getDefaultSchema(); + if (defaultSchema != null) { + // trigger reading meta data asynchronously + defaultSchema.loadTables(true, null, new Runnable() { + @Override + public void run() { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + if (createMetaDataPanel != null) { + createMetaDataPanel.run(); + } + if (metaDataPanel != null) { + metaDataPanel.refresh(); + } + } + }); + } + }); + } else { + if (createMetaDataPanel != null) { + createMetaDataPanel.run(); + } + if (metaDataPanel != null) { + metaDataPanel.refresh(); + } + } + } + }); + thread.setDaemon(true); + thread.start(); + metaDataPanel = null; + } + session.setSessionProperty(DataBrowser.class, "removeMetaDataSource", null); + newSession.setSessionProperty(DataBrowser.class, "MetaDataSource", metaDataSource); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + metaDataViewPanel.remove(metaDataDetailsPanel); + metaDataDetailsPanel = createMetaDataDetailsPanel(executionContext); + metaDataViewPanel.add(metaDataDetailsPanel); + + try { + if (sqlConsoles.isEmpty()) { + createNewSQLConsole(metaDataSource); + workbenchTabbedPane.setSelectedComponent(desktopSplitPane); + } else { + for (SQLConsole sqlConsole: sqlConsoles) { + sqlConsole.reset(session, metaDataSource); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + + ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, "loading"); + + final MetaDataSource fMetaDataSource = metaDataSource; + final Runnable createMetaDataPanelImmediately = new Runnable() { + @Override + public void run() { + if (metaDataPanel == null) { + metaDataPanel = new MetaDataPanel(DataBrowser.this, fMetaDataSource, metaDataDetailsPanel, datamodel.get(), executionContext) { + @Override + protected void open(Table table) { + if (!selectNavTreeNode(navigationTree.getModel().getRoot(), table)) { + if (workbenchTabbedPane.getSelectedComponent() != getCurrentSQLConsole()) { + desktop.addTableBrowser(null, null, table, null, "", null, null, true); + } + } + try { + String sql; + Quoting quoting = Quoting.getQuoting(session); + MDTable mdTable = getMetaDataSource(session).toMDTable(table); + String tableName; + String schemaName; + if (mdTable != null) { + tableName = mdTable.getName(); + schemaName = mdTable.getSchema().isDefaultSchema? "": mdTable.getSchema().getName(); + } else { + tableName = table.getUnqualifiedName(); + schemaName = table.getSchema(""); + } + sql = "Select * From " + (schemaName == null || schemaName.length() == 0? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName); + if (workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) { + workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); + getCurrentSQLConsole().grabFocus(); + getCurrentSQLConsole().appendStatement(sql, true); + } + } catch (SQLException e) { + UIUtil.showException(this, "Error", e); + } + } + + private boolean selectNavTreeNode(Object root, Table table) { + if (root instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); + if (userObject instanceof TreeNodeForRowBrowser) { + RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser; + if (table.equals(rowBrowser.browserContentPane.table)) { + navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath())); + return true; + } + } + int cc = ((DefaultMutableTreeNode) root).getChildCount(); + for (int i = 0; i < cc; ++i) { + if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), table)) { + return true; + } + } + } + return false; + } + + private boolean selectNavTreeNode(Object root, MDTable mdTable) { + if (root instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); + if (userObject instanceof TreeNodeForRowBrowser) { + RowBrowser rowBrowser = ((TreeNodeForRowBrowser) userObject).rowBrowser; + if (mdTable.equals(rowBrowser.getMDTable())) { + navigationTree.getSelectionModel().setSelectionPath(new TreePath(((DefaultMutableTreeNode) root).getPath())); + return true; + } + } + int cc = ((DefaultMutableTreeNode) root).getChildCount(); + for (int i = 0; i < cc; ++i) { + if (selectNavTreeNode(((DefaultMutableTreeNode) root).getChildAt(i), mdTable)) { + return true; + } + } + } + return false; + } + + @Override + protected void analyseSchema(String schemaName) { + updateDataModel(schemaName, false, false); + } + + @Override + protected void open(MDTable mdTable) { + String schemaName = mdTable.getSchema().isDefaultSchema? null : mdTable.getSchema().getName(); + String tableName = mdTable.getName(); + try { + Quoting quoting = Quoting.getQuoting(session); + String sql = "Select * From " + (schemaName == null? "" : quoting.quote(schemaName) + ".") + quoting.quote(tableName); + if (!selectNavTreeNode(navigationTree.getModel().getRoot(), mdTable) + || workbenchTabbedPane.getSelectedComponent() == getCurrentSQLConsole()) { + workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); + getCurrentSQLConsole().grabFocus(); + getCurrentSQLConsole().appendStatement(sql, true); + } + } catch (SQLException e) { + UIUtil.showException(this, "Error", e); + } + } + + @Override + protected void appendScript(String script, boolean execute) { + try { + workbenchTabbedPane.setSelectedComponent(getCurrentSQLConsole()); + getCurrentSQLConsole().grabFocus(); + getCurrentSQLConsole().appendStatement(script, execute); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e); + } + } + + @Override + protected void onTableSelect(MDTable mdTable) { + metaDataDetailsPanel + .showMetaDataDetails(mdTable, getMetaDataSource(session).toTable(mdTable), null, false, datamodel.get()); + } + + @Override + protected void onRowSelect(Table table, Row row) { + metaDataDetailsPanel + .showMetaDataDetails(null, table, row, true, datamodel.get()); + } + + @Override + protected void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext) { + metaDataDetailsPanel + .showMetaDataDetails(mdOther, executionContext); + } + + @Override + protected void onSchemaSelect(MDSchema mdSchema) { + metaDataDetailsPanel.clear(); + } + + @Override + protected void openNewTableBrowser() { + DataBrowser.this.openNewTableBrowser(false); + } + + @Override + protected void updateDataModelView(Table table) { + DataBrowser.this.updateDataModelView(table); + } + + @Override + protected void setCaretPosition(int position) { + getCurrentSQLConsole().setCaretPosition(position); + } + + @Override + protected void setOrResetWaitState(boolean set) { + ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, set? "loading" : "tables"); + } + }; + } + session.setSessionProperty(getClass(), "metaDataPanel", metaDataPanel); + tablesPanel.add(metaDataPanel, java.awt.BorderLayout.CENTER); + ((CardLayout) tablesCardPanel.getLayout()).show(tablesCardPanel, "tables"); + } + }; + createMetaDataPanel = new Runnable() { + @Override + public void run() { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + Session.setThreadSharesConnection(); + + // trigger loading meta data + fMetaDataSource.getSchemas(); + + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + createMetaDataPanelImmediately.run(); + } + }); + } + }); + thread.setDaemon(true); + thread.start(); + createMetaDataPanel = null; + } + }; + if (tableTreesTabbedPane.getSelectedComponent() == tablesPanel) { + createMetaDataPanel.run(); + } + } + finally { + UIUtil.resetWaitCursor(this); + } + } + + private final class SQLConsoleWithTitle extends SQLConsole { + private final String initialTitle; + private final JLabel titleLbl; + private String title; + + private SQLConsoleWithTitle(Session session, MetaDataSource metaDataSource, Reference datamodel, + ExecutionContext executionContext, String title, JLabel titleLbl) throws SQLException { + super(session, metaDataSource, datamodel, executionContext); + this.initialTitle = title; + this.titleLbl = titleLbl; + } + + @Override + protected void refreshMetaData() { + if (metaDataPanel != null) { + metaDataPanel.reset(); + } + } + + @Override + protected void selectTable(MDTable mdTable) { + if (metaDataPanel != null) { + metaDataPanel.select(mdTable); + } + } + + @Override + protected void setOutlineTables(List outlineTables, int indexOfInfoAtCaret) { + if (metaDataPanel != null) { + metaDataPanel.setOutline(outlineTables, indexOfInfoAtCaret); + } + } + + @Override + protected void onContentStateChange(File file, boolean dirty) { + if (file == null) { + title = initialTitle; + } else { + title = file.getName(); + } + if (dirty && file != null) { + titleLbl.setText("* " + title); + } else { + titleLbl.setText(title); + } + updateLoadSaveScriptMenuItemsState(); + } + + public String getTitle() { + return title; + } + + @Override + protected JFrame getOwner() { + return DataBrowser.this; + } + + @Override + protected void openDataModelEditor(boolean merge) { + DataBrowser.this.openDataModelEditor(merge); + } + } + + private int sqlConsoleNr = 0; + + private SQLConsole createNewSQLConsole(MetaDataSource metaDataSource) throws SQLException { + final JLabel titleLbl = new JLabel(sqlConsoleIcon); + String tabName = "SQL Console"; + ++sqlConsoleNr; + String title = tabName + (sqlConsoleNr > 1? " (" + sqlConsoleNr + ")" : "") + " "; + + final SQLConsoleWithTitle sqlConsole = new SQLConsoleWithTitle(session, metaDataSource, datamodel, executionContext, title, titleLbl); + initDnD(sqlConsole.getEditorPane()); + sqlConsoles.add(sqlConsole); + + try { + ignoreTabChangeEvent = true; + for (int i = 0; i < workbenchTabbedPane.getTabCount(); ++i) { + if (workbenchTabbedPane.getComponentAt(i) == consoleDummyPanel) { + workbenchTabbedPane.removeTabAt(i); + break; + } + } + workbenchTabbedPane.insertTab(title, null, sqlConsole, null, sqlConsoles.size()); + JPanel titelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + titelPanel.setOpaque(false); + titleLbl.setText(title); + // titleLbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + titelPanel.add(titleLbl); + SmallButton closeButton = new SmallButton(closeIcon) { + @Override + protected void onClick() { + if (closeSQLConsole(sqlConsole, true)) { + workbenchTabbedPane.setSelectedComponent(desktopSplitPane); + } + } + }; + titelPanel.add(closeButton); + if (sqlConsoles.size() > 1) { + workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.indexOfComponent(sqlConsole), titelPanel); + } else { + workbenchTabbedPane.setTabComponentAt(workbenchTabbedPane.indexOfComponent(sqlConsole), titleLbl); + } + } finally { + ignoreTabChangeEvent = false; + } + workbenchTabbedPane.setSelectedComponent(sqlConsole); + return sqlConsole; + } + + private boolean closeAllSQLConsoles() { + List toClose = new ArrayList(sqlConsoles); + for (SQLConsoleWithTitle sqlConsole: toClose) { + workbenchTabbedPane.setSelectedComponent(sqlConsole); + if (sqlConsole.getFile() != null && sqlConsole.isDirty()) { + if (!closeSQLConsole(sqlConsole, true)) { + return false; + } + } + } + toClose = new ArrayList(sqlConsoles); + for (SQLConsoleWithTitle sqlConsole: toClose) { + workbenchTabbedPane.setSelectedComponent(sqlConsole); + if (!closeSQLConsole(sqlConsole, false)) { + return false; + } + } + return true; + } + + private boolean closeSQLConsole(SQLConsoleWithTitle sqlConsole, boolean ask) { + if (ask) { + if (!sqlConsole.isEmpty() && !(sqlConsole.getFile() != null && !sqlConsole.isDirty())) { + if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(DataBrowser.this, "Close \"" + sqlConsole.getTitle() + "\"" + (sqlConsole.getFile() == null? "?" : " without saving?"), "Close Console", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)) { + return false; + } + } + } + try { + sqlConsole.close(); + ignoreTabChangeEvent = true; + workbenchTabbedPane.remove(sqlConsole); + sqlConsoles.remove(sqlConsole); + } finally { + ignoreTabChangeEvent = false; + } + return true; + } + + private void updateLoadSaveScriptMenuItemsState() { + SQLConsole sqlConsole = null; + Component sc = workbenchTabbedPane.getSelectedComponent(); + if (sc instanceof SQLConsole) { + sqlConsole = (SQLConsole) sc; + } + saveScriptMenuItem.setEnabled(sqlConsole != null && sqlConsole.isDirty()); + saveScriptAsMenuItem.setEnabled(sqlConsole != null && !sqlConsole.isEmpty()); + } + + private void loadScriptMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadScriptMenuItemActionPerformed + String fName = UIUtil.choseFile(null, ".", "Load SQL Script", "", this, false, true); + if (fName != null) { + File file = new File(fName); + loadSQLScriptFile(file); + } + }//GEN-LAST:event_loadScriptMenuItemActionPerformed + + private void loadSQLScriptFile(File file) { + for (SQLConsole sqlConsole: sqlConsoles) { + if (file.equals(sqlConsole.getFile())) { + workbenchTabbedPane.setSelectedComponent(sqlConsole); + return; + } + } + try { + UIUtil.setWaitCursor(this); + createNewSQLConsole(getMetaDataSource()).loadFromFile(file); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } finally { + UIUtil.resetWaitCursor(this); + } + } + + private void saveScriptMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveScriptMenuItemActionPerformed + SQLConsole sqlConsole = getCurrentSQLConsole(); + if (sqlConsole != null) { + if (sqlConsole.getFile() == null) { + saveScriptAsMenuItemActionPerformed(evt); + } else { + try { + UIUtil.setWaitCursor(this); + sqlConsole.storeToFile(null); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } finally { + UIUtil.resetWaitCursor(this); + } + } + } + }//GEN-LAST:event_saveScriptMenuItemActionPerformed + + private void initMenu() { + int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + if (mask != InputEvent.CTRL_MASK) { + for (int i = 0; i < menuBar.getMenuCount(); ++i) { + JMenu menu = menuBar.getMenu(i); + for (int j = 0; j < menu.getItemCount(); ++j) { + JMenuItem item = menu.getItem(j); + if (item != null) { + KeyStroke accelerator = item.getAccelerator(); + if (accelerator != null) { + item.setAccelerator(KeyStroke.getKeyStroke(accelerator.getKeyCode(), mask, accelerator.isOnKeyRelease())); + } + } + } + } + } + } + + private void saveScriptAsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveScriptAsMenuItemActionPerformed + SQLConsole sqlConsole = getCurrentSQLConsole(); + if (sqlConsole != null) { + String fName = UIUtil.choseFile(null, ".", "Save SQL Script", "", this, false, false); + if (fName != null) { + File file = new File(fName); + try { + UIUtil.setWaitCursor(this); + sqlConsole.storeToFile(file); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } finally { + UIUtil.resetWaitCursor(this); + } + } + } + }//GEN-LAST:event_saveScriptAsMenuItemActionPerformed + + private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed + if (closeAllSQLConsoles()) { + DataBrowser.this.dispose(); + } + }//GEN-LAST:event_exitMenuItemActionPerformed + + private void analyseSQLMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analyseSQLMenuItem1ActionPerformed + AssociationProposerView assocProposerView = new AssociationProposerView(this, datamodel.get(), null, executionContext); + if (assocProposerView.isAccepted()) { + openDataModelEditor(true); + } + }//GEN-LAST:event_analyseSQLMenuItem1ActionPerformed + + private void columnOrderItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_columnOrderItemActionPerformed + openColumnOrderEditor(null); + }//GEN-LAST:event_columnOrderItemActionPerformed + + private void openColumnOrderEditor(Table table) { + try { + if (new ColumnOrderEditor(this, table, datamodel.get(), executionContext).wasOk()) { + removeMetaDataSource(session); + desktop.reloadDataModel(desktop.schemaMapping); + dataModelViewFrame = null; + updateDataModelView(null); + updateStatusBar(); + askForDataModel(); + } + } catch (Throwable e) { + UIUtil.showException(this, "Error", e); + } + } + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + updateInfoPanel.setVisible(false); + }//GEN-LAST:event_jButton1ActionPerformed + + private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed + updateInfoPanel.setVisible(false); + UpdateInfoManager.download(); + }//GEN-LAST:event_downloadButtonActionPerformed + + private void nativeLAFCheckBoxMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nativeLAFCheckBoxMenuItemActionPerformed + + }//GEN-LAST:event_nativeLAFCheckBoxMenuItemActionPerformed + + private void addBookmarkMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addBookmarkMenuItemActionPerformed + desktop.storeSession(new BookmarksPanel(this, bookmarkMenu, desktop, executionContext)); + }//GEN-LAST:event_addBookmarkMenuItemActionPerformed + + private void editBookmarkMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editBookmarkMenuItemActionPerformed + new BookmarksPanel(this, bookmarkMenu, desktop, executionContext).editBookmarks(); + desktop.updateAllBookmarkMenues(); + }//GEN-LAST:event_editBookmarkMenuItemActionPerformed + + private void downloadMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadMenuItemActionPerformed + UpdateInfoManager.download(); + }//GEN-LAST:event_downloadMenuItemActionPerformed + + private void zoomInMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomInMenuItemActionPerformed + desktop.zoom(1); + }//GEN-LAST:event_zoomInMenuItemActionPerformed + + private void zoomOutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomOutMenuItemActionPerformed + desktop.zoom(-1); + }//GEN-LAST:event_zoomOutMenuItemActionPerformed + + private void checkPKMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkPKMenuItemActionPerformed + try { + if (dbConnectionDialog.isConnected || dbConnectionDialog.connect("Check Primary Keys")) { + BasicDataSource dataSource = UIUtil.createBasicDataSource(this, dbConnectionDialog.currentConnection.driverClass, dbConnectionDialog.currentConnection.url, dbConnectionDialog.currentConnection.user, dbConnectionDialog.getPassword(), 0, dbConnectionDialog.currentJarURLs()); + UIUtil.validatePrimaryKeys(this, dataSource, new TreeSet
(datamodel.get().getTables())); + } + } catch (Exception e) { + // ignore + } + }//GEN-LAST:event_checkPKMenuItemActionPerformed + + private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed + }//GEN-LAST:event_refreshButtonActionPerformed + + private void createCLIItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createCLIItemActionPerformed + String mapping = desktop.getRawSchemaMapping(); + String bookmark = BookmarksPanel.getLastUsedBookmark(executionContext); + if (bookmark != null) { + bookmark = bookmarkName(bookmark); + } + List bookmarks = new ArrayList(); + for (StringBuilder sb: BookmarksPanel.loadBookmarks(executionContext)) { + bookmarks.add(bookmarkName(sb.toString())); + } + new CLIPanel(dbConnectionDialog, true, null, mapping, bookmarks, bookmark, executionContext).open(this); + }//GEN-LAST:event_createCLIItemActionPerformed + + private void consistencyCheckMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_consistencyCheckMenuItem1ActionPerformed + consistencyCheckMenuItemActionPerformed(evt); + }//GEN-LAST:event_consistencyCheckMenuItem1ActionPerformed + + private String bookmarkName(String bookmarkFileName) { + if (bookmarkFileName.endsWith(BookmarksPanel.BOOKMARKFILE_EXTENSION)) { + return bookmarkFileName.substring(0, bookmarkFileName.length() - BookmarksPanel.BOOKMARKFILE_EXTENSION.length()); + } else { + return bookmarkFileName; + } + } + + private MetaDataDetailsPanel metaDataDetailsPanel; + private List sqlConsoles = new ArrayList(); + + private SQLConsole getCurrentSQLConsole() { + Component sc = workbenchTabbedPane.getSelectedComponent(); + if (sc instanceof SQLConsole) { + return (SQLConsole) sc; + } + if (sqlConsoles.isEmpty()) { + return null; + } + for (int i = sqlConsoles.size() - 1; i >= 0; --i) { + if (sqlConsoles.get(i).getFile() == null) { + return sqlConsoles.get(i); + } + } + return sqlConsoles.get(sqlConsoles.size() - 1); + } + + public MetaDataSource getMetaDataSource() { + return getMetaDataSource(session); + } + + private void switchToDesktop() { + workbenchTabbedPane.setSelectedComponent(desktopSplitPane); + } + + private void initDnD(Component target) { + new DropTarget(target, new DropTargetListener() { + @Override + public void drop(DropTargetDropEvent dtde) { + try { + Transferable tr = dtde.getTransferable(); + DataFlavor[] flavors = tr.getTransferDataFlavors(); + for (int i = 0; i < flavors.length; i++) { + if (flavors[i].isFlavorJavaFileListType()) { + dtde.acceptDrop(dtde.getDropAction()); + @SuppressWarnings("unchecked") + java.util.List files = (java.util.List) tr.getTransferData(flavors[i]); + for (int k = 0; k < files.size(); k++) { + loadSQLScriptFile(files.get(k)); + } + + dtde.dropComplete(true); + } + } + return; + } catch (Throwable t) { + t.printStackTrace(); + } + dtde.rejectDrop(); + } + + @Override + public void dragEnter(DropTargetDragEvent dtde) { + } + + @Override + public void dragOver(DropTargetDragEvent dtde) { + } + + @Override + public void dropActionChanged(DropTargetDragEvent dtde) { + } + + @Override + public void dragExit(DropTargetEvent dte) { + } + + }); + } + + public boolean isReady() { + return session != null; + } + + public SQLConsole getSqlConsole(boolean switchToConsole) { + return desktop.getSqlConsole(switchToConsole); + } + + private static final String LAST_SESSION_FILE = ".lastsession"; + + private void storeLastSession() { + BookmarkId bookmark; + try { + desktop.storeSession(Environment.newFile(LAST_SESSION_FILE).getPath()); + bookmark = new BookmarkId(null, executionContext.getCurrentModelSubfolder(), executionContext.getCurrentConnectionAlias(), desktop.getRawSchemaMapping()); + } catch (IOException e) { + bookmark = null; + } + UISettings.storeLastSession(bookmark, "B"); + } + + public static Date getLastSessionDate() { + try { + long lastModified = Environment.newFile(LAST_SESSION_FILE).lastModified(); + if (lastModified == 0) { + return null; + } + return new Date(lastModified); + } catch (Exception e) { + return null; + } + } + + private DesktopAnchorManager anchorManager; + + private ImageIcon tableIcon; + private ImageIcon databaseIcon; + private ImageIcon redIcon; + private ImageIcon blueIcon; + private ImageIcon greenIcon; + private Icon closeIcon; + private ImageIcon sqlConsoleIcon; + private ImageIcon addSqlConsoleIcon; + private ImageIcon navigationIcon; + private ImageIcon desktopIcon; + { + // load images + tableIcon = UIUtil.readImage("/table.png"); + databaseIcon = UIUtil.readImage("/database.png"); + redIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/reddot.gif")); + blueIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/bluedot.gif")); + greenIcon = UIUtil.scaleIcon(new JLabel(""), UIUtil.readImage("/greendot.gif")); + closeIcon = UIUtil.readImage("/Close-16-1.png"); + sqlConsoleIcon = UIUtil.readImage("/runall.png"); + desktopIcon = UIUtil.readImage("/tables.png"); + addSqlConsoleIcon = UIUtil.readImage("/add.png"); + navigationIcon = UIUtil.readImage("/navigation.png"); + } +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/Desktop.java b/src/main/gui/net/sf/jailer/ui/databrowser/Desktop.java index 2a85eaddd..aa7f51846 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/Desktop.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/Desktop.java @@ -1,3755 +1,3818 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser; - -import java.awt.BasicStroke; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.geom.AffineTransform; -import java.awt.geom.Path2D; -import java.awt.geom.Point2D; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyVetoException; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.AbstractAction; -import javax.swing.ActionMap; -import javax.swing.DefaultDesktopManager; -import javax.swing.Icon; -import javax.swing.InputMap; -import javax.swing.JComponent; -import javax.swing.JDesktopPane; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollBar; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTable; -import javax.swing.JViewport; -import javax.swing.KeyStroke; -import javax.swing.RowSorter.SortKey; -import javax.swing.SortOrder; -import javax.swing.SwingUtilities; -import javax.swing.WindowConstants; -import javax.swing.event.InternalFrameEvent; -import javax.swing.event.InternalFrameListener; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.KnownIdentifierMap; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.Environment; -import net.sf.jailer.ui.QueryBuilderDialog; -import net.sf.jailer.ui.QueryBuilderDialog.Relationship; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; -import net.sf.jailer.ui.databrowser.BrowserContentPane.RunnableWithPriority; -import net.sf.jailer.ui.databrowser.BrowserContentPane.SqlStatementTable; -import net.sf.jailer.ui.databrowser.TreeLayoutOptimizer.Node; -import net.sf.jailer.ui.databrowser.metadata.MDTable; -import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; -import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; -import net.sf.jailer.ui.util.UISettings; -import net.sf.jailer.util.CancellationException; -import net.sf.jailer.util.CsvFile; -import net.sf.jailer.util.CsvFile.Line; -import net.sf.jailer.util.Pair; -import net.sf.jailer.util.SqlUtil; -import prefuse.util.GraphicsLib; - -/** - * Desktop holding row-browsers as {@link JInternalFrame}s. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public abstract class Desktop extends JDesktopPane { - - /** - * The {@link DataModel}. - */ - private final Reference datamodel; - - /** - * Icon for the row-browser frames. - */ - private final Icon jailerIcon; - - /** - * Default width of a row-browser frame. - */ - public static final int BROWSERTABLE_DEFAULT_WIDTH = 476; - private final int BROWSERTABLE_DEFAULT_MIN_X = 0, BROWSERTABLE_DEFAULT_MIN_Y = 6, BROWSERTABLE_DEFAULT_HEIGHT = 460, BROWSERTABLE_DEFAULT_DISTANCE = 110; - - /** - * true while the desktop is visible. - */ - private boolean running; - - /** - * false if links must not be rendered (if a frame is - * maximized). - */ - private boolean renderLinks; - - /** - * Schema mapping. - */ - public final Map schemaMapping; - - /** - * DB session. - */ - public Session session; - DbConnectionDialog dbConnectionDialog; - - /** - * The execution context. - */ - private final ExecutionContext executionContext; - - private RowsClosure rowsClosure = new RowsClosure(); - - final DesktopAnimation desktopAnimation; - - private final QueryBuilderDialog queryBuilderDialog; - private final DesktopIFrameStateChangeRenderer iFrameStateChangeRenderer = new DesktopIFrameStateChangeRenderer(); - private final DesktopAnchorManager anchorManager; - - private static final KeyStroke KS_SQLCONSOLE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK); - - public DesktopIFrameStateChangeRenderer getiFrameStateChangeRenderer() { - return iFrameStateChangeRenderer; - } - - /** - * Constructor. - * - * @param datamodel - * the {@link DataModel} - * @param jailerIcon - * icon for the frames - * @param session - * DB-session - * @param anchorManager - */ - public Desktop(Reference datamodel, Icon jailerIcon, Session session, DataBrowser parentFrame, DbConnectionDialog dbConnectionDialog, Map schemaMapping, DesktopAnchorManager anchorManager, ExecutionContext executionContext) { - this.executionContext = executionContext; - this.anchorManager = anchorManager; - this.parentFrame = parentFrame; - this.datamodel = datamodel; - this.jailerIcon = jailerIcon; - this.queryBuilderDialog = new QueryBuilderDialog(parentFrame); - this.dbConnectionDialog = dbConnectionDialog; - this.schemaMapping = schemaMapping; - - this.desktopAnimation = new DesktopAnimation(this); - - this.queryBuilderDialog.sqlEditButton.setVisible(true); - this.queryBuilderDialog.sqlEditButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // addTableBrowser(null, null, 0, null, null, queryBuilderDialog.getSQL(), null, null, true); - getSqlConsole(true).appendStatement(queryBuilderDialog.getSQL() + LF + ";", true); - queryBuilderDialog.setVisible(false); - } - }); - if (Toolkit.getDefaultToolkit().getScreenSize().height < 740) { - layoutMode = LayoutMode.SMALL; - } - - try { - this.session = session; - setAutoscrolls(true); - manager = new MDIDesktopManager(this); - setDesktopManager(manager); - synchronized (this) { - running = true; - } - Thread updateUIThread = new Thread(new Runnable() { - @Override - public void run() { - final AtomicLong duration = new AtomicLong(); - final AtomicBoolean inProgress = new AtomicBoolean(false); - Map durations = new LinkedHashMap(); - long lastDuration = 0; - final long AVG_INTERVALL_SIZE = 1000; - while (true) { - synchronized (Desktop.this) { - if (!running) { - return; - } - } - try { - inProgress.set(false); - long now = System.currentTimeMillis(); - long d = lastDuration + paintDuration; - if (d <= 0) { - d = 1; - } - Iterator> i = durations.entrySet().iterator(); - while (i.hasNext()) { - if (i.next().getKey() < now - AVG_INTERVALL_SIZE) { - i.remove(); - } else { - break; - } - } - durations.put(now, d); - long dSum = 0; - for (Entry e: durations.entrySet()) { - dSum += e.getValue(); - } - long avgD = dSum / durations.size(); - if (UIUtil.isPopupActive() && !desktopAnimation.isActive()) { - avgD *= 2; - } else { - avgD *= 1.05; - } - - logFPS(durations, now, avgD); - - Thread.sleep(Math.min(desktopAnimation.isActive()? 10 : Math.max(STEP_DELAY, avgD), 500)); - if (!inProgress.get()) { - inProgress.set(true); - duration.set(0); - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - long startTime = System.currentTimeMillis(); - try { - checkAnchorRetension(); - if (isDesktopVisible() && isAnimationEnabled()) { - suppressRepaintDesktop = true; - desktopAnimation.animate(); - boolean cl = calculateLinks(); - if (cl) { - repaintScrollPane(); - } - } - } finally { - suppressRepaintDesktop = false; - inProgress.set(false); - duration.set(System.currentTimeMillis() - startTime); - } - } - }); - } - } catch (Throwable e) { - // ignore - } - lastDuration = duration.get(); - } - } - }, "Databrowser-Animator"); - updateUIThread.setDaemon(true); - updateUIThread.start(); - - AbstractAction a = new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (isDesktopVisible()) { - for (final RowBrowser rb : tableBrowsers) { - if (rb.internalFrame.isSelected()) { - rb.browserContentPane.rowsTable.grabFocus(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - rb.browserContentPane.openQueryBuilder(true); - } - }); - break; - } - } - } - } - }; - Container parent = parentFrame.getContentPane(); - if (parent instanceof JComponent) { - JComponent comp = (JComponent) parent; - InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - im.put(KS_SQLCONSOLE, a); - ActionMap am = comp.getActionMap(); - am.put(a, a); - } - } catch (Exception e) { - UIUtil.showException(null, "Error", e, session); - } - desktops.add(this); - updateMenu(); - } - - public class RowToRowLink { - - /** - * The rows. - */ - public Row parentRow, childRow; - - /** - * Index of parent row in the parent's row browser. - */ - public int parentRowIndex = -1; - - /** - * Index of child row. - */ - public int childRowIndex = -1; - - /** - * Coordinates of the link render. - */ - public int x1 = -1, y1, x2, y2; - - /** - * The link's color. - */ - public Color color1; - - /** - * The link's alternating color. - */ - public Color color2; - - /** - * Is the link visible? - */ - public boolean visible = true; - } - - /** - * Renders a set of {@link Row}s. - */ - public class RowBrowser { - - /** - * Frame holding a {@link BrowserContentPane}. - */ - public JInternalFrame internalFrame; - - /** - * UI for row-browsing. - */ - public BrowserContentPane browserContentPane; - - /** - * Parent browser. - */ - public RowBrowser parent; - - /** - * Association with parent. - */ - public Association association; - - /** - * Coordinates of the link render. - */ - public int x1, y1, x2, y2; - - /** - * The link's color. - */ - public Color color1; - - /** - * The link's alternating color. - */ - public Color color2; - - /** - * Row-to-row links. - */ - public List rowToRowLinks = new ArrayList(); - - public void convertToRoot() { - association = null; - parent = null; - browserContentPane.convertToRoot(); - } - - /** - * Is this RowBrowser hidden? - */ - private boolean hidden; - - /** - * Hides/unhides RowBrowser. - */ - public void setHidden(boolean hidden) { - if (hidden == this.hidden) { - return; - } - rbSourceToLinks = null; - if (hidden) { - internalFrame.setVisible(false); - } else { - internalFrame.setVisible(true); - Rectangle r = layout(parent, association, browserContentPane, new ArrayList(), 0, -1); - internalFrame.setBounds(r); - desktopAnimation.scrollRectToVisible(internalFrame.getBounds(), false); - try { - internalFrame.setSelected(true); - } catch (PropertyVetoException e) { - // ignore - } - internalFrame.grabFocus(); - } - this.hidden = hidden; - checkDesktopSize(); - updateMenu(); - } - - /** - * Is this RowBrowser hidden? - */ - public boolean isHidden() { - return hidden; - } - - private MDTable mdTable; - - public MDTable getMDTable() { - return mdTable; - } - - public void setMDTable(MDTable mdTable) { - this.mdTable = mdTable; - } - - }; - - /** - * All row-browsers. - */ - private List tableBrowsers = new ArrayList(); - - /** - * Opens a new row-browser. - * - * @param parent - * parent browser - * @param origParent - * @param table - * to read rows from. Open SQL browser if table is - * null. - * @param association - * to navigate, or null - * @param condition - * @param selectDistinct - * @param title - * @param limit - * @return new row-browser - */ - public synchronized RowBrowser addTableBrowser(final RowBrowser parent, final RowBrowser origParent, final Table table, final Association association, - String condition, Boolean selectDistinct, String title, boolean reload) { - - Set titles = new HashSet(); - for (RowBrowser rb : tableBrowsers) { - titles.add(rb.internalFrame.getTitle()); - } - demaximize(); - - if (title == null) { - if (table != null) { - title = datamodel.get().getDisplayName(table); - if (titles.contains(title)) { - for (int i = 2;; ++i) { - String titelPlusI = title + " (" + i + ")"; - if (!titles.contains(titelPlusI)) { - title = titelPlusI; - break; - } - } - } - } - } - - final RowBrowser tableBrowser = new RowBrowser(); - final JInternalFrame jInternalFrame = new JInternalFrame(table == null ? "SQL" : title); - - jInternalFrame.setClosable(true); - jInternalFrame.setIconifiable(true); - jInternalFrame.setMaximizable(true); - jInternalFrame.setVisible(true); - jInternalFrame.addMouseWheelListener(new java.awt.event.MouseWheelListener() { - @Override - public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { - long currentTime = System.currentTimeMillis(); - startRescaleMode(currentTime, evt); - onMouseWheelMoved(evt, currentTime); - onMouseWheelMoved(evt, parentFrame.getDesktopScrollPane(), currentTime); - } - }); - javax.swing.GroupLayout jInternalFrame1Layout = new javax.swing.GroupLayout(jInternalFrame.getContentPane()); - jInternalFrame.getContentPane().setLayout(jInternalFrame1Layout); - jInternalFrame1Layout.setHorizontalGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 162, - Short.MAX_VALUE)); - jInternalFrame1Layout.setVerticalGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 102, - Short.MAX_VALUE)); - - jInternalFrame.setResizable(true); - if (jailerIcon != null) { - jInternalFrame.setFrameIcon(jailerIcon); - } - add(jInternalFrame, javax.swing.JLayeredPane.DEFAULT_LAYER); - - jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_MAXIMUM_PROPERTY, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - manager.resizeDesktop(); - } - }); - - jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_ICON_PROPERTY, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (jInternalFrame.isIcon()) { - demaximize(); - tableBrowser.setHidden(true); - try { - jInternalFrame.setIcon(false); - } catch (PropertyVetoException e) { - // ignore - } - } - } - }); - - jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_SELECTED_PROPERTY, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.TRUE.equals(evt.getNewValue())) { - updateMenu(); - } - } - }); - - jInternalFrame.addComponentListener(new ComponentListener() { - - @Override - public void componentShown(ComponentEvent e) { - repaintDesktop(); - } - - @Override - public void componentResized(ComponentEvent e) { - repaintDesktop(); - } - - @Override - public void componentMoved(ComponentEvent e) { - repaintDesktop(); - } - - @Override - public void componentHidden(ComponentEvent e) { - repaintDesktop(); - } - }); - - if (reload) { - ++UISettings.s5; - } - - final BrowserContentPane browserContentPane = new BrowserContentPane(datamodel.get(), table, condition, session, parent == null ? null : parent.browserContentPane.rows, - association, parentFrame, rowsClosure, selectDistinct, reload, executionContext) { - { - MouseListener ml = new MouseAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - updateRowView(e); - } - @Override - public void mouseExited(MouseEvent e) { - if (null != currentlyViewedRow) { - onRowSelect(table, null); - currentlyViewedRow = null; - } - } - }; - singleRowViewScrollPane.addMouseListener(ml); - singleRowViewScrollPane.addMouseMotionListener((MouseMotionListener) ml); - singleRowViewContainterPanel.addMouseListener(ml); - singleRowViewContainterPanel.addMouseMotionListener((MouseMotionListener) ml); - rowsTable.addMouseListener(ml); - rowsTable.addMouseMotionListener((MouseMotionListener) ml); - } - - private void updateRowView(MouseEvent e) { - int ri; - JComponent source = (JComponent) e.getSource(); - if (source == rowsTable) { - ri = rowsTable.rowAtPoint(e.getPoint()); - } else { - ri = 0; - } - if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { - int i = 0; - if (source == rowsTable) { - i = rowsTable.getRowSorter().convertRowIndexToModel(ri); - } else if (source == rowsTableScrollPane || source == singleRowViewContainterPanel) { - if (rows.size() != 1 || getQueryBuilderDialog() == null /* SQL Console */) { - return; - } - ri = 0; - i = 0; - } - Row row = rows.get(i); - if (row != currentlyViewedRow) { - onRowSelect(table, row); - currentlyViewedRow = row; - } - } - } - - @Override - protected void reloadDataModel() throws Exception { - Desktop.this.reloadDataModel(schemaMapping); - } - - @Override - protected QueryBuilderDialog getQueryBuilderDialog() { - return queryBuilderDialog; - } - - @Override - protected RowBrowser navigateTo(Association association, List pRows) { - return addTableBrowser(tableBrowser, tableBrowser, association.destination, association, toCondition(pRows), null, null, true); - } - - @Override - protected void onContentChange(List rows, boolean reloadChildren) { - updateChildren(tableBrowser, rows); - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == tableBrowser) { - updateChildren(rb, rb.browserContentPane.rows); - if (reloadChildren /* && rb.browserContentPane.parentRow == null */) { - rb.browserContentPane.reloadRows(); - } - } - } - } - - @Override - protected void onRedraw() { - repaintDesktop(); - } - - @Override - protected JFrame getOwner() { - return parentFrame; - } - - private Set> addedRowPairs; - - @Override - protected void addRowToRowLink(Row parentRow, Row childRow) { - synchronized (Desktop.this) { - Pair pair = new Pair(parentRow, childRow); - if (addedRowPairs == null || !addedRowPairs.contains(pair)) { - if (addedRowPairs != null) { - addedRowPairs.add(pair); - } - RowToRowLink rowToRowLink = new RowToRowLink(); - rowToRowLink.parentRow = parentRow; - rowToRowLink.childRow = childRow; - rowToRowLink.color1 = getAssociationColor1(association); - rowToRowLink.color2 = getAssociationColor2(association); - tableBrowser.rowToRowLinks.add(rowToRowLink); - } - } - } - - @Override - protected void beforeReload() { - synchronized (Desktop.this) { - addedRowPairs = new HashSet>(); - tableBrowser.rowToRowLinks.clear(); - } - } - - @Override - protected void afterReload() { - synchronized (Desktop.this) { - addedRowPairs = null; - } - } - - @Override - protected void findClosure(Row row) { - Set> rows = new HashSet>(); - findClosure(row, rows, false); - rowsClosure.currentClosure.addAll(rows); - rows = new HashSet>(); - findClosure(row, rows, true); - rowsClosure.currentClosure.addAll(rows); - rowsClosure.parentPath.clear(); - rowsClosure.parentPath.add(this); - for (RowBrowser p = parent; p != null; p = p.parent) { - rowsClosure.parentPath.add(p.browserContentPane); - } - - try { - Set browserInClosure = new HashSet(); - for (Pair rid: rowsClosure.currentClosure) { - browserInClosure.add(rid.a); - } - - for (RowBrowser rb: tableBrowsers) { - rb.browserContentPane.updateRowsCountLabel(browserInClosure); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - protected void findTempClosure(Row row) { - Set> rows = new HashSet>(); - Set> closure = new HashSet>(); - findClosure(row, rows, false); - closure.addAll(rows); - rows = new HashSet>(); - findClosure(row, rows, true); - closure.addAll(rows); - - rowsClosure.tempClosure.clear(); - for (Pair p: closure) { - rowsClosure.tempClosure.add(p.b); - } - } - - @Override - protected void findClosure(Row row, Set> closure, boolean forward) { - synchronized (Desktop.this) { - Pair thisRow = new Pair(this, row); - if (!closure.contains(thisRow)) { - closure.add(thisRow); - if (forward) { - for (RowBrowser child : tableBrowsers) { - if (child.parent == tableBrowser) { - for (RowToRowLink rowToRowLink : child.rowToRowLinks) { - if (row.nonEmptyRowId.equals(rowToRowLink.parentRow.nonEmptyRowId)) { - child.browserContentPane.findClosure(rowToRowLink.childRow, closure, forward); - } - } - } - } - } else { - if (tableBrowser.parent != null) { - for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { - if (row.nonEmptyRowId.equals(rowToRowLink.childRow.nonEmptyRowId)) { - tableBrowser.parent.browserContentPane.findClosure(rowToRowLink.parentRow, closure, forward); - for (RowBrowser sibling : tableBrowsers) { - if (sibling.parent == tableBrowser.parent && sibling.browserContentPane != this) { - for (RowToRowLink sRowToRowLink: sibling.rowToRowLinks) { - if (rowToRowLink.parentRow.nonEmptyRowId.equals(sRowToRowLink.parentRow.nonEmptyRowId)) { - sibling.browserContentPane.findClosure(sRowToRowLink.childRow, closure, true); - } - } - } - } - } - } - } - } - } - } - } - - private void createAnchorSQL(RowBrowser rb, StringBuilder rowIds, boolean indent) { - boolean f = true; - for (Row row : rb.browserContentPane.rows) { - if (!f) { - rowIds.append(indent ? " or\n " : " or\n"); - } - f = false; - rowIds.append(SqlUtil.replaceAliases(row.rowId, "A", "A")); - } - rowIds.append(""); - } - - @Override - protected QueryBuilderDialog.Relationship createQBRelations(boolean withParents) { - QueryBuilderDialog.Relationship root = new QueryBuilderDialog.Relationship(); - root.whereClause = (getAndConditionText().trim()); // .replaceAll("(\r|\n)+", " "); - if (root.whereClause.length() == 0) { - root.whereClause = null; - } - StringBuilder rowIds = new StringBuilder(""); - createAnchorSQL(tableBrowser, rowIds, withParents); - root.anchorWhereClause = rowIds.length() == 0 ? null : rowIds.toString(); - - root.children.addAll(createQBChildrenRelations(null, !withParents)); - - Association a = association; - - QueryBuilderDialog.Relationship r = root; - RowBrowser childRB = tableBrowser; - for (RowBrowser rb = tableBrowser.parent; rb != null && a != null; rb = rb.parent) { - if (!withParents) { - root.needsAnchor = true; - break; - } - QueryBuilderDialog.Relationship child = new QueryBuilderDialog.Relationship(); - child.children.addAll(rb.browserContentPane.createQBChildrenRelations(childRB, false)); - child.parent = r; - r.children.add(0, child); - child.whereClause = (rb.browserContentPane.getAndConditionText().trim()).replaceAll("(\r|\n)+", " "); - if (child.whereClause.length() == 0) { - child.whereClause = null; - } - child.association = a.reversalAssociation; - r.anchor = child.association; - a = rb.association; - rowIds = new StringBuilder(""); - createAnchorSQL(rb, rowIds, true); - child.anchorWhereClause = rowIds.length() == 0 ? null : rowIds.toString(); - - r.originalParent = child; - r = child; - childRB = rb; - } - return root; - } - - @Override - protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { - List result = new ArrayList(); - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == tableBrowser && rb != tabu) { - if (true) { // all || !singleRowParent) { - QueryBuilderDialog.Relationship child = new QueryBuilderDialog.Relationship(); - child.whereClause = (rb.browserContentPane.getAndConditionText().trim()).replaceAll("(\r|\n)+", " "); - child.joinOperator = QueryBuilderDialog.JoinOperator.LeftJoin; - if (child.whereClause.length() == 0) { - child.whereClause = null; - } - child.association = rb.association; - if (child.association != null) { - child.children.addAll(rb.browserContentPane.createQBChildrenRelations(tabu, all)); - result.add(child); - } - } - } - } - return result; - } - - @Override - protected void openSchemaMappingDialog() { - Desktop.this.openSchemaMappingDialog(false); - } - - @Override - protected void openSchemaAnalyzer() { - Desktop.this.openSchemaAnalyzer(); - } - - @Override - protected DbConnectionDialog getDbConnectionDialog() { - return dbConnectionDialog; - } - - @Override - protected double getLayoutFactor() { - return layoutMode.factor; - } - - @Override - protected List getChildBrowsers() { - return Desktop.this.getChildBrowsers(tableBrowser, false); - } - - @Override - protected RowBrowser getParentBrowser() { - return tableBrowser.parent; - } - - @Override - protected RowBrowser getRowBrowser() { - return tableBrowser; - } - - @Override - protected List getTableBrowser() { - return new ArrayList(Desktop.this.tableBrowsers); - } - - @Override - protected void onHide() { - demaximize(); - tableBrowser.setHidden(true); - } - - @Override - protected void unhide() { - tableBrowser.setHidden(false); - } - - @Override - protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { - Desktop.this.adjustClosure(tabu, thisOne); - } - - @Override - protected void close() { - closeAll(Collections.singleton(tableBrowser)); - } - - @Override - protected void showInNewWindow() { - Desktop.this.showInNewWindow(tableBrowser); - } - - @Override - protected void appendLayout() { - Desktop.this.restoreSession(tableBrowser, null); - } - - @Override - protected PriorityBlockingQueue getRunnableQueue() { - return runnableQueue; - } - - @Override - protected void collectPositions(Map> positions) { - Desktop.this.collectPositions(tableBrowser, positions); - } - - @Override - protected boolean renderRowAsPK(Row theRow) { - return false; - } - - @Override - protected MetaDataSource getMetaDataSource() { - return parentFrame.getMetaDataSource(); - } - - @Override - protected SQLConsole getSqlConsole(boolean switchToConsole) { - return Desktop.this.getSqlConsole(switchToConsole); - } - - @Override - protected void deselectChildrenIfNeededWithoutReload() { - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == tableBrowser) { - rb.browserContentPane.deselectIfNeededWithoutReload(); - rb.browserContentPane.deselectChildrenIfNeededWithoutReload(); - } - } - } - - @Override - protected int getReloadLimit() { - return Desktop.this.getRowLimit(); - } - - @Override - protected void changeColumnOrder(Table table) { - Desktop.this.changeColumnOrder(table); - } - - @Override - protected void rebase() { - Component parent = SwingUtilities.getWindowAncestor(this); - if (parent == null) { - parent = this; - } - UIUtil.setWaitCursor(parent); - try { - Desktop.noArrangeLayoutOnNewTableBrowser = true; - Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = true; - - RowBrowser newBrowser = copy(null, null, null, null, true); - RowBrowser newChildBrowser = newBrowser; - - BrowserContentPane root; - BrowserContentPane br = this; - do { - root = br; - RowBrowser pb = br.getParentBrowser(); - if (pb != null) { - if (br.association != null) { - newChildBrowser = pb.browserContentPane.copy(newChildBrowser, br.association.reversalAssociation, null, br.getRowBrowser(), true); - } else { - closeSubTree(newBrowser.browserContentPane, true); - return; - } - br = pb.browserContentPane; - } else { - br = null; - } - } while (br != null); - newBrowser.browserContentPane.reloadRows(); - newBrowser.internalFrame.setSelected(true); - UIUtil.invokeLater(2, new Runnable() { - @Override - public void run() { - onLayoutChanged(false, true); - } - }); - UISettings.s7 += 1000; - closeSubTree(root, true); - } catch (Throwable t) { - UIUtil.showException(parent, "Error", t); - } finally { - Desktop.noArrangeLayoutOnNewTableBrowser = false; - Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = false; - UIUtil.resetWaitCursor(parent); - } - } - - @Override - protected RowBrowser copy(RowBrowser parent, Association newAssociation, Row pRow, RowBrowser childToIgnore, boolean newParent) { - String andConditionText = this.getAndConditionText(); - if (pRow != null && (andConditionText == null || andConditionText.trim().length() == 0)) { - andConditionText = pRow.rowId; - } - if (newParent && andConditionText != null) { - if (!andConditionText.equals(SqlUtil.replaceAliases(andConditionText, "A", ""))) { - andConditionText = ""; - } - } - RowBrowser tb = addTableBrowser(parent, parent, table, newAssociation, andConditionText, null, tableBrowser.internalFrame.getTitle(), false); - tb.internalFrame.setBounds(tableBrowser.internalFrame.getBounds()); - try { - tb.internalFrame.setIcon(!tableBrowser.internalFrame.isVisible()); - } catch (PropertyVetoException e) { - // ignore - } - for (RowBrowser child: getChildBrowsers()) { - if (child != childToIgnore) { - child.browserContentPane.copy(tb, child.association, null, null, false); - } - } - return tb; - } - - @Override - protected boolean shouldShowLoadErrors() { - return isDesktopVisible(); - } - - }; - - Rectangle r = layout(parent, association, browserContentPane, new ArrayList(), 0, -1); - java.awt.event.MouseWheelListener mouseWheelListener = new java.awt.event.MouseWheelListener() { - @Override - public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { - long currentTime = System.currentTimeMillis(); - checkRescaleMode(evt, currentTime); - onMouseWheelMoved(evt, currentTime); - if (evt.getSource() instanceof JScrollPane) { - onMouseWheelMoved(evt, (JScrollPane) evt.getSource(), currentTime); - } - } - }; - browserContentPane.rowsTableScrollPane.addMouseWheelListener(mouseWheelListener); - browserContentPane.singleRowViewScrollPane.addMouseWheelListener(mouseWheelListener); - - jInternalFrame.setBounds(r); - - tableBrowser.internalFrame = jInternalFrame; - tableBrowser.browserContentPane = browserContentPane; - tableBrowser.parent = parent; - tableBrowser.association = association; - if (association != null) { - tableBrowser.color1 = getAssociationColor1(association); - tableBrowser.color2 = getAssociationColor2(association); - } - tableBrowsers.add(tableBrowser); - UISettings.s2 = Math.max(tableBrowsers.size(), UISettings.s2); - - initIFrame(jInternalFrame, browserContentPane); - - anchorManager.onNewTableBrowser(tableBrowser); - - jInternalFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - jInternalFrame.addInternalFrameListener(new InternalFrameListener() { - @Override - public void internalFrameOpened(InternalFrameEvent e) { - onLayoutChanged(false, true); - } - - @Override - public void internalFrameIconified(InternalFrameEvent e) { - repaintDesktop(); - } - - @Override - public void internalFrameDeiconified(InternalFrameEvent e) { - repaintDesktop(); - } - - @Override - public void internalFrameDeactivated(InternalFrameEvent e) { - } - - @Override - public void internalFrameClosing(InternalFrameEvent e) { - if (tableBrowser.browserContentPane.closeWithChildren(jInternalFrame)) { - onLayoutChanged(false, false); - } - } - - @Override - public void internalFrameClosed(InternalFrameEvent e) { - close(tableBrowser, true); - } - - @Override - public void internalFrameActivated(InternalFrameEvent e) { - } - }); - - checkDesktopSize(); - updateMenu(); - - if (!noArrangeLayoutOnNewTableBrowser) { - this.scrollToCenter(jInternalFrame); - try { - jInternalFrame.setSelected(true); - } catch (PropertyVetoException e1) { - // ignore - } - browserContentPane.andCondition.grabFocus(); - onLayoutChanged(false, true); - } else { - lastInternalFrame = jInternalFrame; - lastBrowserContentPane = browserContentPane; - } - - if (tableBrowsers.size() > 1) { - iFrameStateChangeRenderer.onNewIFrame(jInternalFrame); - } - jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_SELECTED_PROPERTY, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Boolean.TRUE.equals(evt.getNewValue())) { - iFrameStateChangeRenderer.onIFrameSelected(jInternalFrame, 0.6); - } - } - }); - - return tableBrowser; - } - - protected abstract int getRowLimit(); - - /** - * Demaximizes all internal frames. - */ - private void demaximize() { - for (RowBrowser rb : tableBrowsers) { - try { - rb.internalFrame.setMaximum(false); - } catch (PropertyVetoException e) { - // ignore - } - } - } - - private void initIFrame(final JInternalFrame jInternalFrame, final BrowserContentPane browserContentPane) { - browserContentPane.thumbnail = new JPanel(); - final JPanel thumbnailInner = new JPanel(); - browserContentPane.thumbnail.setLayout(new GridBagLayout()); - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 1; - gridBagConstraints.gridheight = 1; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 1; - gridBagConstraints.fill = GridBagConstraints.BOTH; - gridBagConstraints.insets = new Insets(8, 8, 8, 8); - browserContentPane.thumbnail.add(thumbnailInner, gridBagConstraints); - - thumbnailInner.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); - String title = jInternalFrame.getTitle(); - String suffix = null; - Pattern tPat = Pattern.compile("^(.*)(\\([0-9]+\\))$"); - Matcher matcher = tPat.matcher(title); - if (matcher.matches()) { - title = matcher.group(1); - suffix = matcher.group(2); - } - -// boolean isEmpty = browserContentPane.get - - List labels = new ArrayList(); - final List jLabels = new ArrayList(); - - for (int i = 0; i < title.length(); ++i) { - labels.add(title.substring(i, i + 1)); - } - if (suffix != null) { - labels.add(suffix); - } - for (String l: labels) { - JLabel jl = new JLabel(l); - jl.setFont(jl.getFont().deriveFont(jl.getFont().getStyle() | Font.BOLD)); - jLabels.add(jl); - thumbnailInner.add(jl); - } - - browserContentPane.setOnReloadAction(new Runnable() { - - @Override - public void run() { - if (browserContentPane.rows != null) { - if (browserContentPane.rows.size() == 0) { - for (JLabel l: jLabels) { - l.setForeground(Color.GRAY); - } - } else { - for (JLabel l: jLabels) { - l.setForeground(Color.BLUE); - } - } - } - } - }); - - jInternalFrame.getContentPane().setLayout(new CardLayout()); - - jInternalFrame.getContentPane().add(browserContentPane, "C"); - jInternalFrame.getContentPane().add(browserContentPane.thumbnail, "T"); - - browserContentPane.thumbnail.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1 && !(browserContentPane.table instanceof SqlStatementTable)) { - JPopupMenu popup = browserContentPane.createPopupMenu(null, -1, 0, 0, false); - JPopupMenu popup2 = browserContentPane.createSqlPopupMenu(-1, 0, 0, true, jInternalFrame); - popup.add(new JSeparator()); - for (Component c : popup2.getComponents()) { - popup.add(c); - } - UIUtil.fit(popup); - popup.show(e.getComponent(), e.getX(), e.getY()); - } - } - }); - - initIFrameContent(jInternalFrame, browserContentPane, browserContentPane.thumbnail); - jInternalFrame.addComponentListener(new ComponentListener() { - @Override - public void componentHidden(ComponentEvent e) { - onLayoutChanged(false, false); - } - - @Override - public void componentMoved(ComponentEvent e) { -// onLayoutChanged(false); - } - - @Override - public void componentResized(ComponentEvent e) { -// onLayoutChanged(jInternalFrame.isMaximum()); - initIFrameContent(jInternalFrame, browserContentPane, browserContentPane.thumbnail); - } - - @Override - public void componentShown(ComponentEvent e) { - onLayoutChanged(false, true); - } - }); - } - - private void initIFrameContent(final JInternalFrame jInternalFrame, final BrowserContentPane browserContentPane, final JPanel thumbnail) { - if (jInternalFrame.getWidth() < 150 || jInternalFrame.getHeight() < 150) { - ((CardLayout) jInternalFrame.getContentPane().getLayout()).show(jInternalFrame.getContentPane(), "T"); - } else { - ((CardLayout) jInternalFrame.getContentPane().getLayout()).show(jInternalFrame.getContentPane(), "C"); - } - } - - private Color getAssociationColor1(Association association) { - Color color = new java.awt.Color(0, 120, 255); - if (association.isIgnored()) { - color = new java.awt.Color(153, 153, 153); - } else if (association.isInsertDestinationBeforeSource()) { - color = new java.awt.Color(190, 30, 0); - } else if (association.isInsertSourceBeforeDestination()) { - color = new java.awt.Color(60, 132, 0); - } - return color; - } - - private Color getAssociationColor2(Association association) { - Color color = new java.awt.Color(0, 60, 235); - if (association.isIgnored()) { - color = new java.awt.Color(133, 133, 153); - } else if (association.isInsertSourceBeforeDestination()) { - color = new java.awt.Color(0, 180, 80); - } else if (association.isInsertDestinationBeforeSource()) { - color = new java.awt.Color(230, 0, 60); - } - return color; - } - - private Rectangle layout(RowBrowser parent, Association association, BrowserContentPane browserContentPane, - Collection ignore, int maxH, int xPosition) { - int x = (int) (BROWSERTABLE_DEFAULT_MIN_X * layoutMode.factor); - int y = (int) (BROWSERTABLE_DEFAULT_MIN_Y * layoutMode.factor); - - while (parent != null && parent.isHidden()) { - parent = parent.parent; - } - - if (parent != null) { - x = (int) (parent.internalFrame.getX() + parent.internalFrame.getWidth() + BROWSERTABLE_DEFAULT_DISTANCE * layoutMode.factor); - y = parent.internalFrame.getY(); - } - if (maxH > 0) { - y = maxH; - } - if (xPosition >= 0) { - x = (int) (xPosition * (BROWSERTABLE_DEFAULT_WIDTH + BROWSERTABLE_DEFAULT_DISTANCE) * layoutMode.factor); - } - // int h = fullSize || association == null || - // (association.getCardinality() != Cardinality.MANY_TO_ONE && - // association.getCardinality() != Cardinality.ONE_TO_ONE)? HEIGHT : - // browserContentPane.getMinimumSize().height + MIN_HEIGHT; - int h = (int) (BROWSERTABLE_DEFAULT_HEIGHT * layoutMode.factor); - Rectangle r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); - for (;;) { - boolean ok = true; - for (RowBrowser tb : tableBrowsers) { - if (!ignore.contains(tb) && !tb.isHidden() && tb.internalFrame.getBounds().intersects(r)) { - ok = false; - break; - } - } - r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); - y += 8 * layoutMode.factor; - if (ok) { - break; - } - } - return r; - } - - protected synchronized void updateChildren(RowBrowser tableBrowser, List rows) { - boolean hasParent = false; - - for (RowBrowser rowBrowser : tableBrowsers) { - if (rowBrowser == tableBrowser.parent) { - hasParent = true; - } - } - - if (!hasParent) { - tableBrowser.rowToRowLinks.clear(); - } else { - Map rowIndex = new IdentityHashMap(); - Map rowIDIndex = new HashMap(); - Map parentRowIndex = new IdentityHashMap(); - Map parentRowIDIndex = new HashMap(); - for (int i = 0; i < rows.size(); ++i) { - Integer iI = i; - Row r = rows.get(i); - rowIndex.put(r, iI); - rowIDIndex.put(r.nonEmptyRowId, iI); - } - List parentRows = tableBrowser.parent.browserContentPane.rows; - for (int i = 0; i < parentRows.size(); ++i) { - Integer iI = i; - Row r = parentRows.get(i); - parentRowIndex.put(r, iI); - parentRowIDIndex.put(r.nonEmptyRowId, iI); - } - for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { - rowToRowLink.childRowIndex = -1; - Integer i = rowIndex.get(rowToRowLink.childRow); - if (i != null) { - rowToRowLink.childRowIndex = i; - } - // for (int i = 0; i < rows.size(); ++i) { - // if (rowToRowLink.childRow == rows.get(i)) { - // rowToRowLink.childRowIndex = i; - // break; - // } - // } - if (rowToRowLink.childRowIndex < 0) { - i = rowIDIndex.get(rowToRowLink.childRow.nonEmptyRowId); - if (i != null) { - rowToRowLink.childRowIndex = i; - } - // for (int i = 0; i < rows.size(); ++i) { - // if - // (rowToRowLink.childRow.rowId.equals(rows.get(i).rowId)) { - // rowToRowLink.childRowIndex = i; - // break; - // } - // } - } - rowToRowLink.parentRowIndex = -1; - i = parentRowIndex.get(rowToRowLink.parentRow); - if (i != null) { - rowToRowLink.parentRowIndex = i; - } - // for (int i = 0; i < parentRows.size(); ++i) { - // if (rowToRowLink.parentRow == parentRows.get(i)) { - // rowToRowLink.parentRowIndex = i; - // break; - // } - // } - - if (rowToRowLink.parentRowIndex < 0) { - i = parentRowIDIndex.get(rowToRowLink.parentRow.nonEmptyRowId); - if (i != null) { - rowToRowLink.parentRowIndex = i; - } - // for (int i = 0; i < parentRows.size(); ++i) { - // if - // (rowToRowLink.parentRow.rowId.equals(parentRows.get(i).rowId)) - // { - // rowToRowLink.parentRowIndex = i; - // break; - // } - // } - } - } - } - } - - private boolean suppressRepaintDesktop = false; - - /** - * Repaints the desktop. - */ - private void repaintDesktop() { - if (!suppressRepaintDesktop) { - calculateLinks(); - repaintScrollPane(); - } - } - - private void repaintScrollPane() { - JScrollPane scrollPane = getScrollPane(); - scrollPane.setSize(scrollPane.getWidth() + 1, scrollPane.getHeight() + 1); - scrollPane.setSize(scrollPane.getWidth() - 1, scrollPane.getHeight() - 1); - scrollPane.invalidate(); - scrollPane.validate(); - } - - /** - * Calculates coordinates of all link-renders. - * - * @return true iff something has changed - */ - private synchronized boolean calculateLinks() { - boolean changed = false; - Set linesHash = new HashSet(20000); - Map yPerRowTable1 = new HashMap(); - Map yPerRowTable2 = new HashMap(); - for (RowBrowser tableBrowser : tableBrowsers) { - JInternalFrame internalFrame = tableBrowser.internalFrame; - if (internalFrame.isMaximum()) { - changed = renderLinks; - renderLinks = false; - if (changed) { - rbSourceToLinks = null; - } - return changed; - } - if (tableBrowser.parent != null) { - int BORDER = 3; - int BOT_H = 32; - int x1 = internalFrame.getX(); // + internalFrame.getWidth() / 2; - int y1 = internalFrame.getY() + internalFrame.getHeight() / 2; - - RowBrowser visParent = tableBrowser.parent; - while (visParent != null && visParent.isHidden()) { - visParent = visParent.parent; - } - if (visParent == null) { - visParent = tableBrowser.parent; - } - - Rectangle cellRect = new Rectangle(); - boolean ignoreScrolling = false; - int i = 0; - - int x2 = visParent.internalFrame.getX(); - int y = cellRect.y; - y = cellRect.height * i; - int y2 = visParent.internalFrame.getY() + y + Math.min(cellRect.height / 2, 100); - // if (midx < x1) { - x2 += visParent.internalFrame.getWidth() - BORDER; - // } else { - // x2 += BORDER; - // } - Container p = visParent.browserContentPane.rowsTable; - if (ignoreScrolling) { - p = p.getParent(); - } - while (p != visParent.internalFrame) { - y2 += p.getY(); - p = p.getParent(); - } - int min = visParent.internalFrame.getY() + Math.min(cellRect.height, 20); - if (y2 < min) { - y2 = min; - } - int max = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() - BOT_H; - if (y2 > max) { - y2 = max; - } - - y2 = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() / 2; - - if (x1 != tableBrowser.x1 || y1 != tableBrowser.y1 || x2 != tableBrowser.x2 || y2 != tableBrowser.y2) { - changed = true; - tableBrowser.x1 = x1; - tableBrowser.y1 = y1; - tableBrowser.x2 = x2; - tableBrowser.y2 = y2; - } - - Rectangle visibleRect = getScrollPane().getViewport().getViewRect(); - int linkAreaXMin = Math.min(visParent.internalFrame.getX() + visParent.internalFrame.getWidth(), internalFrame.getX()); - int linkAreaYMin = Math.min(visParent.internalFrame.getY(), internalFrame.getY()); - int linkAreaXMax = Math.max(visParent.internalFrame.getX() + visParent.internalFrame.getWidth(), internalFrame.getX()); - int linkAreaYMax = Math.max(visParent.internalFrame.getY() + visParent.internalFrame.getHeight(), internalFrame.getY() + internalFrame.getHeight()); - boolean allInvisible = false; - if (!isIconOrHidden(visParent.internalFrame) && !isIconOrHidden(internalFrame)) { - if (linkAreaXMin > visibleRect.getX() + visibleRect.getWidth()) { - allInvisible = true; - } else if (linkAreaYMin > visibleRect.getY() + visibleRect.getHeight()) { - allInvisible = true; - } else if (linkAreaXMax < visibleRect.getX()) { - allInvisible = true; - } else if (linkAreaYMax < visibleRect.getY()) { - allInvisible = true; - } - } - - for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { - rowToRowLink.visible = !allInvisible; - if (!rowToRowLink.visible) { - continue; - } - x1 = y1 = x2 = y2 = -1; - try { - if (rowToRowLink.childRowIndex >= 0 && rowToRowLink.parentRowIndex >= 0) { - cellRect = new Rectangle(); - i = 0; - ignoreScrolling = false; - if (rowToRowLink.childRowIndex >= 0) { - i = tableBrowser.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(rowToRowLink.childRowIndex); - if (i < 0) { - rowToRowLink.visible = false; - continue; - } - cellRect = tableBrowser.browserContentPane.rowsTable.getCellRect(i, 0, true); - if (tableBrowser.browserContentPane.rows != null && tableBrowser.browserContentPane.rows.size() == 1) { - cellRect.setBounds(cellRect.x, 0, cellRect.width, Math.min(cellRect.height, 20)); - ignoreScrolling = true; - } - } - - x1 = internalFrame.getX(); - y = cellRect.height * i; - // if (r1) { - // x1 += internalFrame.getWidth()- BORDER; - // } else { - x1 += BORDER; - // } - - p = tableBrowser.browserContentPane.rowsTable; - Integer pY = yPerRowTable1.get(p); - if (pY != null) { - y1 = pY; - } else { - y1 = internalFrame.getY(); - if (ignoreScrolling) { - p = p.getParent(); - } - while (p != internalFrame) { - y1 += p.getY(); - p = p.getParent(); - } - yPerRowTable1.put(tableBrowser.browserContentPane.rowsTable, y1); - } - y1 += y + cellRect.height / 2; - min = internalFrame.getY() + cellRect.height * 2; - if (y1 < min) { - y1 = min; - } - max = internalFrame.getY() + internalFrame.getHeight() - BOT_H; - if (y1 > max) { - y1 = max; - } - ignoreScrolling = false; - cellRect = new Rectangle(); - i = 0; - if (rowToRowLink.parentRowIndex >= 0) { - i = tableBrowser.parent.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(rowToRowLink.parentRowIndex); - if (i < 0) { - rowToRowLink.visible = false; - continue; - } - cellRect = tableBrowser.parent.browserContentPane.rowsTable.getCellRect(i, 0, true); - if (tableBrowser.parent.browserContentPane.rows != null && tableBrowser.parent.browserContentPane.rows.size() == 1) { - cellRect.setBounds(cellRect.x, 0, cellRect.width, Math.min(cellRect.height, 20)); - ignoreScrolling = true; - } - } - - x2 = visParent.internalFrame.getX(); - y = cellRect.height * i; - // if (r2) { - x2 += visParent.internalFrame.getWidth() - BORDER; - // } else { - // x2 += BORDER; - // } - - p = visParent.browserContentPane.rowsTable; - pY = yPerRowTable2.get(p); - if (pY != null) { - y2 = pY; - } else { - y2 = visParent.internalFrame.getY(); - if (ignoreScrolling) { - p = p.getParent(); - } - while (p != visParent.internalFrame) { - y2 += p.getY(); - p = p.getParent(); - } - yPerRowTable2.put(visParent.browserContentPane.rowsTable, y2); - } - y2 += y + cellRect.height / 2; - min = visParent.internalFrame.getY() + cellRect.height; - if (y2 < min) { - y2 = min; - } - max = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() - BOT_H; - if (y2 > max) { - y2 = max; - } - } - - if (tableBrowser.parent != null && tableBrowser.parent.internalFrame.isVisible() && tableBrowser.internalFrame.isVisible()) { - long shift = 32768; - long start = (long) x2 + shift * (long) y2; - long end = (long) x1 + shift * (long) y1; - long lineHash = start + shift * shift * end; - if (linesHash.contains(lineHash)) { - rowToRowLink.visible = false; - continue; - } else { - linesHash.add(lineHash); - } - } - - if (x1 != rowToRowLink.x1 || y1 != rowToRowLink.y1 || x2 != rowToRowLink.x2 || y2 != rowToRowLink.y2) { - changed = true; - rowToRowLink.x1 = x1; - rowToRowLink.y1 = y1; - rowToRowLink.x2 = x2; - rowToRowLink.y2 = y2; - } - } catch (Exception e) { - // ignore - } - } - } - } - - if (!renderLinks) { - changed = true; - } - renderLinks = true; - long currentTimeMillis = System.currentTimeMillis(); - if (lastPTS + 100 < currentTimeMillis) { - changed = true; - } - if (changed) { - lastPTS = currentTimeMillis; - } - if (changed) { - rbSourceToLinks = null; - } - - animationStep = currentTimeMillis / (double) STEP_DELAY; - - if (lastAnimationStepTime + STEP_DELAY < currentTimeMillis) { - changed = true; - lastAnimationStepTime = currentTimeMillis; - } - return changed; - } - - private boolean isIconOrHidden(JInternalFrame internalFrame) { - return internalFrame.isIcon() || !internalFrame.isVisible(); - } - - private long lastPTS = 0; - - private static class Link { - public boolean visible = true; - public final RowBrowser from, to; - public final String sourceRowID, destRowID; - public int x1, y1, x2, y2; - public final Color color1; - public final Color color2; - public final boolean dotted, intersect; - public final boolean inClosure; - public final boolean restricted; - - public Link(RowBrowser from, RowBrowser to, String sourceRowID, String destRowID, int x1, int y1, int x2, int y2, Color color1, Color color2, boolean dotted, - boolean intersect, boolean inClosure, boolean restricted) { - this.from = from; - this.to = to; - this.sourceRowID = sourceRowID; - this.destRowID = destRowID; - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - this.color1 = restricted? color1.brighter() : color1; - this.color2 = restricted? color2.brighter() : color2; - this.dotted = dotted; - this.intersect = intersect; - this.inClosure = inClosure; - this.restricted = restricted; - } - }; - - private Map>> rbSourceToLinks = null; - private long paintDuration = 0; - - /** - * Paints all link-renders. - */ - @Override - public synchronized void paint(Graphics graphics) { - long startTime = System.currentTimeMillis(); - super.paint(graphics); - if (graphics instanceof Graphics2D) { - final Graphics2D g2d = (Graphics2D) graphics; - renderActiveIFrameMarker(g2d); - if (renderLinks) { - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - if (rbSourceToLinks == null) { - rbSourceToLinks = new HashMap>>(); - final String ALL = "-"; - - for (RowBrowser tableBrowser : tableBrowsers) { - Map> links = new TreeMap>(); - rbSourceToLinks.put(tableBrowser, links); - - Color color1 = tableBrowser.color1; - Color color2 = tableBrowser.color2; - boolean linkAdded = false; - boolean restricted = tableBrowser.parent != null && tableBrowser.browserContentPane.loadedRowsAreRestricted; - for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { - if (rowToRowLink.x1 >= 0) { - linkAdded = true; - if (rowToRowLink.visible) { - String sourceRowID = rowToRowLink.childRow.nonEmptyRowId; - String destRowID = rowToRowLink.parentRow.nonEmptyRowId; - boolean inClosure = false; - - if (tableBrowser.parent != null) { - if (rowsClosure.currentClosure.contains(new Pair(tableBrowser.browserContentPane, rowToRowLink.childRow))) { - if (rowsClosure.currentClosure.contains(new Pair(tableBrowser.parent.browserContentPane, rowToRowLink.parentRow))) { - inClosure = true; - } - } - } - - Link link = new Link(tableBrowser, tableBrowser.parent, sourceRowID, destRowID, rowToRowLink.x1, rowToRowLink.y1, - rowToRowLink.x2, rowToRowLink.y2, color1, color2, false, false, inClosure, restricted); - List l = links.get(sourceRowID); - if (l == null) { - l = new ArrayList(); - links.put(sourceRowID, l); - } - l.add(link); - } - } - } - if (tableBrowser.parent != null && !linkAdded) { - String sourceRowID = ALL; - String destRowID = ALL; - boolean inClosure = false; - - Link link = new Link(tableBrowser, tableBrowser.parent, sourceRowID, destRowID, tableBrowser.x1, tableBrowser.y1, - tableBrowser.x2, tableBrowser.y2, color1, color2, true, true, inClosure, restricted); - List l = links.get(sourceRowID); - if (l == null) { - l = new ArrayList(); - links.put(sourceRowID, l); - } - l.add(link); - } - } - - // join links of hidden browser - List toJoinList = new ArrayList(); - for (RowBrowser tableBrowser : tableBrowsers) { - if (tableBrowser.parent != null && tableBrowser.parent.isHidden()) { - List newLinks = new ArrayList(); - Map> links = rbSourceToLinks.get(tableBrowser); - for (Map.Entry> e : links.entrySet()) { - for (Link link : e.getValue()) { - link.visible = false; - - List ll; - if (link.destRowID == ALL) { - ll = new ArrayList(); - for (List values : rbSourceToLinks.get(link.to).values()) { - for (Link l : values) { - ll.add(l); - } - } - } else { - ll = rbSourceToLinks.get(link.to).get(link.destRowID); - } - - toJoinList.clear(); - if (ll != null) { - toJoinList.addAll(ll); - } - ll = rbSourceToLinks.get(link.to).get(ALL); - if (ll != null) { - toJoinList.addAll(ll); - } - - for (Link toJoin : toJoinList) { - toJoin.visible = false; - boolean intersect = link.intersect; - boolean dotted = link.dotted || toJoin.dotted; - newLinks.add(new Link(link.from, toJoin.to, link.sourceRowID, toJoin.destRowID, link.x1, link.y1, toJoin.x2, toJoin.y2, - Color.yellow.darker().darker(), Color.yellow.darker(), dotted, intersect, link.inClosure && toJoin.inClosure, link.restricted || toJoin.restricted)); - } - } - } - for (Link link : newLinks) { - links.get(link.sourceRowID).add(link); - } - } - } - } - - Set pathToSelectedRowBrowser = new HashSet(); - for (RowBrowser rb: getBrowsers()) { - if (rb.internalFrame.isSelected()) { - for (RowBrowser parent = rb; parent != null; parent = parent.parent) { - pathToSelectedRowBrowser.add(parent); - } - break; - } - } - - Set linesHash = new HashSet(20000); - Map> linksToRenderPerTableBrowser = new HashMap>(); - Map dirPerTableBrowser = new HashMap(); - - for (final RowBrowser tableBrowser : rbSourceToLinks.keySet()) { - if (!tableBrowser.isHidden()) { - Map> links = rbSourceToLinks.get(tableBrowser); - final List linksToRender = new ArrayList(1000); - int dir = 0; - for (Map.Entry> e : links.entrySet()) { - for (Link link : e.getValue()) { - if (link.visible && !link.from.isHidden() && !link.to.isHidden()) { - long shift = 32768; - long start = (long) link.x2 + shift * (long) link.y2; - long end = (long) link.x1 + shift * (long) link.y1; - long lineHash = start + shift * shift * end; - if (!linesHash.contains(lineHash)) { - linksToRender.add(link); - linesHash.add(lineHash); - if (link.y1 < link.y2) { - ++dir; - } else { - --dir; - } - } - } - } - } - - final boolean isToParentLink = tableBrowser.association != null && tableBrowser.association.isInsertDestinationBeforeSource(); - Collections.sort(linksToRender, new Comparator() { - @Override - public int compare(Link a, Link b) { - if (isToParentLink) { - if (a.y1 != b.y1) { - return a.y1 - b.y1; - } else { - return a.y2 - b.y2; - } - } else { - if (a.y2 != b.y2) { - return a.y2 - b.y2; - } else { - return a.y1 - b.y1; - } - } - } - }); - linksToRenderPerTableBrowser.put(tableBrowser, linksToRender); - dirPerTableBrowser.put(tableBrowser, dir); - } - } - - final int MAX_PRIO = 3; - for (int prio = 0; prio <= MAX_PRIO; ++prio) { - for (final boolean pbg : new Boolean[] { true, false }) { - for (final RowBrowser tableBrowser : rbSourceToLinks.keySet()) { - if (!tableBrowser.isHidden()) { - final boolean inClosureRootPath = rowsClosure.parentPath.contains(tableBrowser.browserContentPane); - boolean light = true; - final Map followMe; - final boolean isToParentLink = tableBrowser.association != null && tableBrowser.association.isInsertDestinationBeforeSource(); - if (!isToParentLink) { - followMe = new HashMap(); - } else { - followMe = null; - } - int lastY = -1; - int lastLastY = -1; - boolean lastInClosure = false; - Map> renderTasks = new HashMap>(); - final List linksToRender = linksToRenderPerTableBrowser.get(tableBrowser); - if (linksToRender == null) { - continue; - } - Integer dv = dirPerTableBrowser.get(tableBrowser); - int dir = dv == null? 0 : dv; - for (int i = 0; i < linksToRender.size(); ++i) { - final Link link = linksToRender.get(i); - int y = isToParentLink? link.y1 : link.y2; - if (lastInClosure != link.inClosure) { - light = !light; - } else if (lastY != y) { - if (lastLastY == lastY) { - light = !light; - } else { - if (i < linksToRender.size() - 1) { - int nextY = isToParentLink? linksToRender.get(i + 1).y1 : linksToRender.get(i + 1).y2; - if (nextY == y) { - light = !light; - } - } - } - } - lastLastY = lastY; - lastY = y; - lastInClosure = link.inClosure; - Color cl = pbg ? Color.white : light? link.color1 : link.color2; - if (!Environment.nimbus) { - if (cl.getGreen() > cl.getBlue() && cl.getGreen() > cl.getRed()) { - if (link.restricted) { - cl = cl.brighter(); - } - } else { - double f = link.restricted? 2.0 : 1.5; - cl = new Color( - brighter(cl.getRed(), f), - brighter(cl.getGreen(), f), - brighter(cl.getBlue(), f)); - } - } - final Color color = link.restricted && Environment.nimbus? cl.darker() : cl; - final Point2D start = new Point2D.Double(link.x2, link.y2); - final Point2D end = new Point2D.Double(link.x1, link.y1); - final int ir = dir > 0? i : linksToRender.size() - 1 - i; - final boolean finalLight = light; - int linkPrio = 0; - if (pathToSelectedRowBrowser != null && pathToSelectedRowBrowser.contains(tableBrowser)) { - linkPrio += 2; - } - if (link.inClosure) { - linkPrio += 1; - } - final boolean doPaint = linkPrio == prio; - Runnable task = new Runnable() { - @Override - public void run() { - paintLink(start, end, color, g2d, tableBrowser, pbg, link.intersect, - link.dotted, - linksToRender.size() == 1 ? 0.5 : (ir + 1) * 1.0 / linksToRender.size(), - finalLight, followMe, - link.sourceRowID, link.inClosure, inClosureRootPath, - isToParentLink, - doPaint); - } - }; - List tasks = renderTasks.get(link.sourceRowID); - if (tasks == null) { - tasks = new LinkedList(); - renderTasks.put(link.sourceRowID, tasks); - } - tasks.add(task); - } - for (Entry> entry: renderTasks.entrySet()) { - List tasks = entry.getValue(); - Runnable mid = tasks.get(tasks.size() / 2); - mid.run(); - for (Runnable task: tasks) { - if (task != mid) { - task.run(); - } - } - } - } - } - } - } - iFrameStateChangeRenderer.render(g2d); - } - } - paintDuration = System.currentTimeMillis() - startTime; - deferRescaleMode(startTime); - } - - private int brighter(int col, double f) { - if (col > 128) { - return Math.min((int) (col * f), 255); - } else { - return Math.max(255 - (int) ((255 - col) / f), 0); - } - } - - private void renderActiveIFrameMarker(Graphics2D g2d) { - for (RowBrowser tableBrowser : tableBrowsers) { - if (tableBrowser.internalFrame.isSelected() && !isIconOrHidden(tableBrowser.internalFrame)) { - int z = 20; - double alpha = (animationStep % z) / (double) z * 2 * Math.PI; - double f = Math.sin(alpha) / 2.0 + 0.5; - Color color = markerColor(f, z); - g2d.setColor(color); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - BasicStroke stroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); - g2d.setStroke(stroke); - final int W = 3; - int x1 = tableBrowser.internalFrame.getX() + W ; - int y1 = tableBrowser.internalFrame.getY() - 3; - int x2 = tableBrowser.internalFrame.getX() + tableBrowser.internalFrame.getWidth() - 2 * W; - int y2 = y1; - g2d.drawLine(x1, y1, x2, y2); - f = Math.sin(alpha + Math.PI / 2) / 2.0 + 0.5; - color = markerColor(f, z); - g2d.setColor(color); - stroke = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); - g2d.setStroke(stroke); - g2d.drawLine(x1 - 2, y1 + 2, x2 + 2, y2 + 2); - } - } - } - - private Color markerColor(double f, int z) { - Color c1 = new Color(240, 130, 80); - Color c2 = new Color(225, 240, 100); - int r = (int) (c1.getRed() + f * (c2.getRed() - c1.getRed())); - int g = (int) (c1.getGreen() + f * (c2.getGreen() - c1.getGreen())); - int b = (int) (c1.getBlue() + f * (c2.getBlue() - c1.getBlue())); - Color color = new Color(r, g, b, 240); - return color; - } - - private double animationStep = 0; - long lastAnimationStepTime = 0; - final long STEP_DELAY = 50; - - private void paintLink(Point2D start, Point2D end, Color color, Graphics2D g2d, RowBrowser tableBrowser, - boolean pbg, boolean intersect, boolean dotted, double midPos, boolean light, - Map followMe, String sourceRowID, boolean inClosure, boolean inClosureRootPath, - boolean isToParentLink, boolean doPaint) { - if (doPaint) { - g2d.setColor(color); - BasicStroke stroke = new BasicStroke((!intersect ? (pbg ? inClosure? 3 : 2 : 1) : (pbg ? 3 : 2))); - if (inClosure) { - final int LENGTH = 16; - g2d.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), new float[] { 11f, 5f }, - (float) ((inClosureRootPath ^ isToParentLink)? animationStep % LENGTH : (LENGTH - animationStep % LENGTH)))); - } else { - g2d.setStroke(dotted ? new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), new float[] { 2f, 6f }, - 1.0f) : stroke); - } - } - - // compute the intersection with the target bounding box - if (intersect) { - Point2D[] sect = new Point2D[10]; - int i = GraphicsLib.intersectLineRectangle(start, end, tableBrowser.internalFrame.getBounds(), sect); - if (i > 0) { - end = sect[0]; - } - } - if (start.distance(end) < 2) - return; - - double border = 0.25; - double f = midPos * (1.0 - 2.0 * border); - int midX = (int) (start.getX() + ((end.getX() - start.getX()) * (border + f))); - f = 0.25 * f * (end.getY() - start.getY()); - - if (followMe != null) { - java.awt.geom.Point2D.Double follow = followMe.get(sourceRowID); - if (follow != null) { - midX = (int) follow.getX(); - f = follow.getY(); - } else { - followMe.put(sourceRowID, new Point2D.Double(midX, f)); - } - } - - if (!doPaint) { - return; - } - - Path2D.Double path = new Path2D.Double(); - if (isToParentLink) { - path.moveTo(end.getX() - 5, end.getY()); - path.curveTo(midX, end.getY(), midX, start.getY() + f, start.getX(), start.getY()); - } else { - path.moveTo(start.getX(), start.getY()); - path.curveTo(midX, start.getY() + f, midX, end.getY(), end.getX() - 5, end.getY()); - } - g2d.draw(path); - - // create the arrow head shape - m_arrowHead = new Polygon(); - double ws = 0.4; - double hs = 2.0 / 3.0; - double w = 3, h = w; - m_arrowHead.addPoint(0, 0); - m_arrowHead.addPoint((int) (ws * -w), (int) (hs * (-h))); - // m_arrowHead.addPoint(0, (int) (hs * (-2 * h))); - m_arrowHead.addPoint((int) (ws * w), (int) (hs * (-h))); - m_arrowHead.addPoint(0, 0); - - AffineTransform at = getArrowTrans(new Point2D.Double(midX, end.getY()), end, 9); - Shape m_curArrow = at.createTransformedShape(m_arrowHead); - - g2d.setStroke(new BasicStroke(2)); - g2d.fill(m_curArrow); - if (pbg) { - g2d.draw(m_curArrow); - } - } - - private Polygon m_arrowHead; - - /** - * Returns an affine transformation that maps the arrowhead shape to the - * position and orientation specified by the provided line segment end - * points. - */ - protected AffineTransform getArrowTrans(Point2D p1, Point2D p2, double width) { - AffineTransform m_arrowTrans = new AffineTransform(); - int o = 1; - m_arrowTrans.setToTranslation(p2.getX() + o, p2.getY()); - m_arrowTrans.rotate(-Math.PI / 2.0 + Math.atan2(p2.getY() - p1.getY(), p2.getX() + o - p1.getX())); - if (width > 1) { - double scalar = width / 2; - m_arrowTrans.scale(scalar, scalar); - } - return m_arrowTrans; - } - - private static int FRAME_OFFSET = 20; - private MDIDesktopManager manager; - - @Override - public void setBounds(int x, int y, int w, int h) { - super.setBounds(x, y, w, h); - checkDesktopSize(); - } - - public Component add(JInternalFrame frame) { - JInternalFrame[] array = getAllFrames(); - Point p; - int w; - int h; - - Component retval = super.add(frame); - checkDesktopSize(); - if (array.length > 0) { - p = array[0].getLocation(); - p.x = p.x + FRAME_OFFSET; - p.y = p.y + FRAME_OFFSET; - } else { - p = new Point(0, 0); - } - frame.setLocation(p.x, p.y); - if (frame.isResizable()) { - w = getWidth() - (getWidth() / 3); - h = getHeight() - (getHeight() / 3); - if (w < frame.getMinimumSize().getWidth()) - w = (int) frame.getMinimumSize().getWidth(); - if (h < frame.getMinimumSize().getHeight()) - h = (int) frame.getMinimumSize().getHeight(); - frame.setSize(w, h); - } - moveToFront(frame); - frame.setVisible(true); - try { - frame.setSelected(true); - } catch (PropertyVetoException e) { - frame.toBack(); - } - - return retval; - } - - @Override - public void remove(Component c) { - super.remove(c); - checkDesktopSize(); - } - - /** - * Cascade all internal frames - */ - public void cascadeFrames() { - int x = 0; - int y = 0; - JInternalFrame allFrames[] = getAllFrames(); - - manager.setNormalSize(); - int frameHeight = (getBounds().height - 5) - allFrames.length * FRAME_OFFSET; - int frameWidth = (getBounds().width - 5) - allFrames.length * FRAME_OFFSET; - for (int i = allFrames.length - 1; i >= 0; i--) { - allFrames[i].setSize(frameWidth, frameHeight); - allFrames[i].setLocation(x, y); - x = x + FRAME_OFFSET; - y = y + FRAME_OFFSET; - } - } - - /** - * Tile all internal frames - */ - public void tileFrames() { - java.awt.Component allFrames[] = getAllFrames(); - manager.setNormalSize(); - int frameHeight = getBounds().height / allFrames.length; - int y = 0; - for (int i = 0; i < allFrames.length; i++) { - allFrames[i].setSize(getBounds().width, frameHeight); - allFrames[i].setLocation(0, y); - y = y + frameHeight; - } - } - - private Dimension currentDesktopnSize; - private Dimension postAnimationDesktopnSize; - - /** - * Sets all component size properties ( maximum, minimum, preferred) to the - * given dimension. - */ - public boolean setAllSize(Dimension d) { - if (currentDesktopnSize != null && currentDesktopnSize.equals(d)) { - return false; - } - currentDesktopnSize = d; - setMinimumSize(d); - setMaximumSize(d); - setPreferredSize(d); - return true; - } - - /** - * Sets all component size properties ( maximum, minimum, preferred) to the - * given width and height. - */ - public boolean setAllSize(int width, int height) { - return setAllSize(new Dimension(width, height)); - } - - void checkDesktopSize() { - if (getParent() != null && isVisible()) - manager.resizeDesktop(); - } - - public JScrollPane getScrollPane() { - if (getParent() instanceof JViewport) { - JViewport viewPort = (JViewport) getParent(); - if (viewPort.getParent() instanceof JScrollPane) - return (JScrollPane) viewPort.getParent(); - } - return null; - } - - /** - * Private class used to replace the standard DesktopManager for - * JDesktopPane. Used to provide scrollbar functionality. - */ - class MDIDesktopManager extends DefaultDesktopManager { - private Desktop desktop; - - public MDIDesktopManager(Desktop desktop) { - this.desktop = desktop; - } - - @Override - public void endResizingFrame(JComponent f) { - super.endResizingFrame(f); - resizeDesktop(); - } - - @Override - public void endDraggingFrame(JComponent f) { - super.endDraggingFrame(f); - resizeDesktop(); - } - - public void setNormalSize() { - JScrollPane scrollPane = getScrollPane(); - int x = 0; - int y = 0; - Insets scrollInsets = getScrollPaneInsets(); - - if (scrollPane != null) { - Dimension d = scrollPane.getVisibleRect().getSize(); - if (scrollPane.getBorder() != null) { - d.setSize(d.getWidth() - scrollInsets.left - scrollInsets.right, d.getHeight() - scrollInsets.top - scrollInsets.bottom); - } - - d.setSize(d.getWidth() - 20, d.getHeight() - 20); - desktop.setAllSize(x, y); - scrollPane.invalidate(); - scrollPane.validate(); - } - } - - private Insets getScrollPaneInsets() { - JScrollPane scrollPane = getScrollPane(); - if (scrollPane == null) - return new Insets(0, 0, 0, 0); - else - return getScrollPane().getBorder().getBorderInsets(scrollPane); - } - - private JScrollPane getScrollPane() { - if (desktop.getParent() instanceof JViewport) { - JViewport viewPort = (JViewport) desktop.getParent(); - if (viewPort.getParent() instanceof JScrollPane) - return (JScrollPane) viewPort.getParent(); - } - return null; - } - - public void resizeDesktop() { - int x = 0; - int y = 0; - int paX = 0; - int paY = 0; - JScrollPane scrollPane = getScrollPane(); - Insets scrollInsets = getScrollPaneInsets(); - - if (scrollPane != null) { - boolean isMaximized = false; - JInternalFrame allFrames[] = desktop.getAllFrames(); - for (int i = 0; i < allFrames.length; i++) { - if (allFrames[i].isVisible()) { - if (allFrames[i].isMaximum()) { - isMaximized = true; - } - Rectangle bounds = allFrames[i].getBounds(); - if (bounds.getX() + bounds.getWidth() > x) { - x = (int) (bounds.getX() + bounds.getWidth()); - } - if (bounds.getY() + bounds.getHeight() > y) { - y = (int) (bounds.getY() + bounds.getHeight()); - } - if (bounds.getX() + bounds.getWidth() > paX) { - paX = (int) (bounds.getX() + bounds.getWidth()); - } - if (bounds.getY() + bounds.getHeight() > paY) { - paY = (int) (bounds.getY() + bounds.getHeight()); - } - bounds = desktopAnimation.getIFrameBounds(allFrames[i]); - if (bounds.getX() + bounds.getWidth() > paX) { - paX = (int) (bounds.getX() + bounds.getWidth()); - } - if (bounds.getY() + bounds.getHeight() > paY) { - paY = (int) (bounds.getY() + bounds.getHeight()); - } - } - } - Dimension d = scrollPane.getVisibleRect().getSize(); - if (scrollPane.getBorder() != null) { - d.setSize(d.getWidth() - scrollInsets.left - scrollInsets.right, d.getHeight() - scrollInsets.top - scrollInsets.bottom); - } - - if (x <= d.getWidth() || isMaximized) - x = ((int) d.getWidth()) - 20; - if (y <= d.getHeight() || isMaximized) - y = ((int) d.getHeight()) - 20; - postAnimationDesktopnSize = new Dimension(Math.max(paX, x), Math.max(paY, y)); - if (desktop.setAllSize(x, y) && !desktopAnimation.isActive()) { - scrollPane.invalidate(); - scrollPane.validate(); - } - } - } - } - - public synchronized void stop() { - running = false; - desktops.remove(this); - for (RowBrowser rb : tableBrowsers) { - rb.browserContentPane.cancelLoadJob(false); - } - if (session != null) { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - synchronized (session) { - session.shutDown(); - } - } - }); - thread.setDaemon(true); - thread.start(); - } - } - - private final DataBrowser parentFrame; - - public static enum LayoutMode { - THUMBNAIL(0.22), - TINY(0.57), - L2(0.66), - SMALL(0.75), - L3(0.87), - MEDIUM(1.0), - L6(1.13), - L7(1.26), - LARGE(1.4); - - public final double factor; - - private LayoutMode(double factor) { - this.factor = factor; - } - } - - LayoutMode layoutMode = LayoutMode.MEDIUM; - - private boolean layouting = false; - - public void layoutBrowser(JInternalFrame selectedFrame, boolean scrollToCenter, RowBrowser anchor) { - if (layouting) { - return; - } - - try { - layouting = true; - if (selectedFrame == null) { - selectedFrame = getSelectedFrame(); - } - List all = new ArrayList(tableBrowsers); - // layout(all, 0); - - optimizeLayout(anchor); - - all.clear(); - int maxH = 0; - for (RowBrowser rb : tableBrowsers) { - if (rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable) { - all.add(rb); - } else { - maxH = Math.max(maxH, rb.internalFrame.getBounds().y + rb.internalFrame.getBounds().height); - } - } - layout(all, maxH + (int) (16 * layoutMode.factor)); - - checkDesktopSize(); - if (selectedFrame != null) { - try { - selectedFrame.setSelected(true); - } catch (PropertyVetoException e) { - // ignore - } - if (scrollToCenter) { - this.scrollToCenter(selectedFrame); - } - } - } finally { - layouting = false; - } - } - - private void layout(List toLayout, int maxH) { - List roots = new ArrayList(); - for (RowBrowser rb : toLayout) { - if (rb.parent == null) { - roots.add(rb); - } - } - while (!roots.isEmpty()) { - List nextColumn = new ArrayList(); - int i = 0; - for (RowBrowser rb : roots) { - try { - rb.internalFrame.setMaximum(false); - } catch (PropertyVetoException e) { - // ignore - } - int xPosition = -1; - if (maxH > 0) { - xPosition = i; - } - rb.internalFrame.setBounds(layout(rb.parent, rb.association, rb.browserContentPane, toLayout, maxH, xPosition)); - rb.browserContentPane.adjustRowTableColumnsWidth(); - toLayout.remove(rb); - for (RowBrowser rbc : toLayout) { - if (rbc.parent == rb) { - nextColumn.add(rbc); - } - } - ++i; - } - roots = nextColumn; - } - } - - /** - * Experimental layout optimization. - * @param anchor - */ - private void optimizeLayout(RowBrowser anchor) { - Set anchors = new HashSet(); - while (anchor != null) { - anchors.add(anchor); - anchor = anchor.parent; - } - TreeLayoutOptimizer.Node root = new TreeLayoutOptimizer.Node(null, false); - collectChildren(root, anchors); - TreeLayoutOptimizer.optimizeTreeLayout(root); - arrangeNodes(root); - } - - private void collectChildren(Node root, Set anchors) { - List children; - if (root.getUserObject() == null) { - children = getRootBrowsers(true); - } else { - children = getChildBrowsers(root.getUserObject(), true); - } - for (RowBrowser rb : children) { - if (rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable) { - continue; - } - TreeLayoutOptimizer.Node childNode = new TreeLayoutOptimizer.Node(rb, anchors.contains(rb)); - root.addChild(childNode); - collectChildren(childNode, anchors); - } - } - - private void arrangeNodes(Node root) { - if (root.getUserObject() != null) { - JInternalFrame iFrame = root.getUserObject().internalFrame; - int x = (int) (BROWSERTABLE_DEFAULT_MIN_X * layoutMode.factor); - int y = (int) (BROWSERTABLE_DEFAULT_MIN_Y * layoutMode.factor); - x += (root.getLevel() - 1) * (int) ((BROWSERTABLE_DEFAULT_WIDTH + BROWSERTABLE_DEFAULT_DISTANCE) * layoutMode.factor); - y += (int) (root.getPosition() * (BROWSERTABLE_DEFAULT_HEIGHT + 8) * layoutMode.factor); - int h = (int) (BROWSERTABLE_DEFAULT_HEIGHT * layoutMode.factor); - Rectangle r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); - // iFrame.setBounds(r); - desktopAnimation.setIFrameBounds(iFrame, root.getUserObject().browserContentPane, r, false); - } - for (Node child : root.getChildren()) { - arrangeNodes(child); - } - } - - private Map precBounds = new HashMap(); - - private static Collection desktops = new ArrayList(); - - public void rescaleLayout(LayoutMode layoutMode, Point fixed) { - double scale = layoutMode.factor / this.layoutMode.factor; - - if (fixed == null) { - fixed = new Point(getVisibleRect().x + getVisibleRect().width / 2, getVisibleRect().y + getVisibleRect().height / 2); - } - - try { - UIUtil.setWaitCursor(this); - this.layoutMode = layoutMode; - Map newPrecBounds = new HashMap(); - for (RowBrowser rb : new ArrayList(tableBrowsers)) { - if (rb.internalFrame.isMaximum()) { - try { - rb.internalFrame.setMaximum(false); - } catch (PropertyVetoException e) { - // ignore - } - } - Rectangle bounds = desktopAnimation.getIFrameBounds(rb.internalFrame); - Rectangle newBounds; - double[] pBounds = precBounds.get(bounds); - if (pBounds == null) { - pBounds = new double[] { bounds.x * scale, bounds.y * scale, bounds.width * scale, bounds.height * scale }; - } else { - pBounds = new double[] { pBounds[0] * scale, pBounds[1] * scale, pBounds[2] * scale, pBounds[3] * scale }; - } - newBounds = new Rectangle((int) pBounds[0], (int) pBounds[1], (int) pBounds[2], (int) pBounds[3]); - desktopAnimation.setIFrameBounds(rb.internalFrame, rb.browserContentPane, newBounds, true); - rb.browserContentPane.sortColumnsPanel.setVisible(LayoutMode.SMALL.factor <= layoutMode.factor); - newPrecBounds.put(newBounds, pBounds); - } - precBounds = newPrecBounds; - manager.resizeDesktop(); - - Rectangle vr = new Rectangle(Math.max(0, (int) (fixed.x * scale - getVisibleRect().width / 2)), Math.max(0, - (int) (fixed.y * scale - getVisibleRect().height / 2)), getVisibleRect().width, getVisibleRect().height); - desktopAnimation.scrollRectToVisible(vr, true); - updateMenu(layoutMode); - adjustClosure(null, null); - } finally { - UIUtil.resetWaitCursor(this); - } - } - - void onMouseWheelMoved(java.awt.event.MouseWheelEvent e, JScrollPane scrollPane, long currentTime) { - if (!inRescaleMode(currentTime)) { - if ((e.getScrollAmount() != 0) && (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)) { - JScrollBar toScroll = scrollPane.getVerticalScrollBar(); - int direction = 0; - - // find which scrollbar to scroll, or return if none - if ((toScroll == null) || !toScroll.isVisible() || ((e.getModifiers() & InputEvent.ALT_MASK) != 0)) { - toScroll = scrollPane.getHorizontalScrollBar(); - - if ((toScroll == null) || !toScroll.isVisible()) { - return; - } - } - - if (e.getWheelRotation() != 0) { - direction = (e.getWheelRotation() < 0) ? (-1) : 1; - } - - double f = 1.0; - - double pwr = e.getPreciseWheelRotation(); - if (pwr != 0.0) { - direction = pwr == 0? 0 : (pwr < 0) ? (-1) : 1; - f = Math.abs(pwr); - } - - if (direction != 0) { - int oldValue = toScroll.getValue(); - int blockIncrement = toScroll.getUnitIncrement(direction); - // allow for partial page overlapping - // blockIncrement -= 10; - int delta = (int) (f * blockIncrement * ((direction > 0) ? +1 : -1)); - int newValue = oldValue + delta; - - // Check for overflow. - if ((delta > 0) && (newValue < oldValue)) { - newValue = toScroll.getMaximum(); - } else if ((delta < 0) && (newValue > oldValue)) { - newValue = toScroll.getMinimum(); - } - - toScroll.setValue(newValue); - } - } - } - } - - void onMouseWheelMoved(java.awt.event.MouseWheelEvent e, long currentTime) { - if (inRescaleMode(currentTime)) { - int d = 0; - if (e.getWheelRotation() < 0) { - d = 1; - } - if (e.getWheelRotation() > 0) { - d = -1; - } - if (d != 0) { - for (RowBrowser rb : new ArrayList(tableBrowsers)) { - if (rb.internalFrame.isMaximum()) { - return; - } - } - d += layoutMode.ordinal(); - if (d >= 0 && d < LayoutMode.values().length) { - Point fixed = SwingUtilities.convertPoint(e.getComponent(), e.getPoint().x, e.getPoint().y, Desktop.this); - rescaleLayout(LayoutMode.values()[d], fixed); - rescaleFactorHasChanged = true; - } - } - } - } - - public void closeAll() { - closeAll(new ArrayList(tableBrowsers)); - } - - public void closeAll(Collection toClose) { - for (RowBrowser rb : toClose) { - close(rb, toClose.size() == 1); - // getDesktopManager().closeFrame(rb.internalFrame); - rb.internalFrame.dispose(); - } - updateMenu(); - } - - private void close(final RowBrowser tableBrowser, boolean convertChildrenToRoots) { - List children = new ArrayList(); - for (RowBrowser tb : tableBrowsers) { - if (tb.parent == tableBrowser) { - tb.parent = null; - children.add(tb); - } - } - tableBrowsers.remove(tableBrowser); - tableBrowser.browserContentPane.cancelLoadJob(true); - if (convertChildrenToRoots) { - for (RowBrowser child : children) { - child.convertToRoot(); - } - } - for (RowBrowser rb : tableBrowsers) { - updateChildren(rb, rb.browserContentPane.rows); - } - repaintDesktop(); - updateMenu(); - } - - /** - * Reloads the data model and replaces the tables in all browser windows. - */ - public void reloadDataModel(Map schemamapping) throws Exception { - reloadDataModel(schemamapping, true); - } - - /** - * Reloads the data model and replaces the tables in all browser windows. - */ - public void reloadDataModel(Map schemamapping, boolean forAll) throws Exception { - if (forAll) { - for (Desktop desktop : desktops) { - if (desktop != this) { - desktop.reloadDataModel(desktop.schemaMapping, false); - } - } - } - - try { - Component pFrame = SwingUtilities.getWindowAncestor(this); - if (pFrame == null) { - pFrame = this; - } - String filename = Environment.newFile(".tempsession-" + System.currentTimeMillis()).getPath(); - storeSession(filename); - - DataModel newModel = new DataModel(schemamapping, executionContext, false); - datamodel.set(newModel); - UISettings.dmStats(newModel); - - onNewDataModel(); - - restoreSession(null, pFrame, filename); - File file = new File(filename); - file.delete(); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } - } - - /** - * Reloads the rows in all root-table-browsers. - */ - public void reloadRoots() throws Exception { - for (RowBrowser rb : tableBrowsers) { - if (rb.browserContentPane != null) { - if (rb.parent == null) { - rb.browserContentPane.reloadRows(); - } - } - } - } - - private boolean loadSchemaMapping = true; - - public abstract void openSchemaAnalyzer(); - public abstract void onNewDataModel(); - public abstract void onLayoutChanged(boolean isLayouted, boolean scrollToCenter); - public abstract void updateBookmarksMenu(); - - public void openSchemaMappingDialog(boolean silent) { - try { - Map mapping = schemaMapping; - if (loadSchemaMapping || silent) { - mapping = SchemaMappingDialog.restore(dbConnectionDialog); - loadSchemaMapping = false; - } - if (!silent) { - SchemaMappingDialog schemaMappingDialog = new SchemaMappingDialog(parentFrame, datamodel.get(), dbConnectionDialog, session, mapping, executionContext); - mapping = schemaMappingDialog.getMapping(); - } - if (mapping != null && !mapping.isEmpty()) { - SchemaMappingDialog.store(mapping, dbConnectionDialog); - schemaMapping.clear(); - schemaMapping.putAll(mapping); - parentFrame.updateStatusBar(); - reloadDataModel(mapping, !silent); - reloadRoots(); - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e, session); - } - } - - /** - * Lets user chose a table browser and creates an extraction model for it. - */ - public void createExtractionModel(boolean doExport) { - Set titles = new TreeSet(); - Map rowBrowserByTitle = new HashMap(); - for (RowBrowser rb : tableBrowsers) { - if (rb.browserContentPane.table != null && !(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { - titles.add(rb.internalFrame.getTitle()); - rowBrowserByTitle.put(rb.internalFrame.getTitle(), rb); - } - } - String s = (String) JOptionPane.showInputDialog(this.parentFrame, "Select subject table", "Subject", JOptionPane.QUESTION_MESSAGE, null, - titles.toArray(), null); - if (s != null) { - rowBrowserByTitle.get(s).browserContentPane.openExtractionModelEditor(doExport); - } - } - - private AtomicBoolean updateMenuPending = new AtomicBoolean(false); - - void updateMenu() { - if (updateMenuPending.get()) { - return; - } - UIUtil.invokeLater(1, new Runnable() { - @Override - public void run() { - updateMenuPending.set(false); - - boolean hasTableBrowser = false; - boolean hasIFrame = false; - - for (RowBrowser rb : tableBrowsers) { - hasIFrame = true; - if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { - hasTableBrowser = true; - } - } - updateMenu(hasTableBrowser, hasIFrame); - } - }); - updateMenuPending.set(true); - } - - protected void updateMenu(boolean hasTableBrowser, boolean hasIFrame) { - if (!hasIFrame) { - if (!hasTableBrowser) { - currentSessionFileName = null; - } - } - } - - protected abstract void updateMenu(LayoutMode layoutMode); - - private final String LF = System.getProperty("line.separator", "\n"); - private String currentSessionFileName = null; - - /** - * Stores browser session. - */ - public void storeSession(BookmarksPanel bookmarksPanel) { - String fnProp = null; - int propLen = 0; - final String INVALID_CHARS = "[:;\\*\\?<>'`\"/\\\\\\~]+"; - for (RowBrowser rb : tableBrowsers) { - if (rb.browserContentPane.table != null) { - if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { - int l = 1; - RowBrowser parent; - for (parent = rb; parent.parent != null; parent = parent.parent) { - ++l; - } - String prop = datamodel.get().getDisplayName(parent.browserContentPane.table).replaceAll(INVALID_CHARS, " ").trim(); - if (parent != rb) { - prop += " - " + datamodel.get().getDisplayName(rb.browserContentPane.table).replaceAll(INVALID_CHARS, " ").trim(); - } - if (l > propLen || fnProp == null || l == propLen && fnProp.compareTo(prop) < 0) { - fnProp = prop; - propLen = l; - } - } - } - } - - if (fnProp != null && bookmarksPanel == null) { - fnProp += ".dbl"; - } - - if (bookmarksPanel == null) { - if (currentSessionFileName != null) { - fnProp = currentSessionFileName; - } - } - - String sFile; - - if (bookmarksPanel != null) { - File startDir = BookmarksPanel.getBookmarksFolder(executionContext); - sFile = bookmarksPanel.newBookmark(fnProp); - if (sFile != null) { - File f = new File(startDir, sFile + ".dbl"); - startDir.mkdirs(); - sFile = f.getAbsolutePath(); - } - } else { - File startDir = Environment.newFile("layout"); - Component pFrame = SwingUtilities.getWindowAncestor(this); - if (pFrame == null) { - pFrame = this; - } - sFile = UIUtil.choseFile(fnProp == null ? null : new File(startDir, fnProp), startDir.getPath(), "Store Layout", ".dbl", pFrame, true, false); - } - - if (sFile != null) { - try { - storeSession(sFile); - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } - if (bookmarksPanel == null) { - currentSessionFileName = sFile; - } else { - if (sFile != null && new File(sFile).exists()) { - new File(sFile).setLastModified(System.currentTimeMillis()); - } - bookmarksPanel.updateBookmarksMenu(); - updateAllBookmarkMenues(); - } - } - } - - public void updateAllBookmarkMenues() { - for (Desktop dTop: desktops) { - dTop.updateBookmarksMenu(); - } - } - - /** - * Stores browser session. - */ - void storeSession(String sFile) throws IOException { - int i = 1; - Map browserNumber = new HashMap(); - for (RowBrowser rb : tableBrowsers) { - browserNumber.put(rb, i++); - } - - FileWriter out = new FileWriter(new File(sFile)); - - out.write("Layout; " + layoutMode + LF); - - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == null) { - storeSession(rb, browserNumber, out); - } - } - out.close(); - } - - /** - * Recursively stores row-browser session. - */ - private void storeSession(RowBrowser rb, Map browserNumber, FileWriter out) throws IOException { - if (rb.browserContentPane.table != null) { - String csv = browserNumber.get(rb) + "; " + (rb.parent == null ? "" : browserNumber.get(rb.parent)) + "; "; - - String where = rb.browserContentPane.getAndConditionText().trim(); - - csv += CsvFile.encodeCell(where) + "; "; - - csv += rb.internalFrame.getLocation().x + "; " + rb.internalFrame.getLocation().y + "; "; - csv += rb.internalFrame.getSize().width + "; " + rb.internalFrame.getSize().height + "; "; - csv += 500 + "; " + rb.browserContentPane.selectDistinctCheckBox.isSelected() + "; "; - - if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { - csv += "T; " + CsvFile.encodeCell(rb.browserContentPane.table.getOriginalName()) + "; " - + (rb.association == null ? "" : CsvFile.encodeCell(rb.association.getName())) + "; "; - } - csv += rb.isHidden() + "; "; - csv += rb.browserContentPane.ignoreSortKey? "" : serializedSortKey(rb.browserContentPane.rowsTable); - out.append(csv).append(LF); - for (RowBrowser child : tableBrowsers) { - if (child.parent == rb) { - storeSession(child, browserNumber, out); - } - } - } - } - - private String serializedSortKey(JTable jTable) { - if (jTable != null) { - try { - List sortKeys = jTable.getRowSorter().getSortKeys(); - StringBuilder sb = new StringBuilder(); - for (SortKey sortKey: sortKeys) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(sortKey.getColumn() + "|" + sortKey.getSortOrder()); - } - return sb.toString(); - } catch (Exception e) { - return null; // sort keys are lost - } - } - return null; - } - - private void deserializedSortKey(JTable jTable, String externaliuedSortKey) { - if (jTable != null && externaliuedSortKey != null && !externaliuedSortKey.trim().isEmpty()) { - try { - List sortKeys = new ArrayList(); - for (String externalizedKey: externaliuedSortKey.trim().split(",")) { - String[] columnOrder = externalizedKey.trim().split("\\|"); - if (columnOrder.length == 2) { - sortKeys.add(new SortKey(Integer.parseInt(columnOrder[0]), SortOrder.valueOf(columnOrder[1]))); - } - } - if (!sortKeys.isEmpty()) { - jTable.getRowSorter().setSortKeys(sortKeys); - } - } catch (Exception e) { - // ignore - } - } - } - - /** - * Restores browser session. - * @param bookMarkFile - */ - public void restoreSession(RowBrowser toBeAppended, File bookMarkFile) { - File startDir = Environment.newFile("layout"); - Component pFrame = SwingUtilities.getWindowAncestor(this); - if (pFrame == null) { - pFrame = this; - } - String sFile = bookMarkFile != null? bookMarkFile.getAbsolutePath() : UIUtil.choseFile(null, startDir.getPath(), toBeAppended == null ? "Restore Layout" : "Append Layout", ".dbl", pFrame, true, true); - - if (sFile != null) { - try { - UIUtil.setWaitCursor(pFrame); - noArrangeLayoutOnNewTableBrowser = true; - restoreSession(toBeAppended, pFrame, sFile); - if (toBeAppended == null) { - currentSessionFileName = sFile; - } - } catch (Throwable e) { - UIUtil.showException(this, "Error", e, session); - } finally { - noArrangeLayoutOnNewTableBrowser = false; - UIUtil.resetWaitCursor(pFrame); - } - } - } - - /** - * Restores browser session. - */ - private void restoreSession(RowBrowser toBeAppended, Component pFrame, String sFile) throws Exception { - try { - UIUtil.setWaitCursor(pFrame); - iFrameStateChangeRenderer.startAtomic(); - noArrangeLayoutOnNewTableBrowser = true; - - String tbaPeerID = null; - Map rbByID = new HashMap(); - List lines = new CsvFile(new File(sFile)).getLines(); - if (toBeAppended == null) { - closeAll(); - } - Collection toBeLoaded = new ArrayList(); - List unknownTables = new ArrayList(); - KnownIdentifierMap knownTablesMap = new KnownIdentifierMap(); - Map originalNameToTable = new HashMap(); - for (Table table: datamodel.get().getTables()) { - knownTablesMap.putTableName(table.getOriginalName()); - originalNameToTable.put(table.getOriginalName(), table); - } - for (CsvFile.Line l : lines) { - if (l.cells.get(0).equals("Layout")) { - try { - if (toBeAppended == null) { - layoutMode = LayoutMode.valueOf(l.cells.get(1)); - updateMenu(layoutMode); - } - } catch (Exception e) { - e.printStackTrace(); - } - continue; - } - - String id = l.cells.get(0); - String parent = l.cells.get(1); - String where = l.cells.get(2); - Point loc = new Point(Integer.parseInt(l.cells.get(3)), Integer.parseInt(l.cells.get(4))); - Dimension size = new Dimension(Integer.parseInt(l.cells.get(5)), Integer.parseInt(l.cells.get(6))); - boolean selectDistinct = Boolean.parseBoolean(l.cells.get(8)); - RowBrowser rb = null; - if ("T".equals(l.cells.get(9))) { - Table table = originalNameToTable.get(l.cells.get(10)); - if (table == null) { - String kt = knownTablesMap.getTableName(l.cells.get(10)); - if (kt != null) { - table = originalNameToTable.get(kt); - } - } - if (table == null) { - unknownTables.add(l.cells.get(10)); - } else { - Association association = datamodel.get().namedAssociations.get(l.cells.get(11)); - RowBrowser parentRB = rbByID.get(parent); - if (association == null) { - parentRB = null; - } - boolean add = true; - if (toBeAppended != null) { - if (tbaPeerID == null) { - add = false; - if (parent.trim().length() == 0 && table.equals(toBeAppended.browserContentPane.table)) { - tbaPeerID = id; - } - } else { - if (tbaPeerID.equals(parent)) { - parentRB = toBeAppended; - } else if (!rbByID.containsKey(parent)) { - add = false; - } - } - } - if (add) { - rb = addTableBrowser(parentRB, parentRB, table, parentRB != null ? association : null, where, selectDistinct, null, false); - if (id.length() > 0) { - rbByID.put(id, rb); - } - if (parentRB == null || parentRB == toBeAppended) { - toBeLoaded.add(rb); - } - } - } - } else { - if (toBeAppended == null) { - rb = addTableBrowser(null, null, null, null, where, selectDistinct, null, false); - toBeLoaded.add(rb); - } - } - if (rb != null) { - rb.setHidden(Boolean.parseBoolean(l.cells.get(12))); - if (toBeAppended == null) { - rb.internalFrame.setLocation(loc); - rb.internalFrame.setSize(size); - } - deserializedSortKey(rb.browserContentPane.rowsTable, l.cells.get(13)); - } - } - checkDesktopSize(); - makePrimaryRootVisible(); - - for (RowBrowser rb : toBeLoaded) { - rb.browserContentPane.reloadRows(); - } - - if (toBeAppended != null && toBeLoaded.isEmpty()) { - JOptionPane.showMessageDialog(pFrame, - "Layout doesn't contain table \"" + datamodel.get().getDisplayName(toBeAppended.browserContentPane.table) + "\" as root."); - } else if (!unknownTables.isEmpty()) { - String pList = ""; - for (String ut : unknownTables) { - pList += ut + "\n"; - } - JOptionPane.showMessageDialog(pFrame, "Unknown tables:\n\n" + pList + "\n"); - } - } finally { - noArrangeLayoutOnNewTableBrowser = false; - iFrameStateChangeRenderer.rollbackAtomic(); - UIUtil.resetWaitCursor(pFrame); - } - } - - private void makePrimaryRootVisible() { - RowBrowser root = null; - for (RowBrowser rb : getRootBrowsers(true)) { - if (rb.browserContentPane.table != null) { - if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { - root = rb; - break; - } - } - } - if (root != null) { - try { - root.internalFrame.setSelected(true); - } catch (PropertyVetoException e) { - // ignore - } - this.scrollToCenter(root.internalFrame); - } else { - this.desktopAnimation.scrollRectToVisible(new Rectangle(0, 0, 1, 1), false); - } - } - - public JInternalFrame[] getAllFramesFromTableBrowsers() { - List frames = new ArrayList(); - for (RowBrowser rb : tableBrowsers) { - frames.add(rb.internalFrame); - } - return frames.toArray(new JInternalFrame[frames.size()]); - } - - public List getRootBrowsers(boolean ignoreHidden) { - List roots = new ArrayList(); - - if (ignoreHidden) { - for (RowBrowser rb : tableBrowsers) { - if (!rb.isHidden()) { - RowBrowser p = rb.parent; - while (p != null && p.isHidden()) { - p = p.parent; - } - if (p == null) { - roots.add(rb); - } - } - } - } else { - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == null) { - roots.add(rb); - } - } - } - return roots; - } - - public List getBrowsers() { - return new ArrayList(tableBrowsers); - } - - public List getChildBrowsers(RowBrowser parent, boolean ignoreHidden) { - List roots = new ArrayList(); - - if (ignoreHidden) { - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == parent) { - if (rb.isHidden()) { - roots.addAll(getChildBrowsers(rb, true)); - } else { - roots.add(rb); - } - } - } - } else { - for (RowBrowser rb : tableBrowsers) { - if (rb.parent == parent) { - roots.add(rb); - } - } - } - return roots; - } - - public static Boolean forceAdjustRows = false; - - /** - * Adjusts scroll-position of each table browser s.t. rows in closure are - * visible. - * - * @param tabu don't adjust this one - * @param thisOne only adjust this one if it is not null - */ - protected synchronized void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { - if (forceAdjustRows == null) { - return; - } - for (RowBrowser rb : tableBrowsers) { - if (rb.browserContentPane == tabu) { - continue; - } - if (thisOne != null && rb.browserContentPane != thisOne) { - continue; - } - - Set rowsOfParent = new HashSet(); - if (rb.parent != null) { - for (Pair r : rowsClosure.currentClosure) { - if (r.a == rb.parent.browserContentPane) { - rowsOfParent.add(r.b); - } - } - } - - List rowsOfRB = new ArrayList(); - Set rowsOfRBSet = new LinkedHashSet(); - for (RowToRowLink link: rb.rowToRowLinks) { - if (rowsOfParent.contains(link.parentRow)) { - rowsOfRBSet.add(link.childRow); - } - } - for (Pair r : rowsClosure.currentClosure) { - if (r.a == rb.browserContentPane) { - if (rowsOfRBSet.isEmpty() || rowsOfRBSet.contains(r.b)) { - rowsOfRB.add(r.b); - } - } - } - - int topBorder = -1; - if (rb.parent != null) { - Rectangle firstParentRowPos = null; - for (Row r : rowsOfParent) { - int index = rb.parent.browserContentPane.rows.indexOf(r); - if (index < 0) { - for (int n = 0; n < rb.parent.browserContentPane.rows.size(); ++n) { - if (r.nonEmptyRowId.equals(rb.parent.browserContentPane.rows.get(n).nonEmptyRowId)) { - index = n; - break; - } - } - } - - if (index < 0) { - // not visible due to distinct selection - continue; - } - index = rb.parent.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(index); - Rectangle pos = rb.parent.browserContentPane.rowsTable.getCellRect(index, 0, false); - - if (firstParentRowPos == null || firstParentRowPos.y > pos.y) { - firstParentRowPos = pos; - } - } - if (firstParentRowPos != null) { - Rectangle visibleRect = rb.parent.browserContentPane.rowsTable.getVisibleRect(); - if (!(firstParentRowPos.y > visibleRect.getMaxY() || firstParentRowPos.y < visibleRect.getMinY())) { - topBorder = (int) (firstParentRowPos.y - visibleRect.getMinY()); - } - } - } - - if (!rowsOfRB.isEmpty()) { - Rectangle firstRowPos = null; - Rectangle lastRowPos = null; - Rectangle visibleRect = rb.browserContentPane.rowsTable.getVisibleRect(); - for (Row r : rowsOfRB) { - int index = rb.browserContentPane.rows.indexOf(r); - if (index < 0) { - for (int n = 0; n < rb.browserContentPane.rows.size(); ++n) { - if (r.nonEmptyRowId.equals(rb.browserContentPane.rows.get(n).nonEmptyRowId)) { - index = n; - break; - } - } - } - - if (index < 0) { - // not visible due to distinct selection - continue; - } - index = rb.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(index); - Rectangle pos = rb.browserContentPane.rowsTable.getCellRect(index, 0, false); - - if (!forceAdjustRows && pos.y >= visibleRect.y && pos.y + pos.height < visibleRect.y + visibleRect.height) { - // already a visible row - firstRowPos = null; - lastRowPos = null; - break; - } - if (firstRowPos == null || firstRowPos.y > pos.y) { - firstRowPos = pos; - } - if (lastRowPos == null || lastRowPos.y < pos.y) { - lastRowPos = pos; - } - } - if (lastRowPos != null && firstRowPos != null && rb.browserContentPane.rowsTable.getRowCount() > 0) { - lastRowPos = rb.browserContentPane.rowsTable.getCellRect(rb.browserContentPane.rowsTable.getRowCount(), 0, false); - } - if (lastRowPos != null) { - rb.browserContentPane.rowsTable - .scrollRectToVisible(new Rectangle(visibleRect.x, lastRowPos.y - lastRowPos.height, 1, 3 * lastRowPos.height)); - } - if (firstRowPos != null) { - if (topBorder >= 0 && topBorder < firstRowPos.y && topBorder + 2 * firstRowPos.height < visibleRect.height) { - rb.browserContentPane.rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, firstRowPos.y - topBorder, 1, - topBorder + firstRowPos.height)); - } else { - rb.browserContentPane.rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, firstRowPos.y - firstRowPos.height, 1, - 3 * firstRowPos.height)); - } - } - } - } - for (RowBrowser rb : tableBrowsers) { - rb.browserContentPane.updateSingleRowDetailsView(); - } - - rbSourceToLinks = null; - repaintDesktop(); - } - - /** - * Opens new Browser and adds complete sub-tree of {@link RowBrowser}. - * - * @param tableBrowser - * the root - */ - private void showInNewWindow(RowBrowser tableBrowser) { - DataBrowser newDataBrowser = openNewDataBrowser(); - if (newDataBrowser != null) { - newDataBrowser.desktop.layoutMode = layoutMode; - newDataBrowser.desktop.updateMenu(layoutMode); - - StringBuilder cond = new StringBuilder(); - Set known = new HashSet(); - synchronized (this) { - for (Row r : tableBrowser.browserContentPane.rows) { - if (!known.contains(r.rowId)) { - known.add(r.rowId); - if (cond.length() > 0) { - cond.append(" or \n"); - } - cond.append("(" + SqlUtil.replaceAliases(r.rowId, "A", "A") + ")"); - } - } - } - - RowBrowser root = addTableBrowserSubTree(newDataBrowser, tableBrowser, null, null, cond.length() > 0? cond.toString() : null); - root.browserContentPane.reloadRows(); - newDataBrowser.arrangeLayout(true); - try { - JInternalFrame iFrame = root.internalFrame; - newDataBrowser.desktop.scrollToCenter(iFrame); - iFrame.setSelected(true); - iFrame.grabFocus(); - } catch (PropertyVetoException e1) { - // ignore - } - } - } - - private RowBrowser addTableBrowserSubTree(DataBrowser newDataBrowser, RowBrowser tableBrowser, RowBrowser parent, RowBrowser origParent, String rootCond) { - RowBrowser rb; - if (parent == null) { - rb = newDataBrowser.desktop.addTableBrowser(null, null, tableBrowser.browserContentPane.table, null, - rootCond == null ? tableBrowser.browserContentPane.getAndConditionText() : rootCond, - tableBrowser.browserContentPane.selectDistinctCheckBox.isSelected(), null, false); - } else { - rb = newDataBrowser.desktop.addTableBrowser(parent, origParent, tableBrowser.browserContentPane.table, - tableBrowser.browserContentPane.association, rootCond == null ? tableBrowser.browserContentPane.getAndConditionText() : rootCond, - tableBrowser.browserContentPane.selectDistinctCheckBox.isSelected(), null, false); - } - rb.setHidden(tableBrowser.isHidden()); - - for (RowBrowser child : getChildBrowsers(tableBrowser, false)) { - addTableBrowserSubTree(newDataBrowser, child, rb, tableBrowser, null); - } - return rb; - } - - protected abstract DataBrowser openNewDataBrowser(); - protected abstract SQLConsole getSqlConsole(boolean switchToConsole); - protected abstract boolean isDesktopVisible(); - protected abstract void checkAnchorRetension(); - protected abstract void changeColumnOrder(Table table); - protected abstract void onRowSelect(Table table, Row row); - - /** - * Scrolls an iFrame to the center of the desktop. - */ - public void scrollToCenter(JInternalFrame iFrame) { - demaximize(); - int w = getVisibleRect().width; - int h = getVisibleRect().height; - Rectangle bounds = desktopAnimation.getIFrameBounds(iFrame); - int x = bounds.x + bounds.width / 2 - getVisibleRect().width / 2; - int y = bounds.y + bounds.height / 2 - getVisibleRect().height / 2; - if (x < 0) { - w += x; - x = 0; - } - if (y < 0) { - h += y; - y = 0; - } - Rectangle r = new Rectangle(x, y, Math.max(1, w), Math.max(1, h)); - Rectangle vr = new Rectangle(postAnimationDesktopnSize != null? postAnimationDesktopnSize : currentDesktopnSize == null? getScrollPane().getViewport().getPreferredSize() : currentDesktopnSize); - desktopAnimation.scrollRectToVisible(r.intersection(vr), false); - } - - /** - * Collect layout of tables in a extraction model. - * - * @param positions - * to put positions into - */ - private void collectPositions(RowBrowser root, Map> positions) { - List>> toDo = new LinkedList>>(); - toDo.add(new Pair>(root, new Pair(1, 1))); - String subject = root.browserContentPane.table.getName(); // datamodel.get().getDisplayName(root.browserContentPane.table); - double scaleX = 0.35 / layoutMode.factor; - double scaleY = 0.3 / layoutMode.factor; - double scher = 2; - - while (!toDo.isEmpty()) { - Pair> rowBrowser = toDo.remove(0); - int i = 1; - for (RowBrowser child : getChildBrowsers(rowBrowser.a, true)) { - toDo.add(new Pair>(child, new Pair(rowBrowser.b.a + 1, i++))); - } - String table = rowBrowser.a.browserContentPane.table.getName(); // datamodel.get().getDisplayName(rowBrowser.a.browserContentPane.table); - Map tablePos = positions.get(subject); - if (tablePos == null) { - tablePos = new TreeMap(); - positions.put(subject, tablePos); - } - if (!tablePos.containsKey(table)) { - double x = rowBrowser.a.internalFrame.getX(); - double y = rowBrowser.a.internalFrame.getY(); - tablePos.put(table, new double[] { x * scaleX + scher * (2 * (rowBrowser.b.b % 2) - 1), y * scaleY + scher * (2 * (rowBrowser.b.a % 2) - 1), - 1.0 }); - } - } - } - - /** - * For concurrent reload of rows. - */ - public static final PriorityBlockingQueue runnableQueue = new PriorityBlockingQueue(100, - new Comparator() { - - @Override - public int compare(RunnableWithPriority o1, RunnableWithPriority o2) { - return o2.getPriority() - o1.getPriority(); - } - }); - - static boolean noArrangeLayoutOnNewTableBrowser = false; - static boolean noArrangeLayoutOnNewTableBrowserWithAnchor = false; - private static JInternalFrame lastInternalFrame = null; - private static BrowserContentPane lastBrowserContentPane = null; - public void catchUpLastArrangeLayoutOnNewTableBrowser() { - if (lastInternalFrame != null) { - this.scrollToCenter(lastInternalFrame); - try { - lastInternalFrame.setSelected(true); - } catch (PropertyVetoException e1) { - // ignore - } - if (lastBrowserContentPane != null) { - lastBrowserContentPane.andCondition.grabFocus(); - } - onLayoutChanged(false, true); - } - resetLastArrangeLayoutOnNewTableBrowser(); - } - - public static void resetLastArrangeLayoutOnNewTableBrowser() { - lastInternalFrame = null; - lastBrowserContentPane = null; - } - - private void logFPS(Map durations, long now, long avgD) { -// long k = durations.keySet().iterator().next(); -// if (k != now && desktopAnimation.isActive()) { -// System.out.println(avgD + " FPS " + 1000.0 * (((double) durations.size() / (now - k)))); -// } - } - - private final int RESCALE_DURATION = 500; - private Long rescaleModeEnd; - private Point rescaleStartPosition; - private boolean rescaleFactorHasChanged = false; - - public void startRescaleMode(long currentTime, MouseWheelEvent evt) { - rescaleModeEnd = currentTime + RESCALE_DURATION; - rescaleStartPosition = new Point(evt.getX(), evt.getY()); - SwingUtilities.convertPointToScreen(rescaleStartPosition, evt.getComponent()); - } - - public void checkRescaleMode(MouseWheelEvent evt, long currentTime) { -// if (inRescaleMode(currentTime)) { -// if (rescaleStartPosition != null) { -// Point position = new Point(evt.getX(), evt.getY()); -// SwingUtilities.convertPointToScreen(position, evt.getComponent()); -// if (position.distance(rescaleStartPosition) > 1000) { -// rescaleModeEnd = null; -// } -// } -// } - } - - private boolean inRescaleMode(long currentTime) { - return rescaleModeEnd != null && currentTime < rescaleModeEnd; - } - - private void deferRescaleMode(long startTime) { - if (inRescaleMode(startTime) && rescaleFactorHasChanged) { - long duration = System.currentTimeMillis() - startTime; - rescaleModeEnd += duration; - } - rescaleFactorHasChanged = false; - } - - private boolean animationEnabled = true; - - public boolean isAnimationEnabled() { - return animationEnabled; - } - - public void setAnimationEnabled(boolean animationEnabled) { - this.animationEnabled = animationEnabled; - } - - public void zoom(int d) { - d += layoutMode.ordinal(); - if (d >= 0 && d < LayoutMode.values().length) { - rescaleLayout(LayoutMode.values()[d], null); - } - } - - public String getRawSchemaMapping() { - StringBuilder mapping = new StringBuilder(); - for (String schema: schemaMapping.keySet()) { - String to = schemaMapping.get(schema).trim(); - if (!schema.equals(to)) { - if (mapping.length() > 0) { - mapping.append(","); - } - mapping.append(schema + "=" + to); - } - } - return mapping.toString(); - } - - private Row currentlyViewedRow = null; - - /** - * Maximum number of concurrent DB connections. - */ - private static final int MAX_CONCURRENT_CONNECTIONS = 6; - static { - // initialize listeners for #runnableQueue - for (int i = 0; i < MAX_CONCURRENT_CONNECTIONS; ++i) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - for (;;) { - RunnableWithPriority take = null; - try { - take = runnableQueue.take(); - take.run(); - } catch (InterruptedException e) { - // ignore - } catch (CancellationException e) { - // ignore - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - }, "PQueue-Worker-" + (i + 1)); - t.setDaemon(true); - t.start(); - } - } - -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser; + +import java.awt.BasicStroke; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.DefaultDesktopManager; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTable; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +import javax.swing.RowSorter.SortKey; +import javax.swing.SortOrder; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; +import javax.swing.event.InternalFrameEvent; +import javax.swing.event.InternalFrameListener; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.KnownIdentifierMap; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.Environment; +import net.sf.jailer.ui.QueryBuilderDialog; +import net.sf.jailer.ui.QueryBuilderDialog.Relationship; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; +import net.sf.jailer.ui.databrowser.BrowserContentPane.RunnableWithPriority; +import net.sf.jailer.ui.databrowser.BrowserContentPane.SqlStatementTable; +import net.sf.jailer.ui.databrowser.TreeLayoutOptimizer.Node; +import net.sf.jailer.ui.databrowser.metadata.MDTable; +import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; +import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; +import net.sf.jailer.ui.util.UISettings; +import net.sf.jailer.util.CancellationException; +import net.sf.jailer.util.CsvFile; +import net.sf.jailer.util.CsvFile.Line; +import net.sf.jailer.util.Pair; +import net.sf.jailer.util.SqlUtil; +import prefuse.util.GraphicsLib; + +/** + * Desktop holding row-browsers as {@link JInternalFrame}s. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public abstract class Desktop extends JDesktopPane { + + /** + * The {@link DataModel}. + */ + private final Reference datamodel; + + /** + * Icon for the row-browser frames. + */ + private final Icon jailerIcon; + + /** + * Default width of a row-browser frame. + */ + public static final int BROWSERTABLE_DEFAULT_WIDTH = 476; + private final int BROWSERTABLE_DEFAULT_MIN_X = 0, BROWSERTABLE_DEFAULT_MIN_Y = 6, BROWSERTABLE_DEFAULT_HEIGHT = 460, BROWSERTABLE_DEFAULT_DISTANCE = 110; + + /** + * true while the desktop is visible. + */ + private boolean running; + + /** + * false if links must not be rendered (if a frame is + * maximized). + */ + private boolean renderLinks; + + /** + * Schema mapping. + */ + public final Map schemaMapping; + + /** + * DB session. + */ + public Session session; + DbConnectionDialog dbConnectionDialog; + + /** + * The execution context. + */ + private final ExecutionContext executionContext; + + private RowsClosure rowsClosure = new RowsClosure(); + + final DesktopAnimation desktopAnimation; + + private final QueryBuilderDialog queryBuilderDialog; + private final DesktopIFrameStateChangeRenderer iFrameStateChangeRenderer = new DesktopIFrameStateChangeRenderer(); + private final DesktopAnchorManager anchorManager; + + private static final KeyStroke KS_SQLCONSOLE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK); + + public DesktopIFrameStateChangeRenderer getiFrameStateChangeRenderer() { + return iFrameStateChangeRenderer; + } + + /** + * Constructor. + * + * @param datamodel + * the {@link DataModel} + * @param jailerIcon + * icon for the frames + * @param session + * DB-session + * @param anchorManager + */ + public Desktop(Reference datamodel, Icon jailerIcon, Session session, DataBrowser parentFrame, DbConnectionDialog dbConnectionDialog, Map schemaMapping, DesktopAnchorManager anchorManager, ExecutionContext executionContext) { + this.executionContext = executionContext; + this.anchorManager = anchorManager; + this.parentFrame = parentFrame; + this.datamodel = datamodel; + this.jailerIcon = jailerIcon; + this.queryBuilderDialog = new QueryBuilderDialog(parentFrame); + this.dbConnectionDialog = dbConnectionDialog; + this.schemaMapping = schemaMapping; + + this.desktopAnimation = new DesktopAnimation(this); + + this.queryBuilderDialog.sqlEditButton.setVisible(true); + this.queryBuilderDialog.sqlEditButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // addTableBrowser(null, null, 0, null, null, queryBuilderDialog.getSQL(), null, null, true); + getSqlConsole(true).appendStatement(queryBuilderDialog.getSQL() + LF + ";", true); + queryBuilderDialog.setVisible(false); + } + }); + if (Toolkit.getDefaultToolkit().getScreenSize().height < 740) { + layoutMode = LayoutMode.SMALL; + } + + try { + this.session = session; + setAutoscrolls(true); + manager = new MDIDesktopManager(this); + setDesktopManager(manager); + synchronized (this) { + running = true; + } + Thread updateUIThread = new Thread(new Runnable() { + @Override + public void run() { + final AtomicLong duration = new AtomicLong(); + final AtomicBoolean inProgress = new AtomicBoolean(false); + Map durations = new LinkedHashMap(); + long lastDuration = 0; + final long AVG_INTERVALL_SIZE = 1000; + while (true) { + synchronized (Desktop.this) { + if (!running) { + return; + } + } + try { + inProgress.set(false); + long now = System.currentTimeMillis(); + long d = lastDuration + paintDuration; + if (d <= 0) { + d = 1; + } + Iterator> i = durations.entrySet().iterator(); + while (i.hasNext()) { + if (i.next().getKey() < now - AVG_INTERVALL_SIZE) { + i.remove(); + } else { + break; + } + } + durations.put(now, d); + long dSum = 0; + for (Entry e: durations.entrySet()) { + dSum += e.getValue(); + } + long avgD = dSum / durations.size(); + if (UIUtil.isPopupActive() && !desktopAnimation.isActive()) { + avgD *= 2; + } else { + avgD *= 1.05; + } + + logFPS(durations, now, avgD); + + Thread.sleep(Math.min(desktopAnimation.isActive()? 10 : Math.max(STEP_DELAY, avgD), 500)); + if (!inProgress.get()) { + inProgress.set(true); + duration.set(0); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + long startTime = System.currentTimeMillis(); + try { + checkAnchorRetension(); + if (isDesktopVisible() && isAnimationEnabled()) { + suppressRepaintDesktop = true; + desktopAnimation.animate(); + boolean cl = calculateLinks(); + if (cl) { + repaintScrollPane(); + } + } + } finally { + suppressRepaintDesktop = false; + inProgress.set(false); + duration.set(System.currentTimeMillis() - startTime); + } + } + }); + } + } catch (Throwable e) { + // ignore + } + lastDuration = duration.get(); + } + } + }, "Databrowser-Animator"); + updateUIThread.setDaemon(true); + updateUIThread.start(); + + AbstractAction a = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (isDesktopVisible()) { + for (final RowBrowser rb : tableBrowsers) { + if (rb.internalFrame.isSelected()) { + rb.browserContentPane.rowsTable.grabFocus(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + rb.browserContentPane.openQueryBuilder(true); + } + }); + break; + } + } + } + } + }; + Container parent = parentFrame.getContentPane(); + if (parent instanceof JComponent) { + JComponent comp = (JComponent) parent; + InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + im.put(KS_SQLCONSOLE, a); + ActionMap am = comp.getActionMap(); + am.put(a, a); + } + } catch (Exception e) { + UIUtil.showException(null, "Error", e, session); + } + desktops.add(this); + updateMenu(); + } + + public class RowToRowLink { + + /** + * The rows. + */ + public Row parentRow, childRow; + + /** + * Index of parent row in the parent's row browser. + */ + public int parentRowIndex = -1; + + /** + * Index of child row. + */ + public int childRowIndex = -1; + + /** + * Coordinates of the link render. + */ + public int x1 = -1, y1, x2, y2; + + /** + * The link's color. + */ + public Color color1; + + /** + * The link's alternating color. + */ + public Color color2; + + /** + * Is the link visible? + */ + public boolean visible = true; + } + + /** + * Renders a set of {@link Row}s. + */ + public class RowBrowser { + + /** + * Frame holding a {@link BrowserContentPane}. + */ + public JInternalFrame internalFrame; + + /** + * UI for row-browsing. + */ + public BrowserContentPane browserContentPane; + + /** + * Parent browser. + */ + public RowBrowser parent; + + /** + * Association with parent. + */ + public Association association; + + /** + * Coordinates of the link render. + */ + public int x1, y1, x2, y2; + + /** + * The link's color. + */ + public Color color1; + + /** + * The link's alternating color. + */ + public Color color2; + + /** + * Row-to-row links. + */ + public List rowToRowLinks = new ArrayList(); + + public void convertToRoot() { + association = null; + parent = null; + browserContentPane.convertToRoot(); + } + + /** + * Is this RowBrowser hidden? + */ + private boolean hidden; + + /** + * Hides/unhides RowBrowser. + */ + public void setHidden(boolean hidden) { + if (hidden == this.hidden) { + return; + } + rbSourceToLinks = null; + if (hidden) { + internalFrame.setVisible(false); + } else { + internalFrame.setVisible(true); + Rectangle r = layout(parent, association, browserContentPane, new ArrayList(), 0, -1); + internalFrame.setBounds(r); + desktopAnimation.scrollRectToVisible(internalFrame.getBounds(), false); + try { + internalFrame.setSelected(true); + } catch (PropertyVetoException e) { + // ignore + } + internalFrame.grabFocus(); + } + this.hidden = hidden; + checkDesktopSize(); + updateMenu(); + } + + /** + * Is this RowBrowser hidden? + */ + public boolean isHidden() { + return hidden; + } + + private MDTable mdTable; + + public MDTable getMDTable() { + return mdTable; + } + + public void setMDTable(MDTable mdTable) { + this.mdTable = mdTable; + } + + }; + + /** + * All row-browsers. + */ + private List tableBrowsers = new ArrayList(); + + /** + * Opens a new row-browser. + * + * @param parent + * parent browser + * @param origParent + * @param table + * to read rows from. Open SQL browser if table is + * null. + * @param association + * to navigate, or null + * @param condition + * @param selectDistinct + * @param title + * @param limit + * @return new row-browser + */ + public synchronized RowBrowser addTableBrowser(final RowBrowser parent, final RowBrowser origParent, final Table table, final Association association, + String condition, Boolean selectDistinct, String title, boolean reload) { + + Set titles = new HashSet(); + for (RowBrowser rb : tableBrowsers) { + titles.add(rb.internalFrame.getTitle()); + } + demaximize(); + + if (title == null) { + if (table != null) { + title = datamodel.get().getDisplayName(table); + if (titles.contains(title)) { + for (int i = 2;; ++i) { + String titelPlusI = title + " (" + i + ")"; + if (!titles.contains(titelPlusI)) { + title = titelPlusI; + break; + } + } + } + } + } + + final RowBrowser tableBrowser = new RowBrowser(); + final JInternalFrame jInternalFrame = new JInternalFrame(table == null ? "SQL" : title); + + jInternalFrame.setClosable(true); + jInternalFrame.setIconifiable(true); + jInternalFrame.setMaximizable(true); + jInternalFrame.setVisible(true); + jInternalFrame.addMouseWheelListener(new java.awt.event.MouseWheelListener() { + @Override + public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { + long currentTime = System.currentTimeMillis(); + startRescaleMode(currentTime, evt); + onMouseWheelMoved(evt, currentTime); + onMouseWheelMoved(evt, parentFrame.getDesktopScrollPane(), currentTime); + } + }); + javax.swing.GroupLayout jInternalFrame1Layout = new javax.swing.GroupLayout(jInternalFrame.getContentPane()); + jInternalFrame.getContentPane().setLayout(jInternalFrame1Layout); + jInternalFrame1Layout.setHorizontalGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 162, + Short.MAX_VALUE)); + jInternalFrame1Layout.setVerticalGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 102, + Short.MAX_VALUE)); + + jInternalFrame.setResizable(true); + if (jailerIcon != null) { + jInternalFrame.setFrameIcon(jailerIcon); + } + add(jInternalFrame, javax.swing.JLayeredPane.DEFAULT_LAYER); + + jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_MAXIMUM_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + manager.resizeDesktop(); + } + }); + + jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_ICON_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (jInternalFrame.isIcon()) { + demaximize(); + tableBrowser.setHidden(true); + try { + jInternalFrame.setIcon(false); + } catch (PropertyVetoException e) { + // ignore + } + } + } + }); + + jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_SELECTED_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.TRUE.equals(evt.getNewValue())) { + updateMenu(); + } + } + }); + + jInternalFrame.addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent e) { + repaintDesktop(); + } + + @Override + public void componentResized(ComponentEvent e) { + repaintDesktop(); + } + + @Override + public void componentMoved(ComponentEvent e) { + repaintDesktop(); + } + + @Override + public void componentHidden(ComponentEvent e) { + repaintDesktop(); + } + }); + + if (reload) { + ++UISettings.s5; + } + + final BrowserContentPane browserContentPane = new BrowserContentPane(datamodel.get(), table, condition, session, parent == null ? null : parent.browserContentPane.rows, + association, parentFrame, rowsClosure, selectDistinct, reload, executionContext) { + { + MouseListener ml = new MouseAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + updateRowView(e); + } + @Override + public void mouseExited(MouseEvent e) { + if (null != currentlyViewedRow) { + onRowSelect(table, null); + currentlyViewedRow = null; + } + } + }; + singleRowViewScrollPane.addMouseListener(ml); + singleRowViewScrollPane.addMouseMotionListener((MouseMotionListener) ml); + singleRowViewContainterPanel.addMouseListener(ml); + singleRowViewContainterPanel.addMouseMotionListener((MouseMotionListener) ml); + rowsTable.addMouseListener(ml); + rowsTable.addMouseMotionListener((MouseMotionListener) ml); + } + + private void updateRowView(MouseEvent e) { + int ri; + JComponent source = (JComponent) e.getSource(); + if (source == rowsTable) { + ri = rowsTable.rowAtPoint(e.getPoint()); + } else { + ri = 0; + } + if (ri >= 0 && !rows.isEmpty() && rowsTable.getRowSorter().getViewRowCount() > 0) { + int i = 0; + if (source == rowsTable) { + i = rowsTable.getRowSorter().convertRowIndexToModel(ri); + } else if (source == rowsTableScrollPane || source == singleRowViewContainterPanel) { + if (rows.size() != 1 || getQueryBuilderDialog() == null /* SQL Console */) { + return; + } + ri = 0; + i = 0; + } + Row row = rows.get(i); + if (row != currentlyViewedRow) { + onRowSelect(table, row); + currentlyViewedRow = row; + } + } + } + + @Override + protected void reloadDataModel() throws Exception { + Desktop.this.reloadDataModel(schemaMapping); + } + + @Override + protected QueryBuilderDialog getQueryBuilderDialog() { + return queryBuilderDialog; + } + + @Override + protected RowBrowser navigateTo(Association association, List pRows) { + return addTableBrowser(tableBrowser, tableBrowser, association.destination, association, toCondition(pRows), null, null, true); + } + + @Override + protected void onContentChange(List rows, boolean reloadChildren) { + updateChildren(tableBrowser, rows); + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == tableBrowser) { + updateChildren(rb, rb.browserContentPane.rows); + if (reloadChildren /* && rb.browserContentPane.parentRow == null */) { + rb.browserContentPane.reloadRows(); + } + } + } + } + + @Override + protected void onRedraw() { + repaintDesktop(); + } + + @Override + protected JFrame getOwner() { + return parentFrame; + } + + private Set> addedRowPairs; + + @Override + protected void addRowToRowLink(Row parentRow, Row childRow) { + synchronized (Desktop.this) { + Pair pair = new Pair(parentRow, childRow); + if (addedRowPairs == null || !addedRowPairs.contains(pair)) { + if (addedRowPairs != null) { + addedRowPairs.add(pair); + } + RowToRowLink rowToRowLink = new RowToRowLink(); + rowToRowLink.parentRow = parentRow; + rowToRowLink.childRow = childRow; + rowToRowLink.color1 = getAssociationColor1(association); + rowToRowLink.color2 = getAssociationColor2(association); + tableBrowser.rowToRowLinks.add(rowToRowLink); + } + } + } + + @Override + protected void beforeReload() { + synchronized (Desktop.this) { + addedRowPairs = new HashSet>(); + tableBrowser.rowToRowLinks.clear(); + } + } + + @Override + protected void afterReload() { + synchronized (Desktop.this) { + addedRowPairs = null; + } + } + @Override + protected Object getMonitorForFindClosure() { + return Desktop.this; + } + + @Override + protected void findClosure(Row row) { + Set> rows = new HashSet>(); + synchronized (Desktop.this) { + FindClosureContext findClosureContext = new FindClosureContext(); + findClosure(row, rows, false, findClosureContext); + rowsClosure.currentClosure.addAll(rows); + rows = new HashSet>(); + findClosure(row, rows, true, findClosureContext); + } + rowsClosure.currentClosure.addAll(rows); + rowsClosure.parentPath.clear(); + rowsClosure.parentPath.add(this); + for (RowBrowser p = parent; p != null; p = p.parent) { + rowsClosure.parentPath.add(p.browserContentPane); + } + + try { + Set browserInClosure = new HashSet(); + for (Pair rid: rowsClosure.currentClosure) { + browserInClosure.add(rid.a); + } + + for (RowBrowser rb: tableBrowsers) { + rb.browserContentPane.updateRowsCountLabel(browserInClosure); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void findTempClosure(Row row) { + Set> rows = new HashSet>(); + Set> closure = new HashSet>(); + FindClosureContext findClosureContext = new FindClosureContext(); + synchronized (Desktop.this) { + findClosure(row, rows, false, findClosureContext); + closure.addAll(rows); + rows = new HashSet>(); + findClosure(row, rows, true, findClosureContext); + closure.addAll(rows); + } + + rowsClosure.tempClosure.clear(); + for (Pair p: closure) { + rowsClosure.tempClosure.add(p.b); + } + } + + @Override + protected void findClosure(Row row, Set> closure, boolean forward, FindClosureContext findClosureContext) { + synchronized (Desktop.this) { + Pair thisRow = new Pair(this, row); + if (!closure.contains(thisRow)) { + closure.add(thisRow); + if (forward) { + for (RowBrowser child : tableBrowsers) { + if (child.parent == tableBrowser) { + for (RowToRowLink rowToRowLink : findClosureContext.getParentPartition(child, row)) { +// for (RowToRowLink rowToRowLink : child.rowToRowLinks) { +// if (row.nonEmptyRowId.equals(rowToRowLink.parentRow.nonEmptyRowId)) { + child.browserContentPane.findClosure(rowToRowLink.childRow, closure, forward, findClosureContext); +// } + } + } + } + } else { + if (tableBrowser.parent != null) { + for (RowToRowLink rowToRowLink : findClosureContext.getChildPartition(tableBrowser, row)) { +// for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { +// if (row.nonEmptyRowId.equals(rowToRowLink.childRow.nonEmptyRowId)) { + tableBrowser.parent.browserContentPane.findClosure(rowToRowLink.parentRow, closure, forward, findClosureContext); + for (RowBrowser sibling : tableBrowsers) { + if (sibling.parent == tableBrowser.parent && sibling.browserContentPane != this) { + for (RowToRowLink sRowToRowLink: findClosureContext.getParentPartition(sibling, rowToRowLink.parentRow)) { +// for (RowToRowLink sRowToRowLink: sibling.rowToRowLinks) { +// if (rowToRowLink.parentRow.nonEmptyRowId.equals(sRowToRowLink.parentRow.nonEmptyRowId)) { + sibling.browserContentPane.findClosure(sRowToRowLink.childRow, closure, true, findClosureContext); +// } + } + } + } +// } + } + } + } + } + } + } + + private void createAnchorSQL(RowBrowser rb, StringBuilder rowIds, boolean indent) { + boolean f = true; + for (Row row : rb.browserContentPane.rows) { + if (!f) { + rowIds.append(indent ? " or\n " : " or\n"); + } + f = false; + rowIds.append(SqlUtil.replaceAliases(row.rowId, "A", "A")); + } + rowIds.append(""); + } + + @Override + protected QueryBuilderDialog.Relationship createQBRelations(boolean withParents) { + QueryBuilderDialog.Relationship root = new QueryBuilderDialog.Relationship(); + root.whereClause = (getAndConditionText().trim()); // .replaceAll("(\r|\n)+", " "); + if (root.whereClause.length() == 0) { + root.whereClause = null; + } + StringBuilder rowIds = new StringBuilder(""); + createAnchorSQL(tableBrowser, rowIds, withParents); + root.anchorWhereClause = rowIds.length() == 0 ? null : rowIds.toString(); + + root.children.addAll(createQBChildrenRelations(null, !withParents)); + + Association a = association; + + QueryBuilderDialog.Relationship r = root; + RowBrowser childRB = tableBrowser; + for (RowBrowser rb = tableBrowser.parent; rb != null && a != null; rb = rb.parent) { + if (!withParents) { + root.needsAnchor = true; + break; + } + QueryBuilderDialog.Relationship child = new QueryBuilderDialog.Relationship(); + child.children.addAll(rb.browserContentPane.createQBChildrenRelations(childRB, false)); + child.parent = r; + r.children.add(0, child); + child.whereClause = (rb.browserContentPane.getAndConditionText().trim()).replaceAll("(\r|\n)+", " "); + if (child.whereClause.length() == 0) { + child.whereClause = null; + } + child.association = a.reversalAssociation; + r.anchor = child.association; + a = rb.association; + rowIds = new StringBuilder(""); + createAnchorSQL(rb, rowIds, true); + child.anchorWhereClause = rowIds.length() == 0 ? null : rowIds.toString(); + + r.originalParent = child; + r = child; + childRB = rb; + } + return root; + } + + @Override + protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { + List result = new ArrayList(); + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == tableBrowser && rb != tabu) { + if (true) { // all || !singleRowParent) { + QueryBuilderDialog.Relationship child = new QueryBuilderDialog.Relationship(); + child.whereClause = (rb.browserContentPane.getAndConditionText().trim()).replaceAll("(\r|\n)+", " "); + child.joinOperator = QueryBuilderDialog.JoinOperator.LeftJoin; + if (child.whereClause.length() == 0) { + child.whereClause = null; + } + child.association = rb.association; + if (child.association != null) { + child.children.addAll(rb.browserContentPane.createQBChildrenRelations(tabu, all)); + result.add(child); + } + } + } + } + return result; + } + + @Override + protected void openSchemaMappingDialog() { + Desktop.this.openSchemaMappingDialog(false); + } + + @Override + protected void openSchemaAnalyzer() { + Desktop.this.openSchemaAnalyzer(); + } + + @Override + protected DbConnectionDialog getDbConnectionDialog() { + return dbConnectionDialog; + } + + @Override + protected double getLayoutFactor() { + return layoutMode.factor; + } + + @Override + protected List getChildBrowsers() { + return Desktop.this.getChildBrowsers(tableBrowser, false); + } + + @Override + protected RowBrowser getParentBrowser() { + return tableBrowser.parent; + } + + @Override + protected RowBrowser getRowBrowser() { + return tableBrowser; + } + + @Override + protected List getTableBrowser() { + return new ArrayList(Desktop.this.tableBrowsers); + } + + @Override + protected void onHide() { + demaximize(); + tableBrowser.setHidden(true); + } + + @Override + protected void unhide() { + tableBrowser.setHidden(false); + } + + @Override + protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { + Desktop.this.adjustClosure(tabu, thisOne); + } + + @Override + protected void close() { + closeAll(Collections.singleton(tableBrowser)); + } + + @Override + protected void showInNewWindow() { + Desktop.this.showInNewWindow(tableBrowser); + } + + @Override + protected void appendLayout() { + Desktop.this.restoreSession(tableBrowser, null); + } + + @Override + protected PriorityBlockingQueue getRunnableQueue() { + return runnableQueue; + } + + @Override + protected void collectPositions(Map> positions) { + Desktop.this.collectPositions(tableBrowser, positions); + } + + @Override + protected boolean renderRowAsPK(Row theRow) { + return false; + } + + @Override + protected MetaDataSource getMetaDataSource() { + return parentFrame.getMetaDataSource(); + } + + @Override + protected SQLConsole getSqlConsole(boolean switchToConsole) { + return Desktop.this.getSqlConsole(switchToConsole); + } + + @Override + protected void deselectChildrenIfNeededWithoutReload() { + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == tableBrowser) { + rb.browserContentPane.deselectIfNeededWithoutReload(); + rb.browserContentPane.deselectChildrenIfNeededWithoutReload(); + } + } + } + + @Override + protected int getReloadLimit() { + return Desktop.this.getRowLimit(); + } + + @Override + protected void changeColumnOrder(Table table) { + Desktop.this.changeColumnOrder(table); + } + + @Override + protected void rebase() { + Component parent = SwingUtilities.getWindowAncestor(this); + if (parent == null) { + parent = this; + } + UIUtil.setWaitCursor(parent); + try { + Desktop.noArrangeLayoutOnNewTableBrowser = true; + Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = true; + + RowBrowser newBrowser = copy(null, null, null, null, true); + RowBrowser newChildBrowser = newBrowser; + + BrowserContentPane root; + BrowserContentPane br = this; + do { + root = br; + RowBrowser pb = br.getParentBrowser(); + if (pb != null) { + if (br.association != null) { + newChildBrowser = pb.browserContentPane.copy(newChildBrowser, br.association.reversalAssociation, null, br.getRowBrowser(), true); + } else { + closeSubTree(newBrowser.browserContentPane, true); + return; + } + br = pb.browserContentPane; + } else { + br = null; + } + } while (br != null); + newBrowser.browserContentPane.reloadRows(); + newBrowser.internalFrame.setSelected(true); + UIUtil.invokeLater(2, new Runnable() { + @Override + public void run() { + onLayoutChanged(false, true); + } + }); + UISettings.s7 += 1000; + closeSubTree(root, true); + } catch (Throwable t) { + UIUtil.showException(parent, "Error", t); + } finally { + Desktop.noArrangeLayoutOnNewTableBrowser = false; + Desktop.noArrangeLayoutOnNewTableBrowserWithAnchor = false; + UIUtil.resetWaitCursor(parent); + } + } + + @Override + protected RowBrowser copy(RowBrowser parent, Association newAssociation, Row pRow, RowBrowser childToIgnore, boolean newParent) { + String andConditionText = this.getAndConditionText(); + if (pRow != null && (andConditionText == null || andConditionText.trim().length() == 0)) { + andConditionText = pRow.rowId; + } + if (newParent && andConditionText != null) { + if (!andConditionText.equals(SqlUtil.replaceAliases(andConditionText, "A", ""))) { + andConditionText = ""; + } + } + RowBrowser tb = addTableBrowser(parent, parent, table, newAssociation, andConditionText, null, tableBrowser.internalFrame.getTitle(), false); + tb.internalFrame.setBounds(tableBrowser.internalFrame.getBounds()); + try { + tb.internalFrame.setIcon(!tableBrowser.internalFrame.isVisible()); + } catch (PropertyVetoException e) { + // ignore + } + for (RowBrowser child: getChildBrowsers()) { + if (child != childToIgnore) { + child.browserContentPane.copy(tb, child.association, null, null, false); + } + } + return tb; + } + + @Override + protected boolean shouldShowLoadErrors() { + return isDesktopVisible(); + } + + }; + + Rectangle r = layout(parent, association, browserContentPane, new ArrayList(), 0, -1); + java.awt.event.MouseWheelListener mouseWheelListener = new java.awt.event.MouseWheelListener() { + @Override + public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { + long currentTime = System.currentTimeMillis(); + checkRescaleMode(evt, currentTime); + onMouseWheelMoved(evt, currentTime); + if (evt.getSource() instanceof JScrollPane) { + onMouseWheelMoved(evt, (JScrollPane) evt.getSource(), currentTime); + } + } + }; + browserContentPane.rowsTableScrollPane.addMouseWheelListener(mouseWheelListener); + browserContentPane.singleRowViewScrollPane.addMouseWheelListener(mouseWheelListener); + + jInternalFrame.setBounds(r); + + tableBrowser.internalFrame = jInternalFrame; + tableBrowser.browserContentPane = browserContentPane; + tableBrowser.parent = parent; + tableBrowser.association = association; + if (association != null) { + tableBrowser.color1 = getAssociationColor1(association); + tableBrowser.color2 = getAssociationColor2(association); + } + tableBrowsers.add(tableBrowser); + UISettings.s2 = Math.max(tableBrowsers.size(), UISettings.s2); + + initIFrame(jInternalFrame, browserContentPane); + + anchorManager.onNewTableBrowser(tableBrowser); + + jInternalFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + jInternalFrame.addInternalFrameListener(new InternalFrameListener() { + @Override + public void internalFrameOpened(InternalFrameEvent e) { + onLayoutChanged(false, true); + } + + @Override + public void internalFrameIconified(InternalFrameEvent e) { + repaintDesktop(); + } + + @Override + public void internalFrameDeiconified(InternalFrameEvent e) { + repaintDesktop(); + } + + @Override + public void internalFrameDeactivated(InternalFrameEvent e) { + } + + @Override + public void internalFrameClosing(InternalFrameEvent e) { + if (tableBrowser.browserContentPane.closeWithChildren(jInternalFrame)) { + onLayoutChanged(false, false); + } + } + + @Override + public void internalFrameClosed(InternalFrameEvent e) { + close(tableBrowser, true); + } + + @Override + public void internalFrameActivated(InternalFrameEvent e) { + } + }); + + checkDesktopSize(); + updateMenu(); + + if (!noArrangeLayoutOnNewTableBrowser) { + this.scrollToCenter(jInternalFrame); + try { + jInternalFrame.setSelected(true); + } catch (PropertyVetoException e1) { + // ignore + } + browserContentPane.andCondition.grabFocus(); + onLayoutChanged(false, true); + } else { + lastInternalFrame = jInternalFrame; + lastBrowserContentPane = browserContentPane; + } + + if (tableBrowsers.size() > 1) { + iFrameStateChangeRenderer.onNewIFrame(jInternalFrame); + } + jInternalFrame.addPropertyChangeListener(JInternalFrame.IS_SELECTED_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Boolean.TRUE.equals(evt.getNewValue())) { + iFrameStateChangeRenderer.onIFrameSelected(jInternalFrame, 0.6); + } + } + }); + + return tableBrowser; + } + + protected abstract int getRowLimit(); + + /** + * Demaximizes all internal frames. + */ + private void demaximize() { + for (RowBrowser rb : tableBrowsers) { + try { + rb.internalFrame.setMaximum(false); + } catch (PropertyVetoException e) { + // ignore + } + } + } + + private void initIFrame(final JInternalFrame jInternalFrame, final BrowserContentPane browserContentPane) { + browserContentPane.thumbnail = new JPanel(); + final JPanel thumbnailInner = new JPanel(); + browserContentPane.thumbnail.setLayout(new GridBagLayout()); + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 1; + gridBagConstraints.gridheight = 1; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 1; + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.insets = new Insets(8, 8, 8, 8); + browserContentPane.thumbnail.add(thumbnailInner, gridBagConstraints); + + thumbnailInner.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); + String title = jInternalFrame.getTitle(); + String suffix = null; + Pattern tPat = Pattern.compile("^(.*)(\\([0-9]+\\))$"); + Matcher matcher = tPat.matcher(title); + if (matcher.matches()) { + title = matcher.group(1); + suffix = matcher.group(2); + } + +// boolean isEmpty = browserContentPane.get + + List labels = new ArrayList(); + final List jLabels = new ArrayList(); + + for (int i = 0; i < title.length(); ++i) { + labels.add(title.substring(i, i + 1)); + } + if (suffix != null) { + labels.add(suffix); + } + for (String l: labels) { + JLabel jl = new JLabel(l); + jl.setFont(jl.getFont().deriveFont(jl.getFont().getStyle() | Font.BOLD)); + jLabels.add(jl); + thumbnailInner.add(jl); + } + + browserContentPane.setOnReloadAction(new Runnable() { + + @Override + public void run() { + if (browserContentPane.rows != null) { + if (browserContentPane.rows.size() == 0) { + for (JLabel l: jLabels) { + l.setForeground(Color.GRAY); + } + } else { + for (JLabel l: jLabels) { + l.setForeground(Color.BLUE); + } + } + } + } + }); + + jInternalFrame.getContentPane().setLayout(new CardLayout()); + + jInternalFrame.getContentPane().add(browserContentPane, "C"); + jInternalFrame.getContentPane().add(browserContentPane.thumbnail, "T"); + + browserContentPane.thumbnail.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON1 && !(browserContentPane.table instanceof SqlStatementTable)) { + JPopupMenu popup = browserContentPane.createPopupMenu(null, -1, 0, 0, false); + JPopupMenu popup2 = browserContentPane.createSqlPopupMenu(-1, 0, 0, true, jInternalFrame); + popup.add(new JSeparator()); + for (Component c : popup2.getComponents()) { + popup.add(c); + } + UIUtil.fit(popup); + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + }); + + initIFrameContent(jInternalFrame, browserContentPane, browserContentPane.thumbnail); + jInternalFrame.addComponentListener(new ComponentListener() { + @Override + public void componentHidden(ComponentEvent e) { + onLayoutChanged(false, false); + } + + @Override + public void componentMoved(ComponentEvent e) { +// onLayoutChanged(false); + } + + @Override + public void componentResized(ComponentEvent e) { +// onLayoutChanged(jInternalFrame.isMaximum()); + initIFrameContent(jInternalFrame, browserContentPane, browserContentPane.thumbnail); + } + + @Override + public void componentShown(ComponentEvent e) { + onLayoutChanged(false, true); + } + }); + } + + private void initIFrameContent(final JInternalFrame jInternalFrame, final BrowserContentPane browserContentPane, final JPanel thumbnail) { + if (jInternalFrame.getWidth() < 150 || jInternalFrame.getHeight() < 150) { + ((CardLayout) jInternalFrame.getContentPane().getLayout()).show(jInternalFrame.getContentPane(), "T"); + } else { + ((CardLayout) jInternalFrame.getContentPane().getLayout()).show(jInternalFrame.getContentPane(), "C"); + } + } + + private Color getAssociationColor1(Association association) { + Color color = new java.awt.Color(0, 120, 255); + if (association.isIgnored()) { + color = new java.awt.Color(153, 153, 153); + } else if (association.isInsertDestinationBeforeSource()) { + color = new java.awt.Color(190, 30, 0); + } else if (association.isInsertSourceBeforeDestination()) { + color = new java.awt.Color(60, 132, 0); + } + return color; + } + + private Color getAssociationColor2(Association association) { + Color color = new java.awt.Color(0, 60, 235); + if (association.isIgnored()) { + color = new java.awt.Color(133, 133, 153); + } else if (association.isInsertSourceBeforeDestination()) { + color = new java.awt.Color(0, 180, 80); + } else if (association.isInsertDestinationBeforeSource()) { + color = new java.awt.Color(230, 0, 60); + } + return color; + } + + private Rectangle layout(RowBrowser parent, Association association, BrowserContentPane browserContentPane, + Collection ignore, int maxH, int xPosition) { + int x = (int) (BROWSERTABLE_DEFAULT_MIN_X * layoutMode.factor); + int y = (int) (BROWSERTABLE_DEFAULT_MIN_Y * layoutMode.factor); + + while (parent != null && parent.isHidden()) { + parent = parent.parent; + } + + if (parent != null) { + x = (int) (parent.internalFrame.getX() + parent.internalFrame.getWidth() + BROWSERTABLE_DEFAULT_DISTANCE * layoutMode.factor); + y = parent.internalFrame.getY(); + } + if (maxH > 0) { + y = maxH; + } + if (xPosition >= 0) { + x = (int) (xPosition * (BROWSERTABLE_DEFAULT_WIDTH + BROWSERTABLE_DEFAULT_DISTANCE) * layoutMode.factor); + } + // int h = fullSize || association == null || + // (association.getCardinality() != Cardinality.MANY_TO_ONE && + // association.getCardinality() != Cardinality.ONE_TO_ONE)? HEIGHT : + // browserContentPane.getMinimumSize().height + MIN_HEIGHT; + int h = (int) (BROWSERTABLE_DEFAULT_HEIGHT * layoutMode.factor); + Rectangle r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); + for (;;) { + boolean ok = true; + for (RowBrowser tb : tableBrowsers) { + if (!ignore.contains(tb) && !tb.isHidden() && tb.internalFrame.getBounds().intersects(r)) { + ok = false; + break; + } + } + r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); + y += 8 * layoutMode.factor; + if (ok) { + break; + } + } + return r; + } + + protected synchronized void updateChildren(RowBrowser tableBrowser, List rows) { + boolean hasParent = false; + + for (RowBrowser rowBrowser : tableBrowsers) { + if (rowBrowser == tableBrowser.parent) { + hasParent = true; + } + } + + if (!hasParent) { + tableBrowser.rowToRowLinks.clear(); + } else { + Map rowIndex = new IdentityHashMap(); + Map rowIDIndex = new HashMap(); + Map parentRowIndex = new IdentityHashMap(); + Map parentRowIDIndex = new HashMap(); + for (int i = 0; i < rows.size(); ++i) { + Integer iI = i; + Row r = rows.get(i); + rowIndex.put(r, iI); + rowIDIndex.put(r.nonEmptyRowId, iI); + } + List parentRows = tableBrowser.parent.browserContentPane.rows; + for (int i = 0; i < parentRows.size(); ++i) { + Integer iI = i; + Row r = parentRows.get(i); + parentRowIndex.put(r, iI); + parentRowIDIndex.put(r.nonEmptyRowId, iI); + } + for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { + rowToRowLink.childRowIndex = -1; + Integer i = rowIndex.get(rowToRowLink.childRow); + if (i != null) { + rowToRowLink.childRowIndex = i; + } + // for (int i = 0; i < rows.size(); ++i) { + // if (rowToRowLink.childRow == rows.get(i)) { + // rowToRowLink.childRowIndex = i; + // break; + // } + // } + if (rowToRowLink.childRowIndex < 0) { + i = rowIDIndex.get(rowToRowLink.childRow.nonEmptyRowId); + if (i != null) { + rowToRowLink.childRowIndex = i; + } + // for (int i = 0; i < rows.size(); ++i) { + // if + // (rowToRowLink.childRow.rowId.equals(rows.get(i).rowId)) { + // rowToRowLink.childRowIndex = i; + // break; + // } + // } + } + rowToRowLink.parentRowIndex = -1; + i = parentRowIndex.get(rowToRowLink.parentRow); + if (i != null) { + rowToRowLink.parentRowIndex = i; + } + // for (int i = 0; i < parentRows.size(); ++i) { + // if (rowToRowLink.parentRow == parentRows.get(i)) { + // rowToRowLink.parentRowIndex = i; + // break; + // } + // } + + if (rowToRowLink.parentRowIndex < 0) { + i = parentRowIDIndex.get(rowToRowLink.parentRow.nonEmptyRowId); + if (i != null) { + rowToRowLink.parentRowIndex = i; + } + // for (int i = 0; i < parentRows.size(); ++i) { + // if + // (rowToRowLink.parentRow.rowId.equals(parentRows.get(i).rowId)) + // { + // rowToRowLink.parentRowIndex = i; + // break; + // } + // } + } + } + } + } + + private boolean suppressRepaintDesktop = false; + + /** + * Repaints the desktop. + */ + private void repaintDesktop() { + if (!suppressRepaintDesktop) { + calculateLinks(); + repaintScrollPane(); + } + } + + private void repaintScrollPane() { + JScrollPane scrollPane = getScrollPane(); + scrollPane.setSize(scrollPane.getWidth() + 1, scrollPane.getHeight() + 1); + scrollPane.setSize(scrollPane.getWidth() - 1, scrollPane.getHeight() - 1); + scrollPane.invalidate(); + scrollPane.validate(); + } + + /** + * Calculates coordinates of all link-renders. + * + * @return true iff something has changed + */ + private synchronized boolean calculateLinks() { + boolean changed = false; + Set linesHash = new HashSet(20000); + Map yPerRowTable1 = new HashMap(); + Map yPerRowTable2 = new HashMap(); + for (RowBrowser tableBrowser : tableBrowsers) { + JInternalFrame internalFrame = tableBrowser.internalFrame; + if (internalFrame.isMaximum()) { + changed = renderLinks; + renderLinks = false; + if (changed) { + rbSourceToLinks = null; + } + return changed; + } + if (tableBrowser.parent != null) { + int BORDER = 3; + int BOT_H = 32; + int x1 = internalFrame.getX(); // + internalFrame.getWidth() / 2; + int y1 = internalFrame.getY() + internalFrame.getHeight() / 2; + + RowBrowser visParent = tableBrowser.parent; + while (visParent != null && visParent.isHidden()) { + visParent = visParent.parent; + } + if (visParent == null) { + visParent = tableBrowser.parent; + } + + Rectangle cellRect = new Rectangle(); + boolean ignoreScrolling = false; + int i = 0; + + int x2 = visParent.internalFrame.getX(); + int y = cellRect.y; + y = cellRect.height * i; + int y2 = visParent.internalFrame.getY() + y + Math.min(cellRect.height / 2, 100); + // if (midx < x1) { + x2 += visParent.internalFrame.getWidth() - BORDER; + // } else { + // x2 += BORDER; + // } + Container p = visParent.browserContentPane.rowsTable; + if (ignoreScrolling) { + p = p.getParent(); + } + while (p != visParent.internalFrame) { + y2 += p.getY(); + p = p.getParent(); + } + int min = visParent.internalFrame.getY() + Math.min(cellRect.height, 20); + if (y2 < min) { + y2 = min; + } + int max = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() - BOT_H; + if (y2 > max) { + y2 = max; + } + + y2 = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() / 2; + + if (x1 != tableBrowser.x1 || y1 != tableBrowser.y1 || x2 != tableBrowser.x2 || y2 != tableBrowser.y2) { + changed = true; + tableBrowser.x1 = x1; + tableBrowser.y1 = y1; + tableBrowser.x2 = x2; + tableBrowser.y2 = y2; + } + + Rectangle visibleRect = getScrollPane().getViewport().getViewRect(); + int linkAreaXMin = Math.min(visParent.internalFrame.getX() + visParent.internalFrame.getWidth(), internalFrame.getX()); + int linkAreaYMin = Math.min(visParent.internalFrame.getY(), internalFrame.getY()); + int linkAreaXMax = Math.max(visParent.internalFrame.getX() + visParent.internalFrame.getWidth(), internalFrame.getX()); + int linkAreaYMax = Math.max(visParent.internalFrame.getY() + visParent.internalFrame.getHeight(), internalFrame.getY() + internalFrame.getHeight()); + boolean allInvisible = false; + if (!isIconOrHidden(visParent.internalFrame) && !isIconOrHidden(internalFrame)) { + if (linkAreaXMin > visibleRect.getX() + visibleRect.getWidth()) { + allInvisible = true; + } else if (linkAreaYMin > visibleRect.getY() + visibleRect.getHeight()) { + allInvisible = true; + } else if (linkAreaXMax < visibleRect.getX()) { + allInvisible = true; + } else if (linkAreaYMax < visibleRect.getY()) { + allInvisible = true; + } + } + + for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { + rowToRowLink.visible = !allInvisible; + if (!rowToRowLink.visible) { + continue; + } + x1 = y1 = x2 = y2 = -1; + try { + if (rowToRowLink.childRowIndex >= 0 && rowToRowLink.parentRowIndex >= 0) { + cellRect = new Rectangle(); + i = 0; + ignoreScrolling = false; + if (rowToRowLink.childRowIndex >= 0) { + i = tableBrowser.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(rowToRowLink.childRowIndex); + if (i < 0) { + rowToRowLink.visible = false; + continue; + } + cellRect = tableBrowser.browserContentPane.rowsTable.getCellRect(i, 0, true); + if (tableBrowser.browserContentPane.rows != null && tableBrowser.browserContentPane.rows.size() == 1) { + cellRect.setBounds(cellRect.x, 0, cellRect.width, Math.min(cellRect.height, 20)); + ignoreScrolling = true; + } + } + + x1 = internalFrame.getX(); + y = cellRect.height * i; + // if (r1) { + // x1 += internalFrame.getWidth()- BORDER; + // } else { + x1 += BORDER; + // } + + p = tableBrowser.browserContentPane.rowsTable; + Integer pY = yPerRowTable1.get(p); + if (pY != null) { + y1 = pY; + } else { + y1 = internalFrame.getY(); + if (ignoreScrolling) { + p = p.getParent(); + } + while (p != internalFrame) { + y1 += p.getY(); + p = p.getParent(); + } + yPerRowTable1.put(tableBrowser.browserContentPane.rowsTable, y1); + } + y1 += y + cellRect.height / 2; + min = internalFrame.getY() + cellRect.height * 2; + if (y1 < min) { + y1 = min; + } + max = internalFrame.getY() + internalFrame.getHeight() - BOT_H; + if (y1 > max) { + y1 = max; + } + ignoreScrolling = false; + cellRect = new Rectangle(); + i = 0; + if (rowToRowLink.parentRowIndex >= 0) { + i = tableBrowser.parent.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(rowToRowLink.parentRowIndex); + if (i < 0) { + rowToRowLink.visible = false; + continue; + } + cellRect = tableBrowser.parent.browserContentPane.rowsTable.getCellRect(i, 0, true); + if (tableBrowser.parent.browserContentPane.rows != null && tableBrowser.parent.browserContentPane.rows.size() == 1) { + cellRect.setBounds(cellRect.x, 0, cellRect.width, Math.min(cellRect.height, 20)); + ignoreScrolling = true; + } + } + + x2 = visParent.internalFrame.getX(); + y = cellRect.height * i; + // if (r2) { + x2 += visParent.internalFrame.getWidth() - BORDER; + // } else { + // x2 += BORDER; + // } + + p = visParent.browserContentPane.rowsTable; + pY = yPerRowTable2.get(p); + if (pY != null) { + y2 = pY; + } else { + y2 = visParent.internalFrame.getY(); + if (ignoreScrolling) { + p = p.getParent(); + } + while (p != visParent.internalFrame) { + y2 += p.getY(); + p = p.getParent(); + } + yPerRowTable2.put(visParent.browserContentPane.rowsTable, y2); + } + y2 += y + cellRect.height / 2; + min = visParent.internalFrame.getY() + cellRect.height; + if (y2 < min) { + y2 = min; + } + max = visParent.internalFrame.getY() + visParent.internalFrame.getHeight() - BOT_H; + if (y2 > max) { + y2 = max; + } + } + + if (tableBrowser.parent != null && tableBrowser.parent.internalFrame.isVisible() && tableBrowser.internalFrame.isVisible()) { + long shift = 32768; + long start = (long) x2 + shift * (long) y2; + long end = (long) x1 + shift * (long) y1; + long lineHash = start + shift * shift * end; + if (linesHash.contains(lineHash)) { + rowToRowLink.visible = false; + continue; + } else { + linesHash.add(lineHash); + } + } + + if (x1 != rowToRowLink.x1 || y1 != rowToRowLink.y1 || x2 != rowToRowLink.x2 || y2 != rowToRowLink.y2) { + changed = true; + rowToRowLink.x1 = x1; + rowToRowLink.y1 = y1; + rowToRowLink.x2 = x2; + rowToRowLink.y2 = y2; + } + } catch (Exception e) { + // ignore + } + } + } + } + + if (!renderLinks) { + changed = true; + } + renderLinks = true; + long currentTimeMillis = System.currentTimeMillis(); + if (lastPTS + 100 < currentTimeMillis) { + changed = true; + } + if (changed) { + lastPTS = currentTimeMillis; + } + if (changed) { + rbSourceToLinks = null; + } + + animationStep = currentTimeMillis / (double) STEP_DELAY; + + if (lastAnimationStepTime + STEP_DELAY < currentTimeMillis) { + changed = true; + lastAnimationStepTime = currentTimeMillis; + } + return changed; + } + + private boolean isIconOrHidden(JInternalFrame internalFrame) { + return internalFrame.isIcon() || !internalFrame.isVisible(); + } + + private long lastPTS = 0; + + private static class Link { + public boolean visible = true; + public final RowBrowser from, to; + public final String sourceRowID, destRowID; + public int x1, y1, x2, y2; + public final Color color1; + public final Color color2; + public final boolean dotted, intersect; + public final boolean inClosure; + public final boolean restricted; + + public Link(RowBrowser from, RowBrowser to, String sourceRowID, String destRowID, int x1, int y1, int x2, int y2, Color color1, Color color2, boolean dotted, + boolean intersect, boolean inClosure, boolean restricted) { + this.from = from; + this.to = to; + this.sourceRowID = sourceRowID; + this.destRowID = destRowID; + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.color1 = restricted? color1.brighter() : color1; + this.color2 = restricted? color2.brighter() : color2; + this.dotted = dotted; + this.intersect = intersect; + this.inClosure = inClosure; + this.restricted = restricted; + } + }; + + private Map>> rbSourceToLinks = null; + private long paintDuration = 0; + + /** + * Paints all link-renders. + */ + @Override + public synchronized void paint(Graphics graphics) { + long startTime = System.currentTimeMillis(); + super.paint(graphics); + if (graphics instanceof Graphics2D) { + final Graphics2D g2d = (Graphics2D) graphics; + renderActiveIFrameMarker(g2d); + if (renderLinks) { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + if (rbSourceToLinks == null) { + rbSourceToLinks = new HashMap>>(); + final String ALL = "-"; + + for (RowBrowser tableBrowser : tableBrowsers) { + Map> links = new TreeMap>(); + rbSourceToLinks.put(tableBrowser, links); + + Color color1 = tableBrowser.color1; + Color color2 = tableBrowser.color2; + boolean linkAdded = false; + boolean restricted = tableBrowser.parent != null && tableBrowser.browserContentPane.loadedRowsAreRestricted; + for (RowToRowLink rowToRowLink : tableBrowser.rowToRowLinks) { + if (rowToRowLink.x1 >= 0) { + linkAdded = true; + if (rowToRowLink.visible) { + String sourceRowID = rowToRowLink.childRow.nonEmptyRowId; + String destRowID = rowToRowLink.parentRow.nonEmptyRowId; + boolean inClosure = false; + + if (tableBrowser.parent != null) { + if (rowsClosure.currentClosure.contains(new Pair(tableBrowser.browserContentPane, rowToRowLink.childRow))) { + if (rowsClosure.currentClosure.contains(new Pair(tableBrowser.parent.browserContentPane, rowToRowLink.parentRow))) { + inClosure = true; + } + } + } + + Link link = new Link(tableBrowser, tableBrowser.parent, sourceRowID, destRowID, rowToRowLink.x1, rowToRowLink.y1, + rowToRowLink.x2, rowToRowLink.y2, color1, color2, false, false, inClosure, restricted); + List l = links.get(sourceRowID); + if (l == null) { + l = new ArrayList(); + links.put(sourceRowID, l); + } + l.add(link); + } + } + } + if (tableBrowser.parent != null && !linkAdded) { + String sourceRowID = ALL; + String destRowID = ALL; + boolean inClosure = false; + + Link link = new Link(tableBrowser, tableBrowser.parent, sourceRowID, destRowID, tableBrowser.x1, tableBrowser.y1, + tableBrowser.x2, tableBrowser.y2, color1, color2, true, true, inClosure, restricted); + List l = links.get(sourceRowID); + if (l == null) { + l = new ArrayList(); + links.put(sourceRowID, l); + } + l.add(link); + } + } + + // join links of hidden browser + List toJoinList = new ArrayList(); + for (RowBrowser tableBrowser : tableBrowsers) { + if (tableBrowser.parent != null && tableBrowser.parent.isHidden()) { + List newLinks = new ArrayList(); + Map> links = rbSourceToLinks.get(tableBrowser); + for (Map.Entry> e : links.entrySet()) { + for (Link link : e.getValue()) { + link.visible = false; + + List ll; + if (link.destRowID == ALL) { + ll = new ArrayList(); + for (List values : rbSourceToLinks.get(link.to).values()) { + for (Link l : values) { + ll.add(l); + } + } + } else { + ll = rbSourceToLinks.get(link.to).get(link.destRowID); + } + + toJoinList.clear(); + if (ll != null) { + toJoinList.addAll(ll); + } + ll = rbSourceToLinks.get(link.to).get(ALL); + if (ll != null) { + toJoinList.addAll(ll); + } + + for (Link toJoin : toJoinList) { + toJoin.visible = false; + boolean intersect = link.intersect; + boolean dotted = link.dotted || toJoin.dotted; + newLinks.add(new Link(link.from, toJoin.to, link.sourceRowID, toJoin.destRowID, link.x1, link.y1, toJoin.x2, toJoin.y2, + Color.yellow.darker().darker(), Color.yellow.darker(), dotted, intersect, link.inClosure && toJoin.inClosure, link.restricted || toJoin.restricted)); + } + } + } + for (Link link : newLinks) { + links.get(link.sourceRowID).add(link); + } + } + } + } + + Set pathToSelectedRowBrowser = new HashSet(); + for (RowBrowser rb: getBrowsers()) { + if (rb.internalFrame.isSelected()) { + for (RowBrowser parent = rb; parent != null; parent = parent.parent) { + pathToSelectedRowBrowser.add(parent); + } + break; + } + } + + Set linesHash = new HashSet(20000); + Map> linksToRenderPerTableBrowser = new HashMap>(); + Map dirPerTableBrowser = new HashMap(); + + for (final RowBrowser tableBrowser : rbSourceToLinks.keySet()) { + if (!tableBrowser.isHidden()) { + Map> links = rbSourceToLinks.get(tableBrowser); + final List linksToRender = new ArrayList(1000); + int dir = 0; + for (Map.Entry> e : links.entrySet()) { + for (Link link : e.getValue()) { + if (link.visible && !link.from.isHidden() && !link.to.isHidden()) { + long shift = 32768; + long start = (long) link.x2 + shift * (long) link.y2; + long end = (long) link.x1 + shift * (long) link.y1; + long lineHash = start + shift * shift * end; + if (!linesHash.contains(lineHash)) { + linksToRender.add(link); + linesHash.add(lineHash); + if (link.y1 < link.y2) { + ++dir; + } else { + --dir; + } + } + } + } + } + + final boolean isToParentLink = tableBrowser.association != null && tableBrowser.association.isInsertDestinationBeforeSource(); + Collections.sort(linksToRender, new Comparator() { + @Override + public int compare(Link a, Link b) { + if (isToParentLink) { + if (a.y1 != b.y1) { + return a.y1 - b.y1; + } else { + return a.y2 - b.y2; + } + } else { + if (a.y2 != b.y2) { + return a.y2 - b.y2; + } else { + return a.y1 - b.y1; + } + } + } + }); + linksToRenderPerTableBrowser.put(tableBrowser, linksToRender); + dirPerTableBrowser.put(tableBrowser, dir); + } + } + + final int MAX_PRIO = 3; + for (int prio = 0; prio <= MAX_PRIO; ++prio) { + for (final boolean pbg : new Boolean[] { true, false }) { + for (final RowBrowser tableBrowser : rbSourceToLinks.keySet()) { + if (!tableBrowser.isHidden()) { + final boolean inClosureRootPath = rowsClosure.parentPath.contains(tableBrowser.browserContentPane); + boolean light = true; + final Map followMe; + final boolean isToParentLink = tableBrowser.association != null && tableBrowser.association.isInsertDestinationBeforeSource(); + if (!isToParentLink) { + followMe = new HashMap(); + } else { + followMe = null; + } + int lastY = -1; + int lastLastY = -1; + boolean lastInClosure = false; + Map> renderTasks = new HashMap>(); + final List linksToRender = linksToRenderPerTableBrowser.get(tableBrowser); + if (linksToRender == null) { + continue; + } + Integer dv = dirPerTableBrowser.get(tableBrowser); + int dir = dv == null? 0 : dv; + for (int i = 0; i < linksToRender.size(); ++i) { + final Link link = linksToRender.get(i); + int y = isToParentLink? link.y1 : link.y2; + if (lastInClosure != link.inClosure) { + light = !light; + } else if (lastY != y) { + if (lastLastY == lastY) { + light = !light; + } else { + if (i < linksToRender.size() - 1) { + int nextY = isToParentLink? linksToRender.get(i + 1).y1 : linksToRender.get(i + 1).y2; + if (nextY == y) { + light = !light; + } + } + } + } + lastLastY = lastY; + lastY = y; + lastInClosure = link.inClosure; + Color cl = pbg ? Color.white : light? link.color1 : link.color2; + if (!Environment.nimbus) { + if (cl.getGreen() > cl.getBlue() && cl.getGreen() > cl.getRed()) { + if (link.restricted) { + cl = cl.brighter(); + } + } else { + double f = link.restricted? 2.0 : 1.5; + cl = new Color( + brighter(cl.getRed(), f), + brighter(cl.getGreen(), f), + brighter(cl.getBlue(), f)); + } + } + final Color color = link.restricted && Environment.nimbus? cl.darker() : cl; + final Point2D start = new Point2D.Double(link.x2, link.y2); + final Point2D end = new Point2D.Double(link.x1, link.y1); + final int ir = dir > 0? i : linksToRender.size() - 1 - i; + final boolean finalLight = light; + int linkPrio = 0; + if (pathToSelectedRowBrowser != null && pathToSelectedRowBrowser.contains(tableBrowser)) { + linkPrio += 2; + } + if (link.inClosure) { + linkPrio += 1; + } + final boolean doPaint = linkPrio == prio; + Runnable task = new Runnable() { + @Override + public void run() { + paintLink(start, end, color, g2d, tableBrowser, pbg, link.intersect, + link.dotted, + linksToRender.size() == 1 ? 0.5 : (ir + 1) * 1.0 / linksToRender.size(), + finalLight, followMe, + link.sourceRowID, link.inClosure, inClosureRootPath, + isToParentLink, + doPaint); + } + }; + List tasks = renderTasks.get(link.sourceRowID); + if (tasks == null) { + tasks = new LinkedList(); + renderTasks.put(link.sourceRowID, tasks); + } + tasks.add(task); + } + for (Entry> entry: renderTasks.entrySet()) { + List tasks = entry.getValue(); + Runnable mid = tasks.get(tasks.size() / 2); + mid.run(); + for (Runnable task: tasks) { + if (task != mid) { + task.run(); + } + } + } + } + } + } + } + iFrameStateChangeRenderer.render(g2d); + } + } + paintDuration = System.currentTimeMillis() - startTime; + deferRescaleMode(startTime); + } + + private int brighter(int col, double f) { + if (col > 128) { + return Math.min((int) (col * f), 255); + } else { + return Math.max(255 - (int) ((255 - col) / f), 0); + } + } + + private void renderActiveIFrameMarker(Graphics2D g2d) { + for (RowBrowser tableBrowser : tableBrowsers) { + if (tableBrowser.internalFrame.isSelected() && !isIconOrHidden(tableBrowser.internalFrame)) { + int z = 20; + double alpha = (animationStep % z) / (double) z * 2 * Math.PI; + double f = Math.sin(alpha) / 2.0 + 0.5; + Color color = markerColor(f, z); + g2d.setColor(color); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + BasicStroke stroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); + g2d.setStroke(stroke); + final int W = 3; + int x1 = tableBrowser.internalFrame.getX() + W ; + int y1 = tableBrowser.internalFrame.getY() - 3; + int x2 = tableBrowser.internalFrame.getX() + tableBrowser.internalFrame.getWidth() - 2 * W; + int y2 = y1; + g2d.drawLine(x1, y1, x2, y2); + f = Math.sin(alpha + Math.PI / 2) / 2.0 + 0.5; + color = markerColor(f, z); + g2d.setColor(color); + stroke = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); + g2d.setStroke(stroke); + g2d.drawLine(x1 - 2, y1 + 2, x2 + 2, y2 + 2); + } + } + } + + private Color markerColor(double f, int z) { + Color c1 = new Color(240, 130, 80); + Color c2 = new Color(225, 240, 100); + int r = (int) (c1.getRed() + f * (c2.getRed() - c1.getRed())); + int g = (int) (c1.getGreen() + f * (c2.getGreen() - c1.getGreen())); + int b = (int) (c1.getBlue() + f * (c2.getBlue() - c1.getBlue())); + Color color = new Color(r, g, b, 240); + return color; + } + + private double animationStep = 0; + long lastAnimationStepTime = 0; + final long STEP_DELAY = 50; + + private void paintLink(Point2D start, Point2D end, Color color, Graphics2D g2d, RowBrowser tableBrowser, + boolean pbg, boolean intersect, boolean dotted, double midPos, boolean light, + Map followMe, String sourceRowID, boolean inClosure, boolean inClosureRootPath, + boolean isToParentLink, boolean doPaint) { + if (doPaint) { + g2d.setColor(color); + BasicStroke stroke = new BasicStroke((!intersect ? (pbg ? inClosure? 3 : 2 : 1) : (pbg ? 3 : 2))); + if (inClosure) { + final int LENGTH = 16; + g2d.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), new float[] { 11f, 5f }, + (float) ((inClosureRootPath ^ isToParentLink)? animationStep % LENGTH : (LENGTH - animationStep % LENGTH)))); + } else { + g2d.setStroke(dotted ? new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), new float[] { 2f, 6f }, + 1.0f) : stroke); + } + } + + // compute the intersection with the target bounding box + if (intersect) { + Point2D[] sect = new Point2D[10]; + int i = GraphicsLib.intersectLineRectangle(start, end, tableBrowser.internalFrame.getBounds(), sect); + if (i > 0) { + end = sect[0]; + } + } + if (start.distance(end) < 2) + return; + + double border = 0.25; + double f = midPos * (1.0 - 2.0 * border); + int midX = (int) (start.getX() + ((end.getX() - start.getX()) * (border + f))); + f = 0.25 * f * (end.getY() - start.getY()); + + if (followMe != null) { + java.awt.geom.Point2D.Double follow = followMe.get(sourceRowID); + if (follow != null) { + midX = (int) follow.getX(); + f = follow.getY(); + } else { + followMe.put(sourceRowID, new Point2D.Double(midX, f)); + } + } + + if (!doPaint) { + return; + } + + Path2D.Double path = new Path2D.Double(); + if (isToParentLink) { + path.moveTo(end.getX() - 5, end.getY()); + path.curveTo(midX, end.getY(), midX, start.getY() + f, start.getX(), start.getY()); + } else { + path.moveTo(start.getX(), start.getY()); + path.curveTo(midX, start.getY() + f, midX, end.getY(), end.getX() - 5, end.getY()); + } + g2d.draw(path); + + // create the arrow head shape + m_arrowHead = new Polygon(); + double ws = 0.4; + double hs = 2.0 / 3.0; + double w = 3, h = w; + m_arrowHead.addPoint(0, 0); + m_arrowHead.addPoint((int) (ws * -w), (int) (hs * (-h))); + // m_arrowHead.addPoint(0, (int) (hs * (-2 * h))); + m_arrowHead.addPoint((int) (ws * w), (int) (hs * (-h))); + m_arrowHead.addPoint(0, 0); + + AffineTransform at = getArrowTrans(new Point2D.Double(midX, end.getY()), end, 9); + Shape m_curArrow = at.createTransformedShape(m_arrowHead); + + g2d.setStroke(new BasicStroke(2)); + g2d.fill(m_curArrow); + if (pbg) { + g2d.draw(m_curArrow); + } + } + + private Polygon m_arrowHead; + + /** + * Returns an affine transformation that maps the arrowhead shape to the + * position and orientation specified by the provided line segment end + * points. + */ + protected AffineTransform getArrowTrans(Point2D p1, Point2D p2, double width) { + AffineTransform m_arrowTrans = new AffineTransform(); + int o = 1; + m_arrowTrans.setToTranslation(p2.getX() + o, p2.getY()); + m_arrowTrans.rotate(-Math.PI / 2.0 + Math.atan2(p2.getY() - p1.getY(), p2.getX() + o - p1.getX())); + if (width > 1) { + double scalar = width / 2; + m_arrowTrans.scale(scalar, scalar); + } + return m_arrowTrans; + } + + private static int FRAME_OFFSET = 20; + private MDIDesktopManager manager; + + @Override + public void setBounds(int x, int y, int w, int h) { + super.setBounds(x, y, w, h); + checkDesktopSize(); + } + + public Component add(JInternalFrame frame) { + JInternalFrame[] array = getAllFrames(); + Point p; + int w; + int h; + + Component retval = super.add(frame); + checkDesktopSize(); + if (array.length > 0) { + p = array[0].getLocation(); + p.x = p.x + FRAME_OFFSET; + p.y = p.y + FRAME_OFFSET; + } else { + p = new Point(0, 0); + } + frame.setLocation(p.x, p.y); + if (frame.isResizable()) { + w = getWidth() - (getWidth() / 3); + h = getHeight() - (getHeight() / 3); + if (w < frame.getMinimumSize().getWidth()) + w = (int) frame.getMinimumSize().getWidth(); + if (h < frame.getMinimumSize().getHeight()) + h = (int) frame.getMinimumSize().getHeight(); + frame.setSize(w, h); + } + moveToFront(frame); + frame.setVisible(true); + try { + frame.setSelected(true); + } catch (PropertyVetoException e) { + frame.toBack(); + } + + return retval; + } + + @Override + public void remove(Component c) { + super.remove(c); + checkDesktopSize(); + } + + /** + * Cascade all internal frames + */ + public void cascadeFrames() { + int x = 0; + int y = 0; + JInternalFrame allFrames[] = getAllFrames(); + + manager.setNormalSize(); + int frameHeight = (getBounds().height - 5) - allFrames.length * FRAME_OFFSET; + int frameWidth = (getBounds().width - 5) - allFrames.length * FRAME_OFFSET; + for (int i = allFrames.length - 1; i >= 0; i--) { + allFrames[i].setSize(frameWidth, frameHeight); + allFrames[i].setLocation(x, y); + x = x + FRAME_OFFSET; + y = y + FRAME_OFFSET; + } + } + + /** + * Tile all internal frames + */ + public void tileFrames() { + java.awt.Component allFrames[] = getAllFrames(); + manager.setNormalSize(); + int frameHeight = getBounds().height / allFrames.length; + int y = 0; + for (int i = 0; i < allFrames.length; i++) { + allFrames[i].setSize(getBounds().width, frameHeight); + allFrames[i].setLocation(0, y); + y = y + frameHeight; + } + } + + private Dimension currentDesktopnSize; + private Dimension postAnimationDesktopnSize; + + /** + * Sets all component size properties ( maximum, minimum, preferred) to the + * given dimension. + */ + public boolean setAllSize(Dimension d) { + if (currentDesktopnSize != null && currentDesktopnSize.equals(d)) { + return false; + } + currentDesktopnSize = d; + setMinimumSize(d); + setMaximumSize(d); + setPreferredSize(d); + return true; + } + + /** + * Sets all component size properties ( maximum, minimum, preferred) to the + * given width and height. + */ + public boolean setAllSize(int width, int height) { + return setAllSize(new Dimension(width, height)); + } + + void checkDesktopSize() { + if (getParent() != null && isVisible()) + manager.resizeDesktop(); + } + + public JScrollPane getScrollPane() { + if (getParent() instanceof JViewport) { + JViewport viewPort = (JViewport) getParent(); + if (viewPort.getParent() instanceof JScrollPane) + return (JScrollPane) viewPort.getParent(); + } + return null; + } + + /** + * Private class used to replace the standard DesktopManager for + * JDesktopPane. Used to provide scrollbar functionality. + */ + class MDIDesktopManager extends DefaultDesktopManager { + private Desktop desktop; + + public MDIDesktopManager(Desktop desktop) { + this.desktop = desktop; + } + + @Override + public void endResizingFrame(JComponent f) { + super.endResizingFrame(f); + resizeDesktop(); + } + + @Override + public void endDraggingFrame(JComponent f) { + super.endDraggingFrame(f); + resizeDesktop(); + } + + public void setNormalSize() { + JScrollPane scrollPane = getScrollPane(); + int x = 0; + int y = 0; + Insets scrollInsets = getScrollPaneInsets(); + + if (scrollPane != null) { + Dimension d = scrollPane.getVisibleRect().getSize(); + if (scrollPane.getBorder() != null) { + d.setSize(d.getWidth() - scrollInsets.left - scrollInsets.right, d.getHeight() - scrollInsets.top - scrollInsets.bottom); + } + + d.setSize(d.getWidth() - 20, d.getHeight() - 20); + desktop.setAllSize(x, y); + scrollPane.invalidate(); + scrollPane.validate(); + } + } + + private Insets getScrollPaneInsets() { + JScrollPane scrollPane = getScrollPane(); + if (scrollPane == null) + return new Insets(0, 0, 0, 0); + else + return getScrollPane().getBorder().getBorderInsets(scrollPane); + } + + private JScrollPane getScrollPane() { + if (desktop.getParent() instanceof JViewport) { + JViewport viewPort = (JViewport) desktop.getParent(); + if (viewPort.getParent() instanceof JScrollPane) + return (JScrollPane) viewPort.getParent(); + } + return null; + } + + public void resizeDesktop() { + int x = 0; + int y = 0; + int paX = 0; + int paY = 0; + JScrollPane scrollPane = getScrollPane(); + Insets scrollInsets = getScrollPaneInsets(); + + if (scrollPane != null) { + boolean isMaximized = false; + JInternalFrame allFrames[] = desktop.getAllFrames(); + for (int i = 0; i < allFrames.length; i++) { + if (allFrames[i].isVisible()) { + if (allFrames[i].isMaximum()) { + isMaximized = true; + } + Rectangle bounds = allFrames[i].getBounds(); + if (bounds.getX() + bounds.getWidth() > x) { + x = (int) (bounds.getX() + bounds.getWidth()); + } + if (bounds.getY() + bounds.getHeight() > y) { + y = (int) (bounds.getY() + bounds.getHeight()); + } + if (bounds.getX() + bounds.getWidth() > paX) { + paX = (int) (bounds.getX() + bounds.getWidth()); + } + if (bounds.getY() + bounds.getHeight() > paY) { + paY = (int) (bounds.getY() + bounds.getHeight()); + } + bounds = desktopAnimation.getIFrameBounds(allFrames[i]); + if (bounds.getX() + bounds.getWidth() > paX) { + paX = (int) (bounds.getX() + bounds.getWidth()); + } + if (bounds.getY() + bounds.getHeight() > paY) { + paY = (int) (bounds.getY() + bounds.getHeight()); + } + } + } + Dimension d = scrollPane.getVisibleRect().getSize(); + if (scrollPane.getBorder() != null) { + d.setSize(d.getWidth() - scrollInsets.left - scrollInsets.right, d.getHeight() - scrollInsets.top - scrollInsets.bottom); + } + + if (x <= d.getWidth() || isMaximized) + x = ((int) d.getWidth()) - 20; + if (y <= d.getHeight() || isMaximized) + y = ((int) d.getHeight()) - 20; + postAnimationDesktopnSize = new Dimension(Math.max(paX, x), Math.max(paY, y)); + if (desktop.setAllSize(x, y) && !desktopAnimation.isActive()) { + scrollPane.invalidate(); + scrollPane.validate(); + } + } + } + } + + public synchronized void stop() { + running = false; + desktops.remove(this); + for (RowBrowser rb : tableBrowsers) { + rb.browserContentPane.cancelLoadJob(false); + } + if (session != null) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + synchronized (session) { + session.shutDown(); + } + } + }); + thread.setDaemon(true); + thread.start(); + } + } + + private final DataBrowser parentFrame; + + public static enum LayoutMode { + THUMBNAIL(0.22), + TINY(0.57), + L2(0.66), + SMALL(0.75), + L3(0.87), + MEDIUM(1.0), + L6(1.13), + L7(1.26), + LARGE(1.4); + + public final double factor; + + private LayoutMode(double factor) { + this.factor = factor; + } + } + + LayoutMode layoutMode = LayoutMode.MEDIUM; + + private boolean layouting = false; + + public void layoutBrowser(JInternalFrame selectedFrame, boolean scrollToCenter, RowBrowser anchor) { + if (layouting) { + return; + } + + try { + layouting = true; + if (selectedFrame == null) { + selectedFrame = getSelectedFrame(); + } + List all = new ArrayList(tableBrowsers); + // layout(all, 0); + + optimizeLayout(anchor); + + all.clear(); + int maxH = 0; + for (RowBrowser rb : tableBrowsers) { + if (rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable) { + all.add(rb); + } else { + maxH = Math.max(maxH, rb.internalFrame.getBounds().y + rb.internalFrame.getBounds().height); + } + } + layout(all, maxH + (int) (16 * layoutMode.factor)); + + checkDesktopSize(); + if (selectedFrame != null) { + try { + selectedFrame.setSelected(true); + } catch (PropertyVetoException e) { + // ignore + } + if (scrollToCenter) { + this.scrollToCenter(selectedFrame); + } + } + } finally { + layouting = false; + } + } + + private void layout(List toLayout, int maxH) { + List roots = new ArrayList(); + for (RowBrowser rb : toLayout) { + if (rb.parent == null) { + roots.add(rb); + } + } + while (!roots.isEmpty()) { + List nextColumn = new ArrayList(); + int i = 0; + for (RowBrowser rb : roots) { + try { + rb.internalFrame.setMaximum(false); + } catch (PropertyVetoException e) { + // ignore + } + int xPosition = -1; + if (maxH > 0) { + xPosition = i; + } + rb.internalFrame.setBounds(layout(rb.parent, rb.association, rb.browserContentPane, toLayout, maxH, xPosition)); + rb.browserContentPane.adjustRowTableColumnsWidth(); + toLayout.remove(rb); + for (RowBrowser rbc : toLayout) { + if (rbc.parent == rb) { + nextColumn.add(rbc); + } + } + ++i; + } + roots = nextColumn; + } + } + + /** + * Experimental layout optimization. + * @param anchor + */ + private void optimizeLayout(RowBrowser anchor) { + Set anchors = new HashSet(); + while (anchor != null) { + anchors.add(anchor); + anchor = anchor.parent; + } + TreeLayoutOptimizer.Node root = new TreeLayoutOptimizer.Node(null, false); + collectChildren(root, anchors); + TreeLayoutOptimizer.optimizeTreeLayout(root); + arrangeNodes(root); + } + + private void collectChildren(Node root, Set anchors) { + List children; + if (root.getUserObject() == null) { + children = getRootBrowsers(true); + } else { + children = getChildBrowsers(root.getUserObject(), true); + } + for (RowBrowser rb : children) { + if (rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable) { + continue; + } + TreeLayoutOptimizer.Node childNode = new TreeLayoutOptimizer.Node(rb, anchors.contains(rb)); + root.addChild(childNode); + collectChildren(childNode, anchors); + } + } + + private void arrangeNodes(Node root) { + if (root.getUserObject() != null) { + JInternalFrame iFrame = root.getUserObject().internalFrame; + int x = (int) (BROWSERTABLE_DEFAULT_MIN_X * layoutMode.factor); + int y = (int) (BROWSERTABLE_DEFAULT_MIN_Y * layoutMode.factor); + x += (root.getLevel() - 1) * (int) ((BROWSERTABLE_DEFAULT_WIDTH + BROWSERTABLE_DEFAULT_DISTANCE) * layoutMode.factor); + y += (int) (root.getPosition() * (BROWSERTABLE_DEFAULT_HEIGHT + 8) * layoutMode.factor); + int h = (int) (BROWSERTABLE_DEFAULT_HEIGHT * layoutMode.factor); + Rectangle r = new Rectangle(x, y, (int) (BROWSERTABLE_DEFAULT_WIDTH * layoutMode.factor), h); + // iFrame.setBounds(r); + desktopAnimation.setIFrameBounds(iFrame, root.getUserObject().browserContentPane, r, false); + } + for (Node child : root.getChildren()) { + arrangeNodes(child); + } + } + + private Map precBounds = new HashMap(); + + private static Collection desktops = new ArrayList(); + + public void rescaleLayout(LayoutMode layoutMode, Point fixed) { + double scale = layoutMode.factor / this.layoutMode.factor; + + if (fixed == null) { + fixed = new Point(getVisibleRect().x + getVisibleRect().width / 2, getVisibleRect().y + getVisibleRect().height / 2); + } + + try { + UIUtil.setWaitCursor(this); + this.layoutMode = layoutMode; + Map newPrecBounds = new HashMap(); + for (RowBrowser rb : new ArrayList(tableBrowsers)) { + if (rb.internalFrame.isMaximum()) { + try { + rb.internalFrame.setMaximum(false); + } catch (PropertyVetoException e) { + // ignore + } + } + Rectangle bounds = desktopAnimation.getIFrameBounds(rb.internalFrame); + Rectangle newBounds; + double[] pBounds = precBounds.get(bounds); + if (pBounds == null) { + pBounds = new double[] { bounds.x * scale, bounds.y * scale, bounds.width * scale, bounds.height * scale }; + } else { + pBounds = new double[] { pBounds[0] * scale, pBounds[1] * scale, pBounds[2] * scale, pBounds[3] * scale }; + } + newBounds = new Rectangle((int) pBounds[0], (int) pBounds[1], (int) pBounds[2], (int) pBounds[3]); + desktopAnimation.setIFrameBounds(rb.internalFrame, rb.browserContentPane, newBounds, true); + rb.browserContentPane.sortColumnsPanel.setVisible(LayoutMode.SMALL.factor <= layoutMode.factor); + newPrecBounds.put(newBounds, pBounds); + } + precBounds = newPrecBounds; + manager.resizeDesktop(); + + Rectangle vr = new Rectangle(Math.max(0, (int) (fixed.x * scale - getVisibleRect().width / 2)), Math.max(0, + (int) (fixed.y * scale - getVisibleRect().height / 2)), getVisibleRect().width, getVisibleRect().height); + desktopAnimation.scrollRectToVisible(vr, true); + updateMenu(layoutMode); + adjustClosure(null, null); + } finally { + UIUtil.resetWaitCursor(this); + } + } + + void onMouseWheelMoved(java.awt.event.MouseWheelEvent e, JScrollPane scrollPane, long currentTime) { + if (!inRescaleMode(currentTime)) { + if ((e.getScrollAmount() != 0) && (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)) { + JScrollBar toScroll = scrollPane.getVerticalScrollBar(); + int direction = 0; + + // find which scrollbar to scroll, or return if none + if ((toScroll == null) || !toScroll.isVisible() || ((e.getModifiers() & InputEvent.ALT_MASK) != 0)) { + toScroll = scrollPane.getHorizontalScrollBar(); + + if ((toScroll == null) || !toScroll.isVisible()) { + return; + } + } + + if (e.getWheelRotation() != 0) { + direction = (e.getWheelRotation() < 0) ? (-1) : 1; + } + + double f = 1.0; + + double pwr = e.getPreciseWheelRotation(); + if (pwr != 0.0) { + direction = pwr == 0? 0 : (pwr < 0) ? (-1) : 1; + f = Math.abs(pwr); + } + + if (direction != 0) { + int oldValue = toScroll.getValue(); + int blockIncrement = toScroll.getUnitIncrement(direction); + // allow for partial page overlapping + // blockIncrement -= 10; + int delta = (int) (f * blockIncrement * ((direction > 0) ? +1 : -1)); + int newValue = oldValue + delta; + + // Check for overflow. + if ((delta > 0) && (newValue < oldValue)) { + newValue = toScroll.getMaximum(); + } else if ((delta < 0) && (newValue > oldValue)) { + newValue = toScroll.getMinimum(); + } + + toScroll.setValue(newValue); + } + } + } + } + + void onMouseWheelMoved(java.awt.event.MouseWheelEvent e, long currentTime) { + if (inRescaleMode(currentTime)) { + int d = 0; + if (e.getWheelRotation() < 0) { + d = 1; + } + if (e.getWheelRotation() > 0) { + d = -1; + } + if (d != 0) { + for (RowBrowser rb : new ArrayList(tableBrowsers)) { + if (rb.internalFrame.isMaximum()) { + return; + } + } + d += layoutMode.ordinal(); + if (d >= 0 && d < LayoutMode.values().length) { + Point fixed = SwingUtilities.convertPoint(e.getComponent(), e.getPoint().x, e.getPoint().y, Desktop.this); + rescaleLayout(LayoutMode.values()[d], fixed); + rescaleFactorHasChanged = true; + } + } + } + } + + public void closeAll() { + closeAll(new ArrayList(tableBrowsers)); + } + + public void closeAll(Collection toClose) { + for (RowBrowser rb : toClose) { + close(rb, toClose.size() == 1); + // getDesktopManager().closeFrame(rb.internalFrame); + rb.internalFrame.dispose(); + } + updateMenu(); + } + + private void close(final RowBrowser tableBrowser, boolean convertChildrenToRoots) { + List children = new ArrayList(); + for (RowBrowser tb : tableBrowsers) { + if (tb.parent == tableBrowser) { + tb.parent = null; + children.add(tb); + } + } + tableBrowsers.remove(tableBrowser); + tableBrowser.browserContentPane.cancelLoadJob(true); + if (convertChildrenToRoots) { + for (RowBrowser child : children) { + child.convertToRoot(); + } + } + for (RowBrowser rb : tableBrowsers) { + updateChildren(rb, rb.browserContentPane.rows); + } + repaintDesktop(); + updateMenu(); + } + + /** + * Reloads the data model and replaces the tables in all browser windows. + */ + public void reloadDataModel(Map schemamapping) throws Exception { + reloadDataModel(schemamapping, true); + } + + /** + * Reloads the data model and replaces the tables in all browser windows. + */ + public void reloadDataModel(Map schemamapping, boolean forAll) throws Exception { + if (forAll) { + for (Desktop desktop : desktops) { + if (desktop != this) { + desktop.reloadDataModel(desktop.schemaMapping, false); + } + } + } + + try { + Component pFrame = SwingUtilities.getWindowAncestor(this); + if (pFrame == null) { + pFrame = this; + } + String filename = Environment.newFile(".tempsession-" + System.currentTimeMillis()).getPath(); + storeSession(filename); + + DataModel newModel = new DataModel(schemamapping, executionContext, false); + datamodel.set(newModel); + UISettings.dmStats(newModel); + + onNewDataModel(); + + restoreSession(null, pFrame, filename); + File file = new File(filename); + file.delete(); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } + } + + /** + * Reloads the rows in all root-table-browsers. + */ + public void reloadRoots() throws Exception { + for (RowBrowser rb : tableBrowsers) { + if (rb.browserContentPane != null) { + if (rb.parent == null) { + rb.browserContentPane.reloadRows(); + } + } + } + } + + private boolean loadSchemaMapping = true; + + public abstract void openSchemaAnalyzer(); + public abstract void onNewDataModel(); + public abstract void onLayoutChanged(boolean isLayouted, boolean scrollToCenter); + public abstract void updateBookmarksMenu(); + + public void openSchemaMappingDialog(boolean silent) { + try { + Map mapping = schemaMapping; + if (loadSchemaMapping || silent) { + mapping = SchemaMappingDialog.restore(dbConnectionDialog); + loadSchemaMapping = false; + } + if (!silent) { + SchemaMappingDialog schemaMappingDialog = new SchemaMappingDialog(parentFrame, datamodel.get(), dbConnectionDialog, session, mapping, executionContext); + mapping = schemaMappingDialog.getMapping(); + } + if (mapping != null && !mapping.isEmpty()) { + SchemaMappingDialog.store(mapping, dbConnectionDialog); + schemaMapping.clear(); + schemaMapping.putAll(mapping); + parentFrame.updateStatusBar(); + reloadDataModel(mapping, !silent); + reloadRoots(); + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e, session); + } + } + + /** + * Lets user chose a table browser and creates an extraction model for it. + */ + public void createExtractionModel(boolean doExport) { + Set titles = new TreeSet(); + Map rowBrowserByTitle = new HashMap(); + for (RowBrowser rb : tableBrowsers) { + if (rb.browserContentPane.table != null && !(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { + titles.add(rb.internalFrame.getTitle()); + rowBrowserByTitle.put(rb.internalFrame.getTitle(), rb); + } + } + String s = (String) JOptionPane.showInputDialog(this.parentFrame, "Select subject table", "Subject", JOptionPane.QUESTION_MESSAGE, null, + titles.toArray(), null); + if (s != null) { + rowBrowserByTitle.get(s).browserContentPane.openExtractionModelEditor(doExport); + } + } + + private AtomicBoolean updateMenuPending = new AtomicBoolean(false); + + void updateMenu() { + if (updateMenuPending.get()) { + return; + } + UIUtil.invokeLater(1, new Runnable() { + @Override + public void run() { + updateMenuPending.set(false); + + boolean hasTableBrowser = false; + boolean hasIFrame = false; + + for (RowBrowser rb : tableBrowsers) { + hasIFrame = true; + if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { + hasTableBrowser = true; + } + } + updateMenu(hasTableBrowser, hasIFrame); + } + }); + updateMenuPending.set(true); + } + + protected void updateMenu(boolean hasTableBrowser, boolean hasIFrame) { + if (!hasIFrame) { + if (!hasTableBrowser) { + currentSessionFileName = null; + } + } + } + + protected abstract void updateMenu(LayoutMode layoutMode); + + private final String LF = System.getProperty("line.separator", "\n"); + private String currentSessionFileName = null; + + /** + * Stores browser session. + */ + public void storeSession(BookmarksPanel bookmarksPanel) { + String fnProp = null; + int propLen = 0; + final String INVALID_CHARS = "[:;\\*\\?<>'`\"/\\\\\\~]+"; + for (RowBrowser rb : tableBrowsers) { + if (rb.browserContentPane.table != null) { + if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { + int l = 1; + RowBrowser parent; + for (parent = rb; parent.parent != null; parent = parent.parent) { + ++l; + } + String prop = datamodel.get().getDisplayName(parent.browserContentPane.table).replaceAll(INVALID_CHARS, " ").trim(); + if (parent != rb) { + prop += " - " + datamodel.get().getDisplayName(rb.browserContentPane.table).replaceAll(INVALID_CHARS, " ").trim(); + } + if (l > propLen || fnProp == null || l == propLen && fnProp.compareTo(prop) < 0) { + fnProp = prop; + propLen = l; + } + } + } + } + + if (fnProp != null && bookmarksPanel == null) { + fnProp += ".dbl"; + } + + if (bookmarksPanel == null) { + if (currentSessionFileName != null) { + fnProp = currentSessionFileName; + } + } + + String sFile; + + if (bookmarksPanel != null) { + File startDir = BookmarksPanel.getBookmarksFolder(executionContext); + sFile = bookmarksPanel.newBookmark(fnProp); + if (sFile != null) { + File f = new File(startDir, sFile + ".dbl"); + startDir.mkdirs(); + sFile = f.getAbsolutePath(); + } + } else { + File startDir = Environment.newFile("layout"); + Component pFrame = SwingUtilities.getWindowAncestor(this); + if (pFrame == null) { + pFrame = this; + } + sFile = UIUtil.choseFile(fnProp == null ? null : new File(startDir, fnProp), startDir.getPath(), "Store Layout", ".dbl", pFrame, true, false); + } + + if (sFile != null) { + try { + storeSession(sFile); + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } + if (bookmarksPanel == null) { + currentSessionFileName = sFile; + } else { + if (sFile != null && new File(sFile).exists()) { + new File(sFile).setLastModified(System.currentTimeMillis()); + } + bookmarksPanel.updateBookmarksMenu(); + updateAllBookmarkMenues(); + } + } + } + + public void updateAllBookmarkMenues() { + for (Desktop dTop: desktops) { + dTop.updateBookmarksMenu(); + } + } + + /** + * Stores browser session. + */ + void storeSession(String sFile) throws IOException { + int i = 1; + Map browserNumber = new HashMap(); + for (RowBrowser rb : tableBrowsers) { + browserNumber.put(rb, i++); + } + + FileWriter out = new FileWriter(new File(sFile)); + + out.write("Layout; " + layoutMode + LF); + + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == null) { + storeSession(rb, browserNumber, out); + } + } + out.close(); + } + + /** + * Recursively stores row-browser session. + */ + private void storeSession(RowBrowser rb, Map browserNumber, FileWriter out) throws IOException { + if (rb.browserContentPane.table != null) { + String csv = browserNumber.get(rb) + "; " + (rb.parent == null ? "" : browserNumber.get(rb.parent)) + "; "; + + String where = rb.browserContentPane.getAndConditionText().trim(); + + csv += CsvFile.encodeCell(where) + "; "; + + csv += rb.internalFrame.getLocation().x + "; " + rb.internalFrame.getLocation().y + "; "; + csv += rb.internalFrame.getSize().width + "; " + rb.internalFrame.getSize().height + "; "; + csv += 500 + "; " + rb.browserContentPane.selectDistinctCheckBox.isSelected() + "; "; + + if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { + csv += "T; " + CsvFile.encodeCell(rb.browserContentPane.table.getOriginalName()) + "; " + + (rb.association == null ? "" : CsvFile.encodeCell(rb.association.getName())) + "; "; + } + csv += rb.isHidden() + "; "; + csv += rb.browserContentPane.ignoreSortKey? "" : serializedSortKey(rb.browserContentPane.rowsTable); + out.append(csv).append(LF); + for (RowBrowser child : tableBrowsers) { + if (child.parent == rb) { + storeSession(child, browserNumber, out); + } + } + } + } + + private String serializedSortKey(JTable jTable) { + if (jTable != null) { + try { + List sortKeys = jTable.getRowSorter().getSortKeys(); + StringBuilder sb = new StringBuilder(); + for (SortKey sortKey: sortKeys) { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(sortKey.getColumn() + "|" + sortKey.getSortOrder()); + } + return sb.toString(); + } catch (Exception e) { + return null; // sort keys are lost + } + } + return null; + } + + private void deserializedSortKey(JTable jTable, String externaliuedSortKey) { + if (jTable != null && externaliuedSortKey != null && !externaliuedSortKey.trim().isEmpty()) { + try { + List sortKeys = new ArrayList(); + for (String externalizedKey: externaliuedSortKey.trim().split(",")) { + String[] columnOrder = externalizedKey.trim().split("\\|"); + if (columnOrder.length == 2) { + sortKeys.add(new SortKey(Integer.parseInt(columnOrder[0]), SortOrder.valueOf(columnOrder[1]))); + } + } + if (!sortKeys.isEmpty()) { + jTable.getRowSorter().setSortKeys(sortKeys); + } + } catch (Exception e) { + // ignore + } + } + } + + /** + * Restores browser session. + * @param bookMarkFile + */ + public void restoreSession(RowBrowser toBeAppended, File bookMarkFile) { + File startDir = Environment.newFile("layout"); + Component pFrame = SwingUtilities.getWindowAncestor(this); + if (pFrame == null) { + pFrame = this; + } + String sFile = bookMarkFile != null? bookMarkFile.getAbsolutePath() : UIUtil.choseFile(null, startDir.getPath(), toBeAppended == null ? "Restore Layout" : "Append Layout", ".dbl", pFrame, true, true); + + if (sFile != null) { + try { + UIUtil.setWaitCursor(pFrame); + noArrangeLayoutOnNewTableBrowser = true; + restoreSession(toBeAppended, pFrame, sFile); + if (toBeAppended == null) { + currentSessionFileName = sFile; + } + } catch (Throwable e) { + UIUtil.showException(this, "Error", e, session); + } finally { + noArrangeLayoutOnNewTableBrowser = false; + UIUtil.resetWaitCursor(pFrame); + } + } + } + + /** + * Restores browser session. + */ + private void restoreSession(RowBrowser toBeAppended, Component pFrame, String sFile) throws Exception { + try { + UIUtil.setWaitCursor(pFrame); + iFrameStateChangeRenderer.startAtomic(); + noArrangeLayoutOnNewTableBrowser = true; + + String tbaPeerID = null; + Map rbByID = new HashMap(); + List lines = new CsvFile(new File(sFile)).getLines(); + if (toBeAppended == null) { + closeAll(); + } + Collection toBeLoaded = new ArrayList(); + List unknownTables = new ArrayList(); + KnownIdentifierMap knownTablesMap = new KnownIdentifierMap(); + Map originalNameToTable = new HashMap(); + for (Table table: datamodel.get().getTables()) { + knownTablesMap.putTableName(table.getOriginalName()); + originalNameToTable.put(table.getOriginalName(), table); + } + for (CsvFile.Line l : lines) { + if (l.cells.get(0).equals("Layout")) { + try { + if (toBeAppended == null) { + layoutMode = LayoutMode.valueOf(l.cells.get(1)); + updateMenu(layoutMode); + } + } catch (Exception e) { + e.printStackTrace(); + } + continue; + } + + String id = l.cells.get(0); + String parent = l.cells.get(1); + String where = l.cells.get(2); + Point loc = new Point(Integer.parseInt(l.cells.get(3)), Integer.parseInt(l.cells.get(4))); + Dimension size = new Dimension(Integer.parseInt(l.cells.get(5)), Integer.parseInt(l.cells.get(6))); + boolean selectDistinct = Boolean.parseBoolean(l.cells.get(8)); + RowBrowser rb = null; + if ("T".equals(l.cells.get(9))) { + Table table = originalNameToTable.get(l.cells.get(10)); + if (table == null) { + String kt = knownTablesMap.getTableName(l.cells.get(10)); + if (kt != null) { + table = originalNameToTable.get(kt); + } + } + if (table == null) { + unknownTables.add(l.cells.get(10)); + } else { + Association association = datamodel.get().namedAssociations.get(l.cells.get(11)); + RowBrowser parentRB = rbByID.get(parent); + if (association == null) { + parentRB = null; + } + boolean add = true; + if (toBeAppended != null) { + if (tbaPeerID == null) { + add = false; + if (parent.trim().length() == 0 && table.equals(toBeAppended.browserContentPane.table)) { + tbaPeerID = id; + } + } else { + if (tbaPeerID.equals(parent)) { + parentRB = toBeAppended; + } else if (!rbByID.containsKey(parent)) { + add = false; + } + } + } + if (add) { + rb = addTableBrowser(parentRB, parentRB, table, parentRB != null ? association : null, where, selectDistinct, null, false); + if (id.length() > 0) { + rbByID.put(id, rb); + } + if (parentRB == null || parentRB == toBeAppended) { + toBeLoaded.add(rb); + } + } + } + } else { + if (toBeAppended == null) { + rb = addTableBrowser(null, null, null, null, where, selectDistinct, null, false); + toBeLoaded.add(rb); + } + } + if (rb != null) { + rb.setHidden(Boolean.parseBoolean(l.cells.get(12))); + if (toBeAppended == null) { + rb.internalFrame.setLocation(loc); + rb.internalFrame.setSize(size); + } + deserializedSortKey(rb.browserContentPane.rowsTable, l.cells.get(13)); + } + } + checkDesktopSize(); + makePrimaryRootVisible(); + + for (RowBrowser rb : toBeLoaded) { + rb.browserContentPane.reloadRows(); + } + + if (toBeAppended != null && toBeLoaded.isEmpty()) { + JOptionPane.showMessageDialog(pFrame, + "Layout doesn't contain table \"" + datamodel.get().getDisplayName(toBeAppended.browserContentPane.table) + "\" as root."); + } else if (!unknownTables.isEmpty()) { + String pList = ""; + for (String ut : unknownTables) { + pList += ut + "\n"; + } + JOptionPane.showMessageDialog(pFrame, "Unknown tables:\n\n" + pList + "\n"); + } + } finally { + noArrangeLayoutOnNewTableBrowser = false; + iFrameStateChangeRenderer.rollbackAtomic(); + UIUtil.resetWaitCursor(pFrame); + } + } + + private void makePrimaryRootVisible() { + RowBrowser root = null; + for (RowBrowser rb : getRootBrowsers(true)) { + if (rb.browserContentPane.table != null) { + if (!(rb.browserContentPane.table instanceof BrowserContentPane.SqlStatementTable)) { + root = rb; + break; + } + } + } + if (root != null) { + try { + root.internalFrame.setSelected(true); + } catch (PropertyVetoException e) { + // ignore + } + this.scrollToCenter(root.internalFrame); + } else { + this.desktopAnimation.scrollRectToVisible(new Rectangle(0, 0, 1, 1), false); + } + } + + public JInternalFrame[] getAllFramesFromTableBrowsers() { + List frames = new ArrayList(); + for (RowBrowser rb : tableBrowsers) { + frames.add(rb.internalFrame); + } + return frames.toArray(new JInternalFrame[frames.size()]); + } + + public List getRootBrowsers(boolean ignoreHidden) { + List roots = new ArrayList(); + + if (ignoreHidden) { + for (RowBrowser rb : tableBrowsers) { + if (!rb.isHidden()) { + RowBrowser p = rb.parent; + while (p != null && p.isHidden()) { + p = p.parent; + } + if (p == null) { + roots.add(rb); + } + } + } + } else { + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == null) { + roots.add(rb); + } + } + } + return roots; + } + + public List getBrowsers() { + return new ArrayList(tableBrowsers); + } + + public List getChildBrowsers(RowBrowser parent, boolean ignoreHidden) { + List roots = new ArrayList(); + + if (ignoreHidden) { + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == parent) { + if (rb.isHidden()) { + roots.addAll(getChildBrowsers(rb, true)); + } else { + roots.add(rb); + } + } + } + } else { + for (RowBrowser rb : tableBrowsers) { + if (rb.parent == parent) { + roots.add(rb); + } + } + } + return roots; + } + + public static Boolean forceAdjustRows = false; + + /** + * Adjusts scroll-position of each table browser s.t. rows in closure are + * visible. + * + * @param tabu don't adjust this one + * @param thisOne only adjust this one if it is not null + */ + protected synchronized void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { + if (forceAdjustRows == null) { + return; + } + for (RowBrowser rb : tableBrowsers) { + if (rb.browserContentPane == tabu) { + continue; + } + if (thisOne != null && rb.browserContentPane != thisOne) { + continue; + } + + Set rowsOfParent = new HashSet(); + if (rb.parent != null) { + for (Pair r : rowsClosure.currentClosure) { + if (r.a == rb.parent.browserContentPane) { + rowsOfParent.add(r.b); + } + } + } + + List rowsOfRB = new ArrayList(); + Set rowsOfRBSet = new LinkedHashSet(); + for (RowToRowLink link: rb.rowToRowLinks) { + if (rowsOfParent.contains(link.parentRow)) { + rowsOfRBSet.add(link.childRow); + } + } + for (Pair r : rowsClosure.currentClosure) { + if (r.a == rb.browserContentPane) { + if (rowsOfRBSet.isEmpty() || rowsOfRBSet.contains(r.b)) { + rowsOfRB.add(r.b); + } + } + } + + int topBorder = -1; + if (rb.parent != null) { + Rectangle firstParentRowPos = null; + for (Row r : rowsOfParent) { + int index = rb.parent.browserContentPane.rows.indexOf(r); + if (index < 0) { + for (int n = 0; n < rb.parent.browserContentPane.rows.size(); ++n) { + if (r.nonEmptyRowId.equals(rb.parent.browserContentPane.rows.get(n).nonEmptyRowId)) { + index = n; + break; + } + } + } + + if (index < 0) { + // not visible due to distinct selection + continue; + } + index = rb.parent.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(index); + Rectangle pos = rb.parent.browserContentPane.rowsTable.getCellRect(index, 0, false); + + if (firstParentRowPos == null || firstParentRowPos.y > pos.y) { + firstParentRowPos = pos; + } + } + if (firstParentRowPos != null) { + Rectangle visibleRect = rb.parent.browserContentPane.rowsTable.getVisibleRect(); + if (!(firstParentRowPos.y > visibleRect.getMaxY() || firstParentRowPos.y < visibleRect.getMinY())) { + topBorder = (int) (firstParentRowPos.y - visibleRect.getMinY()); + } + } + } + + if (!rowsOfRB.isEmpty()) { + Rectangle firstRowPos = null; + Rectangle lastRowPos = null; + Rectangle visibleRect = rb.browserContentPane.rowsTable.getVisibleRect(); + for (Row r : rowsOfRB) { + int index = rb.browserContentPane.rows.indexOf(r); + if (index < 0) { + for (int n = 0; n < rb.browserContentPane.rows.size(); ++n) { + if (r.nonEmptyRowId.equals(rb.browserContentPane.rows.get(n).nonEmptyRowId)) { + index = n; + break; + } + } + } + + if (index < 0) { + // not visible due to distinct selection + continue; + } + index = rb.browserContentPane.rowsTable.getRowSorter().convertRowIndexToView(index); + Rectangle pos = rb.browserContentPane.rowsTable.getCellRect(index, 0, false); + + if (!forceAdjustRows && pos.y >= visibleRect.y && pos.y + pos.height < visibleRect.y + visibleRect.height) { + // already a visible row + firstRowPos = null; + lastRowPos = null; + break; + } + if (firstRowPos == null || firstRowPos.y > pos.y) { + firstRowPos = pos; + } + if (lastRowPos == null || lastRowPos.y < pos.y) { + lastRowPos = pos; + } + } + if (lastRowPos != null && firstRowPos != null && rb.browserContentPane.rowsTable.getRowCount() > 0) { + lastRowPos = rb.browserContentPane.rowsTable.getCellRect(rb.browserContentPane.rowsTable.getRowCount(), 0, false); + } + if (lastRowPos != null) { + rb.browserContentPane.rowsTable + .scrollRectToVisible(new Rectangle(visibleRect.x, lastRowPos.y - lastRowPos.height, 1, 3 * lastRowPos.height)); + } + if (firstRowPos != null) { + if (topBorder >= 0 && topBorder < firstRowPos.y && topBorder + 2 * firstRowPos.height < visibleRect.height) { + rb.browserContentPane.rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, firstRowPos.y - topBorder, 1, + topBorder + firstRowPos.height)); + } else { + rb.browserContentPane.rowsTable.scrollRectToVisible(new Rectangle(visibleRect.x, firstRowPos.y - firstRowPos.height, 1, + 3 * firstRowPos.height)); + } + } + } + } + for (RowBrowser rb : tableBrowsers) { + rb.browserContentPane.updateSingleRowDetailsView(); + } + + rbSourceToLinks = null; + repaintDesktop(); + } + + /** + * Opens new Browser and adds complete sub-tree of {@link RowBrowser}. + * + * @param tableBrowser + * the root + */ + private void showInNewWindow(RowBrowser tableBrowser) { + DataBrowser newDataBrowser = openNewDataBrowser(); + if (newDataBrowser != null) { + newDataBrowser.desktop.layoutMode = layoutMode; + newDataBrowser.desktop.updateMenu(layoutMode); + + StringBuilder cond = new StringBuilder(); + Set known = new HashSet(); + synchronized (this) { + for (Row r : tableBrowser.browserContentPane.rows) { + if (!known.contains(r.rowId)) { + known.add(r.rowId); + if (cond.length() > 0) { + cond.append(" or \n"); + } + cond.append("(" + SqlUtil.replaceAliases(r.rowId, "A", "A") + ")"); + } + } + } + + RowBrowser root = addTableBrowserSubTree(newDataBrowser, tableBrowser, null, null, cond.length() > 0? cond.toString() : null); + root.browserContentPane.reloadRows(); + newDataBrowser.arrangeLayout(true); + try { + JInternalFrame iFrame = root.internalFrame; + newDataBrowser.desktop.scrollToCenter(iFrame); + iFrame.setSelected(true); + iFrame.grabFocus(); + } catch (PropertyVetoException e1) { + // ignore + } + } + } + + private RowBrowser addTableBrowserSubTree(DataBrowser newDataBrowser, RowBrowser tableBrowser, RowBrowser parent, RowBrowser origParent, String rootCond) { + RowBrowser rb; + if (parent == null) { + rb = newDataBrowser.desktop.addTableBrowser(null, null, tableBrowser.browserContentPane.table, null, + rootCond == null ? tableBrowser.browserContentPane.getAndConditionText() : rootCond, + tableBrowser.browserContentPane.selectDistinctCheckBox.isSelected(), null, false); + } else { + rb = newDataBrowser.desktop.addTableBrowser(parent, origParent, tableBrowser.browserContentPane.table, + tableBrowser.browserContentPane.association, rootCond == null ? tableBrowser.browserContentPane.getAndConditionText() : rootCond, + tableBrowser.browserContentPane.selectDistinctCheckBox.isSelected(), null, false); + } + rb.setHidden(tableBrowser.isHidden()); + + for (RowBrowser child : getChildBrowsers(tableBrowser, false)) { + addTableBrowserSubTree(newDataBrowser, child, rb, tableBrowser, null); + } + return rb; + } + + protected abstract DataBrowser openNewDataBrowser(); + protected abstract SQLConsole getSqlConsole(boolean switchToConsole); + protected abstract boolean isDesktopVisible(); + protected abstract void checkAnchorRetension(); + protected abstract void changeColumnOrder(Table table); + protected abstract void onRowSelect(Table table, Row row); + + /** + * Scrolls an iFrame to the center of the desktop. + */ + public void scrollToCenter(JInternalFrame iFrame) { + demaximize(); + int w = getVisibleRect().width; + int h = getVisibleRect().height; + Rectangle bounds = desktopAnimation.getIFrameBounds(iFrame); + int x = bounds.x + bounds.width / 2 - getVisibleRect().width / 2; + int y = bounds.y + bounds.height / 2 - getVisibleRect().height / 2; + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + Rectangle r = new Rectangle(x, y, Math.max(1, w), Math.max(1, h)); + Rectangle vr = new Rectangle(postAnimationDesktopnSize != null? postAnimationDesktopnSize : currentDesktopnSize == null? getScrollPane().getViewport().getPreferredSize() : currentDesktopnSize); + desktopAnimation.scrollRectToVisible(r.intersection(vr), false); + } + + /** + * Collect layout of tables in a extraction model. + * + * @param positions + * to put positions into + */ + private void collectPositions(RowBrowser root, Map> positions) { + List>> toDo = new LinkedList>>(); + toDo.add(new Pair>(root, new Pair(1, 1))); + String subject = root.browserContentPane.table.getName(); // datamodel.get().getDisplayName(root.browserContentPane.table); + double scaleX = 0.35 / layoutMode.factor; + double scaleY = 0.3 / layoutMode.factor; + double scher = 2; + + while (!toDo.isEmpty()) { + Pair> rowBrowser = toDo.remove(0); + int i = 1; + for (RowBrowser child : getChildBrowsers(rowBrowser.a, true)) { + toDo.add(new Pair>(child, new Pair(rowBrowser.b.a + 1, i++))); + } + String table = rowBrowser.a.browserContentPane.table.getName(); // datamodel.get().getDisplayName(rowBrowser.a.browserContentPane.table); + Map tablePos = positions.get(subject); + if (tablePos == null) { + tablePos = new TreeMap(); + positions.put(subject, tablePos); + } + if (!tablePos.containsKey(table)) { + double x = rowBrowser.a.internalFrame.getX(); + double y = rowBrowser.a.internalFrame.getY(); + tablePos.put(table, new double[] { x * scaleX + scher * (2 * (rowBrowser.b.b % 2) - 1), y * scaleY + scher * (2 * (rowBrowser.b.a % 2) - 1), + 1.0 }); + } + } + } + + /** + * For concurrent reload of rows. + */ + public static final PriorityBlockingQueue runnableQueue = new PriorityBlockingQueue(100, + new Comparator() { + + @Override + public int compare(RunnableWithPriority o1, RunnableWithPriority o2) { + return o2.getPriority() - o1.getPriority(); + } + }); + + static boolean noArrangeLayoutOnNewTableBrowser = false; + static boolean noArrangeLayoutOnNewTableBrowserWithAnchor = false; + private static JInternalFrame lastInternalFrame = null; + private static BrowserContentPane lastBrowserContentPane = null; + public void catchUpLastArrangeLayoutOnNewTableBrowser() { + if (lastInternalFrame != null) { + this.scrollToCenter(lastInternalFrame); + try { + lastInternalFrame.setSelected(true); + } catch (PropertyVetoException e1) { + // ignore + } + if (lastBrowserContentPane != null) { + lastBrowserContentPane.andCondition.grabFocus(); + } + onLayoutChanged(false, true); + } + resetLastArrangeLayoutOnNewTableBrowser(); + } + + public static void resetLastArrangeLayoutOnNewTableBrowser() { + lastInternalFrame = null; + lastBrowserContentPane = null; + } + + private void logFPS(Map durations, long now, long avgD) { +// long k = durations.keySet().iterator().next(); +// if (k != now && desktopAnimation.isActive()) { +// System.out.println(avgD + " FPS " + 1000.0 * (((double) durations.size() / (now - k)))); +// } + } + + private final int RESCALE_DURATION = 500; + private Long rescaleModeEnd; + private Point rescaleStartPosition; + private boolean rescaleFactorHasChanged = false; + + public void startRescaleMode(long currentTime, MouseWheelEvent evt) { + rescaleModeEnd = currentTime + RESCALE_DURATION; + rescaleStartPosition = new Point(evt.getX(), evt.getY()); + SwingUtilities.convertPointToScreen(rescaleStartPosition, evt.getComponent()); + } + + public void checkRescaleMode(MouseWheelEvent evt, long currentTime) { +// if (inRescaleMode(currentTime)) { +// if (rescaleStartPosition != null) { +// Point position = new Point(evt.getX(), evt.getY()); +// SwingUtilities.convertPointToScreen(position, evt.getComponent()); +// if (position.distance(rescaleStartPosition) > 1000) { +// rescaleModeEnd = null; +// } +// } +// } + } + + private boolean inRescaleMode(long currentTime) { + return rescaleModeEnd != null && currentTime < rescaleModeEnd; + } + + private void deferRescaleMode(long startTime) { + if (inRescaleMode(startTime) && rescaleFactorHasChanged) { + long duration = System.currentTimeMillis() - startTime; + rescaleModeEnd += duration; + } + rescaleFactorHasChanged = false; + } + + private boolean animationEnabled = true; + + public boolean isAnimationEnabled() { + return animationEnabled; + } + + public void setAnimationEnabled(boolean animationEnabled) { + this.animationEnabled = animationEnabled; + } + + public void zoom(int d) { + d += layoutMode.ordinal(); + if (d >= 0 && d < LayoutMode.values().length) { + rescaleLayout(LayoutMode.values()[d], null); + } + } + + public String getRawSchemaMapping() { + StringBuilder mapping = new StringBuilder(); + for (String schema: schemaMapping.keySet()) { + String to = schemaMapping.get(schema).trim(); + if (!schema.equals(to)) { + if (mapping.length() > 0) { + mapping.append(","); + } + mapping.append(schema + "=" + to); + } + } + return mapping.toString(); + } + + private Row currentlyViewedRow = null; + + public static class FindClosureContext { + Map>> childRowsPartitions = new HashMap>>(); + Map>> parentRowsPartitions = new HashMap>>(); + + Collection getChildPartition(RowBrowser browser, Row row) { + Map> partitionPerBrowser = childRowsPartitions.get(browser); + if (partitionPerBrowser == null) { + partitionPerBrowser = new HashMap>(); + childRowsPartitions.put(browser, partitionPerBrowser); + for (RowToRowLink link: browser.rowToRowLinks) { + Collection partition = partitionPerBrowser.get(link.childRow.nonEmptyRowId); + if (partition == null) { + partition = new ArrayList(); + partitionPerBrowser.put(link.childRow.nonEmptyRowId, partition); + } + partition.add(link); + } + } + Collection partition = partitionPerBrowser.get(row.nonEmptyRowId); + if (partition == null) { + partition = new ArrayList(); + partitionPerBrowser.put(row.nonEmptyRowId, partition); + } + return partition; + } + + Collection getParentPartition(RowBrowser browser, Row row) { + Map> partitionPerBrowser = parentRowsPartitions.get(browser); + if (partitionPerBrowser == null) { + partitionPerBrowser = new HashMap>(); + parentRowsPartitions.put(browser, partitionPerBrowser); + for (RowToRowLink link: browser.rowToRowLinks) { + Collection partition = partitionPerBrowser.get(link.parentRow.nonEmptyRowId); + if (partition == null) { + partition = new ArrayList(); + partitionPerBrowser.put(link.parentRow.nonEmptyRowId, partition); + } + partition.add(link); + } + } + Collection partition = partitionPerBrowser.get(row.nonEmptyRowId); + if (partition == null) { + partition = new ArrayList(); + partitionPerBrowser.put(row.nonEmptyRowId, partition); + } + return partition; + } + + } + + /** + * Maximum number of concurrent DB connections. + */ + private static final int MAX_CONCURRENT_CONNECTIONS = 6; + static { + // initialize listeners for #runnableQueue + for (int i = 0; i < MAX_CONCURRENT_CONNECTIONS; ++i) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + for (;;) { + RunnableWithPriority take = null; + try { + take = runnableQueue.take(); + take.run(); + } catch (InterruptedException e) { + // ignore + } catch (CancellationException e) { + // ignore + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + }, "PQueue-Worker-" + (i + 1)); + t.setDaemon(true); + t.start(); + } + } + +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataDetailsPanel.java b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataDetailsPanel.java index b1191232a..a48d106a8 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataDetailsPanel.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataDetailsPanel.java @@ -1,579 +1,580 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser.metadata; - -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; - -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; - -import org.apache.log4j.Logger; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.Column; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.PrimaryKey; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.MemorizedResultSet; -import net.sf.jailer.modelbuilder.ModelBuilder; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.QueryBuilderDialog; -import net.sf.jailer.ui.QueryBuilderDialog.Relationship; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.databrowser.BrowserContentPane; -import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; -import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; -import net.sf.jailer.ui.databrowser.Reference; -import net.sf.jailer.ui.databrowser.Row; -import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; -import net.sf.jailer.util.Pair; - -/** - * Meta Data Details View. - * - * @author Ralf Wisser - */ -public abstract class MetaDataDetailsPanel extends javax.swing.JPanel { - - /** - * The logger. - */ - private static final Logger logger = Logger.getLogger(MetaDataDetailsPanel.class); - - private final Reference datamodel; - private final Session session; - private final ExecutionContext executionContext; - private final JFrame owner; - private static final List> queues = new ArrayList>(); - private final Map detailsPanels = new HashMap(); - private final JPanel ddlPanel; - private final JPanel constraintsPanel; - private final Map, JComponent> detailsViews = new HashMap, JComponent>(); - private final Map tableDetailsViews = new HashMap(); - - /** - * Creates new form MetaDataDetailsPanell - */ - public MetaDataDetailsPanel(Reference datamodel, Session session, JFrame owner, ExecutionContext executionContext) { - this.datamodel = datamodel; - this.session = session; - this.owner = owner; - this.executionContext = executionContext; - initComponents(); - - if (session != null && session.dbms.getConstraintsQuery() != null) { - constraintsPanel = new JPanel(new BorderLayout()); - } else { - constraintsPanel = null; - } - ddlPanel = new JPanel(new BorderLayout()); - for (MetaDataDetails mdd: MetaDataDetails.values()) { - JPanel panel = new JPanel(new BorderLayout()); - detailsPanels.put(mdd, panel); - tabbedPane.addTab(mdd.name, panel); - if (tabbedPane.getTabCount() == 3) { - tabbedPane.addTab("DDL", ddlPanel); - } - if (tabbedPane.getTabCount() == 4) { - if (constraintsPanel != null) { - tabbedPane.addTab("Constraints", constraintsPanel); - } - } - } - ((CardLayout) getLayout()).show(this, "table"); - } - - static { - for (int i = 0; i < 3; ++i) { - final LinkedBlockingQueue queue = new LinkedBlockingQueue(); - queues.add(queue); - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - for (;;) { - try { - queue.take().run(); - } catch (Throwable t) { - logger.info("error", t); - } - } - } - }, "Metadata-LoadDetails-" + (i + 1)); - thread.setDaemon(true); - thread.start(); - } - } - - public void clear() { - setVisible(false); - } - - public void reset() { - detailsViews.clear(); - tableDetailsViews.clear(); - } - - public void showMetaDataDetails(MDGeneric mdOther, ExecutionContext executionContext) { - setVisible(true); - ((CardLayout) getLayout()).show(this, "other"); - otherPanel.removeAll(); - JComponent render = mdOther.getRender(session, executionContext); - otherPanel.add(render); - render.revalidate(); - otherPanel.repaint(); - } - - public void showMetaDataDetails(final MDTable mdTable, Table table, Row row, boolean onlyTable, DataModel dataModel) { - setVisible(true); - ((CardLayout) getLayout()).show(this, "table"); - tableDetailsPanel.removeAll(); - if (table != null) { - TableDetailsView view = tableDetailsViews.get(table); - if (row != null || view == null) { - TableDetailsView tdv = new TableDetailsView(table, mdTable, this, row, dataModel, (TableDetailsView) view); - view = tdv; - if (row == null && tdv.isCacheable()) { - tableDetailsViews.put(table, view); - } - } - tableDetailsPanel.add(view); - } else if (mdTable != null && !ModelBuilder.isJailerTable(mdTable.getUnquotedName())) { - JButton analyseButton = new JButton("Analyse schema \"" + mdTable.getSchema().getUnquotedName() + "\""); - analyseButton.setIcon(MetaDataPanel.getScaledIcon(this, MetaDataPanel.warnIcon, false)); - analyseButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - analyseSchema(mdTable.getSchema().getName(), mdTable.isView(), mdTable.isSynonym()); - } - }); - JPanel panel = new JPanel(new GridBagLayout()); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - panel.add(new JLabel(" Table \"" + mdTable.getUnquotedName() + "\""), gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - panel.add(new JLabel(" is not part of the data model."), gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1; - gridBagConstraints.weighty = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - if (mdTable.isLoaded()) { - List pkColumns = new ArrayList(); - List columns = new ArrayList(); - for (Column c: mdTable.getColumnTypes()) { - columns.add(c); - try { - for (String pk: mdTable.getPrimaryKeyColumns()) { - if (pk.equals(c.name)) { - pkColumns.add(c); - break; - } - } - } catch (SQLException e1) { - // ignore - } - } - PrimaryKey pks = new PrimaryKey(pkColumns, false); - Table tTable = new Table(mdTable.getName(), pks, false, false); - tTable.setColumns(columns); - panel.add(new TableDetailsView(tTable, mdTable, this, null, dataModel, null), gridBagConstraints); - } - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - panel.add(analyseButton, gridBagConstraints); - tableDetailsPanel.add(panel); - } - tabbedPane.repaint(); - if (onlyTable) { - return; - } - for (BlockingQueue queue: queues) { - queue.clear(); - } - for (final MetaDataDetails mdd: MetaDataDetails.values()) { - final JPanel panel = detailsPanels.get(mdd); - panel.removeAll(); - final Pair cacheKey = new Pair(mdd, mdTable); - if (detailsViews.containsKey(cacheKey)) { - JComponent comp = detailsViews.get(cacheKey); - panel.add(comp); - tabbedPane.repaint(); - continue; - } - panel.add(new JLabel(" loading...")); - tabbedPane.repaint(); - try { - final int tableNameColumnIndex = 3; - final Set pkNames = Collections.synchronizedSet(new HashSet()); - final BrowserContentPane rb = new BrowserContentPane(datamodel.get(), null, "", session, null, - null, null, new BrowserContentPane.RowsClosure(), false, false, executionContext) { - { - noSingleRowDetailsView = true; - rowsTableScrollPane.setWheelScrollingEnabled(true); - sortColumnsCheckBox.setVisible(false); - sortColumnsPanel.setVisible(false); - statusPanel.setVisible(false); - } - @Override - protected int getReloadLimit() { - return Integer.MAX_VALUE; - } - - @Override - protected void unhide() { - } - @Override - protected void showInNewWindow() { - } - @Override - protected void reloadDataModel() throws Exception { - } - @Override - protected void openSchemaMappingDialog() { - } - @Override - protected void openSchemaAnalyzer() { - } - @Override - protected void onRedraw() { - tabbedPane.repaint(); - } - @Override - protected void onHide() { - } - @Override - protected void onContentChange(List rows, boolean reloadChildren) { - } - @Override - protected RowBrowser navigateTo(Association association, List pRows) { - return null; - } - @Override - protected List getTableBrowser() { - return null; - } - @Override - protected PriorityBlockingQueue getRunnableQueue() { - return null; - } - @Override - protected QueryBuilderDialog getQueryBuilderDialog() { - return null; - } - @Override - protected RowBrowser getParentBrowser() { - return null; - } - @Override - protected JFrame getOwner() { - return owner; - } - @Override - protected double getLayoutFactor() { - return 0; - } - @Override - protected DbConnectionDialog getDbConnectionDialog() { - return null; - } - @Override - protected List getChildBrowsers() { - return new ArrayList(); - } - @Override - protected void findClosure(Row row, Set> closure, boolean forward) { - } - @Override - protected void findClosure(Row row) { - } - @Override - protected Relationship createQBRelations(boolean withParents) { - return null; - } - @Override - protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { - return null; - } - @Override - protected void collectPositions(Map> positions) { - } - @Override - protected void close() { - } - @Override - protected void beforeReload() { - } - @Override - protected void appendLayout() { - } - @Override - protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { - } - @Override - protected void addRowToRowLink(Row pRow, Row exRow) { - } - @Override - protected boolean renderRowAsPK(Row theRow) { - if (tableNameColumnIndex >= 0 && tableNameColumnIndex < theRow.values.length) { - return pkNames.contains(theRow.values[tableNameColumnIndex]); - } - return false; - } - @Override - protected MetaDataSource getMetaDataSource() { - return null; - } - @Override - protected SQLConsole getSqlConsole(boolean switchToConsole) { - return null; - } - @Override - protected void deselectChildrenIfNeededWithoutReload() { - } - }; - - final MemorizedResultSet[] metaDataDetails = new MemorizedResultSet[1]; - - queues.get(mdd.queueIndex).put(new Runnable() { - @Override - public void run() { - try { - pkNames.addAll(mdTable.getPrimaryKeyColumns(false)); - } catch (SQLException e1) { - logger.info("error", e1); - } - try { - synchronized (session.getMetaData()) { - ResultSet rs = mdd.readMetaDataDetails(session, mdTable); - metaDataDetails[0] = new MemorizedResultSet(rs, null, session, null); - rs.close(); - } - } catch (SQLException e) { - // ignore - } - if (metaDataDetails[0] != null) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - LoadJob loadJob = rb.newLoadJob(metaDataDetails[0], null); - loadJob.run(); - JComponent rTabContainer = rb.getRowsTableContainer(); - detailsViews.put(cacheKey, rTabContainer); - final JTable rTab = rb.getRowsTable(); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - mdd.adjustRowsTable(rTab); - panel.removeAll(); - JComponent rTabContainer = rb.getRowsTableContainer(); - panel.add(rTabContainer); - rb.resetRowsTableContainer(); - tabbedPane.repaint(); - } - }); - } - }); - } - } - }); - } catch (InterruptedException e) { - // ignore - } - } - - // DDL - final JPanel panel = ddlPanel; - final Runnable doRun = new Runnable() { - @Override - public void run() { - final String ddl = mdTable.getDDL(); - panel.removeAll(); - if (ddl == null) { - panel.add(new JLabel(" DDL not available")); - } else { - JScrollPane tab = new JScrollPane(); - RSyntaxTextArea area = new RSyntaxTextArea(); - area.setBracketMatchingEnabled(false); - - area.setEditable(false); - tab.setViewportView(area); - area.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); - area.setText(ddl); - area.setCaretPosition(0); - panel.add(tab); - } - tabbedPane.repaint(); - } - }; - panel.removeAll(); - if (mdTable.isDDLLoaded()) { - doRun.run(); - } else { - panel.add(new JLabel(" loading...")); - tabbedPane.repaint(); - try { - queues.get(2).put(new Runnable() { - @Override - public void run() { - mdTable.getDDL(); - UIUtil.invokeLater(doRun); - } - }); - } catch (InterruptedException e) { - // ignore - } - } - - if (constraintsPanel != null) { - // Constraints - final Runnable doRunGetConstraints = new Runnable() { - @Override - public void run() { - final MemorizedResultSet constraints; - try { - constraints = mdTable.getSchema().getConstraints(mdTable); - } catch (SQLException e) { - constraintsPanel.removeAll(); - constraintsPanel.add(new JLabel(" Error: " + e.getMessage())); - tabbedPane.repaint(); - return; - } - constraintsPanel.removeAll(); - if (constraints == null) { - constraintsPanel.add(new JLabel(" Constraints not available")); - } else { - ResultSetRenderer area; - try { - area = new ResultSetRenderer(constraints, "Constraints", datamodel.get(), session, executionContext); - } catch (SQLException e) { - return; - } - constraintsPanel.add(area); - } - tabbedPane.repaint(); - } - }; - constraintsPanel.removeAll(); - if (mdTable.getSchema().isConstraintsLoaded()) { - doRunGetConstraints.run(); - } else { - constraintsPanel.add(new JLabel(" loading...")); - tabbedPane.repaint(); - MDSchema.loadMetaData(new Runnable() { - @Override - public void run() { - try { - mdTable.getSchema().getConstraints(null); - if (mdTable.getSchema().isConstraintsLoaded()) { - UIUtil.invokeLater(doRunGetConstraints); - } - } catch (final Throwable t) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - constraintsPanel.removeAll(); - constraintsPanel.add(new JLabel(" Error: " + t.getMessage())); - tabbedPane.repaint(); - } - }); - } - } - }, 1); - } - } - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - jPanel1 = new javax.swing.JPanel(); - tabbedPane = new javax.swing.JTabbedPane(); - tableDetailsPanel = new javax.swing.JPanel(); - otherPanel = new javax.swing.JPanel(); - - setLayout(new java.awt.CardLayout()); - - jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.LINE_AXIS)); - - tabbedPane.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT); - - tableDetailsPanel.setLayout(new java.awt.BorderLayout()); - tabbedPane.addTab("Table", tableDetailsPanel); - - jPanel1.add(tabbedPane); - - add(jPanel1, "table"); - - otherPanel.setLayout(new javax.swing.BoxLayout(otherPanel, javax.swing.BoxLayout.LINE_AXIS)); - add(otherPanel, "other"); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel otherPanel; - private javax.swing.JTabbedPane tabbedPane; - private javax.swing.JPanel tableDetailsPanel; - // End of variables declaration//GEN-END:variables - - protected abstract void analyseSchema(String schemaName, boolean withViews, boolean withSynonyms); - -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser.metadata; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +import org.apache.log4j.Logger; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.Column; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.PrimaryKey; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.MemorizedResultSet; +import net.sf.jailer.modelbuilder.ModelBuilder; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.QueryBuilderDialog; +import net.sf.jailer.ui.QueryBuilderDialog.Relationship; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.databrowser.BrowserContentPane; +import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; +import net.sf.jailer.ui.databrowser.Desktop.FindClosureContext; +import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; +import net.sf.jailer.ui.databrowser.Reference; +import net.sf.jailer.ui.databrowser.Row; +import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; +import net.sf.jailer.util.Pair; + +/** + * Meta Data Details View. + * + * @author Ralf Wisser + */ +public abstract class MetaDataDetailsPanel extends javax.swing.JPanel { + + /** + * The logger. + */ + private static final Logger logger = Logger.getLogger(MetaDataDetailsPanel.class); + + private final Reference datamodel; + private final Session session; + private final ExecutionContext executionContext; + private final JFrame owner; + private static final List> queues = new ArrayList>(); + private final Map detailsPanels = new HashMap(); + private final JPanel ddlPanel; + private final JPanel constraintsPanel; + private final Map, JComponent> detailsViews = new HashMap, JComponent>(); + private final Map tableDetailsViews = new HashMap(); + + /** + * Creates new form MetaDataDetailsPanell + */ + public MetaDataDetailsPanel(Reference datamodel, Session session, JFrame owner, ExecutionContext executionContext) { + this.datamodel = datamodel; + this.session = session; + this.owner = owner; + this.executionContext = executionContext; + initComponents(); + + if (session != null && session.dbms.getConstraintsQuery() != null) { + constraintsPanel = new JPanel(new BorderLayout()); + } else { + constraintsPanel = null; + } + ddlPanel = new JPanel(new BorderLayout()); + for (MetaDataDetails mdd: MetaDataDetails.values()) { + JPanel panel = new JPanel(new BorderLayout()); + detailsPanels.put(mdd, panel); + tabbedPane.addTab(mdd.name, panel); + if (tabbedPane.getTabCount() == 3) { + tabbedPane.addTab("DDL", ddlPanel); + } + if (tabbedPane.getTabCount() == 4) { + if (constraintsPanel != null) { + tabbedPane.addTab("Constraints", constraintsPanel); + } + } + } + ((CardLayout) getLayout()).show(this, "table"); + } + + static { + for (int i = 0; i < 3; ++i) { + final LinkedBlockingQueue queue = new LinkedBlockingQueue(); + queues.add(queue); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + for (;;) { + try { + queue.take().run(); + } catch (Throwable t) { + logger.info("error", t); + } + } + } + }, "Metadata-LoadDetails-" + (i + 1)); + thread.setDaemon(true); + thread.start(); + } + } + + public void clear() { + setVisible(false); + } + + public void reset() { + detailsViews.clear(); + tableDetailsViews.clear(); + } + + public void showMetaDataDetails(MDGeneric mdOther, ExecutionContext executionContext) { + setVisible(true); + ((CardLayout) getLayout()).show(this, "other"); + otherPanel.removeAll(); + JComponent render = mdOther.getRender(session, executionContext); + otherPanel.add(render); + render.revalidate(); + otherPanel.repaint(); + } + + public void showMetaDataDetails(final MDTable mdTable, Table table, Row row, boolean onlyTable, DataModel dataModel) { + setVisible(true); + ((CardLayout) getLayout()).show(this, "table"); + tableDetailsPanel.removeAll(); + if (table != null) { + TableDetailsView view = tableDetailsViews.get(table); + if (row != null || view == null) { + TableDetailsView tdv = new TableDetailsView(table, mdTable, this, row, dataModel, (TableDetailsView) view); + view = tdv; + if (row == null && tdv.isCacheable()) { + tableDetailsViews.put(table, view); + } + } + tableDetailsPanel.add(view); + } else if (mdTable != null && !ModelBuilder.isJailerTable(mdTable.getUnquotedName())) { + JButton analyseButton = new JButton("Analyse schema \"" + mdTable.getSchema().getUnquotedName() + "\""); + analyseButton.setIcon(MetaDataPanel.getScaledIcon(this, MetaDataPanel.warnIcon, false)); + analyseButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + analyseSchema(mdTable.getSchema().getName(), mdTable.isView(), mdTable.isSynonym()); + } + }); + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(new JLabel(" Table \"" + mdTable.getUnquotedName() + "\""), gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(new JLabel(" is not part of the data model."), gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1; + gridBagConstraints.weighty = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + if (mdTable.isLoaded()) { + List pkColumns = new ArrayList(); + List columns = new ArrayList(); + for (Column c: mdTable.getColumnTypes()) { + columns.add(c); + try { + for (String pk: mdTable.getPrimaryKeyColumns()) { + if (pk.equals(c.name)) { + pkColumns.add(c); + break; + } + } + } catch (SQLException e1) { + // ignore + } + } + PrimaryKey pks = new PrimaryKey(pkColumns, false); + Table tTable = new Table(mdTable.getName(), pks, false, false); + tTable.setColumns(columns); + panel.add(new TableDetailsView(tTable, mdTable, this, null, dataModel, null), gridBagConstraints); + } + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(analyseButton, gridBagConstraints); + tableDetailsPanel.add(panel); + } + tabbedPane.repaint(); + if (onlyTable) { + return; + } + for (BlockingQueue queue: queues) { + queue.clear(); + } + for (final MetaDataDetails mdd: MetaDataDetails.values()) { + final JPanel panel = detailsPanels.get(mdd); + panel.removeAll(); + final Pair cacheKey = new Pair(mdd, mdTable); + if (detailsViews.containsKey(cacheKey)) { + JComponent comp = detailsViews.get(cacheKey); + panel.add(comp); + tabbedPane.repaint(); + continue; + } + panel.add(new JLabel(" loading...")); + tabbedPane.repaint(); + try { + final int tableNameColumnIndex = 3; + final Set pkNames = Collections.synchronizedSet(new HashSet()); + final BrowserContentPane rb = new BrowserContentPane(datamodel.get(), null, "", session, null, + null, null, new BrowserContentPane.RowsClosure(), false, false, executionContext) { + { + noSingleRowDetailsView = true; + rowsTableScrollPane.setWheelScrollingEnabled(true); + sortColumnsCheckBox.setVisible(false); + sortColumnsPanel.setVisible(false); + statusPanel.setVisible(false); + } + @Override + protected int getReloadLimit() { + return Integer.MAX_VALUE; + } + + @Override + protected void unhide() { + } + @Override + protected void showInNewWindow() { + } + @Override + protected void reloadDataModel() throws Exception { + } + @Override + protected void openSchemaMappingDialog() { + } + @Override + protected void openSchemaAnalyzer() { + } + @Override + protected void onRedraw() { + tabbedPane.repaint(); + } + @Override + protected void onHide() { + } + @Override + protected void onContentChange(List rows, boolean reloadChildren) { + } + @Override + protected RowBrowser navigateTo(Association association, List pRows) { + return null; + } + @Override + protected List getTableBrowser() { + return null; + } + @Override + protected PriorityBlockingQueue getRunnableQueue() { + return null; + } + @Override + protected QueryBuilderDialog getQueryBuilderDialog() { + return null; + } + @Override + protected RowBrowser getParentBrowser() { + return null; + } + @Override + protected JFrame getOwner() { + return owner; + } + @Override + protected double getLayoutFactor() { + return 0; + } + @Override + protected DbConnectionDialog getDbConnectionDialog() { + return null; + } + @Override + protected List getChildBrowsers() { + return new ArrayList(); + } + @Override + protected void findClosure(Row row, Set> closure, boolean forward, FindClosureContext findClosureContext) { + } + @Override + protected void findClosure(Row row) { + } + @Override + protected Relationship createQBRelations(boolean withParents) { + return null; + } + @Override + protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { + return null; + } + @Override + protected void collectPositions(Map> positions) { + } + @Override + protected void close() { + } + @Override + protected void beforeReload() { + } + @Override + protected void appendLayout() { + } + @Override + protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { + } + @Override + protected void addRowToRowLink(Row pRow, Row exRow) { + } + @Override + protected boolean renderRowAsPK(Row theRow) { + if (tableNameColumnIndex >= 0 && tableNameColumnIndex < theRow.values.length) { + return pkNames.contains(theRow.values[tableNameColumnIndex]); + } + return false; + } + @Override + protected MetaDataSource getMetaDataSource() { + return null; + } + @Override + protected SQLConsole getSqlConsole(boolean switchToConsole) { + return null; + } + @Override + protected void deselectChildrenIfNeededWithoutReload() { + } + }; + + final MemorizedResultSet[] metaDataDetails = new MemorizedResultSet[1]; + + queues.get(mdd.queueIndex).put(new Runnable() { + @Override + public void run() { + try { + pkNames.addAll(mdTable.getPrimaryKeyColumns(false)); + } catch (SQLException e1) { + logger.info("error", e1); + } + try { + synchronized (session.getMetaData()) { + ResultSet rs = mdd.readMetaDataDetails(session, mdTable); + metaDataDetails[0] = new MemorizedResultSet(rs, null, session, null); + rs.close(); + } + } catch (SQLException e) { + // ignore + } + if (metaDataDetails[0] != null) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + LoadJob loadJob = rb.newLoadJob(metaDataDetails[0], null); + loadJob.run(); + JComponent rTabContainer = rb.getRowsTableContainer(); + detailsViews.put(cacheKey, rTabContainer); + final JTable rTab = rb.getRowsTable(); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + mdd.adjustRowsTable(rTab); + panel.removeAll(); + JComponent rTabContainer = rb.getRowsTableContainer(); + panel.add(rTabContainer); + rb.resetRowsTableContainer(); + tabbedPane.repaint(); + } + }); + } + }); + } + } + }); + } catch (InterruptedException e) { + // ignore + } + } + + // DDL + final JPanel panel = ddlPanel; + final Runnable doRun = new Runnable() { + @Override + public void run() { + final String ddl = mdTable.getDDL(); + panel.removeAll(); + if (ddl == null) { + panel.add(new JLabel(" DDL not available")); + } else { + JScrollPane tab = new JScrollPane(); + RSyntaxTextArea area = new RSyntaxTextArea(); + area.setBracketMatchingEnabled(false); + + area.setEditable(false); + tab.setViewportView(area); + area.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); + area.setText(ddl); + area.setCaretPosition(0); + panel.add(tab); + } + tabbedPane.repaint(); + } + }; + panel.removeAll(); + if (mdTable.isDDLLoaded()) { + doRun.run(); + } else { + panel.add(new JLabel(" loading...")); + tabbedPane.repaint(); + try { + queues.get(2).put(new Runnable() { + @Override + public void run() { + mdTable.getDDL(); + UIUtil.invokeLater(doRun); + } + }); + } catch (InterruptedException e) { + // ignore + } + } + + if (constraintsPanel != null) { + // Constraints + final Runnable doRunGetConstraints = new Runnable() { + @Override + public void run() { + final MemorizedResultSet constraints; + try { + constraints = mdTable.getSchema().getConstraints(mdTable); + } catch (SQLException e) { + constraintsPanel.removeAll(); + constraintsPanel.add(new JLabel(" Error: " + e.getMessage())); + tabbedPane.repaint(); + return; + } + constraintsPanel.removeAll(); + if (constraints == null) { + constraintsPanel.add(new JLabel(" Constraints not available")); + } else { + ResultSetRenderer area; + try { + area = new ResultSetRenderer(constraints, "Constraints", datamodel.get(), session, executionContext); + } catch (SQLException e) { + return; + } + constraintsPanel.add(area); + } + tabbedPane.repaint(); + } + }; + constraintsPanel.removeAll(); + if (mdTable.getSchema().isConstraintsLoaded()) { + doRunGetConstraints.run(); + } else { + constraintsPanel.add(new JLabel(" loading...")); + tabbedPane.repaint(); + MDSchema.loadMetaData(new Runnable() { + @Override + public void run() { + try { + mdTable.getSchema().getConstraints(null); + if (mdTable.getSchema().isConstraintsLoaded()) { + UIUtil.invokeLater(doRunGetConstraints); + } + } catch (final Throwable t) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + constraintsPanel.removeAll(); + constraintsPanel.add(new JLabel(" Error: " + t.getMessage())); + tabbedPane.repaint(); + } + }); + } + } + }, 1); + } + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + tabbedPane = new javax.swing.JTabbedPane(); + tableDetailsPanel = new javax.swing.JPanel(); + otherPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.CardLayout()); + + jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.LINE_AXIS)); + + tabbedPane.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT); + + tableDetailsPanel.setLayout(new java.awt.BorderLayout()); + tabbedPane.addTab("Table", tableDetailsPanel); + + jPanel1.add(tabbedPane); + + add(jPanel1, "table"); + + otherPanel.setLayout(new javax.swing.BoxLayout(otherPanel, javax.swing.BoxLayout.LINE_AXIS)); + add(otherPanel, "other"); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel otherPanel; + private javax.swing.JTabbedPane tabbedPane; + private javax.swing.JPanel tableDetailsPanel; + // End of variables declaration//GEN-END:variables + + protected abstract void analyseSchema(String schemaName, boolean withViews, boolean withSynonyms); + +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataPanel.java b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataPanel.java index eda6e352f..f1aca0fc7 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataPanel.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/MetaDataPanel.java @@ -1,1944 +1,1944 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser.metadata; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.image.BufferedImage; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JToggleButton; -import javax.swing.JTree; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.ExpandVetoException; -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.TreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; - -import org.apache.log4j.Logger; -import org.fife.rsta.ui.EscapableDialog; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.configuration.DBMS; -import net.sf.jailer.configuration.DatabaseObjectRenderingDescription; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; -import net.sf.jailer.modelbuilder.MemorizedResultSet; -import net.sf.jailer.modelbuilder.ModelBuilder; -import net.sf.jailer.ui.AutoCompletion; -import net.sf.jailer.ui.JComboBox; -import net.sf.jailer.ui.StringSearchPanel; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.UIUtil.IconWithText; -import net.sf.jailer.ui.databrowser.Row; -import net.sf.jailer.util.Quoting; - -/** - * Meta Data UI. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public abstract class MetaDataPanel extends javax.swing.JPanel { - - /** - * The logger. - */ - private static final Logger logger = Logger.getLogger(MetaDataPanel.class); - - private final MetaDataSource metaDataSource; - private final JComboBox tablesComboBox; - private final DataModel dataModel; - private final MetaDataDetailsPanel metaDataDetailsPanel; - private final Frame parent; - private final JToggleButton searchButton; - private final ExecutionContext executionContext; - - private final Object CATEGORY_VIEWS = new String("Views"); - private final Object CATEGORY_TABLES = new String("Tables"); - private final Object CATEGORY_SYNONYMS = new String("Synonyms"); - - /** - * Packages list view. - */ - private class MDPackages extends MDDescriptionBasedGeneric { - - private MDPackages(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { - super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { - { - setIconURL("/net/sf/jailer/ui/resource/packages.png"); - DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); - itemDescr.setIconURL("/net/sf/jailer/ui/resource/package.png"); - itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); - setItemDescription(itemDescr); - } - }); - } - - @Override - public List getDetails() { - ArrayList result = new ArrayList(); - try { - MemorizedResultSet theList = retrieveList(getMetaDataSource().getSession()); - for (final Object[] row: theList.getRowList()) { - MDProcedures procs = new MDProcedures(String.valueOf(row[0]), metaDataSource, schema, dataModel) { - @Override - protected boolean select(Object[] proc) { - return proc[2] != null && proc[2].equals(row[0]); - } - }; - procs.databaseObjectRenderingDescription.setIconURL("/net/sf/jailer/ui/resource/package.png"); - procs.databaseObjectRenderingDescription.setTextQuery(schema.getMetaDataSource().getSession().dbms.getPackageSourceQuery()); - result.add(procs); - } - } catch (Throwable t) { - logger.info("error", t); - } - return result; - } - - @Override - public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { - Set cats = null; - if (session.dbms.getPackageNamesQuery() != null) { - Statement cStmt = null; - try { - Connection connection = session.getConnection(); - cStmt = connection.createStatement(); - if (schema != null) { - schema = Quoting.staticUnquote(schema); - } - ResultSet rs = cStmt.executeQuery(String.format(Locale.ENGLISH, session.dbms.getPackageNamesQuery(), schema)); - MemorizedResultSet result = new MemorizedResultSet(rs, null, session, schema); - result.close(); - rs.close(); - cats = new TreeSet(); - for (Object[] cat: result.getRowList()) { - cats.add((String) cat[0]); - } - } catch (Exception e) { - logger.info("error", e); - } finally { - if (cStmt != null) { - try { - cStmt.close(); - } catch (SQLException e) { - } - } - } - } - if (cats == null) { - cats = new TreeSet(); - ResultSet rs = getProcedures(session, session.getMetaData(), schema, "%"); - while (rs.next()) { - String cat = rs.getString(1); - if (cat != null) { - cats.add(cat); - } - } - rs.close(); - } - List catList = new ArrayList(); - for (String cat: cats) { - catList.add(new Object[] { cat }); - } - MemorizedResultSet result = new MemorizedResultSet(catList, 1, new String[] { "Package", }, new int[] { Types.VARCHAR }); - return result; - } - } - - /** - * Procedures list view. - */ - private abstract class MDProcedures extends MDDescriptionBasedGeneric { - private final MDSchema mdSchema; - - public MDProcedures(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { - super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { - { - setIconURL("/net/sf/jailer/ui/resource/procedures.png"); - DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); - itemDescr.setIconURL("/net/sf/jailer/ui/resource/procedure.png"); - itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); - setItemDescription(itemDescr); - } - }); - this.mdSchema = schema; - } - - @Override - public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { - if (query != null) { - return super.retrieveList(session, query, schema, parentName); - } - MemorizedResultSet procs = new MemorizedResultSet(getProcedures(session, session.getMetaData(), schema, "%"), - null, session, schema, new int[] { 3, 4, 1, 8, 9 }, new String[] { "Name", "Remarks", "Category", "Type", "SpecificName" }); - List catList = new ArrayList(); - for (Object[] cat: procs.getRowList()) { - if (select(cat)) { - catList.add(cat); - } - } - procs.close(); - return new MemorizedResultSet(catList, procs.getMetaData()); - } - - @Override - protected int getDetailIDIndex() { - if (mdSchema.getMetaDataSource().getSession().dbms.isProcedureDetailNeedsSpecificName()) { - return 4; - } - return 0; - } - - protected abstract boolean select(Object[] proc); - - @Override - protected DatabaseObjectRenderingDescription itemDescription(MemorizedResultSet item) { - DatabaseObjectRenderingDescription desc = new DatabaseObjectRenderingDescription(databaseObjectRenderingDescription.getItemDescription()); - if (!item.getRowList().isEmpty() && String.valueOf(DatabaseMetaData.procedureReturnsResult).equals(String.valueOf(item.getRowList().get(0)[3]))) { - desc.setIconURL("/net/sf/jailer/ui/resource/function.png"); - desc.setTextQuery(mdSchema.getMetaDataSource().getSession().dbms.getFunctionSourceQuery()); - } - return desc; - } - } - - /** - * Constraints list view. - */ - private class MDConstraint extends MDDescriptionBasedGeneric { - private final MDSchema mdSchema; - - private Map constraintTypeNames = new LinkedHashMap(); - { - constraintTypeNames.put("PK", "Primary Keys"); - constraintTypeNames.put("Unique", "Unique Constraints"); - constraintTypeNames.put("Check", "Check Constraints"); - } - - public MDConstraint(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { - super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { - { - setIconURL("/net/sf/jailer/ui/resource/constraints.png"); - DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); - itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); - setItemDescription(itemDescr); - } - }); - this.mdSchema = schema; - } - - @Override - public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { - if (query != null) { - return super.retrieveList(session, query, schema, parentName); - } - return mdSchema.getConstraints(null); - } - - /** - * Gets a list of descriptions of the details. - * - * @return list of descriptions of the details - */ - @Override - public List getDetails() { - ArrayList result = new ArrayList(); - try { - MemorizedResultSet theList = retrieveList(getMetaDataSource().getSession()); - Map typeNames = new LinkedHashMap(constraintTypeNames); - for (final Object[] row: theList.getRowList()) { - String type = String.valueOf(row[0]); - if (!typeNames.containsKey(type)) { - typeNames.put(type, type); - } - } - for (Entry e: typeNames.entrySet()) { - List rowsPerType = new ArrayList(); - ArrayList descs = new ArrayList(); - for (final Object[] row: theList.getRowList()) { - if (String.valueOf(row[0]).equals(e.getKey())) { - rowsPerType.add(row); - } - } - for (final Object[] row: theList.getRowList()) { - MemorizedResultSet detailRS = new MemorizedResultSet(Collections.singletonList(row), theList.getMetaData()); - DatabaseObjectRenderingDescription detailDesc = itemDescription(detailRS); - if (detailDesc != null) { - MDDescriptionBasedGeneric mdDetails = createDetailDescription(row, detailDesc); - mdDetails.detailName = String.valueOf(row[getDetailIDIndex()]); - if (detailDesc.getListQuery() == null) { - mdDetails.list = detailRS; - } - descs.add(mdDetails); - } - } - DatabaseObjectRenderingDescription desc = new DatabaseObjectRenderingDescription(); - desc.setItemDescription(new DatabaseObjectRenderingDescription()); - final MemorizedResultSet listPerType = new MemorizedResultSet(rowsPerType, theList.getMetaData()); - final UIUtil.IconWithText label = MDSchema.getConstraintTypeIcon(e.getKey() + "s"); - result.add(new MDDescriptionBasedGeneric(e.getValue(), getMetaDataSource(), schema, dataModel, desc) { - @Override - protected MemorizedResultSet retrieveList(Session session) throws SQLException { - listPerType.reset(); - return listPerType; - } - - @Override - public List getDetails() { - return super.getDetails(); - } - - @Override - protected MDDescriptionBasedGeneric createDetailDescription(final Object[] row, DatabaseObjectRenderingDescription detailDesc) { - final IconWithText label = (IconWithText) row[0]; - return new MDDescriptionBasedGeneric(row[1] + " on " + row[2] + (row[3] != null && row[3].toString().trim().length() > 0? "(" + row[3] + ")" : ""), getMetaDataSource(), schema, dataModel, detailDesc) { - @Override - public ImageIcon getIcon() { - return label == null? null : label.icon; - } - }; - } - - @Override - public ImageIcon getIcon() { - return label == null? null : label.icon; - } - }); - } - } catch (Throwable t) { - logger.info("error", t); - } - return result; - } - @Override - protected MemorizedResultSet distinct(MemorizedResultSet list) throws SQLException { - return list; - } - - @Override - public boolean hasDetails() { - return true; - } - } - - private List getGenericDatabaseObjects(final MDSchema mdSchema) { - List genericDatabaseObjects = new ArrayList(); - genericDatabaseObjects.add( - new MDProcedures("Procedures", metaDataSource, mdSchema, dataModel) { - @Override - protected boolean select(Object[] proc) { - return proc[2] == null || !DBMS.ORACLE.equals(mdSchema.getMetaDataSource().getSession().dbms); - } - } - ); - if (DBMS.ORACLE.equals(mdSchema.getMetaDataSource().getSession().dbms)) { - genericDatabaseObjects.add(new MDPackages("Packages", metaDataSource, mdSchema, dataModel)); - } - if (mdSchema.getMetaDataSource().getSession().dbms.getConstraintsQuery() != null) { - genericDatabaseObjects.add(new MDConstraint("Constraints", metaDataSource, mdSchema, dataModel)); - } - for (DatabaseObjectRenderingDescription desc: mdSchema.getMetaDataSource().getSession().dbms.getObjectRenderers()) { - MDDescriptionBasedGeneric mdObjectRenderer - = new MDDescriptionBasedGeneric( - desc.getName(), metaDataSource, mdSchema, dataModel, desc); - genericDatabaseObjects.add(mdObjectRenderer); - } - return genericDatabaseObjects; - } - - private Map proceduresPerSchema = Collections.synchronizedMap(new HashMap()); - - public ResultSet getProcedures(Session session, DatabaseMetaData metaData, String schema, String context) throws SQLException { - synchronized (proceduresPerSchema) { - MemorizedResultSet rs = proceduresPerSchema.get(schema); - if (rs == null) { - if (schema != null) { - schema = Quoting.staticUnquote(schema); - } - rs = new MemorizedResultSet(JDBCMetaDataBasedModelElementFinder.getProcedures(session, metaData, Quoting.staticUnquote(schema), context), null, session, ""); - proceduresPerSchema.put(schema, rs); - } - rs.reset(); - return rs; - } - } - - private abstract class ExpandingMutableTreeNode extends DefaultMutableTreeNode { - - public ExpandingMutableTreeNode() { - super("loading..."); - } - - protected abstract void expandImmediatelly(); - protected abstract void expand(); - } - - /** - * Creates new form MetaDataPanel - * - * @param metaDataSource the meta data source - * @param dataModel the data mmodel - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public MetaDataPanel(Frame parent, MetaDataSource metaDataSource, MetaDataDetailsPanel metaDataDetailsPanel, final DataModel dataModel, ExecutionContext executionContext) { - this.metaDataSource = metaDataSource; - this.dataModel = dataModel; - this.metaDataDetailsPanel = metaDataDetailsPanel; - this.parent = parent; - this.executionContext = executionContext; - initComponents(); - - hideOutline(); - lastDividerLocation = -1; - - final ListCellRenderer olRenderer = outlineList.getCellRenderer(); - outlineList.setCellRenderer(new ListCellRenderer() { - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) { - String tooltip = null; - boolean withSeparator = false; - double level = 0; - if (value instanceof OutlineInfo) { - tooltip = ((OutlineInfo) value).tooltip; - withSeparator = ((OutlineInfo) value).withSeparator; - level = ((OutlineInfo) value).level; - if (((OutlineInfo) value).isCTE) { - level += 0.5; - } - value = outlineTableRender((OutlineInfo) value, isSelected); - } - Component render = olRenderer.getListCellRendererComponent(list, value, index, false, cellHasFocus); - render.setBackground(isSelected? new Color(240, 240, 255) : index == indexOfInfoAtCaret? new Color(255, 255, 170) : Color.WHITE); - if (render instanceof JLabel) { - ((JLabel) render).setToolTipText(tooltip); - - if (withSeparator) { - final Border border = ((JLabel) render).getBorder() == null? new EmptyBorder(0, 0, 0, 0) : ((JLabel) render).getBorder(); - final Color bg = ((JLabel) render).getBackground(); - final int ind = (int) (level * 22); - final int SEP_LENGTH = 300; - ((JLabel) render).setBorder(new Border() { - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - border.paintBorder(c, g, x, y, width, height); - if (g instanceof Graphics2D) { - Graphics2D g2d = (Graphics2D) g; - Color color = new Color(100, 100, 255); - int ofs = 50; - GradientPaint paint = new GradientPaint( - x + ind - 20, 0, bg==null ? Color.WHITE : bg, - x + ind + ofs, 0, color); - g2d.setPaint(paint); - g2d.fillRect(x + ind - 20, 0, ofs + 20, 1); - if (ind + ofs < SEP_LENGTH) { - paint = new GradientPaint( - x + ind + ofs, 0, color, - x + SEP_LENGTH, 0, bg==null ? Color.WHITE : bg); - g2d.setPaint(paint); - g2d.fillRect(x + ind + ofs, 0, SEP_LENGTH, 1); - } - } - } - @Override - public Insets getBorderInsets(Component c) { - return border.getBorderInsets(c); - } - @Override - public boolean isBorderOpaque() { - return border.isBorderOpaque(); - } - }); - } - - } - return render; - } - }); - - outlineList.addMouseListener(new MouseListener() { - @Override - public void mouseReleased(MouseEvent e) { - } - @Override - public void mousePressed(MouseEvent e) { - } - @Override - public void mouseExited(MouseEvent e) { - } - @Override - public void mouseEntered(MouseEvent e) { - } - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() > 1) { - int i = outlineList.locationToIndex(e.getPoint()); - if (i >= 0) { - Object value = outlineList.getModel().getElementAt(i); - if (value instanceof OutlineInfo) { - setCaretPosition(((OutlineInfo) value).origPosition); - } - } - } - } - }); - - outlineList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - Object value = outlineList.getSelectedValue(); - if (!inSelectOutlineTable && value instanceof OutlineInfo) { - MDTable mdTable = ((OutlineInfo) value).mdTable; - if (mdTable != null) { - inSelectOutlineTable = true; - select(mdTable); - inSelectOutlineTable = false; - } - } - } - }); - - tablesComboBox = new JComboBox() { - @Override - public Dimension getMinimumSize() { - return new Dimension(40, super.getMinimumSize().height); - } - }; - tablesComboBox.setMaximumRowCount(20); - AutoCompletion.enable(tablesComboBox); - - tablesComboBox.grabFocus(); - - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1; - add(tablesComboBox, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - searchButton = StringSearchPanel.createSearchButton(parent, tablesComboBox, "Select Table", new Runnable() { - @Override - public void run() { - onSelectTable(); - } - }, new StringSearchPanel.Prepare() { - @Override - public void prepare(Set selectedSchemas) { - updateTablesCombobox(selectedSchemas); - } - }, metaDataSource, dataModel); - jPanel1.add(searchButton, gridBagConstraints); - - tablesComboBox.setVisible(false); - refreshButton1.setVisible(false); - searchButton.setText("Select Table"); - - metaDataTree.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == '\n') { - if (metaDataTree.getSelectionPath() != null) { - Object last = metaDataTree.getSelectionPath().getLastPathComponent(); - if (last instanceof DefaultMutableTreeNode) { - final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); - if (uo instanceof MDTable) { - openTable((MDTable) uo); - } - } - } - } - } - - @Override - public void keyReleased(KeyEvent e) { - } - - @Override - public void keyPressed(KeyEvent e) { - } - }); - - metaDataTree.addMouseListener(new MouseListener() { - @Override - public void mouseReleased(MouseEvent e) { - } - @Override - public void mousePressed(MouseEvent e) { - } - @Override - public void mouseExited(MouseEvent e) { - } - @Override - public void mouseEntered(MouseEvent e) { - } - @Override - public void mouseClicked(MouseEvent evt) { - final MDTable mdTable = findTable(evt); - TreePath node = findNode(evt); - if (node != null) { - metaDataTree.scrollRectToVisible(new Rectangle(0, (int) evt.getPoint().getY(), 1, 1)); - } - final Set mdTables = new LinkedHashSet(); - findTables(mdTables); - if (evt.getButton() == MouseEvent.BUTTON3) { - if (mdTable != null || !mdTables.isEmpty()) { - int itemCount = 0; - JPopupMenu popup = new JPopupMenu(); - if (mdTable != null) { - JMenuItem open = new JMenuItem("Open"); - popup.add(open); - ++itemCount; - open.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openTable(mdTable); - } - }); - } - if (mdTable != null && MetaDataPanel.this.metaDataSource.toTable(mdTable) == null) { - if (itemCount > 0) { - popup.addSeparator(); - } - JMenuItem analyse = new JMenuItem("Analyse schema \""+ mdTable.getSchema().getUnquotedName() + "\""); - popup.add(analyse); - ++itemCount; - analyse.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - analyseSchema(mdTable.getSchema().getName()); - } - }); - } - if (!mdTables.isEmpty()) { - if (itemCount > 0) { - popup.addSeparator(); - } - JMenu menu = new JMenu("Create Script"); - popup.add(menu); - ++itemCount; - Point pos = new Point(evt.getX(), evt.getY()); - SwingUtilities.convertPointToScreen(pos, evt.getComponent()); - menu.add(createScriptMenuItem("Delete Script", "Delete from %1$s;", "", mdTables, false, pos)); - menu.add(createScriptMenuItem("Create Table Script", "DDL", "", mdTables, false, pos)); - menu.add(createScriptMenuItem("Drop Table Script", "Drop %2$s %1$s;", "", mdTables, false, pos)); - menu.addSeparator(); - menu.add(createScriptMenuItem("Count Rows Script", "Select '%1$s' as Tab, count(*) as NumberOfRows From %1$s", " union all", mdTables, true, pos)); - } - popup.show(evt.getComponent(), evt.getX(), evt.getY()); - } - } - if (evt.getButton() == MouseEvent.BUTTON1) { - if (mdTable != null) { - if (evt.getClickCount() > 1) { - if (node != null && metaDataTree.getSelectionModel().isPathSelected(node)) { - openTable(mdTable); - } - } - } - } - } - private JMenuItem createScriptMenuItem(String title, final String template, final String separator, final Set mdTables, final boolean execute, final Point pos) { - JMenuItem item = new JMenuItem(title); - final AtomicBoolean cancelLoading = new AtomicBoolean(false); - - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final Window wa = SwingUtilities.getWindowAncestor(MetaDataPanel.this); - final boolean withWaitDialog; - if ("DDL".equals(template) && mdTables.size() > 1) { - cancelLoading.set(false); - withWaitDialog = true; - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - JDialog dialog; - dialog = new EscapableDialog((wa instanceof Frame)? (Frame) wa : null, "Script") { - }; - dialog.setModal(true); - waitDialog.set(dialog); - dialog.getContentPane().add(waitingPanel); - dialog.pack(); - dialog.setLocation(pos.x + dialog.getWidth() / 2 - dialog.getWidth() / 2, pos.y + dialog.getHeight() / 2 - dialog.getHeight() / 2); - dialog.setVisible(true); - waitDialog.set(null); - cancelLoading.set(true); - } - }); - } else { - waitDialog.set(null); - withWaitDialog = false; - } - MDSchema.loadMetaData(new Runnable() { - @Override - public void run() { - if (withWaitDialog) { - for (MDTable mdTable: mdTables) { - mdTable.getDDL(); - if (cancelLoading.get()) { - break; - } - } - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - if (!cancelLoading.get()) { - StringBuilder script = new StringBuilder(); - for (MDTable mdTable: mdTables) { - if (script.length() > 0) { - script.append(separator + UIUtil.LINE_SEPARATOR); - } - if ("DDL".equals(template)) { - String ddl = mdTable.getDDL().trim().replaceAll("\\nON ", " ON "); - script.append(ddl); - if (!ddl.endsWith(";")) { - script.append(";"); - } - } else { - String tableName; - String tableType = "Table"; - if (mdTable.isView()) { - tableType = "View"; - } - if (mdTable.isSynonym()) { - tableType = "Synonym"; - } - if (mdTable.getSchema().isDefaultSchema) { - tableName = mdTable.getName(); - } else { - tableName = mdTable.getSchema() + "." + mdTable.getName(); - } - script.append(String.format(Locale.ENGLISH, template, tableName, tableType)); - } - } - script.append("\n"); - appendScript(script.toString(), execute); - } - if (waitDialog.get() != null) { - waitDialog.get().dispose(); - waitDialog.set(null); - } - } - }); - } - }, 2); - } - }); - return item; - } - private void findTables(Set mdTables) { - TreePath[] paths = metaDataTree.getSelectionPaths(); - if (paths != null) { - for (TreePath path: paths) { - findTables(mdTables, path.getLastPathComponent()); - } - } - } - private void findTables(Set mdTables, Object node) { - if (node instanceof DefaultMutableTreeNode && node != metaDataTree.getModel().getRoot()) { - DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) node; - Object selNode = defaultMutableTreeNode.getUserObject(); - if (selNode instanceof MDTable) { - mdTables.add((MDTable) selNode); - } - for (int i = 0; i < defaultMutableTreeNode.getChildCount(); ++i) { - findTables(mdTables, defaultMutableTreeNode.getChildAt(i)); - } - } - } - private MDTable findTable(MouseEvent evt) { - MDTable mdTable = null; - TreePath node = findNode(evt); - if (node != null) { - Object sel = node.getLastPathComponent(); - if (sel instanceof DefaultMutableTreeNode) { - Object selNode = ((DefaultMutableTreeNode) sel).getUserObject(); - if (selNode instanceof MDTable) { - mdTable = (MDTable) selNode; - } - } - } - return mdTable; - } - private TreePath findNode(MouseEvent evt) { - TreePath node = metaDataTree.getPathForLocation(evt.getX(), evt.getY()); - if (node == null) { - for (int x = metaDataTree.getWidth(); x > 0; x -= 32) { - node = metaDataTree.getPathForLocation(x, evt.getY()); - if (node != null) { - break; - } - } - } - return node; - } - }); - - metaDataTree.addTreeWillExpandListener(new TreeWillExpandListener() { - @Override - public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { - Object node = event.getPath().getLastPathComponent(); - if (node instanceof DefaultMutableTreeNode) { - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node; - if (treeNode.getChildCount() == 1 && treeNode.getChildAt(0) instanceof ExpandingMutableTreeNode) - ((ExpandingMutableTreeNode) treeNode.getChildAt(0)).expand(); - } - } - - @Override - public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { - } - }); - - final ImageIcon finalScaledWarnIcon = getScaledIcon(this, warnIcon, true); - - DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { - Map dirtyTables = new HashMap(); - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, - boolean leaf, int row, boolean hasFocus) { - boolean unknownTable = false; - boolean isJailerTable = false; - boolean isView = false; - boolean isSynonym = false; - Boolean isDirty = false; - ImageIcon image = null; - Long estRowCount = null; - if (value instanceof DefaultMutableTreeNode) { - Object uo = ((DefaultMutableTreeNode) value).getUserObject(); - if (uo instanceof JLabel) { - Icon icon = ((JLabel) uo).getIcon(); - if (icon instanceof ImageIcon) { - image = (ImageIcon) ((JLabel) uo).getIcon(); - } - } - if (uo == CATEGORY_VIEWS) { - image = viewsIcon; - } - if (uo == CATEGORY_SYNONYMS) { - image = synonymsIcon; - } - if (uo == CATEGORY_TABLES) { - image = tablesIcon; - } - if (uo instanceof MDDatabase) { - image = databaseIcon; - } - if (uo instanceof MDSchema) { - image = schemaIcon; - } - if (uo instanceof MDDescriptionBasedGeneric) { - image = ((MDDescriptionBasedGeneric) uo).getIcon(); - } - if (uo instanceof MDTable) { - Table table = MetaDataPanel.this.metaDataSource.toTable((MDTable) uo); - if (table == null) { - unknownTable = true; - } else { - if (((MDTable) uo).isLoaded()) { - isDirty = dirtyTables.get(uo); - if (isDirty == null) { - isDirty = !((MDTable) uo).isUptodate(table); - dirtyTables.put(((MDTable) uo), isDirty); - } - } - } - isView = ((MDTable) uo).isView(); - isSynonym = ((MDTable) uo).isSynonym(); - if (!isView) { - estRowCount = ((MDTable) uo).estimatedRowCount; - } - if (isView) { - image = viewIcon; - } else if (isSynonym) { - image = synonymIcon; - } else { - image = tableIcon; - } - if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) { - isJailerTable = true; - } - } - } - Component comp = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - if (comp instanceof JLabel) { - String text = ((JLabel) comp).getText(); - if (estRowCount != null) { - Color fg = ((JLabel) comp).getForeground(); - String estRowCountFormatted; - if (estRowCount >= 1000000) { - estRowCountFormatted = String.format("%,1.1f M", (double) estRowCount / 1000000.0); - } else if (estRowCount >= 1000) { - estRowCountFormatted = String.format("%,1.1f K", (double) estRowCount / 1000.0); - } else { - estRowCountFormatted = estRowCount.toString(); - } - if (fg.getRed() + fg.getGreen() + fg.getBlue() < 255 * 3 / 2) { - ((JLabel) comp).setText("" + text + "  ~" + estRowCountFormatted + ""); - } else { - ((JLabel) comp).setText("" + text + "  ~" + estRowCountFormatted + ""); - } - } - } - if (isJailerTable && !sel) { - if (comp instanceof JLabel) { - ((JLabel) comp).setForeground(Color.gray); - } - } - if (image != null) { - if (comp instanceof JLabel) { - ((JLabel) comp).setIcon(image); - } - } - if ((unknownTable || isDirty) && !isJailerTable) { - if (comp instanceof JLabel) { - if (image != null) { - ImageIcon combinedIcon = combinedIcons.get(image); - if (combinedIcon == null) { - Image im = image.getImage(); - // create the new image, canvas size is the max. of both image sizes - int w = Math.max(image.getIconWidth(), finalScaledWarnIcon.getIconWidth()); - int h = Math.max(image.getIconHeight(), finalScaledWarnIcon.getIconHeight()); - BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - - // paint both images, preserving the alpha channels - Graphics g = combined.getGraphics(); - g.drawImage(im, 0, 0, null); - g.translate(image.getIconWidth() / 4, image.getIconHeight() / 4); - g.drawImage(finalScaledWarnIcon.getImage(), 0, 0, null); - combinedIcon = new ImageIcon(combined); - combinedIcons.put(image, combinedIcon); - } - ((JLabel) comp).setIcon(combinedIcon); - } else { - ((JLabel) comp).setIcon(finalScaledWarnIcon); - } - } - } - return comp; - } - }; - renderer.setOpenIcon(null); - renderer.setLeafIcon(null); - renderer.setClosedIcon(null); - metaDataTree.setCellRenderer(renderer); - metaDataTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - - metaDataTree.addTreeSelectionListener(new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - TreePath path = e.getNewLeadSelectionPath(); - if (path != null) { - final Object last = path.getLastPathComponent(); - if (metaDataTree.getModel().getRoot() == last) { -// searchButton.doClick(); - } - if (last instanceof DefaultMutableTreeNode) { - final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); - if (uo instanceof MDTable) { - selectOutlineTable((MDTable) uo); - Table table = MetaDataPanel.this.metaDataSource.toTable((MDTable) uo); - if (table != null) { - updateDataModelView(table); - } - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - UIUtil.setWaitCursor(MetaDataPanel.this); - try { - if (metaDataTree.getSelectionPath() != null && metaDataTree.getSelectionPath().getLastPathComponent() == last) { - if (uo instanceof MDSchema) { - onSchemaSelect((MDSchema) uo); - } else if (uo instanceof MDTable) { - onTableSelect((MDTable) uo); - } else if (uo instanceof MDGeneric) { - onMDOtherSelect((MDGeneric) uo, MetaDataPanel.this.executionContext); - } else { - onMDOtherSelect(new MDGeneric("", MetaDataPanel.this.metaDataSource) { - @Override - public JComponent createRender(Session session, - ExecutionContext executionContext) throws Exception { - return new JLabel(""); - } - }, MetaDataPanel.this.executionContext); - } - } - } finally { - UIUtil.resetWaitCursor(MetaDataPanel.this); - } - } - }); - } - }); - } - }); - } - } - } - }); - - updateTreeModel(metaDataSource); - - Font font = outlineLabel.getFont(); - if (font != null) { - Font bold = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize()); - outlineLabel.setFont(bold); - } - } - - private Map tablesComboboxMDTablePerName = new HashMap(); - - private void updateTablesCombobox(Set selectedSchemas) { - Set tableSet = new HashSet(); - Set toLoad = new HashSet(); - - for (Table table: dataModel.getTables()) { - MDSchema mdSchema = metaDataSource.getSchemaOfTable(table); - if (mdSchema != null && !mdSchema.isLoaded()) { - toLoad.add(mdSchema); - } else if (metaDataSource.toMDTable(table) == null) { - String schemaName = table.getSchema(""); - MDSchema schema; - if (schemaName.isEmpty()) { - schema = metaDataSource.getDefaultSchema(); - } else { - schema = metaDataSource.find(schemaName); - } - if (schema != null && selectedSchemas.contains(schema)) { - String displayName = dataModel.getDisplayName(table); - tableSet.add(displayName); - } - } - } - for (MDSchema schema: selectedSchemas) { - if (!schema.isLoaded()) { - toLoad.add(schema); - } else { - for (MDTable table: schema.getTables()) { - if (!ModelBuilder.isJailerTable(table.getName())) { - String name; - if (!schema.isDefaultSchema) { - name = schema.getName() + "." + table.getName(); - } else { - name = table.getName(); - } - tableSet.add(name); - tablesComboboxMDTablePerName.put(name, table); - } - } - } - } - List tables = new ArrayList(tableSet); - Collections.sort(tables, new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - }); - ComboBoxModel model = new DefaultComboBoxModel(new Vector(tables)); - tablesComboBox.setModel(model); - - for (MDSchema schema: toLoad) { - schema.loadTables(true, null, null); - } - } - - protected void openTable(MDTable mdTable) { - Table table = metaDataSource.toTable(mdTable); - if (table != null) { - open(table); - } else { - open(mdTable); - } - } - - private int inResetCount = 0; - private static AtomicInteger pendingCount = new AtomicInteger(); - - public void reset() { - if (pendingCount.get() > 0) { - return; - } - inResetCount++; - refreshButton.setEnabled(false); - final AtomicBoolean waitStateIsResetted = new AtomicBoolean(false); - Timer timer = new Timer(100, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (!waitStateIsResetted.get()) { - setOrResetWaitState(true); - } - } - }); - timer.setRepeats(false); - timer.start(); - - JDBCMetaDataBasedModelElementFinder.resetCaches(metaDataSource.getSession()); - setOutline(new ArrayList(), -1); - proceduresPerSchema.clear(); - - MDTable selectedTable = null; - if (metaDataTree.getSelectionPath() != null) { - Object last = metaDataTree.getSelectionPath().getLastPathComponent(); - if (last instanceof DefaultMutableTreeNode) { - final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); - if (uo instanceof MDTable) { - selectedTable = (MDTable) uo; - } - } - } - final MDTable finalSelectedTable = selectedTable; - - pendingCount.incrementAndGet(); - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - try { - Session.setThreadSharesConnection(); - synchronized (metaDataSource) { - pendingCount.getAndDecrement(); - metaDataSource.clear(); - } - } finally { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - if (--inResetCount <= 0) { - try { - metaDataDetailsPanel.reset(); - updateTreeModel(metaDataSource); - if (finalSelectedTable != null) { - final MDSchema schema = metaDataSource.find(finalSelectedTable.getSchema().getName()); - ActionListener al = new ActionListener() { - int cnt = 10; - @Override - public void actionPerformed(ActionEvent e) { - if (schema != null) { - if (!schema.isLoaded()) { - if (--cnt > 0) { - Timer timer = new Timer(200, this); - timer.setRepeats(false); - timer.start(); - } - return; - } - MDTable table = schema.find(finalSelectedTable.getName()); - if (table != null) { - select(table); - } - } - } - }; - Timer timer = new Timer(100, al); - timer.setRepeats(false); - timer.start(); - } - } finally { - refreshButton.setEnabled(true); - setOrResetWaitState(false); - waitStateIsResetted.set(true); - } - } - } - }); - } - } - }); - thread.setDaemon(true); - thread.start(); - } - - public void select(Table table) { - MDSchema mdSchema = metaDataSource.getSchemaOfTable(table); - if (mdSchema != null && !mdSchema.isLoaded()) { - mdSchema.loadTables(true, null, null); - return; - } - select(metaDataSource.toMDTable(table)); - } - - public void select(MDTable mdTable) { - if (mdTable != null) { - TreePath path = find(metaDataTree.getModel().getRoot(), mdTable); - if (path != null) { - selectSchema(mdTable.getSchema(), false); - metaDataTree.expandPath(path); - metaDataTree.getSelectionModel().setSelectionPath(path); - scrollToNode(path); - } else { - selectSchema(mdTable.getSchema()); - } - } - } - - private void scrollToNode(TreePath path) { - Rectangle bounds = metaDataTree.getPathBounds(path); - if (bounds != null) { - int b = 18; - bounds = new Rectangle(bounds.x, Math.max(bounds.y - b, 0), bounds.width, bounds.height + 2 * b); - metaDataTree.scrollRectToVisible(new Rectangle(0, bounds.y, 1, bounds.height)); - } - } - - private TreePath find(Object root, MDTable mdTable) { - if (root instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); - if (userObject instanceof MDSchema) { - if (mdTable.getSchema().equals(userObject)) { - int cc = ((DefaultMutableTreeNode) root).getChildCount(); - for (int i = 0; i < cc; ++i) { - TreeNode catNode = ((DefaultMutableTreeNode) root).getChildAt(i); - Object catUO = ((DefaultMutableTreeNode) catNode).getUserObject(); - if (catNode.getChildCount() > 0 && (CATEGORY_TABLES == catUO || CATEGORY_VIEWS == catUO || CATEGORY_SYNONYMS == catUO)) { - TreeNode firstChild = catNode.getChildAt(0); - if (firstChild instanceof ExpandingMutableTreeNode) { - ((ExpandingMutableTreeNode) firstChild).expandImmediatelly(); - } - } - } - } - } else if (userObject instanceof MDTable) { - if (userObject == mdTable) { - return new TreePath(((DefaultMutableTreeNode) root).getPath()); - } - } - int cc = ((DefaultMutableTreeNode) root).getChildCount(); - for (int i = 0; i < cc; ++i) { - TreePath path = find(((DefaultMutableTreeNode) root).getChildAt(i), mdTable); - if (path != null) { - return path; - } - } - } - return null; - } - - private DefaultMutableTreeNode root; - private Map treeNodePerSchema = new HashMap(); - - private void updateTreeModel(final MetaDataSource metaDataSource) { - root = new DefaultMutableTreeNode(new MDDatabase(metaDataSource.dataSourceName, metaDataSource, dataModel, executionContext)); - for (final MDSchema schema: metaDataSource.getSchemas()) { - final DefaultMutableTreeNode schemaChild = new DefaultMutableTreeNode(schema); - for (final MDDescriptionBasedGeneric desc: getGenericDatabaseObjects(schema)) { - Iterable leafs = new Iterable() { - @Override - public Iterator iterator() { - List details = new ArrayList(); - for (MDDescriptionBasedGeneric detail: desc.getDetails()) { - details.add(detail); - } - return details.iterator(); - } - }; - createCategoryNode(schemaChild, leafs, desc, desc.hasDetails(), desc.isCheap()? 0 : 1); - } - Iterable leafs = new Iterable() { - @Override - public Iterator iterator() { - List leafs = new ArrayList(); - for (MDTable table: schema.getTables()) { - if (table.isView()) { - leafs.add(table); - } - } - return leafs.iterator(); - } - }; - createCategoryNode(schemaChild, leafs, CATEGORY_VIEWS, true, 0); - leafs = new Iterable() { - @Override - public Iterator iterator() { - List leafs = new ArrayList(); - for (MDTable table: schema.getTables()) { - if (table.isSynonym()) { - leafs.add(table); - } - } - return leafs.iterator(); - } - }; - createCategoryNode(schemaChild, leafs, CATEGORY_SYNONYMS, true, 0); - leafs = new Iterable() { - @Override - public Iterator iterator() { - List leafs = new ArrayList(); - for (MDTable table: schema.getTables(true, new Runnable() { - @Override - public void run() { - refresh(); - } - })) { - if (!table.isView() && !table.isSynonym()) { - leafs.add(table); - } - } - return leafs.iterator(); - } - }; - DefaultMutableTreeNode schemaTablesChild = createCategoryNode(schemaChild, leafs, CATEGORY_TABLES, true, 0); - treeNodePerSchema.put(schema, schemaTablesChild); - } - DefaultTreeModel treeModel = new DefaultTreeModel(root); - metaDataTree.setModel(treeModel); - metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1)); - selectSchema(metaDataSource.getDefaultSchema()); - } - - public DefaultMutableTreeNode createCategoryNode(final DefaultMutableTreeNode schemaChild, final Iterable finalLeafs, - Object category, boolean hasDetails, final int queueId) { - final DefaultMutableTreeNode schemaViewsChild = new DefaultMutableTreeNode(category); - schemaChild.add(schemaViewsChild); - root.add(schemaChild); - MutableTreeNode expandSchema; - if (hasDetails) { - synchronized (schemaChild) { - expandSchema = new ExpandingMutableTreeNode() { - private Iterable leafs = finalLeafs; - private boolean expanded = false; - @Override - protected void expandImmediatelly() { - if (!expanded) { - for (Object leaf: leafs) { - DefaultMutableTreeNode tableChild = new DefaultMutableTreeNode(leaf); - schemaViewsChild.add(tableChild); - if (leaf instanceof MDDescriptionBasedGeneric) { - MDDescriptionBasedGeneric md = (MDDescriptionBasedGeneric) leaf; - for (MDDescriptionBasedGeneric detail: md.getDetails()) { - tableChild.add(new DefaultMutableTreeNode(detail)); - } - } - } - schemaViewsChild.remove(this); - TreeModel model = metaDataTree.getModel(); - ((DefaultTreeModel) model).nodeStructureChanged(schemaViewsChild); - } - expanded = true; - } - @Override - protected void expand() { - MDSchema.loadMetaData(new Runnable() { - @Override - public void run() { - synchronized (schemaChild) { - ArrayList leafList = new ArrayList(); - for (Object leaf: leafs) { - leafList.add(leaf); - if (leaf instanceof MDDescriptionBasedGeneric) { - MDDescriptionBasedGeneric md = (MDDescriptionBasedGeneric) leaf; - md.getDetails(); - } - } - leafs = leafList; - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - Window wa = SwingUtilities.getWindowAncestor(MetaDataPanel.this); - try { - UIUtil.setWaitCursor(wa != null? wa : MetaDataPanel.this); - expandImmediatelly(); - } finally { - UIUtil.resetWaitCursor(wa != null? wa : MetaDataPanel.this); - } - } - }); - } - }); - - } - }, queueId); - } - }; - } - schemaViewsChild.add(expandSchema); - } - return schemaViewsChild; - } - - public void selectSchema(MDSchema mdSchema) { - selectSchema(mdSchema, true); - } - - public void selectSchema(MDSchema mdSchema, boolean scrollToNode) { - if (mdSchema != null) { - DefaultMutableTreeNode node = treeNodePerSchema.get(mdSchema); - if (node != null) { - final TreePath path = new TreePath(node.getPath()); - metaDataTree.expandPath(path); - metaDataTree.getSelectionModel().setSelectionPath(path); - if (scrollToNode) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - scrollToNode(path); - } - }); - } - } - } - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - waitingPanel = new javax.swing.JPanel(); - jLabel5 = new javax.swing.JLabel(); - cancelButton = new javax.swing.JButton(); - splitPane = new javax.swing.JSplitPane(); - jPanel1 = new javax.swing.JPanel(); - jScrollPane1 = new javax.swing.JScrollPane(); - metaDataTree = new javax.swing.JTree(); - refreshButton = new javax.swing.JButton(); - refreshButton1 = new javax.swing.JButton(); - jPanel2 = new javax.swing.JPanel(); - outlineScrollPane = new javax.swing.JScrollPane(); - outlineList = new javax.swing.JList(); - outlineLabel = new javax.swing.JLabel(); - placeholderPanel = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); - - waitingPanel.setBackground(java.awt.Color.white); - - jLabel5.setForeground(java.awt.Color.red); - jLabel5.setText("creating..."); - waitingPanel.add(jLabel5); - - cancelButton.setText("Cancel"); - cancelButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelButtonActionPerformed(evt); - } - }); - waitingPanel.add(cancelButton); - - setLayout(new java.awt.GridBagLayout()); - - splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - splitPane.setResizeWeight(1.0); - splitPane.setContinuousLayout(true); - splitPane.setOneTouchExpandable(true); - - jPanel1.setLayout(new java.awt.GridBagLayout()); - - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setViewportView(metaDataTree); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 5; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jScrollPane1, gridBagConstraints); - - refreshButton.setText("Refresh"); - refreshButton.setToolTipText("Refresh Database Meta Data Cache"); - refreshButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - refreshButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - jPanel1.add(refreshButton, gridBagConstraints); - - refreshButton1.setText("Select"); - refreshButton1.setToolTipText("Choose the selecetd table in the tables tree"); - refreshButton1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - refreshButton1ActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 8); - jPanel1.add(refreshButton1, gridBagConstraints); - - splitPane.setLeftComponent(jPanel1); - - jPanel2.setLayout(new java.awt.GridBagLayout()); - - outlineList.setModel(new javax.swing.AbstractListModel() { - String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; - public int getSize() { return strings.length; } - public Object getElementAt(int i) { return strings[i]; } - }); - outlineList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - outlineScrollPane.setViewportView(outlineList); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel2.add(outlineScrollPane, gridBagConstraints); - - outlineLabel.setText(" Outline"); - outlineLabel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0); - jPanel2.add(outlineLabel, gridBagConstraints); - - placeholderPanel.setLayout(new java.awt.GridBagLayout()); - - jLabel1.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - placeholderPanel.add(jLabel1, gridBagConstraints); - - jLabel2.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - placeholderPanel.add(jLabel2, gridBagConstraints); - - jLabel3.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - placeholderPanel.add(jLabel3, gridBagConstraints); - - jLabel4.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 4; - placeholderPanel.add(jLabel4, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - jPanel2.add(placeholderPanel, gridBagConstraints); - - splitPane.setRightComponent(jPanel2); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - add(splitPane, gridBagConstraints); - }// //GEN-END:initComponents - - private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed - reset(); - }//GEN-LAST:event_refreshButtonActionPerformed - - private void refreshButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButton1ActionPerformed - onSelectTable(); - }//GEN-LAST:event_refreshButton1ActionPerformed - - private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - JDialog waitingDialog = waitDialog.get(); - if (waitingDialog != null) { - waitingDialog.dispose(); - } - }//GEN-LAST:event_cancelButtonActionPerformed - - private List outlineTables = new ArrayList(); - private boolean inSelectOutlineTable = false; - private boolean isOutlineVisible = true; - private int lastDividerLocation; - - private void showOutline() { - if (!isOutlineVisible) { - outlineScrollPane.setVisible(true); - placeholderPanel.setVisible(true); - splitPane.setDividerLocation(Math.min(lastDividerLocation, splitPane.getHeight() - 80)); - if (lastDividerLocation == -1) { - final int PREFERRED_HEIGHT = 250; - int prefHeight = Math.min(PREFERRED_HEIGHT, (int) (splitPane.getHeight() * 0.4)); - if (prefHeight > outlineScrollPane.getHeight()) { - splitPane.setDividerLocation(splitPane.getHeight() - prefHeight); - } - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - TreePath path = metaDataTree.getSelectionPath(); - if (path != null) { - Rectangle bounds = metaDataTree.getPathBounds(path); - if (bounds != null) { - metaDataTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height)); - } - } - } - }); - jPanel2.repaint(); - isOutlineVisible = true; - } - } - - private void hideOutline() { - if (isOutlineVisible) { - isOutlineVisible = false; - outlineScrollPane.setVisible(false); - placeholderPanel.setVisible(false); - lastDividerLocation = splitPane.getDividerLocation(); - splitPane.setDividerLocation(splitPane.getHeight() - 32); - } - } - - private final String fontName; { - String name = null; - try { - name = new RSyntaxTextArea().getFont().getName(); - } catch (Throwable t) { - // ignore - } - fontName = name; - } - - private String outlineTableRender(OutlineInfo info, boolean selected) { - String KEYWORD_ATTRIBUTES = "color=\"#0000cc\""; - String face = fontName != null? "face=\"" + fontName + "\" " : ""; - String render = ""; - String KEYWORD_PREFIX = (fontName != null? "" : "") + ""; - String KEYWORD_SUFFIX = "" + (fontName != null? "" : ""); - String scopeDescriptor = info.scopeDescriptor; - if (scopeDescriptor != null) { - scopeDescriptor = scopeDescriptor.replace(" ", " "); - } - if (info.mdTable != null || info.isCTE) { - if (info.isCTE) { - render = scopeDescriptor; - } else { - if (info.mdTable.getSchema().isDefaultSchema) { - render += info.mdTable.getName(); - } else { - render += info.mdTable.getSchema().getName() + "." + info.mdTable.getName(); - } - if (scopeDescriptor != null) { - render = "" + KEYWORD_PREFIX + "" + scopeDescriptor + "" + KEYWORD_SUFFIX + " " + render; - } - } - String alias = info.alias; - if (alias != null) { - if (!render.isEmpty()) { - render += " "; - } - render += "" + KEYWORD_PREFIX + "as" + KEYWORD_SUFFIX + " " + alias; - } - render += ""; - } else if (scopeDescriptor != null) { - render = "" + KEYWORD_PREFIX + "" + scopeDescriptor + "" + KEYWORD_SUFFIX + "" + (info.rowCount > 1? " (" + info.rowCount + " rows)" : "") + ""; - } - - String indent = "      "; - if (info.isCTE && "".equals(info.alias)) { - render = "   " + render; - } else if (scopeDescriptor == null || (info.isCTE && !"".equals(scopeDescriptor))) { - render = indent + render; - } - for (int i = 0; i < info.level; ++i) { - render = indent + render; - } - if (info.context != null) { - render += " " + info.context + ""; - } - render = "" + render; - return render; - } - - private int indexOfInfoAtCaret = -1; - - public void setOutline(List outlineTables, int indexOfInfoAtCaret) { - this.outlineTables = new ArrayList(outlineTables); - this.indexOfInfoAtCaret = indexOfInfoAtCaret; - DefaultListModel model = new DefaultListModel(); - for (OutlineInfo info: outlineTables) { - model.addElement(info); - } - outlineList.setModel(model); - if (outlineTables.isEmpty()) { - hideOutline(); - } else { - showOutline(); - if (indexOfInfoAtCaret >= 0) { - Rectangle aRect = outlineList.getCellBounds(indexOfInfoAtCaret, indexOfInfoAtCaret); - if (aRect != null) { - outlineList.scrollRectToVisible(aRect); - } - } - } - } - - private void selectOutlineTable(MDTable mdTable) { - if (!inSelectOutlineTable) { - inSelectOutlineTable = true; - boolean found = false; - for (OutlineInfo value: outlineTables) { - if (mdTable.equals(value.mdTable)) { - outlineList.setSelectedValue(value, true); - found = true; - break; - } - } - if (!found) { - outlineList.clearSelection(); - } - inSelectOutlineTable = false; - } - } - - - public static class OutlineInfo { - public final MDTable mdTable; - public final String alias; - public int level; - public int position; - public String scopeDescriptor; - public boolean withContext = false; - public int contextPosition; - public String context; - public String tooltip; - public int contextEnd = 0; - public boolean isCTE; - public boolean isBegin; - public boolean isEnd; - public boolean withSeparator; - public int rowCount; - public int origPosition; - - public OutlineInfo(MDTable mdTable, String alias, int level, int position, String scopeDescriptor) { - this.mdTable = mdTable; - this.alias = alias; - this.level = level; - this.position = position; - this.origPosition = position; - this.scopeDescriptor = scopeDescriptor; - } - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton cancelButton; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JTree metaDataTree; - private javax.swing.JLabel outlineLabel; - private javax.swing.JList outlineList; - private javax.swing.JScrollPane outlineScrollPane; - private javax.swing.JPanel placeholderPanel; - private javax.swing.JButton refreshButton; - private javax.swing.JButton refreshButton1; - private javax.swing.JSplitPane splitPane; - private javax.swing.JPanel waitingPanel; - // End of variables declaration//GEN-END:variables - - protected abstract void open(Table table); - protected abstract void open(MDTable mdTable); - protected abstract void analyseSchema(String schemaName); - protected abstract void onTableSelect(MDTable mdTable); - protected abstract void onRowSelect(Table mdTable, Row row); - protected abstract void onSchemaSelect(MDSchema mdSchema); - protected abstract void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext); - protected abstract void openNewTableBrowser(); - protected abstract void updateDataModelView(Table table); - protected abstract void setCaretPosition(int position); - protected abstract void appendScript(String script, boolean execute); - protected abstract void setOrResetWaitState(boolean set); - - public void onSelectTable() { - Object item = tablesComboBox.getSelectedItem(); - if (item != null) { - Table table = dataModel.getTableByDisplayName(item.toString()); - if (table != null) { - MDTable mdTable = metaDataSource.toMDTable(table); - if (mdTable != null) { - select(mdTable); - } else { - JOptionPane.showMessageDialog(parent, "Table \"" + dataModel.getDisplayName(table) + "\" does not exist in the database"); - } - } else { - MDTable mdTable = tablesComboboxMDTablePerName.get(item); - if (mdTable != null) { - select(mdTable); - } - } - } - } - - public void refresh() { - metaDataTree.repaint(); - } - - static ImageIcon warnIcon; - static ImageIcon viewIcon; - static ImageIcon viewsIcon; - static ImageIcon tableIcon; - static ImageIcon tablesIcon; - static ImageIcon synonymIcon; - static ImageIcon synonymsIcon; - static ImageIcon databaseIcon; - static ImageIcon schemaIcon; - private static HashMap combinedIcons = new HashMap(); - - private final AtomicReference waitDialog = new AtomicReference(null); - - static ImageIcon getScaledIcon(JComponent component, ImageIcon icon, boolean small) { - if (icon != null) { - ImageIcon scaledIcon = icon; - if (scaledIcon != null) { - int heigth = component.getFontMetrics(new JLabel("M").getFont()).getHeight(); - double s = heigth / (double) scaledIcon.getIconHeight(); - if (icon == viewIcon) { - s *= 0.8; - } - if (small) { - s *= 0.8; - } - try { - return UIUtil.scaleIcon(scaledIcon, s); - } catch (Exception e) { - logger.info("error", e); - return null; - } - } - } - return null; - } - static { - // load images - warnIcon = UIUtil.readImage("/wanr.png"); - viewIcon = UIUtil.readImage("/view.png"); - synonymIcon = UIUtil.readImage("/synonym.png"); - synonymsIcon = UIUtil.readImage("/synonyms.png"); - viewsIcon = UIUtil.readImage("/views.png"); - tablesIcon = UIUtil.readImage("/tables.png"); - tableIcon = UIUtil.readImage("/table.png"); - databaseIcon = UIUtil.readImage("/database.png"); - schemaIcon = UIUtil.readImage("/schema.png"); - } - -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser.metadata; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.Vector; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JToggleButton; +import javax.swing.JTree; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.ExpandVetoException; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import org.apache.log4j.Logger; +import org.fife.rsta.ui.EscapableDialog; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.configuration.DBMS; +import net.sf.jailer.configuration.DatabaseObjectRenderingDescription; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder; +import net.sf.jailer.modelbuilder.MemorizedResultSet; +import net.sf.jailer.modelbuilder.ModelBuilder; +import net.sf.jailer.ui.AutoCompletion; +import net.sf.jailer.ui.JComboBox; +import net.sf.jailer.ui.StringSearchPanel; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.UIUtil.IconWithText; +import net.sf.jailer.ui.databrowser.Row; +import net.sf.jailer.util.Quoting; + +/** + * Meta Data UI. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public abstract class MetaDataPanel extends javax.swing.JPanel { + + /** + * The logger. + */ + private static final Logger logger = Logger.getLogger(MetaDataPanel.class); + + private final MetaDataSource metaDataSource; + private final JComboBox tablesComboBox; + private final DataModel dataModel; + private final MetaDataDetailsPanel metaDataDetailsPanel; + private final Frame parent; + private final JToggleButton searchButton; + private final ExecutionContext executionContext; + + private final Object CATEGORY_VIEWS = new String("Views"); + private final Object CATEGORY_TABLES = new String("Tables"); + private final Object CATEGORY_SYNONYMS = new String("Synonyms"); + + /** + * Packages list view. + */ + private class MDPackages extends MDDescriptionBasedGeneric { + + private MDPackages(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { + super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { + { + setIconURL("/net/sf/jailer/ui/resource/packages.png"); + DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); + itemDescr.setIconURL("/net/sf/jailer/ui/resource/package.png"); + itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); + setItemDescription(itemDescr); + } + }); + } + + @Override + public List getDetails() { + ArrayList result = new ArrayList(); + try { + MemorizedResultSet theList = retrieveList(getMetaDataSource().getSession()); + for (final Object[] row: theList.getRowList()) { + MDProcedures procs = new MDProcedures(String.valueOf(row[0]), metaDataSource, schema, dataModel) { + @Override + protected boolean select(Object[] proc) { + return proc[2] != null && proc[2].equals(row[0]); + } + }; + procs.databaseObjectRenderingDescription.setIconURL("/net/sf/jailer/ui/resource/package.png"); + procs.databaseObjectRenderingDescription.setTextQuery(schema.getMetaDataSource().getSession().dbms.getPackageSourceQuery()); + result.add(procs); + } + } catch (Throwable t) { + logger.info("error", t); + } + return result; + } + + @Override + public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { + Set cats = null; + if (session.dbms.getPackageNamesQuery() != null) { + Statement cStmt = null; + try { + Connection connection = session.getConnection(); + cStmt = connection.createStatement(); + if (schema != null) { + schema = Quoting.staticUnquote(schema); + } + ResultSet rs = cStmt.executeQuery(String.format(Locale.ENGLISH, session.dbms.getPackageNamesQuery(), schema)); + MemorizedResultSet result = new MemorizedResultSet(rs, null, session, schema); + result.close(); + rs.close(); + cats = new TreeSet(); + for (Object[] cat: result.getRowList()) { + cats.add((String) cat[0]); + } + } catch (Exception e) { + logger.info("error", e); + } finally { + if (cStmt != null) { + try { + cStmt.close(); + } catch (SQLException e) { + } + } + } + } + if (cats == null) { + cats = new TreeSet(); + ResultSet rs = getProcedures(session, session.getMetaData(), schema, "%"); + while (rs.next()) { + String cat = rs.getString(1); + if (cat != null) { + cats.add(cat); + } + } + rs.close(); + } + List catList = new ArrayList(); + for (String cat: cats) { + catList.add(new Object[] { cat }); + } + MemorizedResultSet result = new MemorizedResultSet(catList, 1, new String[] { "Package", }, new int[] { Types.VARCHAR }); + return result; + } + } + + /** + * Procedures list view. + */ + private abstract class MDProcedures extends MDDescriptionBasedGeneric { + private final MDSchema mdSchema; + + public MDProcedures(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { + super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { + { + setIconURL("/net/sf/jailer/ui/resource/procedures.png"); + DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); + itemDescr.setIconURL("/net/sf/jailer/ui/resource/procedure.png"); + itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); + setItemDescription(itemDescr); + } + }); + this.mdSchema = schema; + } + + @Override + public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { + if (query != null) { + return super.retrieveList(session, query, schema, parentName); + } + MemorizedResultSet procs = new MemorizedResultSet(getProcedures(session, session.getMetaData(), schema, "%"), + null, session, schema, new int[] { 3, 4, 1, 8, 9 }, new String[] { "Name", "Remarks", "Category", "Type", "SpecificName" }); + List catList = new ArrayList(); + for (Object[] cat: procs.getRowList()) { + if (select(cat)) { + catList.add(cat); + } + } + procs.close(); + return new MemorizedResultSet(catList, procs.getMetaData()); + } + + @Override + protected int getDetailIDIndex() { + if (mdSchema.getMetaDataSource().getSession().dbms.isProcedureDetailNeedsSpecificName()) { + return 4; + } + return 0; + } + + protected abstract boolean select(Object[] proc); + + @Override + protected DatabaseObjectRenderingDescription itemDescription(MemorizedResultSet item) { + DatabaseObjectRenderingDescription desc = new DatabaseObjectRenderingDescription(databaseObjectRenderingDescription.getItemDescription()); + if (!item.getRowList().isEmpty() && String.valueOf(DatabaseMetaData.procedureReturnsResult).equals(String.valueOf(item.getRowList().get(0)[3]))) { + desc.setIconURL("/net/sf/jailer/ui/resource/function.png"); + desc.setTextQuery(mdSchema.getMetaDataSource().getSession().dbms.getFunctionSourceQuery()); + } + return desc; + } + } + + /** + * Constraints list view. + */ + private class MDConstraint extends MDDescriptionBasedGeneric { + private final MDSchema mdSchema; + + private Map constraintTypeNames = new LinkedHashMap(); + { + constraintTypeNames.put("PK", "Primary Keys"); + constraintTypeNames.put("Unique", "Unique Constraints"); + constraintTypeNames.put("Check", "Check Constraints"); + } + + public MDConstraint(String name, MetaDataSource metaDataSource, final MDSchema schema, DataModel dataModel) { + super(name, metaDataSource, schema, dataModel, new DatabaseObjectRenderingDescription() { + { + setIconURL("/net/sf/jailer/ui/resource/constraints.png"); + DatabaseObjectRenderingDescription itemDescr = new DatabaseObjectRenderingDescription(); + itemDescr.setTextQuery(schema.getMetaDataSource().getSession().dbms.getProcedureSourceQuery()); + setItemDescription(itemDescr); + } + }); + this.mdSchema = schema; + } + + @Override + public MemorizedResultSet retrieveList(Session session, String query, String schema, String parentName) throws SQLException { + if (query != null) { + return super.retrieveList(session, query, schema, parentName); + } + return mdSchema.getConstraints(null); + } + + /** + * Gets a list of descriptions of the details. + * + * @return list of descriptions of the details + */ + @Override + public List getDetails() { + ArrayList result = new ArrayList(); + try { + MemorizedResultSet theList = retrieveList(getMetaDataSource().getSession()); + Map typeNames = new LinkedHashMap(constraintTypeNames); + for (final Object[] row: theList.getRowList()) { + String type = String.valueOf(row[0]); + if (!typeNames.containsKey(type)) { + typeNames.put(type, type); + } + } + for (Entry e: typeNames.entrySet()) { + List rowsPerType = new ArrayList(); + ArrayList descs = new ArrayList(); + for (final Object[] row: theList.getRowList()) { + if (String.valueOf(row[0]).equals(e.getKey())) { + rowsPerType.add(row); + } + } + for (final Object[] row: theList.getRowList()) { + MemorizedResultSet detailRS = new MemorizedResultSet(Collections.singletonList(row), theList.getMetaData()); + DatabaseObjectRenderingDescription detailDesc = itemDescription(detailRS); + if (detailDesc != null) { + MDDescriptionBasedGeneric mdDetails = createDetailDescription(row, detailDesc); + mdDetails.detailName = String.valueOf(row[getDetailIDIndex()]); + if (detailDesc.getListQuery() == null) { + mdDetails.list = detailRS; + } + descs.add(mdDetails); + } + } + DatabaseObjectRenderingDescription desc = new DatabaseObjectRenderingDescription(); + desc.setItemDescription(new DatabaseObjectRenderingDescription()); + final MemorizedResultSet listPerType = new MemorizedResultSet(rowsPerType, theList.getMetaData()); + final UIUtil.IconWithText label = MDSchema.getConstraintTypeIcon(e.getKey() + "s"); + result.add(new MDDescriptionBasedGeneric(e.getValue(), getMetaDataSource(), schema, dataModel, desc) { + @Override + protected MemorizedResultSet retrieveList(Session session) throws SQLException { + listPerType.reset(); + return listPerType; + } + + @Override + public List getDetails() { + return super.getDetails(); + } + + @Override + protected MDDescriptionBasedGeneric createDetailDescription(final Object[] row, DatabaseObjectRenderingDescription detailDesc) { + final IconWithText label = (IconWithText) row[0]; + return new MDDescriptionBasedGeneric(row[1] + " on " + row[2] + (row[3] != null && row[3].toString().trim().length() > 0? "(" + row[3] + ")" : ""), getMetaDataSource(), schema, dataModel, detailDesc) { + @Override + public ImageIcon getIcon() { + return label == null? null : label.icon; + } + }; + } + + @Override + public ImageIcon getIcon() { + return label == null? null : label.icon; + } + }); + } + } catch (Throwable t) { + logger.info("error", t); + } + return result; + } + @Override + protected MemorizedResultSet distinct(MemorizedResultSet list) throws SQLException { + return list; + } + + @Override + public boolean hasDetails() { + return true; + } + } + + private List getGenericDatabaseObjects(final MDSchema mdSchema) { + List genericDatabaseObjects = new ArrayList(); + genericDatabaseObjects.add( + new MDProcedures("Procedures", metaDataSource, mdSchema, dataModel) { + @Override + protected boolean select(Object[] proc) { + return proc[2] == null || !DBMS.ORACLE.equals(mdSchema.getMetaDataSource().getSession().dbms); + } + } + ); + if (DBMS.ORACLE.equals(mdSchema.getMetaDataSource().getSession().dbms)) { + genericDatabaseObjects.add(new MDPackages("Packages", metaDataSource, mdSchema, dataModel)); + } + if (mdSchema.getMetaDataSource().getSession().dbms.getConstraintsQuery() != null) { + genericDatabaseObjects.add(new MDConstraint("Constraints", metaDataSource, mdSchema, dataModel)); + } + for (DatabaseObjectRenderingDescription desc: mdSchema.getMetaDataSource().getSession().dbms.getObjectRenderers()) { + MDDescriptionBasedGeneric mdObjectRenderer + = new MDDescriptionBasedGeneric( + desc.getName(), metaDataSource, mdSchema, dataModel, desc); + genericDatabaseObjects.add(mdObjectRenderer); + } + return genericDatabaseObjects; + } + + private Map proceduresPerSchema = Collections.synchronizedMap(new HashMap()); + + public ResultSet getProcedures(Session session, DatabaseMetaData metaData, String schema, String context) throws SQLException { + synchronized (proceduresPerSchema) { + MemorizedResultSet rs = proceduresPerSchema.get(schema); + if (rs == null) { + if (schema != null) { + schema = Quoting.staticUnquote(schema); + } + rs = new MemorizedResultSet(JDBCMetaDataBasedModelElementFinder.getProcedures(session, metaData, Quoting.staticUnquote(schema), context), null, session, ""); + proceduresPerSchema.put(schema, rs); + } + rs.reset(); + return rs; + } + } + + private abstract class ExpandingMutableTreeNode extends DefaultMutableTreeNode { + + public ExpandingMutableTreeNode() { + super("loading..."); + } + + protected abstract void expandImmediatelly(); + protected abstract void expand(); + } + + /** + * Creates new form MetaDataPanel + * + * @param metaDataSource the meta data source + * @param dataModel the data mmodel + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public MetaDataPanel(Frame parent, MetaDataSource metaDataSource, MetaDataDetailsPanel metaDataDetailsPanel, final DataModel dataModel, ExecutionContext executionContext) { + this.metaDataSource = metaDataSource; + this.dataModel = dataModel; + this.metaDataDetailsPanel = metaDataDetailsPanel; + this.parent = parent; + this.executionContext = executionContext; + initComponents(); + + hideOutline(); + lastDividerLocation = -1; + + final ListCellRenderer olRenderer = outlineList.getCellRenderer(); + outlineList.setCellRenderer(new ListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + String tooltip = null; + boolean withSeparator = false; + double level = 0; + if (value instanceof OutlineInfo) { + tooltip = ((OutlineInfo) value).tooltip; + withSeparator = ((OutlineInfo) value).withSeparator; + level = ((OutlineInfo) value).level; + if (((OutlineInfo) value).isCTE) { + level += 0.5; + } + value = outlineTableRender((OutlineInfo) value, isSelected); + } + Component render = olRenderer.getListCellRendererComponent(list, value, index, false, cellHasFocus); + render.setBackground(isSelected? new Color(240, 240, 255) : index == indexOfInfoAtCaret? new Color(255, 255, 170) : Color.WHITE); + if (render instanceof JLabel) { + ((JLabel) render).setToolTipText(tooltip); + + if (withSeparator) { + final Border border = ((JLabel) render).getBorder() == null? new EmptyBorder(0, 0, 0, 0) : ((JLabel) render).getBorder(); + final Color bg = ((JLabel) render).getBackground(); + final int ind = (int) (level * 22); + final int SEP_LENGTH = 300; + ((JLabel) render).setBorder(new Border() { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + border.paintBorder(c, g, x, y, width, height); + if (g instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g; + Color color = new Color(100, 100, 255); + int ofs = 50; + GradientPaint paint = new GradientPaint( + x + ind - 20, 0, bg==null ? Color.WHITE : bg, + x + ind + ofs, 0, color); + g2d.setPaint(paint); + g2d.fillRect(x + ind - 20, 0, ofs + 20, 1); + if (ind + ofs < SEP_LENGTH) { + paint = new GradientPaint( + x + ind + ofs, 0, color, + x + SEP_LENGTH, 0, bg==null ? Color.WHITE : bg); + g2d.setPaint(paint); + g2d.fillRect(x + ind + ofs, 0, SEP_LENGTH, 1); + } + } + } + @Override + public Insets getBorderInsets(Component c) { + return border.getBorderInsets(c); + } + @Override + public boolean isBorderOpaque() { + return border.isBorderOpaque(); + } + }); + } + + } + return render; + } + }); + + outlineList.addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent e) { + } + @Override + public void mousePressed(MouseEvent e) { + } + @Override + public void mouseExited(MouseEvent e) { + } + @Override + public void mouseEntered(MouseEvent e) { + } + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() > 1) { + int i = outlineList.locationToIndex(e.getPoint()); + if (i >= 0) { + Object value = outlineList.getModel().getElementAt(i); + if (value instanceof OutlineInfo) { + setCaretPosition(((OutlineInfo) value).origPosition); + } + } + } + } + }); + + outlineList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + Object value = outlineList.getSelectedValue(); + if (!inSelectOutlineTable && value instanceof OutlineInfo) { + MDTable mdTable = ((OutlineInfo) value).mdTable; + if (mdTable != null) { + inSelectOutlineTable = true; + select(mdTable); + inSelectOutlineTable = false; + } + } + } + }); + + tablesComboBox = new JComboBox() { + @Override + public Dimension getMinimumSize() { + return new Dimension(40, super.getMinimumSize().height); + } + }; + tablesComboBox.setMaximumRowCount(20); + AutoCompletion.enable(tablesComboBox); + + tablesComboBox.grabFocus(); + + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1; + add(tablesComboBox, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + searchButton = StringSearchPanel.createSearchButton(parent, tablesComboBox, "Select Table", new Runnable() { + @Override + public void run() { + onSelectTable(); + } + }, new StringSearchPanel.Prepare() { + @Override + public void prepare(Set selectedSchemas) { + updateTablesCombobox(selectedSchemas); + } + }, metaDataSource, dataModel); + jPanel1.add(searchButton, gridBagConstraints); + + tablesComboBox.setVisible(false); + refreshButton1.setVisible(false); + searchButton.setText("Select Table"); + + metaDataTree.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\n') { + if (metaDataTree.getSelectionPath() != null) { + Object last = metaDataTree.getSelectionPath().getLastPathComponent(); + if (last instanceof DefaultMutableTreeNode) { + final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); + if (uo instanceof MDTable) { + openTable((MDTable) uo); + } + } + } + } + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + } + }); + + metaDataTree.addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent e) { + } + @Override + public void mousePressed(MouseEvent e) { + } + @Override + public void mouseExited(MouseEvent e) { + } + @Override + public void mouseEntered(MouseEvent e) { + } + @Override + public void mouseClicked(MouseEvent evt) { + final MDTable mdTable = findTable(evt); + TreePath node = findNode(evt); + if (node != null) { + metaDataTree.scrollRectToVisible(new Rectangle(0, (int) evt.getPoint().getY(), 1, 1)); + } + final Set mdTables = new LinkedHashSet(); + findTables(mdTables); + if (evt.getButton() == MouseEvent.BUTTON3) { + if (mdTable != null || !mdTables.isEmpty()) { + int itemCount = 0; + JPopupMenu popup = new JPopupMenu(); + if (mdTable != null) { + JMenuItem open = new JMenuItem("Open"); + popup.add(open); + ++itemCount; + open.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + openTable(mdTable); + } + }); + } + if (mdTable != null && MetaDataPanel.this.metaDataSource.toTable(mdTable) == null) { + if (itemCount > 0) { + popup.addSeparator(); + } + JMenuItem analyse = new JMenuItem("Analyse schema \""+ mdTable.getSchema().getUnquotedName() + "\""); + popup.add(analyse); + ++itemCount; + analyse.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + analyseSchema(mdTable.getSchema().getName()); + } + }); + } + if (!mdTables.isEmpty()) { + if (itemCount > 0) { + popup.addSeparator(); + } + JMenu menu = new JMenu("Create Script"); + popup.add(menu); + ++itemCount; + Point pos = new Point(evt.getX(), evt.getY()); + SwingUtilities.convertPointToScreen(pos, evt.getComponent()); + menu.add(createScriptMenuItem("Delete Script", "Delete from %1$s;", "", mdTables, false, pos)); + menu.add(createScriptMenuItem("Create Table Script", "DDL", "", mdTables, false, pos)); + menu.add(createScriptMenuItem("Drop Table Script", "Drop %2$s %1$s;", "", mdTables, false, pos)); + menu.addSeparator(); + menu.add(createScriptMenuItem("Count Rows Script", "Select '%1$s' as Tab, count(*) as NumberOfRows From %1$s", " union all", mdTables, true, pos)); + } + popup.show(evt.getComponent(), evt.getX(), evt.getY()); + } + } + if (evt.getButton() == MouseEvent.BUTTON1) { + if (mdTable != null) { + if (evt.getClickCount() > 1) { + if (node != null && metaDataTree.getSelectionModel().isPathSelected(node)) { + openTable(mdTable); + } + } + } + } + } + private JMenuItem createScriptMenuItem(String title, final String template, final String separator, final Set mdTables, final boolean execute, final Point pos) { + JMenuItem item = new JMenuItem(title); + final AtomicBoolean cancelLoading = new AtomicBoolean(false); + + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final Window wa = SwingUtilities.getWindowAncestor(MetaDataPanel.this); + final boolean withWaitDialog; + if ("DDL".equals(template) && mdTables.size() > 1) { + cancelLoading.set(false); + withWaitDialog = true; + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + JDialog dialog; + dialog = new EscapableDialog((wa instanceof Frame)? (Frame) wa : null, "Script") { + }; + dialog.setModal(true); + waitDialog.set(dialog); + dialog.getContentPane().add(waitingPanel); + dialog.pack(); + dialog.setLocation(pos.x + dialog.getWidth() / 2 - dialog.getWidth() / 2, pos.y + dialog.getHeight() / 2 - dialog.getHeight() / 2); + dialog.setVisible(true); + waitDialog.set(null); + cancelLoading.set(true); + } + }); + } else { + waitDialog.set(null); + withWaitDialog = false; + } + MDSchema.loadMetaData(new Runnable() { + @Override + public void run() { + if (withWaitDialog) { + for (MDTable mdTable: mdTables) { + mdTable.getDDL(); + if (cancelLoading.get()) { + break; + } + } + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + if (!cancelLoading.get()) { + StringBuilder script = new StringBuilder(); + for (MDTable mdTable: mdTables) { + if (script.length() > 0) { + script.append(separator + UIUtil.LINE_SEPARATOR); + } + if ("DDL".equals(template)) { + String ddl = mdTable.getDDL().trim().replaceAll("\\nON ", " ON "); + script.append(ddl); + if (!ddl.endsWith(";")) { + script.append(";"); + } + } else { + String tableName; + String tableType = "Table"; + if (mdTable.isView()) { + tableType = "View"; + } + if (mdTable.isSynonym()) { + tableType = "Synonym"; + } + if (mdTable.getSchema().isDefaultSchema) { + tableName = mdTable.getName(); + } else { + tableName = mdTable.getSchema() + "." + mdTable.getName(); + } + script.append(String.format(Locale.ENGLISH, template, tableName, tableType)); + } + } + script.append("\n"); + appendScript(script.toString(), execute); + } + if (waitDialog.get() != null) { + waitDialog.get().dispose(); + waitDialog.set(null); + } + } + }); + } + }, 2); + } + }); + return item; + } + private void findTables(Set mdTables) { + TreePath[] paths = metaDataTree.getSelectionPaths(); + if (paths != null) { + for (TreePath path: paths) { + findTables(mdTables, path.getLastPathComponent()); + } + } + } + private void findTables(Set mdTables, Object node) { + if (node instanceof DefaultMutableTreeNode && node != metaDataTree.getModel().getRoot()) { + DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) node; + Object selNode = defaultMutableTreeNode.getUserObject(); + if (selNode instanceof MDTable) { + mdTables.add((MDTable) selNode); + } + for (int i = 0; i < defaultMutableTreeNode.getChildCount(); ++i) { + findTables(mdTables, defaultMutableTreeNode.getChildAt(i)); + } + } + } + private MDTable findTable(MouseEvent evt) { + MDTable mdTable = null; + TreePath node = findNode(evt); + if (node != null) { + Object sel = node.getLastPathComponent(); + if (sel instanceof DefaultMutableTreeNode) { + Object selNode = ((DefaultMutableTreeNode) sel).getUserObject(); + if (selNode instanceof MDTable) { + mdTable = (MDTable) selNode; + } + } + } + return mdTable; + } + private TreePath findNode(MouseEvent evt) { + TreePath node = metaDataTree.getPathForLocation(evt.getX(), evt.getY()); + if (node == null) { + for (int x = metaDataTree.getWidth(); x > 0; x -= 32) { + node = metaDataTree.getPathForLocation(x, evt.getY()); + if (node != null) { + break; + } + } + } + return node; + } + }); + + metaDataTree.addTreeWillExpandListener(new TreeWillExpandListener() { + @Override + public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { + Object node = event.getPath().getLastPathComponent(); + if (node instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node; + if (treeNode.getChildCount() == 1 && treeNode.getChildAt(0) instanceof ExpandingMutableTreeNode) + ((ExpandingMutableTreeNode) treeNode.getChildAt(0)).expand(); + } + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { + } + }); + + final ImageIcon finalScaledWarnIcon = getScaledIcon(this, warnIcon, true); + + DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { + Map dirtyTables = new HashMap(); + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + boolean unknownTable = false; + boolean isJailerTable = false; + boolean isView = false; + boolean isSynonym = false; + Boolean isDirty = false; + ImageIcon image = null; + Long estRowCount = null; + if (value instanceof DefaultMutableTreeNode) { + Object uo = ((DefaultMutableTreeNode) value).getUserObject(); + if (uo instanceof JLabel) { + Icon icon = ((JLabel) uo).getIcon(); + if (icon instanceof ImageIcon) { + image = (ImageIcon) ((JLabel) uo).getIcon(); + } + } + if (uo == CATEGORY_VIEWS) { + image = viewsIcon; + } + if (uo == CATEGORY_SYNONYMS) { + image = synonymsIcon; + } + if (uo == CATEGORY_TABLES) { + image = tablesIcon; + } + if (uo instanceof MDDatabase) { + image = databaseIcon; + } + if (uo instanceof MDSchema) { + image = schemaIcon; + } + if (uo instanceof MDDescriptionBasedGeneric) { + image = ((MDDescriptionBasedGeneric) uo).getIcon(); + } + if (uo instanceof MDTable) { + Table table = MetaDataPanel.this.metaDataSource.toTable((MDTable) uo); + if (table == null) { + unknownTable = true; + } else { + if (((MDTable) uo).isLoaded()) { + isDirty = dirtyTables.get(uo); + if (isDirty == null) { + isDirty = !((MDTable) uo).isUptodate(table); + dirtyTables.put(((MDTable) uo), isDirty); + } + } + } + isView = ((MDTable) uo).isView(); + isSynonym = ((MDTable) uo).isSynonym(); + if (!isView) { + estRowCount = ((MDTable) uo).estimatedRowCount; + } + if (isView) { + image = viewIcon; + } else if (isSynonym) { + image = synonymIcon; + } else { + image = tableIcon; + } + if (ModelBuilder.isJailerTable(((MDTable) uo).getUnquotedName())) { + isJailerTable = true; + } + } + } + Component comp = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (comp instanceof JLabel) { + String text = ((JLabel) comp).getText(); + if (estRowCount != null) { + Color fg = ((JLabel) comp).getForeground(); + String estRowCountFormatted; + if (estRowCount >= 1000000) { + estRowCountFormatted = String.format("%,1.1f M", (double) estRowCount / 1000000.0); + } else if (estRowCount >= 1000) { + estRowCountFormatted = String.format("%,1.1f K", (double) estRowCount / 1000.0); + } else { + estRowCountFormatted = estRowCount.toString(); + } + if (fg.getRed() + fg.getGreen() + fg.getBlue() < 255 * 3 / 2) { + ((JLabel) comp).setText("" + text + "  ~" + estRowCountFormatted + ""); + } else { + ((JLabel) comp).setText("" + text + "  ~" + estRowCountFormatted + ""); + } + } + } + if (isJailerTable && !sel) { + if (comp instanceof JLabel) { + ((JLabel) comp).setForeground(Color.gray); + } + } + if (image != null) { + if (comp instanceof JLabel) { + ((JLabel) comp).setIcon(image); + } + } + if ((unknownTable || isDirty) && !isJailerTable) { + if (comp instanceof JLabel) { + if (image != null) { + ImageIcon combinedIcon = combinedIcons.get(image); + if (combinedIcon == null) { + Image im = image.getImage(); + // create the new image, canvas size is the max. of both image sizes + int w = Math.max(image.getIconWidth(), finalScaledWarnIcon.getIconWidth()); + int h = Math.max(image.getIconHeight(), finalScaledWarnIcon.getIconHeight()); + BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + + // paint both images, preserving the alpha channels + Graphics g = combined.getGraphics(); + g.drawImage(im, 0, 0, null); + g.translate(image.getIconWidth() / 4, image.getIconHeight() / 4); + g.drawImage(finalScaledWarnIcon.getImage(), 0, 0, null); + combinedIcon = new ImageIcon(combined); + combinedIcons.put(image, combinedIcon); + } + ((JLabel) comp).setIcon(combinedIcon); + } else { + ((JLabel) comp).setIcon(finalScaledWarnIcon); + } + } + } + return comp; + } + }; + renderer.setOpenIcon(null); + renderer.setLeafIcon(null); + renderer.setClosedIcon(null); + metaDataTree.setCellRenderer(renderer); + metaDataTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + + metaDataTree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + TreePath path = e.getNewLeadSelectionPath(); + if (path != null) { + final Object last = path.getLastPathComponent(); + if (metaDataTree.getModel().getRoot() == last) { +// searchButton.doClick(); + } + if (last instanceof DefaultMutableTreeNode) { + final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); + if (uo instanceof MDTable) { + selectOutlineTable((MDTable) uo); + Table table = MetaDataPanel.this.metaDataSource.toTable((MDTable) uo); + if (table != null) { + updateDataModelView(table); + } + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + UIUtil.setWaitCursor(MetaDataPanel.this); + try { + if (metaDataTree.getSelectionPath() != null && metaDataTree.getSelectionPath().getLastPathComponent() == last) { + if (uo instanceof MDSchema) { + onSchemaSelect((MDSchema) uo); + } else if (uo instanceof MDTable) { + onTableSelect((MDTable) uo); + } else if (uo instanceof MDGeneric) { + onMDOtherSelect((MDGeneric) uo, MetaDataPanel.this.executionContext); + } else { + onMDOtherSelect(new MDGeneric("", MetaDataPanel.this.metaDataSource) { + @Override + public JComponent createRender(Session session, + ExecutionContext executionContext) throws Exception { + return new JLabel(""); + } + }, MetaDataPanel.this.executionContext); + } + } + } finally { + UIUtil.resetWaitCursor(MetaDataPanel.this); + } + } + }); + } + }); + } + }); + } + } + } + }); + + updateTreeModel(metaDataSource); + + Font font = outlineLabel.getFont(); + if (font != null) { + Font bold = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize()); + outlineLabel.setFont(bold); + } + } + + private Map tablesComboboxMDTablePerName = new HashMap(); + + private void updateTablesCombobox(Set selectedSchemas) { + Set tableSet = new HashSet(); + Set toLoad = new HashSet(); + + for (Table table: dataModel.getTables()) { + MDSchema mdSchema = metaDataSource.getSchemaOfTable(table); + if (mdSchema != null && !mdSchema.isLoaded()) { + toLoad.add(mdSchema); + } else if (metaDataSource.toMDTable(table) == null) { + String schemaName = table.getSchema(""); + MDSchema schema; + if (schemaName.isEmpty()) { + schema = metaDataSource.getDefaultSchema(); + } else { + schema = metaDataSource.find(schemaName); + } + if (schema != null && selectedSchemas.contains(schema)) { + String displayName = dataModel.getDisplayName(table); + tableSet.add(displayName); + } + } + } + for (MDSchema schema: selectedSchemas) { + if (!schema.isLoaded()) { + toLoad.add(schema); + } else { + for (MDTable table: schema.getTables()) { + if (!ModelBuilder.isJailerTable(table.getName())) { + String name; + if (!schema.isDefaultSchema) { + name = schema.getName() + "." + table.getName(); + } else { + name = table.getName(); + } + tableSet.add(name); + tablesComboboxMDTablePerName.put(name, table); + } + } + } + } + List tables = new ArrayList(tableSet); + Collections.sort(tables, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + }); + ComboBoxModel model = new DefaultComboBoxModel(new Vector(tables)); + tablesComboBox.setModel(model); + + for (MDSchema schema: toLoad) { + schema.loadTables(true, null, null); + } + } + + protected void openTable(MDTable mdTable) { + Table table = metaDataSource.toTable(mdTable); + if (table != null) { + open(table); + } else { + open(mdTable); + } + } + + private int inResetCount = 0; + private static AtomicInteger pendingCount = new AtomicInteger(); + + public void reset() { + if (pendingCount.get() > 0) { + return; + } + inResetCount++; + refreshButton.setEnabled(false); + final AtomicBoolean waitStateIsResetted = new AtomicBoolean(false); + Timer timer = new Timer(100, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!waitStateIsResetted.get()) { + setOrResetWaitState(true); + } + } + }); + timer.setRepeats(false); + timer.start(); + + JDBCMetaDataBasedModelElementFinder.resetCaches(metaDataSource.getSession()); + setOutline(new ArrayList(), -1); + proceduresPerSchema.clear(); + + MDTable selectedTable = null; + if (metaDataTree.getSelectionPath() != null) { + Object last = metaDataTree.getSelectionPath().getLastPathComponent(); + if (last instanceof DefaultMutableTreeNode) { + final Object uo = ((DefaultMutableTreeNode) last).getUserObject(); + if (uo instanceof MDTable) { + selectedTable = (MDTable) uo; + } + } + } + final MDTable finalSelectedTable = selectedTable; + + pendingCount.incrementAndGet(); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + try { + Session.setThreadSharesConnection(); + synchronized (metaDataSource) { + pendingCount.getAndDecrement(); + metaDataSource.clear(); + } + } finally { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + if (--inResetCount <= 0) { + try { + metaDataDetailsPanel.reset(); + updateTreeModel(metaDataSource); + if (finalSelectedTable != null) { + final MDSchema schema = metaDataSource.find(finalSelectedTable.getSchema().getName()); + ActionListener al = new ActionListener() { + int cnt = 10; + @Override + public void actionPerformed(ActionEvent e) { + if (schema != null) { + if (!schema.isLoaded()) { + if (--cnt > 0) { + Timer timer = new Timer(200, this); + timer.setRepeats(false); + timer.start(); + } + return; + } + MDTable table = schema.find(finalSelectedTable.getName()); + if (table != null) { + select(table); + } + } + } + }; + Timer timer = new Timer(100, al); + timer.setRepeats(false); + timer.start(); + } + } finally { + refreshButton.setEnabled(true); + setOrResetWaitState(false); + waitStateIsResetted.set(true); + } + } + } + }); + } + } + }); + thread.setDaemon(true); + thread.start(); + } + + public void select(Table table) { + MDSchema mdSchema = metaDataSource.getSchemaOfTable(table); + if (mdSchema != null && !mdSchema.isLoaded()) { + mdSchema.loadTables(true, null, null); + return; + } + select(metaDataSource.toMDTable(table)); + } + + public void select(MDTable mdTable) { + if (mdTable != null) { + TreePath path = find(metaDataTree.getModel().getRoot(), mdTable); + if (path != null) { + selectSchema(mdTable.getSchema(), false); + metaDataTree.expandPath(path); + metaDataTree.getSelectionModel().setSelectionPath(path); + scrollToNode(path); + } else { + selectSchema(mdTable.getSchema()); + } + } + } + + private void scrollToNode(TreePath path) { + Rectangle bounds = metaDataTree.getPathBounds(path); + if (bounds != null) { + int b = 18; + bounds = new Rectangle(bounds.x, Math.max(bounds.y - b, 0), bounds.width, bounds.height + 2 * b); + metaDataTree.scrollRectToVisible(new Rectangle(0, bounds.y, 1, bounds.height)); + } + } + + private TreePath find(Object root, MDTable mdTable) { + if (root instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode) root).getUserObject(); + if (userObject instanceof MDSchema) { + if (mdTable.getSchema().equals(userObject)) { + int cc = ((DefaultMutableTreeNode) root).getChildCount(); + for (int i = 0; i < cc; ++i) { + TreeNode catNode = ((DefaultMutableTreeNode) root).getChildAt(i); + Object catUO = ((DefaultMutableTreeNode) catNode).getUserObject(); + if (catNode.getChildCount() > 0 && (CATEGORY_TABLES == catUO || CATEGORY_VIEWS == catUO || CATEGORY_SYNONYMS == catUO)) { + TreeNode firstChild = catNode.getChildAt(0); + if (firstChild instanceof ExpandingMutableTreeNode) { + ((ExpandingMutableTreeNode) firstChild).expandImmediatelly(); + } + } + } + } + } else if (userObject instanceof MDTable) { + if (userObject == mdTable) { + return new TreePath(((DefaultMutableTreeNode) root).getPath()); + } + } + int cc = ((DefaultMutableTreeNode) root).getChildCount(); + for (int i = 0; i < cc; ++i) { + TreePath path = find(((DefaultMutableTreeNode) root).getChildAt(i), mdTable); + if (path != null) { + return path; + } + } + } + return null; + } + + private DefaultMutableTreeNode root; + private Map treeNodePerSchema = new HashMap(); + + private void updateTreeModel(final MetaDataSource metaDataSource) { + root = new DefaultMutableTreeNode(new MDDatabase(metaDataSource.dataSourceName, metaDataSource, dataModel, executionContext)); + for (final MDSchema schema: metaDataSource.getSchemas()) { + final DefaultMutableTreeNode schemaChild = new DefaultMutableTreeNode(schema); + for (final MDDescriptionBasedGeneric desc: getGenericDatabaseObjects(schema)) { + Iterable leafs = new Iterable() { + @Override + public Iterator iterator() { + List details = new ArrayList(); + for (MDDescriptionBasedGeneric detail: desc.getDetails()) { + details.add(detail); + } + return details.iterator(); + } + }; + createCategoryNode(schemaChild, leafs, desc, desc.hasDetails(), desc.isCheap()? 0 : 1); + } + Iterable leafs = new Iterable() { + @Override + public Iterator iterator() { + List leafs = new ArrayList(); + for (MDTable table: schema.getTables()) { + if (table.isView()) { + leafs.add(table); + } + } + return leafs.iterator(); + } + }; + createCategoryNode(schemaChild, leafs, CATEGORY_VIEWS, true, 0); + leafs = new Iterable() { + @Override + public Iterator iterator() { + List leafs = new ArrayList(); + for (MDTable table: schema.getTables()) { + if (table.isSynonym()) { + leafs.add(table); + } + } + return leafs.iterator(); + } + }; + createCategoryNode(schemaChild, leafs, CATEGORY_SYNONYMS, true, 0); + leafs = new Iterable() { + @Override + public Iterator iterator() { + List leafs = new ArrayList(); + for (MDTable table: schema.getTables(true, new Runnable() { + @Override + public void run() { + refresh(); + } + })) { + if (!table.isView() && !table.isSynonym()) { + leafs.add(table); + } + } + return leafs.iterator(); + } + }; + DefaultMutableTreeNode schemaTablesChild = createCategoryNode(schemaChild, leafs, CATEGORY_TABLES, true, 0); + treeNodePerSchema.put(schema, schemaTablesChild); + } + DefaultTreeModel treeModel = new DefaultTreeModel(root); + metaDataTree.setModel(treeModel); + metaDataTree.scrollRectToVisible(new Rectangle(0, 0, 1, 1)); + selectSchema(metaDataSource.getDefaultSchema()); + } + + public DefaultMutableTreeNode createCategoryNode(final DefaultMutableTreeNode schemaChild, final Iterable finalLeafs, + Object category, boolean hasDetails, final int queueId) { + final DefaultMutableTreeNode schemaViewsChild = new DefaultMutableTreeNode(category); + schemaChild.add(schemaViewsChild); + root.add(schemaChild); + MutableTreeNode expandSchema; + if (hasDetails) { + synchronized (schemaChild) { + expandSchema = new ExpandingMutableTreeNode() { + private Iterable leafs = finalLeafs; + private boolean expanded = false; + @Override + protected void expandImmediatelly() { + if (!expanded) { + for (Object leaf: leafs) { + DefaultMutableTreeNode tableChild = new DefaultMutableTreeNode(leaf); + schemaViewsChild.add(tableChild); + if (leaf instanceof MDDescriptionBasedGeneric) { + MDDescriptionBasedGeneric md = (MDDescriptionBasedGeneric) leaf; + for (MDDescriptionBasedGeneric detail: md.getDetails()) { + tableChild.add(new DefaultMutableTreeNode(detail)); + } + } + } + schemaViewsChild.remove(this); + TreeModel model = metaDataTree.getModel(); + ((DefaultTreeModel) model).nodeStructureChanged(schemaViewsChild); + } + expanded = true; + } + @Override + protected void expand() { + MDSchema.loadMetaData(new Runnable() { + @Override + public void run() { + synchronized (schemaChild) { + ArrayList leafList = new ArrayList(); + for (Object leaf: leafs) { + leafList.add(leaf); + if (leaf instanceof MDDescriptionBasedGeneric) { + MDDescriptionBasedGeneric md = (MDDescriptionBasedGeneric) leaf; + md.getDetails(); + } + } + leafs = leafList; + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + Window wa = SwingUtilities.getWindowAncestor(MetaDataPanel.this); + try { + UIUtil.setWaitCursor(wa != null? wa : MetaDataPanel.this); + expandImmediatelly(); + } finally { + UIUtil.resetWaitCursor(wa != null? wa : MetaDataPanel.this); + } + } + }); + } + }); + + } + }, queueId); + } + }; + } + schemaViewsChild.add(expandSchema); + } + return schemaViewsChild; + } + + public void selectSchema(MDSchema mdSchema) { + selectSchema(mdSchema, true); + } + + public void selectSchema(MDSchema mdSchema, boolean scrollToNode) { + if (mdSchema != null) { + DefaultMutableTreeNode node = treeNodePerSchema.get(mdSchema); + if (node != null) { + final TreePath path = new TreePath(node.getPath()); + metaDataTree.expandPath(path); + metaDataTree.getSelectionModel().setSelectionPath(path); + if (scrollToNode) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + scrollToNode(path); + } + }); + } + } + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + waitingPanel = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + cancelButton = new javax.swing.JButton(); + splitPane = new javax.swing.JSplitPane(); + jPanel1 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + metaDataTree = new javax.swing.JTree(); + refreshButton = new javax.swing.JButton(); + refreshButton1 = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + outlineScrollPane = new javax.swing.JScrollPane(); + outlineList = new javax.swing.JList(); + outlineLabel = new javax.swing.JLabel(); + placeholderPanel = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + + waitingPanel.setBackground(java.awt.Color.white); + + jLabel5.setForeground(java.awt.Color.red); + jLabel5.setText("creating..."); + waitingPanel.add(jLabel5); + + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + waitingPanel.add(cancelButton); + + setLayout(new java.awt.GridBagLayout()); + + splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + splitPane.setResizeWeight(1.0); + splitPane.setContinuousLayout(true); + splitPane.setOneTouchExpandable(true); + + jPanel1.setLayout(new java.awt.GridBagLayout()); + + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane1.setViewportView(metaDataTree); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 5; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel1.add(jScrollPane1, gridBagConstraints); + + refreshButton.setText("Refresh"); + refreshButton.setToolTipText("Refresh Database Meta Data Cache"); + refreshButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + refreshButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + jPanel1.add(refreshButton, gridBagConstraints); + + refreshButton1.setText("Select"); + refreshButton1.setToolTipText("Choose the selecetd table in the tables tree"); + refreshButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + refreshButton1ActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 8); + jPanel1.add(refreshButton1, gridBagConstraints); + + splitPane.setLeftComponent(jPanel1); + + jPanel2.setLayout(new java.awt.GridBagLayout()); + + outlineList.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; + public int getSize() { return strings.length; } + public Object getElementAt(int i) { return strings[i]; } + }); + outlineList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + outlineScrollPane.setViewportView(outlineList); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel2.add(outlineScrollPane, gridBagConstraints); + + outlineLabel.setText(" Outline"); + outlineLabel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0); + jPanel2.add(outlineLabel, gridBagConstraints); + + placeholderPanel.setLayout(new java.awt.GridBagLayout()); + + jLabel1.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + placeholderPanel.add(jLabel1, gridBagConstraints); + + jLabel2.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + placeholderPanel.add(jLabel2, gridBagConstraints); + + jLabel3.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + placeholderPanel.add(jLabel3, gridBagConstraints); + + jLabel4.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + placeholderPanel.add(jLabel4, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + jPanel2.add(placeholderPanel, gridBagConstraints); + + splitPane.setRightComponent(jPanel2); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(splitPane, gridBagConstraints); + }// //GEN-END:initComponents + + private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed + reset(); + }//GEN-LAST:event_refreshButtonActionPerformed + + private void refreshButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButton1ActionPerformed + onSelectTable(); + }//GEN-LAST:event_refreshButton1ActionPerformed + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + JDialog waitingDialog = waitDialog.get(); + if (waitingDialog != null) { + waitingDialog.dispose(); + } + }//GEN-LAST:event_cancelButtonActionPerformed + + private List outlineTables = new ArrayList(); + private boolean inSelectOutlineTable = false; + private boolean isOutlineVisible = true; + private int lastDividerLocation; + + private void showOutline() { + if (!isOutlineVisible) { + outlineScrollPane.setVisible(true); + placeholderPanel.setVisible(true); + splitPane.setDividerLocation(Math.min(lastDividerLocation, splitPane.getHeight() - 80)); + if (lastDividerLocation == -1) { + final int PREFERRED_HEIGHT = 250; + int prefHeight = Math.min(PREFERRED_HEIGHT, (int) (splitPane.getHeight() * 0.4)); + if (prefHeight > outlineScrollPane.getHeight()) { + splitPane.setDividerLocation(splitPane.getHeight() - prefHeight); + } + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + TreePath path = metaDataTree.getSelectionPath(); + if (path != null) { + Rectangle bounds = metaDataTree.getPathBounds(path); + if (bounds != null) { + metaDataTree.scrollRectToVisible(new Rectangle(bounds.x, bounds.y, 1, bounds.height)); + } + } + } + }); + jPanel2.repaint(); + isOutlineVisible = true; + } + } + + private void hideOutline() { + if (isOutlineVisible) { + isOutlineVisible = false; + outlineScrollPane.setVisible(false); + placeholderPanel.setVisible(false); + lastDividerLocation = splitPane.getDividerLocation(); + splitPane.setDividerLocation(splitPane.getHeight() - 32); + } + } + + private final String fontName; { + String name = null; + try { + name = new RSyntaxTextArea().getFont().getName(); + } catch (Throwable t) { + // ignore + } + fontName = name; + } + + private String outlineTableRender(OutlineInfo info, boolean selected) { + String KEYWORD_ATTRIBUTES = "color=\"#0000cc\""; + String face = fontName != null? "face=\"" + fontName + "\" " : ""; + String render = ""; + String KEYWORD_PREFIX = (fontName != null? "" : "") + ""; + String KEYWORD_SUFFIX = "" + (fontName != null? "" : ""); + String scopeDescriptor = info.scopeDescriptor; + if (scopeDescriptor != null) { + scopeDescriptor = scopeDescriptor.replace(" ", " "); + } + if (info.mdTable != null || info.isCTE) { + if (info.isCTE) { + render = scopeDescriptor; + } else { + if (info.mdTable.getSchema().isDefaultSchema) { + render += info.mdTable.getName(); + } else { + render += info.mdTable.getSchema().getName() + "." + info.mdTable.getName(); + } + if (scopeDescriptor != null) { + render = "" + KEYWORD_PREFIX + "" + scopeDescriptor + "" + KEYWORD_SUFFIX + " " + render; + } + } + String alias = info.alias; + if (alias != null) { + if (!render.isEmpty()) { + render += " "; + } + render += "" + KEYWORD_PREFIX + "as" + KEYWORD_SUFFIX + " " + alias; + } + render += ""; + } else if (scopeDescriptor != null) { + render = "" + KEYWORD_PREFIX + "" + scopeDescriptor + "" + KEYWORD_SUFFIX + "" + (info.rowCount > 1? " (" + info.rowCount + " rows)" : "") + ""; + } + + String indent = "      "; + if (info.isCTE && "".equals(info.alias)) { + render = "   " + render; + } else if (scopeDescriptor == null || (info.isCTE && !"".equals(scopeDescriptor))) { + render = indent + render; + } + for (int i = 0; i < info.level; ++i) { + render = indent + render; + } + if (info.context != null) { + render += " " + info.context + ""; + } + render = "" + render; + return render; + } + + private int indexOfInfoAtCaret = -1; + + public void setOutline(List outlineTables, int indexOfInfoAtCaret) { + this.outlineTables = new ArrayList(outlineTables); + this.indexOfInfoAtCaret = indexOfInfoAtCaret; + DefaultListModel model = new DefaultListModel(); + for (OutlineInfo info: outlineTables) { + model.addElement(info); + } + outlineList.setModel(model); + if (outlineTables.isEmpty()) { + hideOutline(); + } else { + showOutline(); + if (indexOfInfoAtCaret >= 0) { + Rectangle aRect = outlineList.getCellBounds(indexOfInfoAtCaret, indexOfInfoAtCaret); + if (aRect != null) { + outlineList.scrollRectToVisible(aRect); + } + } + } + } + + private void selectOutlineTable(MDTable mdTable) { + if (!inSelectOutlineTable) { + inSelectOutlineTable = true; + boolean found = false; + for (OutlineInfo value: outlineTables) { + if (mdTable.equals(value.mdTable)) { + outlineList.setSelectedValue(value, true); + found = true; + break; + } + } + if (!found) { + outlineList.clearSelection(); + } + inSelectOutlineTable = false; + } + } + + + public static class OutlineInfo { + public final MDTable mdTable; + public final String alias; + public int level; + public int position; + public String scopeDescriptor; + public boolean withContext = false; + public int contextPosition; + public String context; + public String tooltip; + public int contextEnd = 0; + public boolean isCTE; + public boolean isBegin; + public boolean isEnd; + public boolean withSeparator; + public int rowCount; + public int origPosition; + + public OutlineInfo(MDTable mdTable, String alias, int level, int position, String scopeDescriptor) { + this.mdTable = mdTable; + this.alias = alias; + this.level = level; + this.position = position; + this.origPosition = position; + this.scopeDescriptor = scopeDescriptor; + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cancelButton; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTree metaDataTree; + private javax.swing.JLabel outlineLabel; + private javax.swing.JList outlineList; + private javax.swing.JScrollPane outlineScrollPane; + private javax.swing.JPanel placeholderPanel; + private javax.swing.JButton refreshButton; + private javax.swing.JButton refreshButton1; + private javax.swing.JSplitPane splitPane; + private javax.swing.JPanel waitingPanel; + // End of variables declaration//GEN-END:variables + + protected abstract void open(Table table); + protected abstract void open(MDTable mdTable); + protected abstract void analyseSchema(String schemaName); + protected abstract void onTableSelect(MDTable mdTable); + protected abstract void onRowSelect(Table mdTable, Row row); + protected abstract void onSchemaSelect(MDSchema mdSchema); + protected abstract void onMDOtherSelect(MDGeneric mdOther, ExecutionContext executionContext); + protected abstract void openNewTableBrowser(); + protected abstract void updateDataModelView(Table table); + protected abstract void setCaretPosition(int position); + protected abstract void appendScript(String script, boolean execute); + protected abstract void setOrResetWaitState(boolean set); + + public void onSelectTable() { + Object item = tablesComboBox.getSelectedItem(); + if (item != null) { + Table table = dataModel.getTableByDisplayName(item.toString()); + if (table != null) { + MDTable mdTable = metaDataSource.toMDTable(table); + if (mdTable != null) { + select(mdTable); + } else { + JOptionPane.showMessageDialog(parent, "Table \"" + dataModel.getDisplayName(table) + "\" does not exist in the database"); + } + } else { + MDTable mdTable = tablesComboboxMDTablePerName.get(item); + if (mdTable != null) { + select(mdTable); + } + } + } + } + + public void refresh() { + metaDataTree.repaint(); + } + + static ImageIcon warnIcon; + static ImageIcon viewIcon; + static ImageIcon viewsIcon; + static ImageIcon tableIcon; + static ImageIcon tablesIcon; + static ImageIcon synonymIcon; + static ImageIcon synonymsIcon; + static ImageIcon databaseIcon; + static ImageIcon schemaIcon; + private static HashMap combinedIcons = new HashMap(); + + private final AtomicReference waitDialog = new AtomicReference(null); + + static ImageIcon getScaledIcon(JComponent component, ImageIcon icon, boolean small) { + if (icon != null) { + ImageIcon scaledIcon = icon; + if (scaledIcon != null) { + int heigth = component.getFontMetrics(new JLabel("M").getFont()).getHeight(); + double s = heigth / (double) scaledIcon.getIconHeight(); + if (icon == viewIcon) { + s *= 0.8; + } + if (small) { + s *= 0.8; + } + try { + return UIUtil.scaleIcon(scaledIcon, s); + } catch (Exception e) { + logger.info("error", e); + return null; + } + } + } + return null; + } + static { + // load images + warnIcon = UIUtil.readImage("/wanr.png"); + viewIcon = UIUtil.readImage("/view.png"); + synonymIcon = UIUtil.readImage("/synonym.png"); + synonymsIcon = UIUtil.readImage("/synonyms.png"); + viewsIcon = UIUtil.readImage("/views.png"); + tablesIcon = UIUtil.readImage("/tables.png"); + tableIcon = UIUtil.readImage("/table.png"); + databaseIcon = UIUtil.readImage("/database.png"); + schemaIcon = UIUtil.readImage("/schema.png"); + } + +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/ResultSetRenderer.java b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/ResultSetRenderer.java index d4b6f4258..ab87c8522 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/ResultSetRenderer.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/ResultSetRenderer.java @@ -1,268 +1,269 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser.metadata; - -import java.awt.Frame; -import java.awt.Window; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.PriorityBlockingQueue; - -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.SwingUtilities; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.MemorizedResultSet; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.QueryBuilderDialog; -import net.sf.jailer.ui.QueryBuilderDialog.Relationship; -import net.sf.jailer.ui.databrowser.BrowserContentPane; -import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; -import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; -import net.sf.jailer.ui.databrowser.Desktop; -import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; -import net.sf.jailer.ui.databrowser.Row; -import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; -import net.sf.jailer.util.Pair; - -/** - * Renders content of {@link ResultSet}. - * - * @author Ralf Wisser - */ -public class ResultSetRenderer extends javax.swing.JPanel { - - /** - * Creates new form ResultSetRenderer - * @param executionContext - */ - public ResultSetRenderer(ResultSet resultSet, String titel, DataModel datamodel, Session session, ExecutionContext executionContext) throws SQLException { - initComponents(); - if (titel != null && titel.length() > 40) { - titelLabel.setText(titel.substring(0, 40) + "..."); - titelLabel.setToolTipText(titel); - } else { - titelLabel.setText(titel); - titelLabel.setToolTipText(null); - } - - final BrowserContentPane rb = new ResultContentPane(datamodel, null, "", session, null, - null, null, new RowsClosure(), Integer.MAX_VALUE, false, false, - executionContext); - if (resultSet instanceof MemorizedResultSet && ((MemorizedResultSet) resultSet).getSize() > 1) { - rb.setTableFilterEnabled(true); - } else { - rb.setTableFilterEnabled(false); - } - LoadJob loadJob = rb.newLoadJob(resultSet, Integer.MAX_VALUE); - loadJob.run(); - JComponent rTabContainer = rb.getRowsTableContainer(); - rb.sortColumnsCheckBox.setVisible(false); - rb.sortColumnsPanel.setVisible(false); - renderPanel.add(rTabContainer); - rb.resetRowsTableContainer(); - renderPanel.repaint(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - titelLabel = new javax.swing.JLabel(); - renderPanel = new javax.swing.JPanel(); - jSeparator1 = new javax.swing.JSeparator(); - - setLayout(new java.awt.GridBagLayout()); - - titelLabel.setText("jLabel1"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0); - add(titelLabel, gridBagConstraints); - - renderPanel.setLayout(new javax.swing.BoxLayout(renderPanel, javax.swing.BoxLayout.LINE_AXIS)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - add(renderPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - add(jSeparator1, gridBagConstraints); - }// //GEN-END:initComponents - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JSeparator jSeparator1; - private javax.swing.JPanel renderPanel; - private javax.swing.JLabel titelLabel; - // End of variables declaration//GEN-END:variables - class ResultContentPane extends BrowserContentPane { - private final Integer limit; - public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, - List parentRows, Association association, Frame parentFrame, - RowsClosure rowsClosure, Integer limit, Boolean selectDistinct, - boolean reload, ExecutionContext executionContext) { - super(dataModel, table, condition, session, parentRows, association, parentFrame, - rowsClosure, selectDistinct, reload, executionContext); - singleRowDetailsViewTitel = "Details"; - this.limit = limit; - rowsTableScrollPane.setWheelScrollingEnabled(true); - statusPanel.setVisible(false); - } - @Override - protected int getReloadLimit() { - if (limit == null) { - return Integer.MAX_VALUE; - } - return limit; - } - @Override - protected void unhide() { - } - @Override - protected void showInNewWindow() { - } - @Override - protected void reloadDataModel() throws Exception { - } - @Override - protected void openSchemaMappingDialog() { - } - @Override - protected void openSchemaAnalyzer() { - } - @Override - protected void onRedraw() { - ResultSetRenderer.this.repaint(); - } - @Override - protected void onHide() { - } - @Override - protected void onContentChange(List rows, boolean reloadChildren) { - } - @Override - protected RowBrowser navigateTo(Association association, List pRows) { - return null; - } - @Override - protected List getTableBrowser() { - return null; - } - @Override - protected PriorityBlockingQueue getRunnableQueue() { - return Desktop.runnableQueue; - } - @Override - protected QueryBuilderDialog getQueryBuilderDialog() { - return null; - } - @Override - protected RowBrowser getParentBrowser() { - return null; - } - @Override - protected JFrame getOwner() { - Window owner = SwingUtilities.getWindowAncestor(ResultSetRenderer.this); - if (owner instanceof JFrame) { - return (JFrame) owner; - } - return null; - } - @Override - protected double getLayoutFactor() { - return 0; - } - @Override - protected DbConnectionDialog getDbConnectionDialog() { - return null; - } - @Override - protected List getChildBrowsers() { - return new ArrayList(); - } - @Override - protected void findClosure(Row row, Set> closure, boolean forward) { - } - @Override - protected void findClosure(Row row) {} - @Override - protected Relationship createQBRelations(boolean withParents) { - return null; - } - @Override - protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { - return null; - } - @Override - protected void collectPositions(Map> positions) { - } - @Override - protected void close() { - } - @Override - protected void beforeReload() { - } - @Override - protected void appendLayout() { - } - @Override - protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { - } - @Override - protected void addRowToRowLink(Row pRow, Row exRow) { - } - @Override - protected boolean renderRowAsPK(Row theRow) { - return false; - } - @Override - protected MetaDataSource getMetaDataSource() { - return null; - } - @Override - protected SQLConsole getSqlConsole(boolean switchToConsole) { - return null; - } - @Override - protected void deselectChildrenIfNeededWithoutReload() { - } - }; - -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser.metadata; + +import java.awt.Frame; +import java.awt.Window; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.PriorityBlockingQueue; + +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.MemorizedResultSet; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.QueryBuilderDialog; +import net.sf.jailer.ui.QueryBuilderDialog.Relationship; +import net.sf.jailer.ui.databrowser.BrowserContentPane; +import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; +import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; +import net.sf.jailer.ui.databrowser.Desktop; +import net.sf.jailer.ui.databrowser.Desktop.FindClosureContext; +import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; +import net.sf.jailer.ui.databrowser.Row; +import net.sf.jailer.ui.databrowser.sqlconsole.SQLConsole; +import net.sf.jailer.util.Pair; + +/** + * Renders content of {@link ResultSet}. + * + * @author Ralf Wisser + */ +public class ResultSetRenderer extends javax.swing.JPanel { + + /** + * Creates new form ResultSetRenderer + * @param executionContext + */ + public ResultSetRenderer(ResultSet resultSet, String titel, DataModel datamodel, Session session, ExecutionContext executionContext) throws SQLException { + initComponents(); + if (titel != null && titel.length() > 40) { + titelLabel.setText(titel.substring(0, 40) + "..."); + titelLabel.setToolTipText(titel); + } else { + titelLabel.setText(titel); + titelLabel.setToolTipText(null); + } + + final BrowserContentPane rb = new ResultContentPane(datamodel, null, "", session, null, + null, null, new RowsClosure(), Integer.MAX_VALUE, false, false, + executionContext); + if (resultSet instanceof MemorizedResultSet && ((MemorizedResultSet) resultSet).getSize() > 1) { + rb.setTableFilterEnabled(true); + } else { + rb.setTableFilterEnabled(false); + } + LoadJob loadJob = rb.newLoadJob(resultSet, Integer.MAX_VALUE); + loadJob.run(); + JComponent rTabContainer = rb.getRowsTableContainer(); + rb.sortColumnsCheckBox.setVisible(false); + rb.sortColumnsPanel.setVisible(false); + renderPanel.add(rTabContainer); + rb.resetRowsTableContainer(); + renderPanel.repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + titelLabel = new javax.swing.JLabel(); + renderPanel = new javax.swing.JPanel(); + jSeparator1 = new javax.swing.JSeparator(); + + setLayout(new java.awt.GridBagLayout()); + + titelLabel.setText("jLabel1"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0); + add(titelLabel, gridBagConstraints); + + renderPanel.setLayout(new javax.swing.BoxLayout(renderPanel, javax.swing.BoxLayout.LINE_AXIS)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(renderPanel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + add(jSeparator1, gridBagConstraints); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JSeparator jSeparator1; + private javax.swing.JPanel renderPanel; + private javax.swing.JLabel titelLabel; + // End of variables declaration//GEN-END:variables + class ResultContentPane extends BrowserContentPane { + private final Integer limit; + public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, + List parentRows, Association association, Frame parentFrame, + RowsClosure rowsClosure, Integer limit, Boolean selectDistinct, + boolean reload, ExecutionContext executionContext) { + super(dataModel, table, condition, session, parentRows, association, parentFrame, + rowsClosure, selectDistinct, reload, executionContext); + singleRowDetailsViewTitel = "Details"; + this.limit = limit; + rowsTableScrollPane.setWheelScrollingEnabled(true); + statusPanel.setVisible(false); + } + @Override + protected int getReloadLimit() { + if (limit == null) { + return Integer.MAX_VALUE; + } + return limit; + } + @Override + protected void unhide() { + } + @Override + protected void showInNewWindow() { + } + @Override + protected void reloadDataModel() throws Exception { + } + @Override + protected void openSchemaMappingDialog() { + } + @Override + protected void openSchemaAnalyzer() { + } + @Override + protected void onRedraw() { + ResultSetRenderer.this.repaint(); + } + @Override + protected void onHide() { + } + @Override + protected void onContentChange(List rows, boolean reloadChildren) { + } + @Override + protected RowBrowser navigateTo(Association association, List pRows) { + return null; + } + @Override + protected List getTableBrowser() { + return null; + } + @Override + protected PriorityBlockingQueue getRunnableQueue() { + return Desktop.runnableQueue; + } + @Override + protected QueryBuilderDialog getQueryBuilderDialog() { + return null; + } + @Override + protected RowBrowser getParentBrowser() { + return null; + } + @Override + protected JFrame getOwner() { + Window owner = SwingUtilities.getWindowAncestor(ResultSetRenderer.this); + if (owner instanceof JFrame) { + return (JFrame) owner; + } + return null; + } + @Override + protected double getLayoutFactor() { + return 0; + } + @Override + protected DbConnectionDialog getDbConnectionDialog() { + return null; + } + @Override + protected List getChildBrowsers() { + return new ArrayList(); + } + @Override + protected void findClosure(Row row, Set> closure, boolean forward, FindClosureContext findClosureContext) { + } + @Override + protected void findClosure(Row row) {} + @Override + protected Relationship createQBRelations(boolean withParents) { + return null; + } + @Override + protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { + return null; + } + @Override + protected void collectPositions(Map> positions) { + } + @Override + protected void close() { + } + @Override + protected void beforeReload() { + } + @Override + protected void appendLayout() { + } + @Override + protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { + } + @Override + protected void addRowToRowLink(Row pRow, Row exRow) { + } + @Override + protected boolean renderRowAsPK(Row theRow) { + return false; + } + @Override + protected MetaDataSource getMetaDataSource() { + return null; + } + @Override + protected SQLConsole getSqlConsole(boolean switchToConsole) { + return null; + } + @Override + protected void deselectChildrenIfNeededWithoutReload() { + } + }; + +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/TableDetailsView.java b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/TableDetailsView.java index bc2e781de..02c52f9f0 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/metadata/TableDetailsView.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/metadata/TableDetailsView.java @@ -1,581 +1,581 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser.metadata; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import net.sf.jailer.datamodel.Column; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.ModelBuilder; -import net.sf.jailer.ui.JComboBox; -import net.sf.jailer.ui.StringSearchPanel; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.databrowser.Row; -import net.sf.jailer.util.Quoting; - -/** - * Table Details View. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public class TableDetailsView extends javax.swing.JPanel { - - private final Color selectedBG = new Color(255, 200, 200); - private final Runnable updateColumnsTable; - private boolean cacheable = true; - private Map rows = new HashMap(); - - /** - * Creates new form TableDetailsView - * @param row - */ - public TableDetailsView(final Table table, final MDTable mdTable, final MetaDataDetailsPanel metaDataDetailsPanel, final Row row, final DataModel dataModel, TableDetailsView currentView) { - initComponents(); - if (jScrollPane1.getHorizontalScrollBar() != null) { - jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16); - } - if (jScrollPane1.getVerticalScrollBar() != null) { - jScrollPane1.getVerticalScrollBar().setUnitIncrement(16); - } - if (currentView != null) { - sortColumnsCheckBox.setSelected(currentView.sortColumnsCheckBox.isSelected()); - foundColumn = currentView.foundColumn; - } - findColumnsLabel.setText(null); - findColumnsLabel.setToolTipText("Find Column..."); - findColumnsLabel.setIcon(StringSearchPanel.getSearchIcon(false, this)); - - findColumnsLabel.addMouseListener(new java.awt.event.MouseAdapter() { - private boolean in = false; - - @Override - public void mousePressed(MouseEvent e) { - if (findColumnsLabel.isEnabled()) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - in = false; - updateBorder(); - if (findColumnsPanel.isShowing()) { - Point point = new Point(); - SwingUtilities.convertPointToScreen(point, findColumnsPanel); - findColumns((int) point.getX(), (int) point.getY()); - } - } - }); - } - } - - @Override - public void mouseEntered(java.awt.event.MouseEvent evt) { - if (findColumnsLabel.isEnabled()) { - in = true; - updateBorder(); - } - } - - @Override - public void mouseExited(java.awt.event.MouseEvent evt) { - in = false; - updateBorder(); - } - - private void updateBorder() { - findColumnsPanel.setBackground(in? new Color(240, 240, 0) : null); - findColumnsPanel.setOpaque(in); - } - }); - updateColumnsTable = new Runnable() { - final Font font = new JLabel().getFont(); - final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize()); - final Font italic = new Font(nonbold.getName(), nonbold.getStyle() | Font.ITALIC, nonbold.getSize()); - - @Override - public void run() { - String typeLabel = ""; - if (mdTable != null) { - if (mdTable.isView()) { - typeLabel = "View "; - } else if (mdTable.isSynonym()) { - typeLabel = "Synonym "; - } - } - tableNameLabel.setText(typeLabel + dataModel.getDisplayName(table)); - Font font = new JLabel("L").getFont(); - tableNameLabel.setFont(new Font(font.getName(), font.getStyle(), (int)(font.getSize() * 1.2))); - - boolean mdTableIsUpTodate = true; - if (mdTable != null) { - if (!mdTable.isLoaded()) { - cacheable = false; - } else { - mdTableIsUpTodate = mdTable.isUptodate(table); - } - } else { - cacheable = false; - } - if (mdTable != null && !mdTableIsUpTodate && !ModelBuilder.isJailerTable(table.getUnqualifiedName())) { - warnLabel.setIcon(MetaDataPanel.getScaledIcon(TableDetailsView.this, MetaDataPanel.warnIcon, false)); - analyseButton.setText("Analyse schema \"" + mdTable.getSchema().getUnquotedName() + "\""); - analyseButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - metaDataDetailsPanel.analyseSchema(mdTable.getSchema().getName(), mdTable.isView(), mdTable.isSynonym()); - } - }); - } else { - warnPanel.setVisible(false); - } - - int y = 1; - List columns = table.getColumns(); - Map columnValue = new IdentityHashMap(); - for (int i = 0; i < columns.size(); ++i) { - if (row != null && row.values.length > i) { - columnValue.put(columns.get(i), row.values[i]); - } - } - if (sortColumnsCheckBox.isSelected()) { - columns = new ArrayList(columns); - Collections.sort(columns, new Comparator() { - @Override - public int compare(Column o1, Column o2) { - return Quoting.staticUnquote(o1.name).compareToIgnoreCase(Quoting.staticUnquote(o2.name)); - } - }); - } - columnsPanel.removeAll(); - java.awt.Color bgDarker = new java.awt.Color(255, 255, 206); - boolean hasConstraints = false; - for (Column column: columns) { - hasConstraints = hasConstraints || !column.isNullable || column.isVirtual || column.isIdentityColumn; - } - rows.clear(); - for (Column column: columns) { - boolean isPk = false; - if (table.primaryKey.getColumns() != null) { - for (Column pk: table.primaryKey.getColumns()) { - if (pk.name.equals(column.name)) { - isPk = true; - } - } - } - - JPanel panel = new JPanel(); - rows.put(column.name, panel); - if (y % 2 == 0) { - panel.setOpaque(false); - } else { - panel.setBackground(bgDarker); - } - panel.setLayout(new java.awt.GridBagLayout()); - if (column.name.equals(foundColumn)) { - panel.setOpaque(true); - panel.setBackground(selectedBG); - } - - JLabel label; - label = new JLabel(); - - if (isPk) { - label.setForeground(Color.red); - } - - label.setText(Quoting.staticUnquote(column.name)); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = y; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - panel.add(label, gridBagConstraints); - - if (row != null) { - final JLabel finalLabel = label; - label = new JLabel() { - @Override - public Dimension getPreferredSize() { - Dimension preferredSize = super.getPreferredSize(); - int maxWidth = TableDetailsView.this.getWidth() - finalLabel.getPreferredSize().width - 34; - if (maxWidth < 1) { - maxWidth = 1; - } - preferredSize.setSize(Math.min(preferredSize.width, maxWidth), preferredSize.height); - return preferredSize; - } - }; - Object obj = columnValue.get(column); - label.setForeground(obj == null? Color.gray : Color.black); - if (obj == null) { - label.setFont(italic); - } - label.setText(String.valueOf(obj)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = y; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - panel.add(label, gridBagConstraints); - } else { - label = new JLabel(); - label.setForeground(Color.gray); - label.setText(column.toSQL("").substring(column.name.length()).trim()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = y; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - panel.add(label, gridBagConstraints); - - StringBuilder constraints = new StringBuilder(); - - if (!column.isNullable) { - constraints.append("not null "); - } - if (column.isVirtual) { - constraints.append("virtual "); - } - if (column.isIdentityColumn) { - constraints.append("identity "); - } - - if (hasConstraints) { - label = new JLabel(); - label.setForeground(Color.gray); - JPanel panelC = new JPanel(); - if (y % 2 == 0) { - panelC.setOpaque(false); - } else { - panelC.setBackground(bgDarker); - } - if (column.name.equals(foundColumn)) { - panelC.setOpaque(true); - panelC.setBackground(selectedBG); - } - panelC.setLayout(new java.awt.GridBagLayout()); - if (column.type.toUpperCase(Locale.ENGLISH).equals(column.type)) { - label.setText(" " + constraints.toString().toUpperCase(Locale.ENGLISH)); - } else { - label.setText(" " + constraints.toString()); - } - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1; - panelC.add(label, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = y; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - columnsPanel.add(panelC, gridBagConstraints); - } - } - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = y; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1; - columnsPanel.add(panel, gridBagConstraints); - - ++y; - } - } - }; - updateColumnsTable.run(); - if (currentView != null) { - jPanel1.scrollRectToVisible(currentView.jPanel1.getVisibleRect()); - } - } - - private String foundColumn; - - private void findColumns(final int x, final int y) { - List columNames = new ArrayList(); - Map columNamesCount = new HashMap(); - for (String nameObj: rows.keySet()) { - if (nameObj != null) { - String name = nameObj.toString(); - if (columNamesCount.containsKey(name)) { - columNamesCount.put(name, columNamesCount.get(name) + 1); - } else { - columNames.add(name); - columNamesCount.put(name, 1); - } - } - } - Collections.sort(columNames, new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - }); - - final Window owner = SwingUtilities.getWindowAncestor(this); - - final JComboBox combobox = new JComboBox(); - combobox.setModel(new DefaultComboBoxModel(columNames.toArray())); - StringSearchPanel searchPanel = new StringSearchPanel(null, combobox, null, null, null, new Runnable() { - @Override - public void run() { - Object selected = combobox.getSelectedItem(); - if (selected != null) { - foundColumn = null; - for (String name: rows.keySet()) { - if (name != null && name.equals(selected)) { - Rectangle visibleRect = jPanel1.getVisibleRect(); - Rectangle cellRect = rows.get(name).getBounds(); - foundColumn = name; - updateColumnsTable.run(); - jPanel1.scrollRectToVisible( - new Rectangle( - visibleRect.x + visibleRect.width / 2, - cellRect.y + columnsPanel.getBounds().y - 32, - 1, cellRect.height + 64)); - break; - } - } - } - } - }) { - @Override - protected Integer preferredWidth() { - return 260; - } - @Override - protected Integer maxX() { - if (owner != null) { - return owner.getX() + owner.getWidth() - preferredWidth(); - } else { - return null; - } - } - @Override - protected Integer maxY(int height) { - if (owner != null) { - return owner.getY() + owner.getHeight() - height - 8; - } else { - return null; - } - } - }; - - searchPanel.setStringCount(columNamesCount); - searchPanel.find(owner, "Find Column", x, y, true); - } - - public boolean isCacheable() { - return cacheable; - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - jScrollPane1 = new javax.swing.JScrollPane(); - jPanel1 = new javax.swing.JPanel(); - tableNameLabel = new javax.swing.JLabel(); - jSeparator1 = new javax.swing.JSeparator(); - columnsPanel = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - warnPanel = new javax.swing.JPanel(); - warnLabel = new javax.swing.JLabel(); - analyseButton = new javax.swing.JButton(); - warnLabel1 = new javax.swing.JLabel(); - warnLabel2 = new javax.swing.JLabel(); - sortColumnsCheckBox = new javax.swing.JCheckBox(); - findColumnsPanel = new javax.swing.JPanel(); - findColumnsLabel = new javax.swing.JLabel(); - - setBackground(new java.awt.Color(255, 255, 230)); - setLayout(new java.awt.GridBagLayout()); - - jScrollPane1.setBorder(null); - - jPanel1.setBackground(new java.awt.Color(255, 255, 230)); - jPanel1.setLayout(new java.awt.GridBagLayout()); - - tableNameLabel.setText("Test"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 0); - jPanel1.add(tableNameLabel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - jPanel1.add(jSeparator1, gridBagConstraints); - - columnsPanel.setOpaque(false); - columnsPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4); - jPanel1.add(columnsPanel, gridBagConstraints); - - jLabel1.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 5; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel1, gridBagConstraints); - - warnPanel.setOpaque(false); - warnPanel.setLayout(new java.awt.GridBagLayout()); - - warnLabel.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - warnPanel.add(warnLabel, gridBagConstraints); - - analyseButton.setText("jButton1"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 2; - warnPanel.add(analyseButton, gridBagConstraints); - - warnLabel1.setText("Data model differs from"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - warnPanel.add(warnLabel1, gridBagConstraints); - - warnLabel2.setText("database table definition"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - warnPanel.add(warnLabel2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(4, 12, 2, 0); - jPanel1.add(warnPanel, gridBagConstraints); - - jScrollPane1.setViewportView(jPanel1); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - add(jScrollPane1, gridBagConstraints); - - sortColumnsCheckBox.setText("sort columns "); - sortColumnsCheckBox.setOpaque(false); - sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - sortColumnsCheckBoxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - add(sortColumnsCheckBox, gridBagConstraints); - - findColumnsPanel.setOpaque(false); - findColumnsPanel.setLayout(new java.awt.GridBagLayout()); - - findColumnsLabel.setText("Find Columns"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 6); - findColumnsPanel.add(findColumnsLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); - add(findColumnsPanel, gridBagConstraints); - }// //GEN-END:initComponents - - private void sortColumnsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortColumnsCheckBoxActionPerformed - updateColumnsTable.run(); - repaint(); - }//GEN-LAST:event_sortColumnsCheckBoxActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton analyseButton; - private javax.swing.JPanel columnsPanel; - private javax.swing.JLabel findColumnsLabel; - public javax.swing.JPanel findColumnsPanel; - private javax.swing.JLabel jLabel1; - private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JSeparator jSeparator1; - private javax.swing.JCheckBox sortColumnsCheckBox; - private javax.swing.JLabel tableNameLabel; - private javax.swing.JLabel warnLabel; - private javax.swing.JLabel warnLabel1; - private javax.swing.JLabel warnLabel2; - private javax.swing.JPanel warnPanel; - // End of variables declaration//GEN-END:variables -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser.metadata; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import net.sf.jailer.datamodel.Column; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.ModelBuilder; +import net.sf.jailer.ui.JComboBox; +import net.sf.jailer.ui.StringSearchPanel; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.databrowser.Row; +import net.sf.jailer.util.Quoting; + +/** + * Table Details View. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public class TableDetailsView extends javax.swing.JPanel { + + private final Color selectedBG = new Color(255, 200, 200); + private final Runnable updateColumnsTable; + private boolean cacheable = true; + private Map rows = new HashMap(); + + /** + * Creates new form TableDetailsView + * @param row + */ + public TableDetailsView(final Table table, final MDTable mdTable, final MetaDataDetailsPanel metaDataDetailsPanel, final Row row, final DataModel dataModel, TableDetailsView currentView) { + initComponents(); + if (jScrollPane1.getHorizontalScrollBar() != null) { + jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16); + } + if (jScrollPane1.getVerticalScrollBar() != null) { + jScrollPane1.getVerticalScrollBar().setUnitIncrement(16); + } + if (currentView != null) { + sortColumnsCheckBox.setSelected(currentView.sortColumnsCheckBox.isSelected()); + foundColumn = currentView.foundColumn; + } + findColumnsLabel.setText(null); + findColumnsLabel.setToolTipText("Find Column..."); + findColumnsLabel.setIcon(StringSearchPanel.getSearchIcon(false, this)); + + findColumnsLabel.addMouseListener(new java.awt.event.MouseAdapter() { + private boolean in = false; + + @Override + public void mousePressed(MouseEvent e) { + if (findColumnsLabel.isEnabled()) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + in = false; + updateBorder(); + if (findColumnsPanel.isShowing()) { + Point point = new Point(); + SwingUtilities.convertPointToScreen(point, findColumnsPanel); + findColumns((int) point.getX(), (int) point.getY()); + } + } + }); + } + } + + @Override + public void mouseEntered(java.awt.event.MouseEvent evt) { + if (findColumnsLabel.isEnabled()) { + in = true; + updateBorder(); + } + } + + @Override + public void mouseExited(java.awt.event.MouseEvent evt) { + in = false; + updateBorder(); + } + + private void updateBorder() { + findColumnsPanel.setBackground(in? new Color(240, 240, 0) : null); + findColumnsPanel.setOpaque(in); + } + }); + updateColumnsTable = new Runnable() { + final Font font = new JLabel().getFont(); + final Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize()); + final Font italic = new Font(nonbold.getName(), nonbold.getStyle() | Font.ITALIC, nonbold.getSize()); + + @Override + public void run() { + String typeLabel = ""; + if (mdTable != null) { + if (mdTable.isView()) { + typeLabel = "View "; + } else if (mdTable.isSynonym()) { + typeLabel = "Synonym "; + } + } + tableNameLabel.setText(typeLabel + dataModel.getDisplayName(table)); + Font font = new JLabel("L").getFont(); + tableNameLabel.setFont(new Font(font.getName(), font.getStyle(), (int)(font.getSize() * 1.2))); + + boolean mdTableIsUpTodate = true; + if (mdTable != null) { + if (!mdTable.isLoaded()) { + cacheable = false; + } else { + mdTableIsUpTodate = mdTable.isUptodate(table); + } + } else { + cacheable = false; + } + if (mdTable != null && !mdTableIsUpTodate && !ModelBuilder.isJailerTable(table.getUnqualifiedName())) { + warnLabel.setIcon(MetaDataPanel.getScaledIcon(TableDetailsView.this, MetaDataPanel.warnIcon, false)); + analyseButton.setText("Analyse schema \"" + mdTable.getSchema().getUnquotedName() + "\""); + analyseButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + metaDataDetailsPanel.analyseSchema(mdTable.getSchema().getName(), mdTable.isView(), mdTable.isSynonym()); + } + }); + } else { + warnPanel.setVisible(false); + } + + int y = 1; + List columns = table.getColumns(); + Map columnValue = new IdentityHashMap(); + for (int i = 0; i < columns.size(); ++i) { + if (row != null && row.values.length > i) { + columnValue.put(columns.get(i), row.values[i]); + } + } + if (sortColumnsCheckBox.isSelected()) { + columns = new ArrayList(columns); + Collections.sort(columns, new Comparator() { + @Override + public int compare(Column o1, Column o2) { + return Quoting.staticUnquote(o1.name).compareToIgnoreCase(Quoting.staticUnquote(o2.name)); + } + }); + } + columnsPanel.removeAll(); + java.awt.Color bgDarker = new java.awt.Color(255, 255, 206); + boolean hasConstraints = false; + for (Column column: columns) { + hasConstraints = hasConstraints || !column.isNullable || column.isVirtual || column.isIdentityColumn; + } + rows.clear(); + for (Column column: columns) { + boolean isPk = false; + if (table.primaryKey.getColumns() != null) { + for (Column pk: table.primaryKey.getColumns()) { + if (pk.name.equals(column.name)) { + isPk = true; + } + } + } + + JPanel panel = new JPanel(); + rows.put(column.name, panel); + if (y % 2 == 0) { + panel.setOpaque(false); + } else { + panel.setBackground(bgDarker); + } + panel.setLayout(new java.awt.GridBagLayout()); + if (column.name.equals(foundColumn)) { + panel.setOpaque(true); + panel.setBackground(selectedBG); + } + + JLabel label; + label = new JLabel(); + + if (isPk) { + label.setForeground(Color.red); + } + + label.setText(Quoting.staticUnquote(column.name)); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = y; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + panel.add(label, gridBagConstraints); + + if (row != null) { + final JLabel finalLabel = label; + label = new JLabel() { + @Override + public Dimension getPreferredSize() { + Dimension preferredSize = super.getPreferredSize(); + int maxWidth = TableDetailsView.this.getWidth() - finalLabel.getPreferredSize().width - 34; + if (maxWidth < 1) { + maxWidth = 1; + } + preferredSize.setSize(Math.min(preferredSize.width, maxWidth), preferredSize.height); + return preferredSize; + } + }; + Object obj = columnValue.get(column); + label.setForeground(obj == null? Color.gray : Color.black); + if (obj == null) { + label.setFont(italic); + } + label.setText(String.valueOf(obj)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = y; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + panel.add(label, gridBagConstraints); + } else { + label = new JLabel(); + label.setForeground(Color.gray); + label.setText(column.toSQL("").substring(column.name.length()).trim()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = y; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + panel.add(label, gridBagConstraints); + + StringBuilder constraints = new StringBuilder(); + + if (!column.isNullable) { + constraints.append("not null "); + } + if (column.isVirtual) { + constraints.append("virtual "); + } + if (column.isIdentityColumn) { + constraints.append("identity "); + } + + if (hasConstraints) { + label = new JLabel(); + label.setForeground(Color.gray); + JPanel panelC = new JPanel(); + if (y % 2 == 0) { + panelC.setOpaque(false); + } else { + panelC.setBackground(bgDarker); + } + if (column.name.equals(foundColumn)) { + panelC.setOpaque(true); + panelC.setBackground(selectedBG); + } + panelC.setLayout(new java.awt.GridBagLayout()); + if (column.type.toUpperCase(Locale.ENGLISH).equals(column.type)) { + label.setText(" " + constraints.toString().toUpperCase(Locale.ENGLISH)); + } else { + label.setText(" " + constraints.toString()); + } + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1; + panelC.add(label, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = y; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + columnsPanel.add(panelC, gridBagConstraints); + } + } + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = y; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1; + columnsPanel.add(panel, gridBagConstraints); + + ++y; + } + } + }; + updateColumnsTable.run(); + if (currentView != null) { + jPanel1.scrollRectToVisible(currentView.jPanel1.getVisibleRect()); + } + } + + private String foundColumn; + + private void findColumns(final int x, final int y) { + List columNames = new ArrayList(); + Map columNamesCount = new HashMap(); + for (String nameObj: rows.keySet()) { + if (nameObj != null) { + String name = nameObj.toString(); + if (columNamesCount.containsKey(name)) { + columNamesCount.put(name, columNamesCount.get(name) + 1); + } else { + columNames.add(name); + columNamesCount.put(name, 1); + } + } + } + Collections.sort(columNames, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + }); + + final Window owner = SwingUtilities.getWindowAncestor(this); + + final JComboBox combobox = new JComboBox(); + combobox.setModel(new DefaultComboBoxModel(columNames.toArray())); + StringSearchPanel searchPanel = new StringSearchPanel(null, combobox, null, null, null, new Runnable() { + @Override + public void run() { + Object selected = combobox.getSelectedItem(); + if (selected != null) { + foundColumn = null; + for (String name: rows.keySet()) { + if (name != null && name.equals(selected)) { + Rectangle visibleRect = jPanel1.getVisibleRect(); + Rectangle cellRect = rows.get(name).getBounds(); + foundColumn = name; + updateColumnsTable.run(); + jPanel1.scrollRectToVisible( + new Rectangle( + visibleRect.x + visibleRect.width / 2, + cellRect.y + columnsPanel.getBounds().y - 32, + 1, cellRect.height + 64)); + break; + } + } + } + } + }) { + @Override + protected Integer preferredWidth() { + return 260; + } + @Override + protected Integer maxX() { + if (owner != null) { + return owner.getX() + owner.getWidth() - preferredWidth(); + } else { + return null; + } + } + @Override + protected Integer maxY(int height) { + if (owner != null) { + return owner.getY() + owner.getHeight() - height - 8; + } else { + return null; + } + } + }; + + searchPanel.setStringCount(columNamesCount); + searchPanel.find(owner, "Find Column", x, y, true); + } + + public boolean isCacheable() { + return cacheable; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + jScrollPane1 = new javax.swing.JScrollPane(); + jPanel1 = new javax.swing.JPanel(); + tableNameLabel = new javax.swing.JLabel(); + jSeparator1 = new javax.swing.JSeparator(); + columnsPanel = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + warnPanel = new javax.swing.JPanel(); + warnLabel = new javax.swing.JLabel(); + analyseButton = new javax.swing.JButton(); + warnLabel1 = new javax.swing.JLabel(); + warnLabel2 = new javax.swing.JLabel(); + sortColumnsCheckBox = new javax.swing.JCheckBox(); + findColumnsPanel = new javax.swing.JPanel(); + findColumnsLabel = new javax.swing.JLabel(); + + setBackground(new java.awt.Color(255, 255, 230)); + setLayout(new java.awt.GridBagLayout()); + + jScrollPane1.setBorder(null); + + jPanel1.setBackground(new java.awt.Color(255, 255, 230)); + jPanel1.setLayout(new java.awt.GridBagLayout()); + + tableNameLabel.setText("Test"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 0); + jPanel1.add(tableNameLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + jPanel1.add(jSeparator1, gridBagConstraints); + + columnsPanel.setOpaque(false); + columnsPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4); + jPanel1.add(columnsPanel, gridBagConstraints); + + jLabel1.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 5; + gridBagConstraints.weighty = 1.0; + jPanel1.add(jLabel1, gridBagConstraints); + + warnPanel.setOpaque(false); + warnPanel.setLayout(new java.awt.GridBagLayout()); + + warnLabel.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + warnPanel.add(warnLabel, gridBagConstraints); + + analyseButton.setText("jButton1"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; + warnPanel.add(analyseButton, gridBagConstraints); + + warnLabel1.setText("Data model differs from"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + warnPanel.add(warnLabel1, gridBagConstraints); + + warnLabel2.setText("database table definition"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + warnPanel.add(warnLabel2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(4, 12, 2, 0); + jPanel1.add(warnPanel, gridBagConstraints); + + jScrollPane1.setViewportView(jPanel1); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(jScrollPane1, gridBagConstraints); + + sortColumnsCheckBox.setText("sort columns "); + sortColumnsCheckBox.setOpaque(false); + sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + sortColumnsCheckBoxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + add(sortColumnsCheckBox, gridBagConstraints); + + findColumnsPanel.setOpaque(false); + findColumnsPanel.setLayout(new java.awt.GridBagLayout()); + + findColumnsLabel.setText("Find Columns"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 6); + findColumnsPanel.add(findColumnsLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 2); + add(findColumnsPanel, gridBagConstraints); + }// //GEN-END:initComponents + + private void sortColumnsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortColumnsCheckBoxActionPerformed + updateColumnsTable.run(); + repaint(); + }//GEN-LAST:event_sortColumnsCheckBoxActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton analyseButton; + private javax.swing.JPanel columnsPanel; + private javax.swing.JLabel findColumnsLabel; + public javax.swing.JPanel findColumnsPanel; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JSeparator jSeparator1; + private javax.swing.JCheckBox sortColumnsCheckBox; + private javax.swing.JLabel tableNameLabel; + private javax.swing.JLabel warnLabel; + private javax.swing.JLabel warnLabel1; + private javax.swing.JLabel warnLabel2; + private javax.swing.JPanel warnPanel; + // End of variables declaration//GEN-END:variables +} diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java b/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java index be41ea4e6..39a43fcd9 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java @@ -1,2459 +1,2460 @@ -/* - * Copyright 2007 - 2020 Ralf Wisser. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.sf.jailer.ui.databrowser.sqlconsole; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GridBagConstraints; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.sql.CallableStatement; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.BorderFactory; -import javax.swing.DefaultComboBoxModel; -import javax.swing.DefaultListCellRenderer; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.RowSorter.SortKey; -import javax.swing.SwingUtilities; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.table.TableModel; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Segment; - -import org.apache.log4j.Logger; -import org.fife.ui.rtextarea.RTextScrollPane; - -import net.sf.jailer.ExecutionContext; -import net.sf.jailer.configuration.Configuration; -import net.sf.jailer.configuration.DBMS; -import net.sf.jailer.database.Session; -import net.sf.jailer.datamodel.Association; -import net.sf.jailer.datamodel.DataModel; -import net.sf.jailer.datamodel.Table; -import net.sf.jailer.modelbuilder.MemorizedResultSet; -import net.sf.jailer.ui.DbConnectionDialog; -import net.sf.jailer.ui.Environment; -import net.sf.jailer.ui.JComboBox; -import net.sf.jailer.ui.QueryBuilderDialog; -import net.sf.jailer.ui.QueryBuilderDialog.Relationship; -import net.sf.jailer.ui.UIUtil; -import net.sf.jailer.ui.associationproposer.AssociationProposerView; -import net.sf.jailer.ui.databrowser.BrowserContentPane; -import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; -import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; -import net.sf.jailer.ui.databrowser.DataBrowser; -import net.sf.jailer.ui.databrowser.Desktop; -import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; -import net.sf.jailer.ui.databrowser.Reference; -import net.sf.jailer.ui.databrowser.Row; -import net.sf.jailer.ui.databrowser.metadata.MDSchema; -import net.sf.jailer.ui.databrowser.metadata.MDTable; -import net.sf.jailer.ui.databrowser.metadata.MetaDataDetailsPanel; -import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel.OutlineInfo; -import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; -import net.sf.jailer.ui.databrowser.metadata.ResultSetRenderer; -import net.sf.jailer.ui.syntaxtextarea.RSyntaxTextAreaWithSQLSyntaxStyle; -import net.sf.jailer.ui.syntaxtextarea.SQLAutoCompletion; -import net.sf.jailer.ui.syntaxtextarea.SQLCompletionProvider; -import net.sf.jailer.ui.util.FixedColumnTable; -import net.sf.jailer.ui.util.SmallButton; -import net.sf.jailer.ui.util.UISettings; -import net.sf.jailer.util.CancellationException; -import net.sf.jailer.util.CancellationHandler; -import net.sf.jailer.util.CsvFile; -import net.sf.jailer.util.Pair; - -/** - * SQL Console. - * - * @author Ralf Wisser - */ -@SuppressWarnings("serial") -public abstract class SQLConsole extends javax.swing.JPanel { - - /** - * The logger. - */ - private static final Logger logger = Logger.getLogger(MetaDataDetailsPanel.class); - - private static final int MAX_TAB_COUNT = 8; - private static final int MAX_HISTORY_SIZE = 100; - - private Session session; - MetaDataSource metaDataSource; - private RSyntaxTextAreaWithSQLSyntaxStyle editorPane; - private final MetaDataBasedSQLCompletionProvider provider; - private final BlockingQueue queue = new LinkedBlockingQueue(); - private final Reference datamodel; - private final ExecutionContext executionContext; - private final List history = new ArrayList(); - private final AtomicBoolean running = new AtomicBoolean(false); - private final AtomicBoolean updatingStatus = new AtomicBoolean(false); - private final ImageIcon scaledCancelIcon; - private final ImageIcon scaledExplainIcon; - private final SQLPlusSupport sqlPlusSupport = new SQLPlusSupport(); - private File file; - private JMenuItem menuItemToggle; - private JMenuItem menuItemToSingleLine; - private JMenuItem menuItemSubstituteVariables; - private JMenuItem menuItemAnalyse; - private int initialTabbedPaneSelection = 0; - private List initialSortKeys = null; - private String initialSortKeysSql = null; - private int initialTabbedPaneSelectionLoc = -1; - - private final String IGNORED_STATEMENTS = "(\\s*/\\s*)"; - - /** - * Stops the consumer thread. - */ - private final Runnable STOP = new Runnable() { - @Override - public void run() { - // nothing to do - } - }; - - /** - * Creates new form SQLConsole - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public SQLConsole(Session session, MetaDataSource metaDataSource, Reference datamodel, ExecutionContext executionContext) throws SQLException { - this.session = session; - this.metaDataSource = metaDataSource; - this.datamodel = datamodel; - this.executionContext = executionContext; - initComponents(); - initMenuItems(); - historyComboBox.setMaximumRowCount(25); - GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 16); - jPanel5.add(historyComboBox, gridBagConstraints); - - this.editorPane = new RSyntaxTextAreaWithSQLSyntaxStyle(true, true) { - { - setBracketMatchingEnabled(true); - } - @Override - protected boolean canExplain() { - return SQLConsole.this.canExplain(); - } - @Override - protected void runBlock() { - executeSelectedStatements(false, null, true); - } - @Override - protected void explainBlock() { - executeSelectedStatements(true, null, true); - } - @Override - protected void runAll() { - executeAllStatements(); - } - @Override - public void updateMenuItemState() { - updateMenuItemState(!running.get(), !running.get()); - } - @Override - protected void selectTable(MDTable mdTable) { - SQLConsole.this.selectTable(mdTable); - } - @Override - protected void updateMenuItems(boolean isTextSelected) { - SQLConsole.this.updateMenuItems(isTextSelected); - } - @Override - protected MDTable getSelectedTable() { - Document doc = getDocument(); - - int dot = getCaretPosition(); - int start = getLineStartOffsetOfCurrentLine(); - int lineEndOffsetOfCurrentLine = getLineEndOffsetOfCurrentLine(); - int len = lineEndOffsetOfCurrentLine - start; - Segment seg = new Segment(); - try { - doc.getText(start, len, seg); - } catch (BadLocationException ble) { - logger.info("error", ble); - return null; - } - - start = dot - getLineStartOffsetOfCurrentLine(); - String segment = seg.toString(); - char ch = start < segment.length()? segment.charAt(start) : ' '; - while (start list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - if (index == 0) { - value = null; - } - Object shortValue = value; - if (value instanceof String) { - shortValue = shortSQL((String) value, 120); - } - Component c = super.getListCellRendererComponent(list, shortValue, index, isSelected, cellHasFocus); - if (c instanceof JLabel) { - if (value instanceof String && value.toString().length() > 0) { - ((JLabel) c).setToolTipText(UIUtil.toHTML(value.toString(), 100)); - } else { - ((JLabel) c).setToolTipText(null); - } - } - return c; - } - }); - restoreHistory(); - - provider = new MetaDataBasedSQLCompletionProvider(session, metaDataSource) { - @Override - protected String prepareStatementForAliasAnalysis(String statement) { - return sqlPlusSupport.replaceVariables(statement, null); - } - }; - new SQLAutoCompletion(provider, editorPane); - - RTextScrollPane jScrollPane = new RTextScrollPane(); - jScrollPane.setViewportView(editorPane); - editorPane.setGutter(jScrollPane.getGutter()); - consoleContainerPanel.add(jScrollPane); - jScrollPane.setLineNumbersEnabled(true); - jScrollPane.setIconRowHeaderEnabled(true); - - runSQLButton.setAction(editorPane.runBlock); - runnAllButton.setAction(editorPane.runAll); - explainButton.setAction(editorPane.explain); - - runSQLButton.setText("Run"); - runnAllButton.setText("Run all"); - - runSQLButton.setIcon(UIUtil.scaleIcon(this, runIcon)); - runnAllButton.setIcon(UIUtil.scaleIcon(this, runAllIcon)); - runSQLButton.setToolTipText(runSQLButton.getText() + " - Ctrl-Enter"); - runnAllButton.setToolTipText(runnAllButton.getText() + " - Alt-Enter"); - - scaledCancelIcon = UIUtil.scaleIcon(this, cancelIcon); - cancelButton.setIcon(scaledCancelIcon); - - scaledExplainIcon = UIUtil.scaleIcon(this, explainIcon); - explainButton.setIcon(scaledExplainIcon); - - limitComboBox.setModel(new DefaultComboBoxModel(DataBrowser.ROW_LIMITS)); - limitComboBox.setSelectedItem(1000); - - resetStatus(); - statusLabel.setVisible(true); - - editorPane.addCaretListener(new CaretListener() { - @Override - public void caretUpdate(CaretEvent e) { - updateOutline(false); - } - }); - - initialContentSize = editorPane.getDocument().getLength(); - initialContentHash = editorPane.getText().hashCode(); - editorPane.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void removeUpdate(DocumentEvent e) { - checkDirty(); - } - @Override - public void insertUpdate(DocumentEvent e) { - checkDirty(); - } - @Override - public void changedUpdate(DocumentEvent e) { - checkDirty(); - } - }); - - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - Runnable action = null; - do { - try { - action = queue.take(); - action.run(); - } catch (Throwable t) { - logger.info("error", t); - } - } while (action != STOP); - } - }, "SQLConsole-" + (threadNum++)); - thread.setDaemon(true); - thread.start(); - } - - protected void initMenuItems() { - JMenuItem item = new JMenuItem("Toggle Line Continuation"); - item.setEnabled(false); - menuItemToggle = item; - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - toggleLineContinuation(); - } - }); - item.setToolTipText( - "Adds (or remove) line-continuation-character ('\\')
" + - " to each line terminated by ';'
" - + "(allowing you to execute PL/SQL code)"); - - item = new JMenuItem("To Single Line"); - item.setEnabled(false); - menuItemToSingleLine = item; - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - toSingleLine(); - } - }); - - item = new JMenuItem("Substitute Variables"); - item.setEnabled(false); - menuItemSubstituteVariables = item; - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - substituteVariables(); - } - }); - item.setToolTipText( - "Substitutes variables (&VAR[.]) with corresponding values.

\n" + - "Statements:\n" + - "
\n" + - "\n" + - "\n" + - "\n" + - "
 DEFINE VAR=\"VALUE\"   Assigns a value to variable VAR
 DEFINELists all variables
 &VAR  or   &VAR.Variable substitution (inside other statements)
"); - item = new JMenuItem("Analyze SQL"); - item.setEnabled(false); - menuItemAnalyse = item; - item.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - analyzeSQL(); - } - }); - item.setToolTipText("Analyzes selected SQL and proposes association definitions."); - } - - private void updateMenuItems(boolean isTextSelected) { - if (menuItemToggle != null) { - menuItemToggle.setEnabled(isTextSelected); - } - if (menuItemToSingleLine != null) { - menuItemToSingleLine.setEnabled(isTextSelected); - } - if (menuItemSubstituteVariables != null) { - menuItemSubstituteVariables.setEnabled(isTextSelected); - } - if (menuItemAnalyse != null) { - menuItemAnalyse.setEnabled(isTextSelected); - } - } - - private static int threadNum = 1; - - private boolean canExplain() { - return metaDataSource.getSession().dbms.getExplainQuery() != null && !metaDataSource.getSession().dbms.getExplainQuery().isEmpty(); - } - - private AtomicBoolean pending = new AtomicBoolean(false); - private AtomicBoolean stopped = new AtomicBoolean(false); - private String prevSql = null; - private int prevCaretPos; - - /** - * Update of outline of statement under caret and history after switching from another console to this. - */ - public void update() { - updateOutline(false); - restoreHistory(); - } - - /** - * Update of outline of statement under caret. - */ - private void updateOutline(boolean checkPrevSql) { - if (!pending.get()) { - Pair loc = editorPane.getCurrentStatementLocation(true, true, null, false); - String sql = editorPane.getText(loc.a, loc.b, true); - if (sql.trim().isEmpty()) { - loc = editorPane.getCurrentStatementLocation(true, true, null, true); - sql = editorPane.getText(loc.a, loc.b, true); - } - if (checkPrevSql && sql.equals(prevSql) && editorPane.getCaretPosition() == prevCaretPos) { - return; - } - prevSql = sql; - prevCaretPos = editorPane.getCaretPosition(); - - try { - updateOutline(sql, editorPane.getLineStartOffset(loc.a)); - } catch (Exception e1) { - logger.info("error", e1); - return; - } - - if (sql.length() > 20000) { - stopped.set(false); - pending.set(true); - new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - } - pending.set(false); - if (!stopped.get()) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - updateOutline(true); - } - }); - } - } - }).start(); - } else { - stopped.set(true); - } - } - } - - protected String shortSQL(String sql, int maxLength) { - sql = sql.trim().replaceAll("\\s+", " "); - if (sql.length() > maxLength) { - sql = sql.replaceFirst("^(?is)(\\bselect\\b).........*?(\\bfrom\\b)(.*)$", "$1 ... $2$3"); - } - if (sql.length() > maxLength) { - sql = sql.substring(0, maxLength) + "..."; - } - return sql; - } - - private void resetStatus() { - statusLabel.setVisible(false); - cancelButton.setEnabled(false); - } - - /** - * Executes a block of SQL statements (each statement separated by a ';' at the end of the line). - * - * @param sqlBlock the sql block - * @param location location of the block in the console - * @param emptyLineSeparatesStatements - * @param locFragmentOffset location of statement fragment, if any - * @param explain - * @param tabContentPanel the panel to show result (option) - */ - protected void executeSQLBlock(final String sqlBlock, final Pair location, final boolean emptyLineSeparatesStatements, final Pair locFragmentOffset, final boolean explain, final TabContentPanel tabContentPanel) { - if (!running.get()) { - int lineStartOffset = -1; - try { - if (location != null) { - lineStartOffset = editorPane.getLineStartOffset(location.a); - } - } catch (BadLocationException e) { - lineStartOffset = -1; - } - disableLastErrorTab(); - final Pair caretDotMark = new Pair(editorPane.getCaret().getDot(), editorPane.getCaret().getMark()); - final int finalLineStartOffset = lineStartOffset; - queue.add(new Runnable() { - @Override - public void run() { - running.set(true); - updatingStatus.set(false); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - editorPane.updateMenuItemState(); - } - }); - Status status = new Status(); - status.location = location; - status.linesExecuted = 0; - status.linesExecuting = 0; - status.running = true; - int lineStartOffset = finalLineStartOffset; - try { - Pattern pattern; - if (emptyLineSeparatesStatements) { - pattern = Pattern.compile("(?:(;\\s*(\\n\\r?|$))|(\\n\\r?([ \\t\\r]*\\n\\r?)+))", Pattern.DOTALL); - } else { - pattern = Pattern.compile("(?:(;\\s*(\\n\\r?|$)))", Pattern.DOTALL); - } - - Matcher matcher = pattern.matcher(sqlBlock); - boolean result = matcher.find(); - StringBuffer sb = new StringBuffer(); - if (result || locFragmentOffset != null) { - do { - String sql; - String pureSql; - if (locFragmentOffset != null) { - sql = sqlBlock; - pureSql = sqlBlock; - } else { - sb.setLength(0); - matcher.appendReplacement(sb, ""); - pureSql = sb.toString(); - sb.append(matcher.group()); - sql = sb.toString(); - } - status.linesExecuting += countLines(pureSql); - if (sql.trim().length() > 0) { - executeSQL(pureSql, status, lineStartOffset, explain, tabContentPanel, caretDotMark); - if (status.failed) { - if (locFragmentOffset != null) { - if (status.errorPositionIsKnown) { - try { - status.errorPosition += locFragmentOffset.a - editorPane.getLineStartOffset(editorPane.getLineOfOffset(locFragmentOffset.a)); - } catch (BadLocationException e) { - logger.info("error", e); - } - } - } - break; - } - } - if (lineStartOffset >= 0) { - lineStartOffset += sql.length(); - } - status.linesExecuted += countLines(sql) - 1; - if (locFragmentOffset != null) { - pattern = Pattern.compile("(\\n\\s*)$", Pattern.DOTALL); - matcher = pattern.matcher(sql); - if (!matcher.find()) { - status.linesExecuted++; - } - break; - } - String terminator = matcher.group(1); - if (terminator != null && !terminator.contains("\n")) { // ';' without nl - status.linesExecuted++; - } - status.linesExecuting = status.linesExecuted; - result = matcher.find(); - } while (result); - } - if (!status.failed && locFragmentOffset == null) { - sb.setLength(0); - matcher.appendTail(sb); - String sbToString = sb.toString(); - String sql = sbToString; - if (sql.trim().length() > 0) { - status.linesExecuting += countLines(sql); - executeSQL(sql, status, lineStartOffset, explain, tabContentPanel, caretDotMark); - if (!status.failed) { - status.linesExecuted = status.linesExecuting; - } - } - } - if (status.numStatements <= 7) { - storeHistory(); - } else { - restoreHistory(); - } - } finally { - status.running = false; - running.set(false); - status.updateView(true); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - editorPane.updateMenuItemState(true, false); - } - }); - } - } - - private int countLines(String line) { - int lines = 1; - for (int i = 0; i < line.length(); ++i) { - if (line.charAt(i) == '\n') { - ++lines; - } - } - return lines; - } - }); - } - } - - /** - * Executes a single SQL statment. - * - * @param sql the statement - * @param status the status to update - * @param statementStartOffset - * @param explain - * @param origTabContentPanel the panel to show result (option) - */ - private void executeSQL(final String sql, final Status status, int statementStartOffset, final boolean explain, final TabContentPanel origTabContentPanel, final Pair caretDotMark) { - Statement statement = null; - ResultSet resultSet = null; - final Status localStatus = new Status(); - String sqlStatement = null; - String stmtId = null; - TreeMap positionOffsets = new TreeMap(); - Connection resetAutoCommitConnection = null; - try { - Connection connection = session.getConnection(); - if (!explain && session.dbms.equals(DBMS.POSTGRESQL)) { - if (connection.getAutoCommit()) { - connection.setAutoCommit(false); - resetAutoCommitConnection = connection; - } - } - status.numStatements++; - localStatus.numStatements++; - UISettings.s3++; - status.updateView(false); - statement = connection.createStatement(); - if (session.dbms != null) { - if (session.dbms.getFetchSize() != null) { - statement.setFetchSize(session.dbms.getFetchSize()); - } - } - CancellationHandler.reset(SQLConsole.this); - CancellationHandler.begin(statement, SQLConsole.this); - long startTime = System.currentTimeMillis(); - sqlStatement = - sql - .replaceFirst("(?is)(;\\s*)+$", "") - .replaceAll("((?:(?:;(?: |\\t|\\r)*?(?:--[^\\n]*)?))) ?\\\\([ \\t\\r]*\\n)", "$1$2") - .replaceAll("((?:\\n(?: |\\t|\\r)*?)) ?\\\\([ \\t\\r]*)(?=\\n)", "$1"); - sqlStatement = sqlPlusSupport.replaceVariables(sqlStatement, positionOffsets); - status.statement = sqlStatement; - boolean loadButtonIsVisible = true; - boolean hasResultSet; - boolean hasUpdateCount = true; - ResultSet sqlPlusResultSet = null; - if (explain) { - if (session.dbms.getExplainCreateExplainTable() != null) { - Statement createStatement = connection.createStatement(); - try { - createStatement.execute(session.dbms.getExplainCreateExplainTable()); - } catch (Exception e) { - // ignore - } finally { - try { - createStatement.close(); - } catch (Exception e) { - // ignore - } - } - } - synchronized (this) { - stmtId = "Jailer" + (nextPlanID++ % 8); - } - if (session.dbms.getExplainPrepare() != null && !session.dbms.getExplainPrepare().isEmpty()) { - statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainPrepare(), sqlStatement, stmtId)); - statement.close(); - } - statement = connection.createStatement(); - hasResultSet = statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainQuery(), sqlStatement, stmtId)); - } else { - sqlPlusResultSet = sqlPlusSupport.executeSQLPLusQuery(sqlStatement); - if (sqlPlusResultSet != null) { - hasResultSet = true; - loadButtonIsVisible = false; - } else if (sqlPlusSupport.executeSQLPLusStatement(sqlStatement)) { - hasUpdateCount = false; - hasResultSet = false; - } else if (sqlStatement.matches(IGNORED_STATEMENTS)) { - hasUpdateCount = false; - hasResultSet = false; - } else { - hasResultSet = executeStatementWithLimit(statement, sqlStatement, session); - } - } - if (hasResultSet) { - resultSet = sqlPlusResultSet != null? sqlPlusResultSet : statement.getResultSet(); - ResultSetMetaData metaData = resultSet.getMetaData(); - final String columnLabels[] = new String[metaData.getColumnCount()]; - for (int i = 0; i < metaData.getColumnCount(); ++i) { - columnLabels[i] = metaData.getColumnLabel(i + 1); - } - ResultSet theMetaDataResultSet = null; - String resultSetType = null; - try { - resultSetType = TabContentPanel.toType(metaData, session, executionContext); - theMetaDataResultSet = TabContentPanel.toMetaDataResultSet(metaData, session, executionContext); - } catch (Throwable e1) { - logger.info("error", e1); - } - final ResultSet metaDataResultSet = theMetaDataResultSet; - final String finalResultSetType = resultSetType; - final Integer limit = (Integer) limitComboBox.getSelectedItem(); - List nfResultTypes = explain || sqlPlusResultSet != null? null : QueryTypeAnalyser.getType(sqlStatement, metaDataSource); - Table resultType = null; - if (nfResultTypes != null && !nfResultTypes.isEmpty()) { - if (nfResultTypes.size() == 1) { - resultType = nfResultTypes.get(0); - } - int columnCount = metaData.getColumnCount(); - for (Table table: nfResultTypes) { - while (table.getColumns().size() < columnCount) { - table.getColumns().add(new net.sf.jailer.datamodel.Column(null, "", 0, -1)); - } - } - } - if (resultType != null) { - if (resultType.getColumns().size() > metaData.getColumnCount()) { - // stale meta data - resultType = null; - nfResultTypes = null; - } - } - final List
resultTypes = nfResultTypes; - final MemorizedResultSet metaDataDetails = new MemorizedResultSet(resultSet, limit, session, SQLConsole.this) { - @Override - protected Object convertCellContent(Object object) { - Object lobRender = BrowserContentPane.toLobRender(object); - if (lobRender != null) { - return lobRender; - } - return object; - } - - @Override - protected void prepareHook(ResultSetMetaData rmd) throws SQLException { - sqlPlusSupport.prepareColumnSubstitution(rmd); - } - - @Override - protected void readRowHook(ResultSet resultSet) throws SQLException { - try { - sqlPlusSupport.substituteColumns(resultSet); - } catch (SQLException e) { - // ignore - } - } - }; - resultSet.close(); - long now = System.currentTimeMillis(); - status.hasSelected = true; - status.timeInMS += (now - startTime); - localStatus.timeInMS += (now - startTime); - status.numRowsRead += metaDataDetails.getSize(); - localStatus.numRowsRead += metaDataDetails.getSize(); - localStatus.hasSelected = true; - if (metaDataDetails.getSize() > limit) { - status.limitExceeded = true; - localStatus.limitExceeded = true; - } - status.updateView(false); - status.statement = sqlStatement; - final String finalSqlStatement = sqlStatement; - final Table finalResultType = resultType; - final boolean finalLoadButtonIsVisible = loadButtonIsVisible; - - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - final BrowserContentPane rb = new ResultContentPane(datamodel.get(), finalResultType, "", session, null, - null, null, new RowsClosure(), false, false, executionContext); - if (resultTypes != null && resultTypes.size() > 1) { - rb.setResultSetType(resultTypes); - } - rb.setAlternativeColumnLabels(columnLabels); - rb.setTableFilterEnabled(metaDataDetails.getSize() > 1 && metaDataDetails.getSize() <= limit); - rb.setStatementForReloading(finalSqlStatement); - metaDataDetails.reset(); - LoadJob loadJob = rb.newLoadJob(metaDataDetails, limit); - loadJob.run(); - JComponent rTabContainer = rb.getRowsTableContainer(); - metaDataDetails.reset(); - JComponent metaDataRenderer = null; - try { - metaDataRenderer = new ResultSetRenderer(metaDataResultSet, null, datamodel.get(), session, executionContext); - } catch (Throwable e1) { - logger.info("error", e1); - } - final TabContentPanel tabContentPanel = - new TabContentPanel(rb.rowsCount, - metaDataRenderer, - finalResultSetType, - explain, - origTabContentPanel == null? null : origTabContentPanel.shimPanel, - caretDotMark); - tabContentPanel.contentPanel.add(rTabContainer); - - rb.setCurrentRowsTable(new Reference() { - public JTable get() { - return tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel? columnsTable : rb.rowsTable; - } - }); - - rb.sortColumnsCheckBox.setVisible(true); - rb.sortColumnsPanel.setVisible(false); - rb.findColumnsPanel.setVisible(true); - rb.sortColumnsCheckBox.setText(rb.sortColumnsCheckBox.getText().trim()); - tabContentPanel.controlsPanel1.add(rb.sortColumnsCheckBox); - tabContentPanel.controlsPanel1.add(rb.findColumnsPanel); - rb.sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - updateColumnsAndTextView(rb, tabContentPanel); - } - }); - } - }); - final JButton loadButton = new JButton(rb.loadButton.getText(), rb.loadButton.getIcon()); - tabContentPanel.loadButton = loadButton; - loadButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tabContentPanel.loadingPanel.setVisible(true); - tabContentPanel.repaint(); - loadButton.setEnabled(false); - initialSortKeysSql = sql; - try { - initialSortKeys = rb.rowsTable.getRowSorter().getSortKeys(); - } catch (Exception e2) { - initialSortKeys = null; - } - reload(tabContentPanel, sql); - } - }); - tabContentPanel.cancelLoadButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - CancellationHandler.cancel(SQLConsole.this); - tabContentPanel.loadingPanel.setVisible(false); - tabContentPanel.repaint(); - loadButton.setEnabled(true); - } - }); - tabContentPanel.controlsPanel1.add(loadButton); - loadButton.setVisible(finalLoadButtonIsVisible); - loadButton.setIcon(UIUtil.scaleIcon(SQLConsole.this, runIcon)); - rb.setOnReloadAction(new Runnable() { - @Override - public void run() { - updateColumnsAndTextView(rb, tabContentPanel); - } - }); - String sqlE = sql.trim(); - if (explain) { - sqlE = "Explain Plan for " + sqlE; - } - String stmt = sqlE; - - tabContentPanel.statementLabel.setToolTipText(UIUtil.toHTML(sqlE, 100)); - if (stmt.length() > 200) { - stmt = stmt.substring(0, 200) + "..."; - } - tabContentPanel.statementLabel.setText(stmt.replaceAll("\\s+", " ")); - rTabContainer = tabContentPanel.shimPanel; - final int MAXLENGTH = 30; - String title = shortSQL(sqlE, MAXLENGTH); - final int loc = status != null && status.location != null? status.location.a : -1; - if (initialTabbedPaneSelection >= 0 && initialTabbedPaneSelectionLoc == loc) { - if (initialTabbedPaneSelection < tabContentPanel.tabbedPane.getTabCount()) { - tabContentPanel.tabbedPane.setSelectedIndex(initialTabbedPaneSelection); - } - } - try { - if (initialSortKeys != null && initialSortKeysSql != null && initialSortKeysSql.equals(sql)) { - rb.getRowsTable().getRowSorter().setSortKeys(initialSortKeys); - } - } catch (Exception e) { - // ignore - } - tabContentPanel.tabbedPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - initialTabbedPaneSelection = tabContentPanel.tabbedPane.getSelectedIndex(); - initialTabbedPaneSelectionLoc = loc; - updateColumnsAndTextView(rb, tabContentPanel); - if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel) { - columnsTable.scrollToCurrentRow(); - } - } - }); - removeLastErrorTab(); - - if (origTabContentPanel == null) { - jTabbedPane1.add(rTabContainer); - jTabbedPane1.setTabComponentAt(jTabbedPane1.indexOfComponent(rTabContainer), getTitlePanel(jTabbedPane1, rTabContainer, title)); - - if (jTabbedPane1.getTabCount() > MAX_TAB_COUNT) { - jTabbedPane1.remove(0); - } - jTabbedPane1.setSelectedIndex(jTabbedPane1.getTabCount() - 1); - } - rb.resetRowsTableContainer(); - jTabbedPane1.repaint(); - } - - private ColumnsTable columnsTable; - - public void updateColumnsAndTextView(final BrowserContentPane rb, - final TabContentPanel tabContentPanel) { - String tableSortAndFilterState = ""; - RowSorter sorter = rb.rowsTable.getRowSorter(); - if (sorter.getModelRowCount() > sorter.getViewRowCount()) { - tableSortAndFilterState = "Filtered"; - } - List skeys = sorter.getSortKeys(); - if (!skeys.isEmpty()) { - for (int i = 0; i < rb.rowsTable.getColumnCount(); ++i) { - if (rb.rowsTable.getColumnModel().getColumn(i).getModelIndex() == skeys.get(0).getColumn()) { - tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted") - + " by \"" + rb.rowsTable.getColumnName(i) + "\""; - break; - } - } - } - if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel || tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.contentPanel) { - Point vp = null; - if (columnsTable != null) { - if (tabContentPanel.columnsScrollPane.getViewport() != null) { - vp = tabContentPanel.columnsScrollPane.getViewport().getViewPosition(); - } - } - columnsTable = new ColumnsTable(rb); - tabContentPanel.columnsScrollPane.setViewportView(columnsTable); - new FixedColumnTable(1, tabContentPanel.columnsScrollPane); - if (vp != null) { - if (tabContentPanel.columnsScrollPane.getViewport() != null) { - tabContentPanel.columnsScrollPane.getViewport().setViewPosition(vp); - } - } - tabContentPanel.columnsSortedStateLabel.setText(" " + tableSortAndFilterState); - tabContentPanel.columnsSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty()); - } - if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.textTabPanel) { - tabContentPanel.updateTextView(rb.rowsTable); - tabContentPanel.textSortedStateLabel.setText(" " + tableSortAndFilterState); - tabContentPanel.textSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty()); - } - } - }); - } else { - status.timeInMS += (System.currentTimeMillis() - startTime); - int updateCount = !hasUpdateCount? 0 : statement.getUpdateCount(); - if (updateCount >= 0) { - status.numRowsUpdated += updateCount; - } - status.updateView(false); - status.hasUpdated = true; - if (updateCount != 0) { - setDataHasChanged(true); - } - if (isDDLStatement(sql)) { - status.withDDL = true; - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - removeLastErrorTab(); - if (origTabContentPanel != null) { - origTabContentPanel.loadingPanel.setVisible(false); - origTabContentPanel.repaint(); - if (origTabContentPanel.loadButton != null) { - origTabContentPanel.loadButton.setEnabled(true); - } - } - } - }); - } - CancellationHandler.end(statement, SQLConsole.this); - statement.close(); - if (!explain) { - appendHistory(sql); - } - } catch (Throwable error) { - try { - CancellationHandler.checkForCancellation(SQLConsole.this); - } catch (CancellationException e) { - error = e; - } - if (statement != null) { - try { - statement.close(); - } catch (SQLException e) { - } - } - if (resultSet != null) { - try { - resultSet.close(); - } catch (SQLException e) { - } - } - if (!isCommentOnly(sqlStatement)) { - if (error instanceof SQLException && sqlStatement != null && statementStartOffset >= 0) { - int pos = retrieveErrorPos(sqlStatement, error.getMessage()); - if (pos >= 0) { - Entry floor = positionOffsets.floorEntry(pos); - int positionOffset; - if (floor == null) { - positionOffset = 0; - } else { - positionOffset = floor.getValue(); - } - status.errorPosition = statementStartOffset + pos + positionOffset; - status.origErrorPosition = pos; - status.errorPositionIsKnown = true; - } else { - status.errorPosition = statementStartOffset; - status.errorPositionIsKnown = false; - } - } - status.failed = true; - status.error = error; - } - if (error instanceof CancellationException) { - CancellationHandler.reset(SQLConsole.this); - queue.clear(); - } - status.updateView(false); - final Throwable finalError = error; - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - if (origTabContentPanel != null) { - origTabContentPanel.loadingPanel.setVisible(false); - origTabContentPanel.repaint(); - if (origTabContentPanel.loadButton != null) { - origTabContentPanel.loadButton.setEnabled(true); - } - } - if (!(finalError instanceof SQLException || finalError instanceof CancellationException)) { - UIUtil.showException(SQLConsole.this, "Error", finalError); - } - } - }); - } finally { - if (explain && session.dbms.getExplainCleanup() != null && !session.dbms.getExplainCleanup().isEmpty()) { - if (session.dbms.getExplainPrepare() != null) { - try { - statement = session.getConnection().createStatement(); - statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainCleanup(), sqlStatement, stmtId)); - statement.close(); - } catch (SQLException e) { - logger.info("error", e); - } - } - } - if (resetAutoCommitConnection != null) { - try { - resetAutoCommitConnection.setAutoCommit(true); - } catch (SQLException e) { - // ignore - } - } - } - } - - private boolean executeStatementWithLimit(Statement statement, String sqlStatement, Session session) throws SQLException { - try { - int limit = 1 + (Integer) limitComboBox.getSelectedItem(); - if (limit > 0) { - statement.setMaxRows(limit + 1); - } - } catch (Exception e) { - // ignore - } - return statement.execute(sqlStatement); - } - - public void setCaretPosition(int position) { - if (editorPane.getDocument().getLength() >= position) { - try { - int l = editorPane.getLineOfOffset(position); - editorPane.setCaretPosition(position); - int lineHeight = editorPane.getLineHeight(); - editorPane.scrollRectToVisible(new Rectangle(0, Math.max(0, l - 2) * lineHeight, 1, 4 * lineHeight)); - } catch (Exception e) { - // ignore - } - editorPane.setCaretPosition(position); - grabFocus(); - } - } - - private void updateOutline(String sql, int startPosition) { - sql = sql.replaceFirst(";\\s*$", ""); - final int MAX_CONTEXT_LENGTH = 80; - final int MAX_TOOLTIP_LENGTH = 100; - List outlineInfos = new ArrayList(); - TreeMap offsets = new TreeMap(); - sql = sqlPlusSupport.replaceVariables(sql, offsets); - provider.findAliases(SQLCompletionProvider.removeCommentsAndLiterals(sql), null, outlineInfos); - adjustLevels(outlineInfos); - List relocatedOutlineInfos = new ArrayList(); - int indexOfInfoAtCaret = -1; - int caretPos = editorPane.getCaretPosition(); - OutlineInfo predInfo = null; - for (int i = 0; i < outlineInfos.size(); ++i) { - OutlineInfo info = outlineInfos.get(i); - Entry floor = offsets.floorEntry(info.position); - if (floor != null) { - info.origPosition = info.position + floor.getValue(); - } - } - for (int i = 0; i < outlineInfos.size(); ++i) { - OutlineInfo info = outlineInfos.get(i); - if (info.isBegin || info.isEnd) { - continue; - } - int pos = info.position; - if (pos + startPosition <= caretPos || indexOfInfoAtCaret < 0) { - indexOfInfoAtCaret = relocatedOutlineInfos.size(); - } - OutlineInfo rlInfo = new OutlineInfo(info.mdTable, info.alias, info.level, pos + startPosition, info.scopeDescriptor); - rlInfo.isCTE = info.isCTE; - rlInfo.rowCount = info.rowCount; - if (info.withContext) { - int cStart = info.contextPosition; - int cEnd = sql.length(); - int ttEnd = sql.length(); - if (i < outlineInfos.size() - 1) { - cEnd = Math.min(cEnd, outlineInfos.get(i + 1).position); - ttEnd = Math.min(ttEnd, outlineInfos.get(i + 1).position); - } - if (info.contextEnd > 0) { - cEnd = Math.min(cEnd, info.contextEnd); - ttEnd = Math.min(ttEnd, info.contextEnd); - } - if (cStart < cEnd) { - String context = UIUtil.removesuperfluousSpaces(sql.substring(cStart, cEnd).trim().replaceAll("\\s+", " ")); - if (context.length() > MAX_CONTEXT_LENGTH) { - context = context.substring(0, MAX_CONTEXT_LENGTH) + "..."; - } - rlInfo.context = UIUtil.toHTML(context, 0); - rlInfo.tooltip = UIUtil.toHTML(sql.substring(info.position, ttEnd), MAX_TOOLTIP_LENGTH); - } - } - rlInfo.withSeparator = info.withSeparator || predInfo != null && predInfo.level + (predInfo.mdTable != null? 1 : 0) == info.level && i > 0 && outlineInfos.get(i - 1).isBegin; - relocatedOutlineInfos.add(rlInfo); - predInfo = info; - } - indexOfInfoAtCaret -= simplifyOutline(relocatedOutlineInfos, indexOfInfoAtCaret); - setOutlineTables(relocatedOutlineInfos, indexOfInfoAtCaret); - } - - private int simplifyOutline(List outlineInfos, int indexOfInfoAtCaret) { - // "From " - int caretOffset = 0; - List toRemove = new ArrayList(); - for (int i = 1; i < outlineInfos.size(); ++i) { - OutlineInfo info = outlineInfos.get(i); - OutlineInfo pred = outlineInfos.get(i - 1); - if (info.mdTable != null && "From".equalsIgnoreCase(pred.scopeDescriptor)) { - if (info.level == pred.level) { - OutlineInfo succ = null; - if (i + 1 < outlineInfos.size()) { - succ = outlineInfos.get(i + 1); - } - if (succ == null || (succ.level != info.level || succ.mdTable == null)) { - info.scopeDescriptor = pred.scopeDescriptor; - info.position = pred.position; - info.origPosition = pred.origPosition; - toRemove.add(pred); - if (i - 1 < indexOfInfoAtCaret) { - ++caretOffset; - } - } - } - } - } - outlineInfos.removeAll(toRemove); - return caretOffset; - } - - private void adjustLevels(List outlineInfos) { - if (outlineInfos.size() > 0) { - int lastLevel = outlineInfos.get(outlineInfos.size() - 1).level; - for (int level = lastLevel - 1; level >= 0; --level) { - OutlineInfo info = new OutlineInfo(null, null, level, 0, ""); - info.isEnd = true; - outlineInfos.add(info); - } - } - Map lastBegin = new HashMap(); - List> pairs = new ArrayList>(); - Map> pairsPerEnd = new HashMap>(); - for (int i = 0; i < outlineInfos.size(); ++i) { - OutlineInfo info = outlineInfos.get(i); - if (info.isBegin) { - lastBegin.put(info.level, i); - } else if (info.isEnd) { - if (lastBegin.containsKey(info.level)) { - Pair pair = new Pair(lastBegin.get(info.level), i); - pairs.add(pair); - pairsPerEnd.put(i, pair); - } - } - } - for (int i = pairs.size() - 1; i > 0; --i) { - Pair thePair = pairs.get(i); - boolean ok = false; - int findA = thePair.a + 1; - Pair pair = pairsPerEnd.get(thePair.b - 1);; - while (pair != null) { - if (findA == pair.a) { - ok = true; - break; - } - if (findA > pair.a) { - break; - } - Pair predPair = pairsPerEnd.get(pair.a - 1); - if (predPair != null && pair.a - 1 != predPair.b) { - break; - } - pair = predPair; - } - - if (ok) { - for (int j = thePair.a; j < thePair.b; ++j) { - outlineInfos.get(j).level--; - } - } - } - } - - private boolean isDDLStatement(String sql) { - return sql.trim().matches("^(?is)\\b(drop|create|alter|rename)\\b.*"); - } - - protected abstract void refreshMetaData(); - protected abstract void selectTable(MDTable mdTable); - protected abstract void setOutlineTables(List outlineTables, int indexOfInfoAtCaret); - protected abstract JFrame getOwner(); - protected abstract void openDataModelEditor(boolean merge); - - private boolean dataHasChanged = false; - - public synchronized void setDataHasChanged(boolean b) { - dataHasChanged = b; - } - - public synchronized boolean getDataHasChanged() { - return dataHasChanged; - } - - /** - * Resets the console. - * - * @param session - * new session - * @param metaDataSource - * new meta data source - */ - public void reset(Session session, MetaDataSource metaDataSource) throws SQLException { - this.session = session; - this.metaDataSource = metaDataSource; - provider.reset(session, metaDataSource); - editorPane.forceCaretEvent(); - } - - private class Status { - public int origErrorPosition; - public int errorPosition = -1; - public boolean errorPositionIsKnown = false; - protected int linesExecuting; - protected int linesExecuted; - public boolean withDDL; - boolean failed; - boolean running; - boolean limitExceeded; - int numRowsRead; - int numRowsUpdated; - int numStatements; - boolean hasSelected = false; - boolean hasUpdated = false; - long timeInMS; - Throwable error; - String statement; - Pair location; - - private synchronized void updateView(boolean force) { - if (force || !updatingStatus.get()) { - updatingStatus.set(true); - - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - try { - synchronized (Status.this) { - Font font = new JLabel("X").getFont(); - statusLabel.setFont(new Font(font.getName(), font.getStyle(), (font.getSize() * 14) / 10)); - statusLabel.setVisible(false); - cancelButton.setEnabled(false); - if (!failed) { - cancelButton.setEnabled(running); - statusLabel.setVisible(true); - statusLabel.setForeground(running? new Color(0, 100, 0) : Color.BLACK); - statusLabel.setText(getText()); - } else { - statusLabel.setVisible(true); - if (error instanceof CancellationException) { - statusLabel.setForeground(Color.RED); - statusLabel.setText("Cancelled"); - removeLastErrorTab(); - } else if (error instanceof SQLException) { - String pos = ""; - int errorLine = -1; - try { - errorLine = editorPane.getLineOfOffset(errorPosition); - if (errorPositionIsKnown) { - int col = errorPosition - editorPane.getLineStartOffset(errorLine) + 1; - pos = "Error at line " + (errorLine + 1) + ", column " + col + ": "; - } - setCaretPosition(errorPosition); - } catch (BadLocationException e) { - } - if (errorLine >= 0) { - editorPane.setLineTrackingIcon(errorLine, scaledCancelIcon); - } - showError(pos + error.getMessage(), statement, origErrorPosition); - } else { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - error.printStackTrace(pw); - String sStackTrace = sw.toString(); // stack trace as a string - showError(sStackTrace, statement, origErrorPosition); - } - } - } - Color failedColor = new Color(255, 200, 200); - Color okColor = new Color(210, 255, 210); - Color pendingColor = new Color(235, 235, 255); - Color runningColor = new Color(255, 249, 200); - if (location != null) { - editorPane.removeAllLineHighlights(); - editorPane.setHighlightCurrentLine(false); - try { - for (int i = location.a; i <= location.b; ++i) { - Color hl; - if (i < linesExecuted + location.a) { - hl = okColor; - } else if (i >= linesExecuting + location.a) { - hl = pendingColor; - } else { - if (failed) { - hl = failedColor; - } else if (running){ - hl = runningColor; - } else { - hl = pendingColor; - } - } - editorPane.addLineHighlight(i, hl); - } - } catch (BadLocationException e) { - } - } - - jPanel2.repaint(); - - if (withDDL && !running) { - withDDL = false; - refreshMetaData(); - } - } finally { - updatingStatus.set(false); - } - } - }); - } - } - - private String getText() { - String text = ""; - if (running) { - text = "Running... "; - if (numStatements <= 1 && numRowsRead == 0 && numRowsUpdated == 0) { - return text; - } - } - if (numStatements > 1) { - text += numStatements + " Statements. "; - } - if (hasSelected) { - text += (limitExceeded? numRowsRead - 1 : numRowsRead) + " rows read"; - if (limitExceeded) { - text += " (limit exceeded)"; - } - text += ". "; - } - if (hasUpdated) { - text += numRowsUpdated + " rows updated. "; - } - return text + "Elapsed time: " + (timeInMS / 1000.0) + " sec"; - } - } - - private void showError(String errorMessage, String statement, int errorPosition) { - statusLabel.setVisible(true); - statusLabel.setForeground(Color.RED); - statusLabel.setText("Error"); - - removeLastErrorTab(); - - JComponent rTabContainer = new ErrorPanel(errorMessage, statement, errorPosition); - jTabbedPane1.add(rTabContainer); - jTabbedPane1.setTabComponentAt(jTabbedPane1.indexOfComponent(rTabContainer), getTitlePanel(jTabbedPane1, rTabContainer, "Error")); - - if (jTabbedPane1.getTabCount() > MAX_TAB_COUNT) { - jTabbedPane1.remove(0); - } - jTabbedPane1.setSelectedIndex(jTabbedPane1.getTabCount() - 1); - jTabbedPane1.repaint(); - } - - private void removeLastErrorTab() { - if (jTabbedPane1.getTabCount() > 0) { - if (jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1) instanceof TitelPanel) { - if (((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer instanceof ErrorPanel) { - jTabbedPane1.removeTabAt(jTabbedPane1.getTabCount() - 1); - } - } - } - } - - private void disableLastErrorTab() { - if (jTabbedPane1.getTabCount() > 0) { - if (jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1) instanceof TitelPanel) { - if (((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer instanceof ErrorPanel) { - ((ErrorPanel)((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer).doDisable(); - - } - } - } - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - jPanel1 = new javax.swing.JPanel(); - jSplitPane2 = new javax.swing.JSplitPane(); - jPanel2 = new javax.swing.JPanel(); - consoleContainerPanel = new javax.swing.JPanel(); - jPanel5 = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - limitComboBox = new javax.swing.JComboBox(); - cancelButton = new javax.swing.JButton(); - runSQLButton = new javax.swing.JButton(); - runnAllButton = new javax.swing.JButton(); - explainButton = new javax.swing.JButton(); - jPanel6 = new javax.swing.JPanel(); - statusLabel = new javax.swing.JLabel(); - dummyLabel = new javax.swing.JLabel(); - jPanel3 = new javax.swing.JPanel(); - jTabbedPane1 = new javax.swing.JTabbedPane(); - jLabel2 = new javax.swing.JLabel(); - - setLayout(new java.awt.GridBagLayout()); - - jPanel1.setLayout(new java.awt.GridBagLayout()); - - jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - jSplitPane2.setResizeWeight(0.6); - jSplitPane2.setContinuousLayout(true); - jSplitPane2.setOneTouchExpandable(true); - - jPanel2.setLayout(new java.awt.GridBagLayout()); - - consoleContainerPanel.setLayout(new java.awt.BorderLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel2.add(consoleContainerPanel, gridBagConstraints); - - jPanel5.setLayout(new java.awt.GridBagLayout()); - - jLabel1.setText("Row limit "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 13; - gridBagConstraints.gridy = 2; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); - jPanel5.add(jLabel1, gridBagConstraints); - - limitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 14; - gridBagConstraints.gridy = 2; - jPanel5.add(limitComboBox, gridBagConstraints); - - cancelButton.setText("Cancel"); - cancelButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelButtonActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 12; - gridBagConstraints.gridy = 2; - jPanel5.add(cancelButton, gridBagConstraints); - - runSQLButton.setText("Run"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - jPanel5.add(runSQLButton, gridBagConstraints); - - runnAllButton.setText("Run all"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 2; - jPanel5.add(runnAllButton, gridBagConstraints); - - explainButton.setText("Explain"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 2; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 8); - jPanel5.add(explainButton, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - gridBagConstraints.weightx = 1.0; - jPanel2.add(jPanel5, gridBagConstraints); - - jPanel6.setLayout(new java.awt.GridBagLayout()); - - statusLabel.setForeground(java.awt.Color.gray); - statusLabel.setText(" ctrl-space for code completion"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridheight = 20; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); - jPanel6.add(statusLabel, gridBagConstraints); - - dummyLabel.setForeground(java.awt.Color.gray); - dummyLabel.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridheight = 20; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); - jPanel6.add(dummyLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - jPanel2.add(jPanel6, gridBagConstraints); - - jSplitPane2.setLeftComponent(jPanel2); - - jPanel3.setLayout(new java.awt.GridBagLayout()); - - jTabbedPane1.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel3.add(jTabbedPane1, gridBagConstraints); - - jLabel2.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST; - jPanel3.add(jLabel2, gridBagConstraints); - - jSplitPane2.setRightComponent(jPanel3); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jSplitPane2, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - add(jPanel1, gridBagConstraints); - }// //GEN-END:initComponents - - private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - statusLabel.setText("Canceling..."); - statusLabel.setForeground(Color.RED); - CancellationHandler.cancel(this); - cancelButton.setEnabled(false); - }//GEN-LAST:event_cancelButtonActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton cancelButton; - private javax.swing.JPanel consoleContainerPanel; - private javax.swing.JLabel dummyLabel; - private javax.swing.JButton explainButton; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JPanel jPanel3; - private javax.swing.JPanel jPanel5; - private javax.swing.JPanel jPanel6; - private javax.swing.JSplitPane jSplitPane2; - private javax.swing.JTabbedPane jTabbedPane1; - private javax.swing.JComboBox limitComboBox; - private javax.swing.JButton runSQLButton; - private javax.swing.JButton runnAllButton; - private javax.swing.JLabel statusLabel; - // End of variables declaration//GEN-END:variables - - class ResultContentPane extends BrowserContentPane { - public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, - List parentRows, Association association, Frame parentFrame, - RowsClosure rowsClosure, Boolean selectDistinct, - boolean reload, ExecutionContext executionContext) { - super(dataModel, table, condition, session, parentRows, association, parentFrame, - rowsClosure, selectDistinct, reload, executionContext); - noSingleRowDetailsView = true; - rowsTableScrollPane.setWheelScrollingEnabled(true); - } - @Override - protected int getReloadLimit() { - return (Integer) limitComboBox.getSelectedItem(); - } - @Override - protected void unhide() { - } - @Override - protected void showInNewWindow() { - } - @Override - protected void reloadDataModel() throws Exception { - } - @Override - protected void openSchemaMappingDialog() { - } - @Override - protected void openSchemaAnalyzer() { - } - @Override - protected void onRedraw() { - jTabbedPane1.repaint(); - } - @Override - protected void onHide() { - } - @Override - protected void onContentChange(List rows, boolean reloadChildren) { - } - @Override - protected RowBrowser navigateTo(Association association, List pRows) { - return null; - } - @Override - protected List getTableBrowser() { - return null; - } - @Override - protected PriorityBlockingQueue getRunnableQueue() { - return Desktop.runnableQueue; - } - @Override - protected QueryBuilderDialog getQueryBuilderDialog() { - return null; - } - @Override - protected RowBrowser getParentBrowser() { - return null; - } - @Override - protected JFrame getOwner() { - Window owner = SwingUtilities.getWindowAncestor(SQLConsole.this); - if (owner instanceof JFrame) { - return (JFrame) owner; - } - return null; - } - @Override - protected double getLayoutFactor() { - return 0; - } - @Override - protected DbConnectionDialog getDbConnectionDialog() { - return null; - } - @Override - protected List getChildBrowsers() { - return new ArrayList(); - } - @Override - protected void findClosure(Row row, Set> closure, boolean forward) { - } - @Override - protected void findClosure(Row row) { - } - @Override - protected Relationship createQBRelations(boolean withParents) { - return null; - } - @Override - protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { - return null; - } - @Override - protected void collectPositions(Map> positions) { - } - @Override - protected void close() { - } - @Override - protected void beforeReload() { - } - @Override - protected void appendLayout() { - } - @Override - protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { - } - @Override - protected void addRowToRowLink(Row pRow, Row exRow) { - } - @Override - protected boolean renderRowAsPK(Row theRow) { - return false; - } - @Override - protected MetaDataSource getMetaDataSource() { - return null; - } - @Override - protected SQLConsole getSqlConsole(boolean switchToConsole) { - return SQLConsole.this; - } - @Override - protected void deselectChildrenIfNeededWithoutReload() { - } - }; - - private class TitelPanel extends JPanel { - public final JComponent rTabContainer; - - public TitelPanel(final JTabbedPane tabbedPane, final JComponent rTabContainer, String title) { - super(new FlowLayout(FlowLayout.LEFT, 0, 0)); - this.rTabContainer = rTabContainer; - setOpaque(false); - JLabel titleLbl = new JLabel(title); - titleLbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - add(titleLbl); - SmallButton closeButton = new SmallButton(closeIcon) { - @Override - protected void onClick() { - tabbedPane.remove(rTabContainer); - } - }; - add(closeButton); - } - } - - private JPanel getTitlePanel(final JTabbedPane tabbedPane, final JComponent rTabContainer, String title) { - return new TitelPanel(tabbedPane, rTabContainer, title); - } - - @Override - public void grabFocus() { - editorPane.grabFocus(); - } - - private Icon closeIcon; - { - // load images - closeIcon = UIUtil.readImage("/Close-16-1.png"); - } - - /** - * Appends a statement and eventually executes it. - * - * @param sql the statement - * @param execute execute the statement? - * @param useLineContinuation - * @param tabContentPanel - */ - public void appendStatement(String sql, boolean execute) { - appendStatement(sql, execute, null, false); - } - - /** - * Appends a statement and eventually executes it. - * - * @param sql the statement - * @param execute execute the statement? - * @param tabContentPanel the panel to show result (option) - */ - public void appendStatement(String sql, boolean execute, TabContentPanel tabContentPanel, boolean useLineContinuation) { - if (!findAndSetCaretPosition(sql, tabContentPanel)) { - String pre = ""; - int lineCount = editorPane.getLineCount(); - if (lineCount > 0 && editorPane.getDocument().getLength() > 0) { - pre = "\n"; - if (editorPane.getText(lineCount - 1, lineCount - 1, true).trim().length() > 0) { - pre += "\n"; - } - } - if (useLineContinuation) { - sql = addLineContinuation(sql); - } else { - sql = sql.replaceAll("\\n\\s*\\n", "\n").trim(); - } - if (!sql.endsWith(";") && !sql.endsWith(" \\")) { - sql += ";"; - } - editorPane.append(pre + sql.replace("\r", "") + "\n"); - setCaretPosition(editorPane.getDocument().getLength()); - } - if (!running.get()) { - resetStatus(); - } - if (execute) { - executeSelectedStatements(false, tabContentPanel, true); - } - } - - /** - * Searches a statement and sets caret position s.t. current statement equals the given one. - */ - private boolean findAndSetCaretPosition(String statement, TabContentPanel tabContentPanel) { - statement = statement.replaceFirst("(;\\s*)+$", "").trim(); - - if (tabContentPanel != null && tabContentPanel.caretDotMark.a != tabContentPanel.caretDotMark.b) { - try { - try { - editorPane.setCaretPosition(0); - } catch (Exception e) { - // ignore - } - editorPane.setCaretPosition(tabContentPanel.caretDotMark.a); - editorPane.moveCaretPosition(tabContentPanel.caretDotMark.b); - String existingStatement = executeSelectedStatements(false, tabContentPanel, false); - if (existingStatement.replaceFirst("(;\\s*)+$", "").trim().equals(statement)) { - return true; - } - } catch (/*IllegalArgument*/ Exception e) { - // ignore - } - } - - String[] statementLines = statement.split("\\s*\\n\\s*"); - int lineCount = editorPane.getLineCount(); - for (int lineNr = 0; lineNr < lineCount; ++lineNr) { - if (lineNr + statementLines.length <= lineCount) { - boolean found = true; - for (int i = 0; i < statementLines.length; ++i) { - String line = getLineContent(lineNr + i); - line = line.trim().replaceFirst("(;\\s*)+$", ""); - if (!line.equals(statementLines[i])) { - found = false; - break; - } - } - if (found) { - try { - editorPane.setCaretPosition(0); - } catch (Exception e) { - // ignore - } - try { - editorPane.setCaretPosition(editorPane.getLineStartOffset(lineNr)); - String existingStatement = executeSelectedStatements(false, tabContentPanel, false).replaceFirst("(;\\s*)+$", "").trim(); - if (existingStatement.equals(statement)) { - return true; - } - } catch (Exception e) { - return false; - } - } - } - } - - return false; - } - - private String getLineContent(int line) { - try { - Segment txt = new Segment(); - int sOff = editorPane.getLineStartOffset(line); - editorPane.getDocument().getText(sOff, editorPane.getLineEndOffset(line) - sOff, txt); - return txt.toString(); - } catch (BadLocationException e) { - return ""; - } - } - - private String executeSelectedStatements(boolean explain, TabContentPanel tabContentPanel, boolean execute) { - try { - String sql; - Pair loc = null; - Pair locFragmentOffset = null; - Pair, Pair> locFragment = editorPane.getCurrentStatementFragmentLocation(); - if (locFragment != null) { - loc = locFragment.a; - locFragmentOffset = locFragment.b; - sql = editorPane.getDocument().getText(locFragmentOffset.a, locFragmentOffset.b - locFragmentOffset.a); - if (loc.a < loc.b) { - Pattern pattern = Pattern.compile("(\\n\\s*)$", Pattern.DOTALL); - Matcher matcher = pattern.matcher(sql); - if (matcher.find()) { - loc = new Pair(loc.a, loc.b - 1); - } - } - } else { - loc = editorPane.getCurrentStatementLocation(null); - sql = editorPane.getText(loc.a, loc.b, true); - } - if (loc != null && execute) { - executeSQLBlock(sql, loc, editorPane.getCaret().getDot() == editorPane.getCaret().getMark(), locFragmentOffset, explain, tabContentPanel); - } - return sql; - } catch (BadLocationException e) { - e.printStackTrace(); - return ""; - } - } - - private void executeAllStatements() { - if (editorPane.getLineCount() > 0) { - int start = 0; - - try { - while (start < editorPane.getLineCount()) { - Segment txt = new Segment(); - int sOff = editorPane.getLineStartOffset(start); - editorPane.getDocument().getText(sOff, editorPane.getLineEndOffset(start) - sOff, txt); - String sLine = txt.toString().trim(); - if (sLine.length() > 0) { - break; - } - ++start; - } - } catch (BadLocationException e) { - // ignore - } - Pair loc = new Pair(start, editorPane.getLineCount() - 1); - executeSQLBlock(editorPane.getText(loc.a, loc.b, true), loc, false, null, false, null); - } - } - - private boolean isCommentOnly(String statement) { - if (statement == null) { - return false; - } - Pattern pattern = Pattern.compile("('([^']*'))|(/\\*.*?\\*/)|(\\-\\-.*?(\n|$))", Pattern.DOTALL); - Matcher matcher = pattern.matcher(statement); - boolean result = matcher.find(); - StringBuffer sb = new StringBuffer(); - if (result) { - do { - if (matcher.group(1) == null) { - matcher.appendReplacement(sb, ""); - } else { - matcher.appendReplacement(sb, "$0"); - } - result = matcher.find(); - } while (result); - } - matcher.appendTail(sb); - return sb.toString().trim().isEmpty(); - } - - private final String HISTORY_FILE = ".history"; - private final String LF = System.getProperty("line.separator", "\n"); - private final JComboBox historyComboBox = new JComboBox() { - @Override - public java.awt.Dimension getMinimumSize() { - Dimension s = super.getMinimumSize(); - return new Dimension(Math.min(80, s.width), s.height); - } - }; - - private synchronized void restoreHistory() { - try { - File file = Environment.newFile(HISTORY_FILE); - if (file.exists()) { - BufferedReader in = new BufferedReader(new FileReader(file)); - history.clear(); - String line; - while ((line = in.readLine()) != null) { - String[] lines = CsvFile.decodeLine(line.trim()); - if (lines.length > 0 && !lines[0].isEmpty()) { - history.add(lines[0]); - } - } - in.close(); - } - } catch (Exception e) { - logger.info("error", e); - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - historyComboBox.setModel(historyComboboxModel()); - } - }); - } - - private synchronized void storeHistory() { - try { - File file = Environment.newFile(HISTORY_FILE); - FileWriter out = new FileWriter(file); - for (String sql: history) { - out.write(CsvFile.encodeCell(sql) + LF); - } - out.close(); - } catch (Exception e) { - logger.info("error", e); - } - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - historyComboBox.setModel(historyComboboxModel()); - } - }); - } - - private final ItemListener historyCBItemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED && e.getItem() != null && historyComboBox.getSelectedIndex() > 0) { - appendStatement(e.getItem().toString(), false, null, true); - historyComboBox.setSelectedIndex(0); - } - } - }; - - private DefaultComboBoxModel historyComboboxModel() { - ArrayList model = new ArrayList(history); - if (!model.isEmpty()) { - model.add(0, new String(model.get(0) + " ")); - } - historyComboBox.removeItemListener(historyCBItemListener); - DefaultComboBoxModel cbModel = new DefaultComboBoxModel(model.toArray()); - historyComboBox.addItemListener(historyCBItemListener); - return cbModel; - } - - private synchronized void appendHistory(String sql) { - sql = sql.trim(); - if (!sql.isEmpty() && sql.length() < 100000) { - history.remove(sql); - history.add(0, sql); - if (history.size() > MAX_HISTORY_SIZE) { - history.remove(history.size() - 1); - } - } - } - - private int retrieveErrorPos(String sqlStatement, CharSequence errorMessage) { - if (DBMS.ORACLE.equals(session.dbms)) { - String statement = "declare " - + "l_theCursor integer default dbms_sql.open_cursor;" + "begin " + " begin " - + " dbms_sql.parse( l_theCursor, ?, dbms_sql.native );" - + " exception when others then ? := dbms_sql.last_error_position;" + " end;" - + " dbms_sql.close_cursor( l_theCursor );" + "end;"; - - CallableStatement cStmt = null; - try { - Connection connection = session.getConnection(); - cStmt = connection.prepareCall(statement); - cStmt.registerOutParameter(2, Types.INTEGER); - cStmt.setString(1, sqlStatement); - - cStmt.execute(); - - return cStmt.getInt(2); - } catch (Exception e) { - logger.info("error", e); - } finally { - if (cStmt != null) { - try { - cStmt.close(); - } catch (SQLException e) { - } - } - } - } else if (DBMS.POSTGRESQL.equals(session.dbms)) { - Pattern pattern = Pattern.compile("\\n\\s*Position: ([0-9]+)"); - Matcher matcher = pattern.matcher(errorMessage); - if (matcher.find()) { - return Integer.parseInt(matcher.group(1)) - 1; - } - } - return -1; - } - - private void toSingleLine() { - String currentStatement = editorPane.getCurrentStatement(false); - String newStatement = UIUtil.toSingleLineSQL(currentStatement); - if (!currentStatement.equals(newStatement)) { - editorPane.replaceCurrentStatement(newStatement, false); - } - } - - private void toggleLineContinuation() { - String currentStatement = editorPane.getCurrentStatement(false); - String newStatement; - Pattern p = Pattern.compile("(?:(?:;( |\\t|\\r)*(?:--[^\\n]*)?)|(?:\\n( |\\t|\\r)*)) ?\\\\( |\\t|\\r)*\\n", Pattern.DOTALL); - Matcher m = p.matcher(currentStatement); - if (m.find()) { - newStatement = currentStatement.replaceAll("((?:(?:;(?: |\\t|\\r)*?(?:--[^\\n]*)?))) ?\\\\([ \\t\\r]*\\n)", "$1$2"); - newStatement = newStatement.replaceAll("((?:\\n(?: |\\t|\\r)*?)) ?\\\\([ \\t\\r]*)(?=\\n)", "$1$2"); - } else { - newStatement = addLineContinuation(currentStatement); - } - if (!currentStatement.equals(newStatement)) { - editorPane.replaceCurrentStatement(newStatement, false); - } - } - - private String addLineContinuation(String statement) { - String newStatement = statement; - newStatement = newStatement.replace("\r", ""); - newStatement = newStatement.replaceAll("((?:(?:;(?: |\\t|\\r)*(?:--[^\\n]*)?)))(\\n(\\r)?)", "$1 \\\\$2"); - newStatement = newStatement.replaceAll("((?:(?:\\n(?: |\\t|\\r)*)))(?=\\n)", "$1 \\\\"); - newStatement = newStatement.replaceAll("\\\\(\\s*)$", "$1"); - return newStatement; - } - - private void analyzeSQL() { - String currentStatement = editorPane.getCurrentStatement(false); - File tempFile = Configuration.getInstance().createTempFile(); - try { - BufferedWriter out = new BufferedWriter(new FileWriter(tempFile)); - Pair loc = editorPane.getCurrentStatementLocation(false, false, null, false); - if (loc != null) { - for (int i = 0; i < loc.a; ++i) { - out.write("\n"); - } - } - out.write(currentStatement); - out.close(); - AssociationProposerView associationProposer = new AssociationProposerView(getOwner(), datamodel.get(), tempFile, executionContext); - if (associationProposer.isAccepted()) { - openDataModelEditor(true); - } - } catch (Exception e) { - UIUtil.showException(this, "Error", e); - } - tempFile.delete(); - } - - private void substituteVariables() { - String currentStatement = editorPane.getCurrentStatement(true); - String newStatement = sqlPlusSupport.replaceVariables(currentStatement, null); - if (!currentStatement.equals(newStatement)) { - editorPane.replaceCurrentStatement(newStatement, true); - } - } - - /** - * @return true iff console editor is empty - */ - public boolean isEmpty() { - return editorPane.getDocument().getLength() == 0; - } - - /** - * Sets the row limit. - * - * @param limit the row limit - */ - public void setRowLimit(Integer limit) { - limitComboBox.setSelectedItem(limit); - } - - private int initialContentSize; - private int initialContentHash; - private boolean dirty; - - /** - * Loads content from file. - * - * @param file the file - */ - public void loadFromFile(File file) throws IOException { - this.file = file; - if (file.exists()) { - BufferedReader in = new BufferedReader(new FileReader(file)); - StringBuilder sb = new StringBuilder(); - int c; - while ((c = in.read()) != -1) { - if (c != '\r') { - sb.append((char) c); - } - } - in.close(); - editorPane.setText(sb.toString()); - dirty = false; - } else { - editorPane.setText(""); - dirty = true; - } - initialContentSize = editorPane.getDocument().getLength(); - initialContentHash = editorPane.getText().hashCode(); - consoleContainerPanel.setVisible(false); - UIUtil.invokeLater(new Runnable() { - @Override - public void run() { - consoleContainerPanel.setVisible(true); - grabFocus(); - } - }); - setCaretPosition(0); - onContentStateChange(file, dirty); - } - - /** - * Stores content to file if console is dirty or new file is given. - * - * @param newFile the file or null to store into assigned file - */ - public void storeToFile(File newFile) throws IOException { - if (newFile != null || file != null && dirty) { - if (newFile != null) { - file = newFile; - } - PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); - int lines = editorPane.getLineCount(); - for (int line = 0; line < lines; ++line) { - out.print(getLineContent(line).replace("\r", "").replace("\n", "")); - if (line < lines - 1) { - out.println(); - } - } - out.close(); - initialContentSize = editorPane.getDocument().getLength(); - initialContentHash = editorPane.getText().hashCode(); - dirty = false; - onContentStateChange(file, dirty); - } - } - - private void checkDirty() { - boolean newState = false; - if (initialContentSize != editorPane.getDocument().getLength()) { - newState = true; - } else { - newState = initialContentHash != editorPane.getText().hashCode(); - } - if (newState != dirty) { - dirty = newState; - onContentStateChange(file, dirty); - } - } - - /** - * Reloads tab content - * - * @param tabContentPanel to be reloaded - * @param sql statement to be executed again - */ - private void reload(TabContentPanel tabContentPanel, String sql) { - try { - UIUtil.setWaitCursor(tabContentPanel); - appendStatement(sql.replaceFirst("(;\\s*)+$", ""), true, tabContentPanel, true); - } finally { - UIUtil.resetWaitCursor(tabContentPanel); - } - } - - /** - * Gets the file associated with this console. - * - * @return file associated with this console or null, if the console is not assigned to a file - */ - public File getFile() { - return file; - } - - public boolean isDirty() { - return dirty; - } - - /** - * Closes this console. - */ - public void close() { - CancellationHandler.cancel(this); - queue.add(STOP); - } - - /** - * Gets the editor pane. - * - * @return the editor pane - */ - public RSyntaxTextAreaWithSQLSyntaxStyle getEditorPane() { - return editorPane; - } - - protected abstract void onContentStateChange(File file, boolean dirty); - - static private ImageIcon runIcon; - static private ImageIcon runAllIcon; - static private ImageIcon cancelIcon; - static private ImageIcon explainIcon; - - private int nextPlanID = 0; - - static { - // load images - runIcon = UIUtil.readImage("/run.png"); - runAllIcon = UIUtil.readImage("/runall.png"); - cancelIcon = UIUtil.readImage("/Cancel.png"); - explainIcon = UIUtil.readImage("/explain.png"); - } - -} +/* + * Copyright 2007 - 2020 Ralf Wisser. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.jailer.ui.databrowser.sqlconsole; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.RowSorter; +import javax.swing.RowSorter.SortKey; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.table.TableModel; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Segment; + +import org.apache.log4j.Logger; +import org.fife.ui.rtextarea.RTextScrollPane; + +import net.sf.jailer.ExecutionContext; +import net.sf.jailer.configuration.Configuration; +import net.sf.jailer.configuration.DBMS; +import net.sf.jailer.database.Session; +import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.DataModel; +import net.sf.jailer.datamodel.Table; +import net.sf.jailer.modelbuilder.MemorizedResultSet; +import net.sf.jailer.ui.DbConnectionDialog; +import net.sf.jailer.ui.Environment; +import net.sf.jailer.ui.JComboBox; +import net.sf.jailer.ui.QueryBuilderDialog; +import net.sf.jailer.ui.QueryBuilderDialog.Relationship; +import net.sf.jailer.ui.UIUtil; +import net.sf.jailer.ui.associationproposer.AssociationProposerView; +import net.sf.jailer.ui.databrowser.BrowserContentPane; +import net.sf.jailer.ui.databrowser.BrowserContentPane.LoadJob; +import net.sf.jailer.ui.databrowser.BrowserContentPane.RowsClosure; +import net.sf.jailer.ui.databrowser.DataBrowser; +import net.sf.jailer.ui.databrowser.Desktop; +import net.sf.jailer.ui.databrowser.Desktop.FindClosureContext; +import net.sf.jailer.ui.databrowser.Desktop.RowBrowser; +import net.sf.jailer.ui.databrowser.Reference; +import net.sf.jailer.ui.databrowser.Row; +import net.sf.jailer.ui.databrowser.metadata.MDSchema; +import net.sf.jailer.ui.databrowser.metadata.MDTable; +import net.sf.jailer.ui.databrowser.metadata.MetaDataDetailsPanel; +import net.sf.jailer.ui.databrowser.metadata.MetaDataPanel.OutlineInfo; +import net.sf.jailer.ui.databrowser.metadata.MetaDataSource; +import net.sf.jailer.ui.databrowser.metadata.ResultSetRenderer; +import net.sf.jailer.ui.syntaxtextarea.RSyntaxTextAreaWithSQLSyntaxStyle; +import net.sf.jailer.ui.syntaxtextarea.SQLAutoCompletion; +import net.sf.jailer.ui.syntaxtextarea.SQLCompletionProvider; +import net.sf.jailer.ui.util.FixedColumnTable; +import net.sf.jailer.ui.util.SmallButton; +import net.sf.jailer.ui.util.UISettings; +import net.sf.jailer.util.CancellationException; +import net.sf.jailer.util.CancellationHandler; +import net.sf.jailer.util.CsvFile; +import net.sf.jailer.util.Pair; + +/** + * SQL Console. + * + * @author Ralf Wisser + */ +@SuppressWarnings("serial") +public abstract class SQLConsole extends javax.swing.JPanel { + + /** + * The logger. + */ + private static final Logger logger = Logger.getLogger(MetaDataDetailsPanel.class); + + private static final int MAX_TAB_COUNT = 8; + private static final int MAX_HISTORY_SIZE = 100; + + private Session session; + MetaDataSource metaDataSource; + private RSyntaxTextAreaWithSQLSyntaxStyle editorPane; + private final MetaDataBasedSQLCompletionProvider provider; + private final BlockingQueue queue = new LinkedBlockingQueue(); + private final Reference datamodel; + private final ExecutionContext executionContext; + private final List history = new ArrayList(); + private final AtomicBoolean running = new AtomicBoolean(false); + private final AtomicBoolean updatingStatus = new AtomicBoolean(false); + private final ImageIcon scaledCancelIcon; + private final ImageIcon scaledExplainIcon; + private final SQLPlusSupport sqlPlusSupport = new SQLPlusSupport(); + private File file; + private JMenuItem menuItemToggle; + private JMenuItem menuItemToSingleLine; + private JMenuItem menuItemSubstituteVariables; + private JMenuItem menuItemAnalyse; + private int initialTabbedPaneSelection = 0; + private List initialSortKeys = null; + private String initialSortKeysSql = null; + private int initialTabbedPaneSelectionLoc = -1; + + private final String IGNORED_STATEMENTS = "(\\s*/\\s*)"; + + /** + * Stops the consumer thread. + */ + private final Runnable STOP = new Runnable() { + @Override + public void run() { + // nothing to do + } + }; + + /** + * Creates new form SQLConsole + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public SQLConsole(Session session, MetaDataSource metaDataSource, Reference datamodel, ExecutionContext executionContext) throws SQLException { + this.session = session; + this.metaDataSource = metaDataSource; + this.datamodel = datamodel; + this.executionContext = executionContext; + initComponents(); + initMenuItems(); + historyComboBox.setMaximumRowCount(25); + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 16); + jPanel5.add(historyComboBox, gridBagConstraints); + + this.editorPane = new RSyntaxTextAreaWithSQLSyntaxStyle(true, true) { + { + setBracketMatchingEnabled(true); + } + @Override + protected boolean canExplain() { + return SQLConsole.this.canExplain(); + } + @Override + protected void runBlock() { + executeSelectedStatements(false, null, true); + } + @Override + protected void explainBlock() { + executeSelectedStatements(true, null, true); + } + @Override + protected void runAll() { + executeAllStatements(); + } + @Override + public void updateMenuItemState() { + updateMenuItemState(!running.get(), !running.get()); + } + @Override + protected void selectTable(MDTable mdTable) { + SQLConsole.this.selectTable(mdTable); + } + @Override + protected void updateMenuItems(boolean isTextSelected) { + SQLConsole.this.updateMenuItems(isTextSelected); + } + @Override + protected MDTable getSelectedTable() { + Document doc = getDocument(); + + int dot = getCaretPosition(); + int start = getLineStartOffsetOfCurrentLine(); + int lineEndOffsetOfCurrentLine = getLineEndOffsetOfCurrentLine(); + int len = lineEndOffsetOfCurrentLine - start; + Segment seg = new Segment(); + try { + doc.getText(start, len, seg); + } catch (BadLocationException ble) { + logger.info("error", ble); + return null; + } + + start = dot - getLineStartOffsetOfCurrentLine(); + String segment = seg.toString(); + char ch = start < segment.length()? segment.charAt(start) : ' '; + while (start list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (index == 0) { + value = null; + } + Object shortValue = value; + if (value instanceof String) { + shortValue = shortSQL((String) value, 120); + } + Component c = super.getListCellRendererComponent(list, shortValue, index, isSelected, cellHasFocus); + if (c instanceof JLabel) { + if (value instanceof String && value.toString().length() > 0) { + ((JLabel) c).setToolTipText(UIUtil.toHTML(value.toString(), 100)); + } else { + ((JLabel) c).setToolTipText(null); + } + } + return c; + } + }); + restoreHistory(); + + provider = new MetaDataBasedSQLCompletionProvider(session, metaDataSource) { + @Override + protected String prepareStatementForAliasAnalysis(String statement) { + return sqlPlusSupport.replaceVariables(statement, null); + } + }; + new SQLAutoCompletion(provider, editorPane); + + RTextScrollPane jScrollPane = new RTextScrollPane(); + jScrollPane.setViewportView(editorPane); + editorPane.setGutter(jScrollPane.getGutter()); + consoleContainerPanel.add(jScrollPane); + jScrollPane.setLineNumbersEnabled(true); + jScrollPane.setIconRowHeaderEnabled(true); + + runSQLButton.setAction(editorPane.runBlock); + runnAllButton.setAction(editorPane.runAll); + explainButton.setAction(editorPane.explain); + + runSQLButton.setText("Run"); + runnAllButton.setText("Run all"); + + runSQLButton.setIcon(UIUtil.scaleIcon(this, runIcon)); + runnAllButton.setIcon(UIUtil.scaleIcon(this, runAllIcon)); + runSQLButton.setToolTipText(runSQLButton.getText() + " - Ctrl-Enter"); + runnAllButton.setToolTipText(runnAllButton.getText() + " - Alt-Enter"); + + scaledCancelIcon = UIUtil.scaleIcon(this, cancelIcon); + cancelButton.setIcon(scaledCancelIcon); + + scaledExplainIcon = UIUtil.scaleIcon(this, explainIcon); + explainButton.setIcon(scaledExplainIcon); + + limitComboBox.setModel(new DefaultComboBoxModel(DataBrowser.ROW_LIMITS)); + limitComboBox.setSelectedItem(1000); + + resetStatus(); + statusLabel.setVisible(true); + + editorPane.addCaretListener(new CaretListener() { + @Override + public void caretUpdate(CaretEvent e) { + updateOutline(false); + } + }); + + initialContentSize = editorPane.getDocument().getLength(); + initialContentHash = editorPane.getText().hashCode(); + editorPane.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void removeUpdate(DocumentEvent e) { + checkDirty(); + } + @Override + public void insertUpdate(DocumentEvent e) { + checkDirty(); + } + @Override + public void changedUpdate(DocumentEvent e) { + checkDirty(); + } + }); + + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + Runnable action = null; + do { + try { + action = queue.take(); + action.run(); + } catch (Throwable t) { + logger.info("error", t); + } + } while (action != STOP); + } + }, "SQLConsole-" + (threadNum++)); + thread.setDaemon(true); + thread.start(); + } + + protected void initMenuItems() { + JMenuItem item = new JMenuItem("Toggle Line Continuation"); + item.setEnabled(false); + menuItemToggle = item; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toggleLineContinuation(); + } + }); + item.setToolTipText( + "Adds (or remove) line-continuation-character ('\\')
" + + " to each line terminated by ';'
" + + "(allowing you to execute PL/SQL code)"); + + item = new JMenuItem("To Single Line"); + item.setEnabled(false); + menuItemToSingleLine = item; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toSingleLine(); + } + }); + + item = new JMenuItem("Substitute Variables"); + item.setEnabled(false); + menuItemSubstituteVariables = item; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + substituteVariables(); + } + }); + item.setToolTipText( + "Substitutes variables (&VAR[.]) with corresponding values.

\n" + + "Statements:\n" + + "
\n" + + "\n" + + "\n" + + "\n" + + "
 DEFINE VAR=\"VALUE\"   Assigns a value to variable VAR
 DEFINELists all variables
 &VAR  or   &VAR.Variable substitution (inside other statements)
"); + item = new JMenuItem("Analyze SQL"); + item.setEnabled(false); + menuItemAnalyse = item; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + analyzeSQL(); + } + }); + item.setToolTipText("Analyzes selected SQL and proposes association definitions."); + } + + private void updateMenuItems(boolean isTextSelected) { + if (menuItemToggle != null) { + menuItemToggle.setEnabled(isTextSelected); + } + if (menuItemToSingleLine != null) { + menuItemToSingleLine.setEnabled(isTextSelected); + } + if (menuItemSubstituteVariables != null) { + menuItemSubstituteVariables.setEnabled(isTextSelected); + } + if (menuItemAnalyse != null) { + menuItemAnalyse.setEnabled(isTextSelected); + } + } + + private static int threadNum = 1; + + private boolean canExplain() { + return metaDataSource.getSession().dbms.getExplainQuery() != null && !metaDataSource.getSession().dbms.getExplainQuery().isEmpty(); + } + + private AtomicBoolean pending = new AtomicBoolean(false); + private AtomicBoolean stopped = new AtomicBoolean(false); + private String prevSql = null; + private int prevCaretPos; + + /** + * Update of outline of statement under caret and history after switching from another console to this. + */ + public void update() { + updateOutline(false); + restoreHistory(); + } + + /** + * Update of outline of statement under caret. + */ + private void updateOutline(boolean checkPrevSql) { + if (!pending.get()) { + Pair loc = editorPane.getCurrentStatementLocation(true, true, null, false); + String sql = editorPane.getText(loc.a, loc.b, true); + if (sql.trim().isEmpty()) { + loc = editorPane.getCurrentStatementLocation(true, true, null, true); + sql = editorPane.getText(loc.a, loc.b, true); + } + if (checkPrevSql && sql.equals(prevSql) && editorPane.getCaretPosition() == prevCaretPos) { + return; + } + prevSql = sql; + prevCaretPos = editorPane.getCaretPosition(); + + try { + updateOutline(sql, editorPane.getLineStartOffset(loc.a)); + } catch (Exception e1) { + logger.info("error", e1); + return; + } + + if (sql.length() > 20000) { + stopped.set(false); + pending.set(true); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + pending.set(false); + if (!stopped.get()) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + updateOutline(true); + } + }); + } + } + }).start(); + } else { + stopped.set(true); + } + } + } + + protected String shortSQL(String sql, int maxLength) { + sql = sql.trim().replaceAll("\\s+", " "); + if (sql.length() > maxLength) { + sql = sql.replaceFirst("^(?is)(\\bselect\\b).........*?(\\bfrom\\b)(.*)$", "$1 ... $2$3"); + } + if (sql.length() > maxLength) { + sql = sql.substring(0, maxLength) + "..."; + } + return sql; + } + + private void resetStatus() { + statusLabel.setVisible(false); + cancelButton.setEnabled(false); + } + + /** + * Executes a block of SQL statements (each statement separated by a ';' at the end of the line). + * + * @param sqlBlock the sql block + * @param location location of the block in the console + * @param emptyLineSeparatesStatements + * @param locFragmentOffset location of statement fragment, if any + * @param explain + * @param tabContentPanel the panel to show result (option) + */ + protected void executeSQLBlock(final String sqlBlock, final Pair location, final boolean emptyLineSeparatesStatements, final Pair locFragmentOffset, final boolean explain, final TabContentPanel tabContentPanel) { + if (!running.get()) { + int lineStartOffset = -1; + try { + if (location != null) { + lineStartOffset = editorPane.getLineStartOffset(location.a); + } + } catch (BadLocationException e) { + lineStartOffset = -1; + } + disableLastErrorTab(); + final Pair caretDotMark = new Pair(editorPane.getCaret().getDot(), editorPane.getCaret().getMark()); + final int finalLineStartOffset = lineStartOffset; + queue.add(new Runnable() { + @Override + public void run() { + running.set(true); + updatingStatus.set(false); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + editorPane.updateMenuItemState(); + } + }); + Status status = new Status(); + status.location = location; + status.linesExecuted = 0; + status.linesExecuting = 0; + status.running = true; + int lineStartOffset = finalLineStartOffset; + try { + Pattern pattern; + if (emptyLineSeparatesStatements) { + pattern = Pattern.compile("(?:(;\\s*(\\n\\r?|$))|(\\n\\r?([ \\t\\r]*\\n\\r?)+))", Pattern.DOTALL); + } else { + pattern = Pattern.compile("(?:(;\\s*(\\n\\r?|$)))", Pattern.DOTALL); + } + + Matcher matcher = pattern.matcher(sqlBlock); + boolean result = matcher.find(); + StringBuffer sb = new StringBuffer(); + if (result || locFragmentOffset != null) { + do { + String sql; + String pureSql; + if (locFragmentOffset != null) { + sql = sqlBlock; + pureSql = sqlBlock; + } else { + sb.setLength(0); + matcher.appendReplacement(sb, ""); + pureSql = sb.toString(); + sb.append(matcher.group()); + sql = sb.toString(); + } + status.linesExecuting += countLines(pureSql); + if (sql.trim().length() > 0) { + executeSQL(pureSql, status, lineStartOffset, explain, tabContentPanel, caretDotMark); + if (status.failed) { + if (locFragmentOffset != null) { + if (status.errorPositionIsKnown) { + try { + status.errorPosition += locFragmentOffset.a - editorPane.getLineStartOffset(editorPane.getLineOfOffset(locFragmentOffset.a)); + } catch (BadLocationException e) { + logger.info("error", e); + } + } + } + break; + } + } + if (lineStartOffset >= 0) { + lineStartOffset += sql.length(); + } + status.linesExecuted += countLines(sql) - 1; + if (locFragmentOffset != null) { + pattern = Pattern.compile("(\\n\\s*)$", Pattern.DOTALL); + matcher = pattern.matcher(sql); + if (!matcher.find()) { + status.linesExecuted++; + } + break; + } + String terminator = matcher.group(1); + if (terminator != null && !terminator.contains("\n")) { // ';' without nl + status.linesExecuted++; + } + status.linesExecuting = status.linesExecuted; + result = matcher.find(); + } while (result); + } + if (!status.failed && locFragmentOffset == null) { + sb.setLength(0); + matcher.appendTail(sb); + String sbToString = sb.toString(); + String sql = sbToString; + if (sql.trim().length() > 0) { + status.linesExecuting += countLines(sql); + executeSQL(sql, status, lineStartOffset, explain, tabContentPanel, caretDotMark); + if (!status.failed) { + status.linesExecuted = status.linesExecuting; + } + } + } + if (status.numStatements <= 7) { + storeHistory(); + } else { + restoreHistory(); + } + } finally { + status.running = false; + running.set(false); + status.updateView(true); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + editorPane.updateMenuItemState(true, false); + } + }); + } + } + + private int countLines(String line) { + int lines = 1; + for (int i = 0; i < line.length(); ++i) { + if (line.charAt(i) == '\n') { + ++lines; + } + } + return lines; + } + }); + } + } + + /** + * Executes a single SQL statment. + * + * @param sql the statement + * @param status the status to update + * @param statementStartOffset + * @param explain + * @param origTabContentPanel the panel to show result (option) + */ + private void executeSQL(final String sql, final Status status, int statementStartOffset, final boolean explain, final TabContentPanel origTabContentPanel, final Pair caretDotMark) { + Statement statement = null; + ResultSet resultSet = null; + final Status localStatus = new Status(); + String sqlStatement = null; + String stmtId = null; + TreeMap positionOffsets = new TreeMap(); + Connection resetAutoCommitConnection = null; + try { + Connection connection = session.getConnection(); + if (!explain && session.dbms.equals(DBMS.POSTGRESQL)) { + if (connection.getAutoCommit()) { + connection.setAutoCommit(false); + resetAutoCommitConnection = connection; + } + } + status.numStatements++; + localStatus.numStatements++; + UISettings.s3++; + status.updateView(false); + statement = connection.createStatement(); + if (session.dbms != null) { + if (session.dbms.getFetchSize() != null) { + statement.setFetchSize(session.dbms.getFetchSize()); + } + } + CancellationHandler.reset(SQLConsole.this); + CancellationHandler.begin(statement, SQLConsole.this); + long startTime = System.currentTimeMillis(); + sqlStatement = + sql + .replaceFirst("(?is)(;\\s*)+$", "") + .replaceAll("((?:(?:;(?: |\\t|\\r)*?(?:--[^\\n]*)?))) ?\\\\([ \\t\\r]*\\n)", "$1$2") + .replaceAll("((?:\\n(?: |\\t|\\r)*?)) ?\\\\([ \\t\\r]*)(?=\\n)", "$1"); + sqlStatement = sqlPlusSupport.replaceVariables(sqlStatement, positionOffsets); + status.statement = sqlStatement; + boolean loadButtonIsVisible = true; + boolean hasResultSet; + boolean hasUpdateCount = true; + ResultSet sqlPlusResultSet = null; + if (explain) { + if (session.dbms.getExplainCreateExplainTable() != null) { + Statement createStatement = connection.createStatement(); + try { + createStatement.execute(session.dbms.getExplainCreateExplainTable()); + } catch (Exception e) { + // ignore + } finally { + try { + createStatement.close(); + } catch (Exception e) { + // ignore + } + } + } + synchronized (this) { + stmtId = "Jailer" + (nextPlanID++ % 8); + } + if (session.dbms.getExplainPrepare() != null && !session.dbms.getExplainPrepare().isEmpty()) { + statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainPrepare(), sqlStatement, stmtId)); + statement.close(); + } + statement = connection.createStatement(); + hasResultSet = statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainQuery(), sqlStatement, stmtId)); + } else { + sqlPlusResultSet = sqlPlusSupport.executeSQLPLusQuery(sqlStatement); + if (sqlPlusResultSet != null) { + hasResultSet = true; + loadButtonIsVisible = false; + } else if (sqlPlusSupport.executeSQLPLusStatement(sqlStatement)) { + hasUpdateCount = false; + hasResultSet = false; + } else if (sqlStatement.matches(IGNORED_STATEMENTS)) { + hasUpdateCount = false; + hasResultSet = false; + } else { + hasResultSet = executeStatementWithLimit(statement, sqlStatement, session); + } + } + if (hasResultSet) { + resultSet = sqlPlusResultSet != null? sqlPlusResultSet : statement.getResultSet(); + ResultSetMetaData metaData = resultSet.getMetaData(); + final String columnLabels[] = new String[metaData.getColumnCount()]; + for (int i = 0; i < metaData.getColumnCount(); ++i) { + columnLabels[i] = metaData.getColumnLabel(i + 1); + } + ResultSet theMetaDataResultSet = null; + String resultSetType = null; + try { + resultSetType = TabContentPanel.toType(metaData, session, executionContext); + theMetaDataResultSet = TabContentPanel.toMetaDataResultSet(metaData, session, executionContext); + } catch (Throwable e1) { + logger.info("error", e1); + } + final ResultSet metaDataResultSet = theMetaDataResultSet; + final String finalResultSetType = resultSetType; + final Integer limit = (Integer) limitComboBox.getSelectedItem(); + List nfResultTypes = explain || sqlPlusResultSet != null? null : QueryTypeAnalyser.getType(sqlStatement, metaDataSource); + Table resultType = null; + if (nfResultTypes != null && !nfResultTypes.isEmpty()) { + if (nfResultTypes.size() == 1) { + resultType = nfResultTypes.get(0); + } + int columnCount = metaData.getColumnCount(); + for (Table table: nfResultTypes) { + while (table.getColumns().size() < columnCount) { + table.getColumns().add(new net.sf.jailer.datamodel.Column(null, "", 0, -1)); + } + } + } + if (resultType != null) { + if (resultType.getColumns().size() > metaData.getColumnCount()) { + // stale meta data + resultType = null; + nfResultTypes = null; + } + } + final List
resultTypes = nfResultTypes; + final MemorizedResultSet metaDataDetails = new MemorizedResultSet(resultSet, limit, session, SQLConsole.this) { + @Override + protected Object convertCellContent(Object object) { + Object lobRender = BrowserContentPane.toLobRender(object); + if (lobRender != null) { + return lobRender; + } + return object; + } + + @Override + protected void prepareHook(ResultSetMetaData rmd) throws SQLException { + sqlPlusSupport.prepareColumnSubstitution(rmd); + } + + @Override + protected void readRowHook(ResultSet resultSet) throws SQLException { + try { + sqlPlusSupport.substituteColumns(resultSet); + } catch (SQLException e) { + // ignore + } + } + }; + resultSet.close(); + long now = System.currentTimeMillis(); + status.hasSelected = true; + status.timeInMS += (now - startTime); + localStatus.timeInMS += (now - startTime); + status.numRowsRead += metaDataDetails.getSize(); + localStatus.numRowsRead += metaDataDetails.getSize(); + localStatus.hasSelected = true; + if (metaDataDetails.getSize() > limit) { + status.limitExceeded = true; + localStatus.limitExceeded = true; + } + status.updateView(false); + status.statement = sqlStatement; + final String finalSqlStatement = sqlStatement; + final Table finalResultType = resultType; + final boolean finalLoadButtonIsVisible = loadButtonIsVisible; + + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + final BrowserContentPane rb = new ResultContentPane(datamodel.get(), finalResultType, "", session, null, + null, null, new RowsClosure(), false, false, executionContext); + if (resultTypes != null && resultTypes.size() > 1) { + rb.setResultSetType(resultTypes); + } + rb.setAlternativeColumnLabels(columnLabels); + rb.setTableFilterEnabled(metaDataDetails.getSize() > 1 && metaDataDetails.getSize() <= limit); + rb.setStatementForReloading(finalSqlStatement); + metaDataDetails.reset(); + LoadJob loadJob = rb.newLoadJob(metaDataDetails, limit); + loadJob.run(); + JComponent rTabContainer = rb.getRowsTableContainer(); + metaDataDetails.reset(); + JComponent metaDataRenderer = null; + try { + metaDataRenderer = new ResultSetRenderer(metaDataResultSet, null, datamodel.get(), session, executionContext); + } catch (Throwable e1) { + logger.info("error", e1); + } + final TabContentPanel tabContentPanel = + new TabContentPanel(rb.rowsCount, + metaDataRenderer, + finalResultSetType, + explain, + origTabContentPanel == null? null : origTabContentPanel.shimPanel, + caretDotMark); + tabContentPanel.contentPanel.add(rTabContainer); + + rb.setCurrentRowsTable(new Reference() { + public JTable get() { + return tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel? columnsTable : rb.rowsTable; + } + }); + + rb.sortColumnsCheckBox.setVisible(true); + rb.sortColumnsPanel.setVisible(false); + rb.findColumnsPanel.setVisible(true); + rb.sortColumnsCheckBox.setText(rb.sortColumnsCheckBox.getText().trim()); + tabContentPanel.controlsPanel1.add(rb.sortColumnsCheckBox); + tabContentPanel.controlsPanel1.add(rb.findColumnsPanel); + rb.sortColumnsCheckBox.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + updateColumnsAndTextView(rb, tabContentPanel); + } + }); + } + }); + final JButton loadButton = new JButton(rb.loadButton.getText(), rb.loadButton.getIcon()); + tabContentPanel.loadButton = loadButton; + loadButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tabContentPanel.loadingPanel.setVisible(true); + tabContentPanel.repaint(); + loadButton.setEnabled(false); + initialSortKeysSql = sql; + try { + initialSortKeys = rb.rowsTable.getRowSorter().getSortKeys(); + } catch (Exception e2) { + initialSortKeys = null; + } + reload(tabContentPanel, sql); + } + }); + tabContentPanel.cancelLoadButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CancellationHandler.cancel(SQLConsole.this); + tabContentPanel.loadingPanel.setVisible(false); + tabContentPanel.repaint(); + loadButton.setEnabled(true); + } + }); + tabContentPanel.controlsPanel1.add(loadButton); + loadButton.setVisible(finalLoadButtonIsVisible); + loadButton.setIcon(UIUtil.scaleIcon(SQLConsole.this, runIcon)); + rb.setOnReloadAction(new Runnable() { + @Override + public void run() { + updateColumnsAndTextView(rb, tabContentPanel); + } + }); + String sqlE = sql.trim(); + if (explain) { + sqlE = "Explain Plan for " + sqlE; + } + String stmt = sqlE; + + tabContentPanel.statementLabel.setToolTipText(UIUtil.toHTML(sqlE, 100)); + if (stmt.length() > 200) { + stmt = stmt.substring(0, 200) + "..."; + } + tabContentPanel.statementLabel.setText(stmt.replaceAll("\\s+", " ")); + rTabContainer = tabContentPanel.shimPanel; + final int MAXLENGTH = 30; + String title = shortSQL(sqlE, MAXLENGTH); + final int loc = status != null && status.location != null? status.location.a : -1; + if (initialTabbedPaneSelection >= 0 && initialTabbedPaneSelectionLoc == loc) { + if (initialTabbedPaneSelection < tabContentPanel.tabbedPane.getTabCount()) { + tabContentPanel.tabbedPane.setSelectedIndex(initialTabbedPaneSelection); + } + } + try { + if (initialSortKeys != null && initialSortKeysSql != null && initialSortKeysSql.equals(sql)) { + rb.getRowsTable().getRowSorter().setSortKeys(initialSortKeys); + } + } catch (Exception e) { + // ignore + } + tabContentPanel.tabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + initialTabbedPaneSelection = tabContentPanel.tabbedPane.getSelectedIndex(); + initialTabbedPaneSelectionLoc = loc; + updateColumnsAndTextView(rb, tabContentPanel); + if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel) { + columnsTable.scrollToCurrentRow(); + } + } + }); + removeLastErrorTab(); + + if (origTabContentPanel == null) { + jTabbedPane1.add(rTabContainer); + jTabbedPane1.setTabComponentAt(jTabbedPane1.indexOfComponent(rTabContainer), getTitlePanel(jTabbedPane1, rTabContainer, title)); + + if (jTabbedPane1.getTabCount() > MAX_TAB_COUNT) { + jTabbedPane1.remove(0); + } + jTabbedPane1.setSelectedIndex(jTabbedPane1.getTabCount() - 1); + } + rb.resetRowsTableContainer(); + jTabbedPane1.repaint(); + } + + private ColumnsTable columnsTable; + + public void updateColumnsAndTextView(final BrowserContentPane rb, + final TabContentPanel tabContentPanel) { + String tableSortAndFilterState = ""; + RowSorter sorter = rb.rowsTable.getRowSorter(); + if (sorter.getModelRowCount() > sorter.getViewRowCount()) { + tableSortAndFilterState = "Filtered"; + } + List skeys = sorter.getSortKeys(); + if (!skeys.isEmpty()) { + for (int i = 0; i < rb.rowsTable.getColumnCount(); ++i) { + if (rb.rowsTable.getColumnModel().getColumn(i).getModelIndex() == skeys.get(0).getColumn()) { + tableSortAndFilterState = tableSortAndFilterState + (tableSortAndFilterState.isEmpty()? "Sorted" : " and sorted") + + " by \"" + rb.rowsTable.getColumnName(i) + "\""; + break; + } + } + } + if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.columnsPanel || tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.contentPanel) { + Point vp = null; + if (columnsTable != null) { + if (tabContentPanel.columnsScrollPane.getViewport() != null) { + vp = tabContentPanel.columnsScrollPane.getViewport().getViewPosition(); + } + } + columnsTable = new ColumnsTable(rb); + tabContentPanel.columnsScrollPane.setViewportView(columnsTable); + new FixedColumnTable(1, tabContentPanel.columnsScrollPane); + if (vp != null) { + if (tabContentPanel.columnsScrollPane.getViewport() != null) { + tabContentPanel.columnsScrollPane.getViewport().setViewPosition(vp); + } + } + tabContentPanel.columnsSortedStateLabel.setText(" " + tableSortAndFilterState); + tabContentPanel.columnsSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty()); + } + if (tabContentPanel.tabbedPane.getSelectedComponent() == tabContentPanel.textTabPanel) { + tabContentPanel.updateTextView(rb.rowsTable); + tabContentPanel.textSortedStateLabel.setText(" " + tableSortAndFilterState); + tabContentPanel.textSortedStateLabel.setVisible(!tableSortAndFilterState.isEmpty()); + } + } + }); + } else { + status.timeInMS += (System.currentTimeMillis() - startTime); + int updateCount = !hasUpdateCount? 0 : statement.getUpdateCount(); + if (updateCount >= 0) { + status.numRowsUpdated += updateCount; + } + status.updateView(false); + status.hasUpdated = true; + if (updateCount != 0) { + setDataHasChanged(true); + } + if (isDDLStatement(sql)) { + status.withDDL = true; + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + removeLastErrorTab(); + if (origTabContentPanel != null) { + origTabContentPanel.loadingPanel.setVisible(false); + origTabContentPanel.repaint(); + if (origTabContentPanel.loadButton != null) { + origTabContentPanel.loadButton.setEnabled(true); + } + } + } + }); + } + CancellationHandler.end(statement, SQLConsole.this); + statement.close(); + if (!explain) { + appendHistory(sql); + } + } catch (Throwable error) { + try { + CancellationHandler.checkForCancellation(SQLConsole.this); + } catch (CancellationException e) { + error = e; + } + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + } + } + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + } + } + if (!isCommentOnly(sqlStatement)) { + if (error instanceof SQLException && sqlStatement != null && statementStartOffset >= 0) { + int pos = retrieveErrorPos(sqlStatement, error.getMessage()); + if (pos >= 0) { + Entry floor = positionOffsets.floorEntry(pos); + int positionOffset; + if (floor == null) { + positionOffset = 0; + } else { + positionOffset = floor.getValue(); + } + status.errorPosition = statementStartOffset + pos + positionOffset; + status.origErrorPosition = pos; + status.errorPositionIsKnown = true; + } else { + status.errorPosition = statementStartOffset; + status.errorPositionIsKnown = false; + } + } + status.failed = true; + status.error = error; + } + if (error instanceof CancellationException) { + CancellationHandler.reset(SQLConsole.this); + queue.clear(); + } + status.updateView(false); + final Throwable finalError = error; + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + if (origTabContentPanel != null) { + origTabContentPanel.loadingPanel.setVisible(false); + origTabContentPanel.repaint(); + if (origTabContentPanel.loadButton != null) { + origTabContentPanel.loadButton.setEnabled(true); + } + } + if (!(finalError instanceof SQLException || finalError instanceof CancellationException)) { + UIUtil.showException(SQLConsole.this, "Error", finalError); + } + } + }); + } finally { + if (explain && session.dbms.getExplainCleanup() != null && !session.dbms.getExplainCleanup().isEmpty()) { + if (session.dbms.getExplainPrepare() != null) { + try { + statement = session.getConnection().createStatement(); + statement.execute(String.format(Locale.ENGLISH, session.dbms.getExplainCleanup(), sqlStatement, stmtId)); + statement.close(); + } catch (SQLException e) { + logger.info("error", e); + } + } + } + if (resetAutoCommitConnection != null) { + try { + resetAutoCommitConnection.setAutoCommit(true); + } catch (SQLException e) { + // ignore + } + } + } + } + + private boolean executeStatementWithLimit(Statement statement, String sqlStatement, Session session) throws SQLException { + try { + int limit = 1 + (Integer) limitComboBox.getSelectedItem(); + if (limit > 0) { + statement.setMaxRows(limit + 1); + } + } catch (Exception e) { + // ignore + } + return statement.execute(sqlStatement); + } + + public void setCaretPosition(int position) { + if (editorPane.getDocument().getLength() >= position) { + try { + int l = editorPane.getLineOfOffset(position); + editorPane.setCaretPosition(position); + int lineHeight = editorPane.getLineHeight(); + editorPane.scrollRectToVisible(new Rectangle(0, Math.max(0, l - 2) * lineHeight, 1, 4 * lineHeight)); + } catch (Exception e) { + // ignore + } + editorPane.setCaretPosition(position); + grabFocus(); + } + } + + private void updateOutline(String sql, int startPosition) { + sql = sql.replaceFirst(";\\s*$", ""); + final int MAX_CONTEXT_LENGTH = 80; + final int MAX_TOOLTIP_LENGTH = 100; + List outlineInfos = new ArrayList(); + TreeMap offsets = new TreeMap(); + sql = sqlPlusSupport.replaceVariables(sql, offsets); + provider.findAliases(SQLCompletionProvider.removeCommentsAndLiterals(sql), null, outlineInfos); + adjustLevels(outlineInfos); + List relocatedOutlineInfos = new ArrayList(); + int indexOfInfoAtCaret = -1; + int caretPos = editorPane.getCaretPosition(); + OutlineInfo predInfo = null; + for (int i = 0; i < outlineInfos.size(); ++i) { + OutlineInfo info = outlineInfos.get(i); + Entry floor = offsets.floorEntry(info.position); + if (floor != null) { + info.origPosition = info.position + floor.getValue(); + } + } + for (int i = 0; i < outlineInfos.size(); ++i) { + OutlineInfo info = outlineInfos.get(i); + if (info.isBegin || info.isEnd) { + continue; + } + int pos = info.position; + if (pos + startPosition <= caretPos || indexOfInfoAtCaret < 0) { + indexOfInfoAtCaret = relocatedOutlineInfos.size(); + } + OutlineInfo rlInfo = new OutlineInfo(info.mdTable, info.alias, info.level, pos + startPosition, info.scopeDescriptor); + rlInfo.isCTE = info.isCTE; + rlInfo.rowCount = info.rowCount; + if (info.withContext) { + int cStart = info.contextPosition; + int cEnd = sql.length(); + int ttEnd = sql.length(); + if (i < outlineInfos.size() - 1) { + cEnd = Math.min(cEnd, outlineInfos.get(i + 1).position); + ttEnd = Math.min(ttEnd, outlineInfos.get(i + 1).position); + } + if (info.contextEnd > 0) { + cEnd = Math.min(cEnd, info.contextEnd); + ttEnd = Math.min(ttEnd, info.contextEnd); + } + if (cStart < cEnd) { + String context = UIUtil.removesuperfluousSpaces(sql.substring(cStart, cEnd).trim().replaceAll("\\s+", " ")); + if (context.length() > MAX_CONTEXT_LENGTH) { + context = context.substring(0, MAX_CONTEXT_LENGTH) + "..."; + } + rlInfo.context = UIUtil.toHTML(context, 0); + rlInfo.tooltip = UIUtil.toHTML(sql.substring(info.position, ttEnd), MAX_TOOLTIP_LENGTH); + } + } + rlInfo.withSeparator = info.withSeparator || predInfo != null && predInfo.level + (predInfo.mdTable != null? 1 : 0) == info.level && i > 0 && outlineInfos.get(i - 1).isBegin; + relocatedOutlineInfos.add(rlInfo); + predInfo = info; + } + indexOfInfoAtCaret -= simplifyOutline(relocatedOutlineInfos, indexOfInfoAtCaret); + setOutlineTables(relocatedOutlineInfos, indexOfInfoAtCaret); + } + + private int simplifyOutline(List outlineInfos, int indexOfInfoAtCaret) { + // "From " + int caretOffset = 0; + List toRemove = new ArrayList(); + for (int i = 1; i < outlineInfos.size(); ++i) { + OutlineInfo info = outlineInfos.get(i); + OutlineInfo pred = outlineInfos.get(i - 1); + if (info.mdTable != null && "From".equalsIgnoreCase(pred.scopeDescriptor)) { + if (info.level == pred.level) { + OutlineInfo succ = null; + if (i + 1 < outlineInfos.size()) { + succ = outlineInfos.get(i + 1); + } + if (succ == null || (succ.level != info.level || succ.mdTable == null)) { + info.scopeDescriptor = pred.scopeDescriptor; + info.position = pred.position; + info.origPosition = pred.origPosition; + toRemove.add(pred); + if (i - 1 < indexOfInfoAtCaret) { + ++caretOffset; + } + } + } + } + } + outlineInfos.removeAll(toRemove); + return caretOffset; + } + + private void adjustLevels(List outlineInfos) { + if (outlineInfos.size() > 0) { + int lastLevel = outlineInfos.get(outlineInfos.size() - 1).level; + for (int level = lastLevel - 1; level >= 0; --level) { + OutlineInfo info = new OutlineInfo(null, null, level, 0, ""); + info.isEnd = true; + outlineInfos.add(info); + } + } + Map lastBegin = new HashMap(); + List> pairs = new ArrayList>(); + Map> pairsPerEnd = new HashMap>(); + for (int i = 0; i < outlineInfos.size(); ++i) { + OutlineInfo info = outlineInfos.get(i); + if (info.isBegin) { + lastBegin.put(info.level, i); + } else if (info.isEnd) { + if (lastBegin.containsKey(info.level)) { + Pair pair = new Pair(lastBegin.get(info.level), i); + pairs.add(pair); + pairsPerEnd.put(i, pair); + } + } + } + for (int i = pairs.size() - 1; i > 0; --i) { + Pair thePair = pairs.get(i); + boolean ok = false; + int findA = thePair.a + 1; + Pair pair = pairsPerEnd.get(thePair.b - 1);; + while (pair != null) { + if (findA == pair.a) { + ok = true; + break; + } + if (findA > pair.a) { + break; + } + Pair predPair = pairsPerEnd.get(pair.a - 1); + if (predPair != null && pair.a - 1 != predPair.b) { + break; + } + pair = predPair; + } + + if (ok) { + for (int j = thePair.a; j < thePair.b; ++j) { + outlineInfos.get(j).level--; + } + } + } + } + + private boolean isDDLStatement(String sql) { + return sql.trim().matches("^(?is)\\b(drop|create|alter|rename)\\b.*"); + } + + protected abstract void refreshMetaData(); + protected abstract void selectTable(MDTable mdTable); + protected abstract void setOutlineTables(List outlineTables, int indexOfInfoAtCaret); + protected abstract JFrame getOwner(); + protected abstract void openDataModelEditor(boolean merge); + + private boolean dataHasChanged = false; + + public synchronized void setDataHasChanged(boolean b) { + dataHasChanged = b; + } + + public synchronized boolean getDataHasChanged() { + return dataHasChanged; + } + + /** + * Resets the console. + * + * @param session + * new session + * @param metaDataSource + * new meta data source + */ + public void reset(Session session, MetaDataSource metaDataSource) throws SQLException { + this.session = session; + this.metaDataSource = metaDataSource; + provider.reset(session, metaDataSource); + editorPane.forceCaretEvent(); + } + + private class Status { + public int origErrorPosition; + public int errorPosition = -1; + public boolean errorPositionIsKnown = false; + protected int linesExecuting; + protected int linesExecuted; + public boolean withDDL; + boolean failed; + boolean running; + boolean limitExceeded; + int numRowsRead; + int numRowsUpdated; + int numStatements; + boolean hasSelected = false; + boolean hasUpdated = false; + long timeInMS; + Throwable error; + String statement; + Pair location; + + private synchronized void updateView(boolean force) { + if (force || !updatingStatus.get()) { + updatingStatus.set(true); + + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + try { + synchronized (Status.this) { + Font font = new JLabel("X").getFont(); + statusLabel.setFont(new Font(font.getName(), font.getStyle(), (font.getSize() * 14) / 10)); + statusLabel.setVisible(false); + cancelButton.setEnabled(false); + if (!failed) { + cancelButton.setEnabled(running); + statusLabel.setVisible(true); + statusLabel.setForeground(running? new Color(0, 100, 0) : Color.BLACK); + statusLabel.setText(getText()); + } else { + statusLabel.setVisible(true); + if (error instanceof CancellationException) { + statusLabel.setForeground(Color.RED); + statusLabel.setText("Cancelled"); + removeLastErrorTab(); + } else if (error instanceof SQLException) { + String pos = ""; + int errorLine = -1; + try { + errorLine = editorPane.getLineOfOffset(errorPosition); + if (errorPositionIsKnown) { + int col = errorPosition - editorPane.getLineStartOffset(errorLine) + 1; + pos = "Error at line " + (errorLine + 1) + ", column " + col + ": "; + } + setCaretPosition(errorPosition); + } catch (BadLocationException e) { + } + if (errorLine >= 0) { + editorPane.setLineTrackingIcon(errorLine, scaledCancelIcon); + } + showError(pos + error.getMessage(), statement, origErrorPosition); + } else { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + error.printStackTrace(pw); + String sStackTrace = sw.toString(); // stack trace as a string + showError(sStackTrace, statement, origErrorPosition); + } + } + } + Color failedColor = new Color(255, 200, 200); + Color okColor = new Color(210, 255, 210); + Color pendingColor = new Color(235, 235, 255); + Color runningColor = new Color(255, 249, 200); + if (location != null) { + editorPane.removeAllLineHighlights(); + editorPane.setHighlightCurrentLine(false); + try { + for (int i = location.a; i <= location.b; ++i) { + Color hl; + if (i < linesExecuted + location.a) { + hl = okColor; + } else if (i >= linesExecuting + location.a) { + hl = pendingColor; + } else { + if (failed) { + hl = failedColor; + } else if (running){ + hl = runningColor; + } else { + hl = pendingColor; + } + } + editorPane.addLineHighlight(i, hl); + } + } catch (BadLocationException e) { + } + } + + jPanel2.repaint(); + + if (withDDL && !running) { + withDDL = false; + refreshMetaData(); + } + } finally { + updatingStatus.set(false); + } + } + }); + } + } + + private String getText() { + String text = ""; + if (running) { + text = "Running... "; + if (numStatements <= 1 && numRowsRead == 0 && numRowsUpdated == 0) { + return text; + } + } + if (numStatements > 1) { + text += numStatements + " Statements. "; + } + if (hasSelected) { + text += (limitExceeded? numRowsRead - 1 : numRowsRead) + " rows read"; + if (limitExceeded) { + text += " (limit exceeded)"; + } + text += ". "; + } + if (hasUpdated) { + text += numRowsUpdated + " rows updated. "; + } + return text + "Elapsed time: " + (timeInMS / 1000.0) + " sec"; + } + } + + private void showError(String errorMessage, String statement, int errorPosition) { + statusLabel.setVisible(true); + statusLabel.setForeground(Color.RED); + statusLabel.setText("Error"); + + removeLastErrorTab(); + + JComponent rTabContainer = new ErrorPanel(errorMessage, statement, errorPosition); + jTabbedPane1.add(rTabContainer); + jTabbedPane1.setTabComponentAt(jTabbedPane1.indexOfComponent(rTabContainer), getTitlePanel(jTabbedPane1, rTabContainer, "Error")); + + if (jTabbedPane1.getTabCount() > MAX_TAB_COUNT) { + jTabbedPane1.remove(0); + } + jTabbedPane1.setSelectedIndex(jTabbedPane1.getTabCount() - 1); + jTabbedPane1.repaint(); + } + + private void removeLastErrorTab() { + if (jTabbedPane1.getTabCount() > 0) { + if (jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1) instanceof TitelPanel) { + if (((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer instanceof ErrorPanel) { + jTabbedPane1.removeTabAt(jTabbedPane1.getTabCount() - 1); + } + } + } + } + + private void disableLastErrorTab() { + if (jTabbedPane1.getTabCount() > 0) { + if (jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1) instanceof TitelPanel) { + if (((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer instanceof ErrorPanel) { + ((ErrorPanel)((TitelPanel) jTabbedPane1.getTabComponentAt(jTabbedPane1.getTabCount() - 1)).rTabContainer).doDisable(); + + } + } + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + jPanel1 = new javax.swing.JPanel(); + jSplitPane2 = new javax.swing.JSplitPane(); + jPanel2 = new javax.swing.JPanel(); + consoleContainerPanel = new javax.swing.JPanel(); + jPanel5 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + limitComboBox = new javax.swing.JComboBox(); + cancelButton = new javax.swing.JButton(); + runSQLButton = new javax.swing.JButton(); + runnAllButton = new javax.swing.JButton(); + explainButton = new javax.swing.JButton(); + jPanel6 = new javax.swing.JPanel(); + statusLabel = new javax.swing.JLabel(); + dummyLabel = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + jTabbedPane1 = new javax.swing.JTabbedPane(); + jLabel2 = new javax.swing.JLabel(); + + setLayout(new java.awt.GridBagLayout()); + + jPanel1.setLayout(new java.awt.GridBagLayout()); + + jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane2.setResizeWeight(0.6); + jSplitPane2.setContinuousLayout(true); + jSplitPane2.setOneTouchExpandable(true); + + jPanel2.setLayout(new java.awt.GridBagLayout()); + + consoleContainerPanel.setLayout(new java.awt.BorderLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel2.add(consoleContainerPanel, gridBagConstraints); + + jPanel5.setLayout(new java.awt.GridBagLayout()); + + jLabel1.setText("Row limit "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 13; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); + jPanel5.add(jLabel1, gridBagConstraints); + + limitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 14; + gridBagConstraints.gridy = 2; + jPanel5.add(limitComboBox, gridBagConstraints); + + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 12; + gridBagConstraints.gridy = 2; + jPanel5.add(cancelButton, gridBagConstraints); + + runSQLButton.setText("Run"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + jPanel5.add(runSQLButton, gridBagConstraints); + + runnAllButton.setText("Run all"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + jPanel5.add(runnAllButton, gridBagConstraints); + + explainButton.setText("Explain"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 8); + jPanel5.add(explainButton, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + gridBagConstraints.weightx = 1.0; + jPanel2.add(jPanel5, gridBagConstraints); + + jPanel6.setLayout(new java.awt.GridBagLayout()); + + statusLabel.setForeground(java.awt.Color.gray); + statusLabel.setText(" ctrl-space for code completion"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridheight = 20; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0); + jPanel6.add(statusLabel, gridBagConstraints); + + dummyLabel.setForeground(java.awt.Color.gray); + dummyLabel.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridheight = 20; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 0); + jPanel6.add(dummyLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + jPanel2.add(jPanel6, gridBagConstraints); + + jSplitPane2.setLeftComponent(jPanel2); + + jPanel3.setLayout(new java.awt.GridBagLayout()); + + jTabbedPane1.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel3.add(jTabbedPane1, gridBagConstraints); + + jLabel2.setText(" "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST; + jPanel3.add(jLabel2, gridBagConstraints); + + jSplitPane2.setRightComponent(jPanel3); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + jPanel1.add(jSplitPane2, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(jPanel1, gridBagConstraints); + }// //GEN-END:initComponents + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + statusLabel.setText("Canceling..."); + statusLabel.setForeground(Color.RED); + CancellationHandler.cancel(this); + cancelButton.setEnabled(false); + }//GEN-LAST:event_cancelButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cancelButton; + private javax.swing.JPanel consoleContainerPanel; + private javax.swing.JLabel dummyLabel; + private javax.swing.JButton explainButton; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JSplitPane jSplitPane2; + private javax.swing.JTabbedPane jTabbedPane1; + private javax.swing.JComboBox limitComboBox; + private javax.swing.JButton runSQLButton; + private javax.swing.JButton runnAllButton; + private javax.swing.JLabel statusLabel; + // End of variables declaration//GEN-END:variables + + class ResultContentPane extends BrowserContentPane { + public ResultContentPane(DataModel dataModel, Table table, String condition, Session session, + List parentRows, Association association, Frame parentFrame, + RowsClosure rowsClosure, Boolean selectDistinct, + boolean reload, ExecutionContext executionContext) { + super(dataModel, table, condition, session, parentRows, association, parentFrame, + rowsClosure, selectDistinct, reload, executionContext); + noSingleRowDetailsView = true; + rowsTableScrollPane.setWheelScrollingEnabled(true); + } + @Override + protected int getReloadLimit() { + return (Integer) limitComboBox.getSelectedItem(); + } + @Override + protected void unhide() { + } + @Override + protected void showInNewWindow() { + } + @Override + protected void reloadDataModel() throws Exception { + } + @Override + protected void openSchemaMappingDialog() { + } + @Override + protected void openSchemaAnalyzer() { + } + @Override + protected void onRedraw() { + jTabbedPane1.repaint(); + } + @Override + protected void onHide() { + } + @Override + protected void onContentChange(List rows, boolean reloadChildren) { + } + @Override + protected RowBrowser navigateTo(Association association, List pRows) { + return null; + } + @Override + protected List getTableBrowser() { + return null; + } + @Override + protected PriorityBlockingQueue getRunnableQueue() { + return Desktop.runnableQueue; + } + @Override + protected QueryBuilderDialog getQueryBuilderDialog() { + return null; + } + @Override + protected RowBrowser getParentBrowser() { + return null; + } + @Override + protected JFrame getOwner() { + Window owner = SwingUtilities.getWindowAncestor(SQLConsole.this); + if (owner instanceof JFrame) { + return (JFrame) owner; + } + return null; + } + @Override + protected double getLayoutFactor() { + return 0; + } + @Override + protected DbConnectionDialog getDbConnectionDialog() { + return null; + } + @Override + protected List getChildBrowsers() { + return new ArrayList(); + } + @Override + protected void findClosure(Row row, Set> closure, boolean forward, FindClosureContext findClosureContext) { + } + @Override + protected void findClosure(Row row) { + } + @Override + protected Relationship createQBRelations(boolean withParents) { + return null; + } + @Override + protected List createQBChildrenRelations(RowBrowser tabu, boolean all) { + return null; + } + @Override + protected void collectPositions(Map> positions) { + } + @Override + protected void close() { + } + @Override + protected void beforeReload() { + } + @Override + protected void appendLayout() { + } + @Override + protected void adjustClosure(BrowserContentPane tabu, BrowserContentPane thisOne) { + } + @Override + protected void addRowToRowLink(Row pRow, Row exRow) { + } + @Override + protected boolean renderRowAsPK(Row theRow) { + return false; + } + @Override + protected MetaDataSource getMetaDataSource() { + return null; + } + @Override + protected SQLConsole getSqlConsole(boolean switchToConsole) { + return SQLConsole.this; + } + @Override + protected void deselectChildrenIfNeededWithoutReload() { + } + }; + + private class TitelPanel extends JPanel { + public final JComponent rTabContainer; + + public TitelPanel(final JTabbedPane tabbedPane, final JComponent rTabContainer, String title) { + super(new FlowLayout(FlowLayout.LEFT, 0, 0)); + this.rTabContainer = rTabContainer; + setOpaque(false); + JLabel titleLbl = new JLabel(title); + titleLbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + add(titleLbl); + SmallButton closeButton = new SmallButton(closeIcon) { + @Override + protected void onClick() { + tabbedPane.remove(rTabContainer); + } + }; + add(closeButton); + } + } + + private JPanel getTitlePanel(final JTabbedPane tabbedPane, final JComponent rTabContainer, String title) { + return new TitelPanel(tabbedPane, rTabContainer, title); + } + + @Override + public void grabFocus() { + editorPane.grabFocus(); + } + + private Icon closeIcon; + { + // load images + closeIcon = UIUtil.readImage("/Close-16-1.png"); + } + + /** + * Appends a statement and eventually executes it. + * + * @param sql the statement + * @param execute execute the statement? + * @param useLineContinuation + * @param tabContentPanel + */ + public void appendStatement(String sql, boolean execute) { + appendStatement(sql, execute, null, false); + } + + /** + * Appends a statement and eventually executes it. + * + * @param sql the statement + * @param execute execute the statement? + * @param tabContentPanel the panel to show result (option) + */ + public void appendStatement(String sql, boolean execute, TabContentPanel tabContentPanel, boolean useLineContinuation) { + if (!findAndSetCaretPosition(sql, tabContentPanel)) { + String pre = ""; + int lineCount = editorPane.getLineCount(); + if (lineCount > 0 && editorPane.getDocument().getLength() > 0) { + pre = "\n"; + if (editorPane.getText(lineCount - 1, lineCount - 1, true).trim().length() > 0) { + pre += "\n"; + } + } + if (useLineContinuation) { + sql = addLineContinuation(sql); + } else { + sql = sql.replaceAll("\\n\\s*\\n", "\n").trim(); + } + if (!sql.endsWith(";") && !sql.endsWith(" \\")) { + sql += ";"; + } + editorPane.append(pre + sql.replace("\r", "") + "\n"); + setCaretPosition(editorPane.getDocument().getLength()); + } + if (!running.get()) { + resetStatus(); + } + if (execute) { + executeSelectedStatements(false, tabContentPanel, true); + } + } + + /** + * Searches a statement and sets caret position s.t. current statement equals the given one. + */ + private boolean findAndSetCaretPosition(String statement, TabContentPanel tabContentPanel) { + statement = statement.replaceFirst("(;\\s*)+$", "").trim(); + + if (tabContentPanel != null && tabContentPanel.caretDotMark.a != tabContentPanel.caretDotMark.b) { + try { + try { + editorPane.setCaretPosition(0); + } catch (Exception e) { + // ignore + } + editorPane.setCaretPosition(tabContentPanel.caretDotMark.a); + editorPane.moveCaretPosition(tabContentPanel.caretDotMark.b); + String existingStatement = executeSelectedStatements(false, tabContentPanel, false); + if (existingStatement.replaceFirst("(;\\s*)+$", "").trim().equals(statement)) { + return true; + } + } catch (/*IllegalArgument*/ Exception e) { + // ignore + } + } + + String[] statementLines = statement.split("\\s*\\n\\s*"); + int lineCount = editorPane.getLineCount(); + for (int lineNr = 0; lineNr < lineCount; ++lineNr) { + if (lineNr + statementLines.length <= lineCount) { + boolean found = true; + for (int i = 0; i < statementLines.length; ++i) { + String line = getLineContent(lineNr + i); + line = line.trim().replaceFirst("(;\\s*)+$", ""); + if (!line.equals(statementLines[i])) { + found = false; + break; + } + } + if (found) { + try { + editorPane.setCaretPosition(0); + } catch (Exception e) { + // ignore + } + try { + editorPane.setCaretPosition(editorPane.getLineStartOffset(lineNr)); + String existingStatement = executeSelectedStatements(false, tabContentPanel, false).replaceFirst("(;\\s*)+$", "").trim(); + if (existingStatement.equals(statement)) { + return true; + } + } catch (Exception e) { + return false; + } + } + } + } + + return false; + } + + private String getLineContent(int line) { + try { + Segment txt = new Segment(); + int sOff = editorPane.getLineStartOffset(line); + editorPane.getDocument().getText(sOff, editorPane.getLineEndOffset(line) - sOff, txt); + return txt.toString(); + } catch (BadLocationException e) { + return ""; + } + } + + private String executeSelectedStatements(boolean explain, TabContentPanel tabContentPanel, boolean execute) { + try { + String sql; + Pair loc = null; + Pair locFragmentOffset = null; + Pair, Pair> locFragment = editorPane.getCurrentStatementFragmentLocation(); + if (locFragment != null) { + loc = locFragment.a; + locFragmentOffset = locFragment.b; + sql = editorPane.getDocument().getText(locFragmentOffset.a, locFragmentOffset.b - locFragmentOffset.a); + if (loc.a < loc.b) { + Pattern pattern = Pattern.compile("(\\n\\s*)$", Pattern.DOTALL); + Matcher matcher = pattern.matcher(sql); + if (matcher.find()) { + loc = new Pair(loc.a, loc.b - 1); + } + } + } else { + loc = editorPane.getCurrentStatementLocation(null); + sql = editorPane.getText(loc.a, loc.b, true); + } + if (loc != null && execute) { + executeSQLBlock(sql, loc, editorPane.getCaret().getDot() == editorPane.getCaret().getMark(), locFragmentOffset, explain, tabContentPanel); + } + return sql; + } catch (BadLocationException e) { + e.printStackTrace(); + return ""; + } + } + + private void executeAllStatements() { + if (editorPane.getLineCount() > 0) { + int start = 0; + + try { + while (start < editorPane.getLineCount()) { + Segment txt = new Segment(); + int sOff = editorPane.getLineStartOffset(start); + editorPane.getDocument().getText(sOff, editorPane.getLineEndOffset(start) - sOff, txt); + String sLine = txt.toString().trim(); + if (sLine.length() > 0) { + break; + } + ++start; + } + } catch (BadLocationException e) { + // ignore + } + Pair loc = new Pair(start, editorPane.getLineCount() - 1); + executeSQLBlock(editorPane.getText(loc.a, loc.b, true), loc, false, null, false, null); + } + } + + private boolean isCommentOnly(String statement) { + if (statement == null) { + return false; + } + Pattern pattern = Pattern.compile("('([^']*'))|(/\\*.*?\\*/)|(\\-\\-.*?(\n|$))", Pattern.DOTALL); + Matcher matcher = pattern.matcher(statement); + boolean result = matcher.find(); + StringBuffer sb = new StringBuffer(); + if (result) { + do { + if (matcher.group(1) == null) { + matcher.appendReplacement(sb, ""); + } else { + matcher.appendReplacement(sb, "$0"); + } + result = matcher.find(); + } while (result); + } + matcher.appendTail(sb); + return sb.toString().trim().isEmpty(); + } + + private final String HISTORY_FILE = ".history"; + private final String LF = System.getProperty("line.separator", "\n"); + private final JComboBox historyComboBox = new JComboBox() { + @Override + public java.awt.Dimension getMinimumSize() { + Dimension s = super.getMinimumSize(); + return new Dimension(Math.min(80, s.width), s.height); + } + }; + + private synchronized void restoreHistory() { + try { + File file = Environment.newFile(HISTORY_FILE); + if (file.exists()) { + BufferedReader in = new BufferedReader(new FileReader(file)); + history.clear(); + String line; + while ((line = in.readLine()) != null) { + String[] lines = CsvFile.decodeLine(line.trim()); + if (lines.length > 0 && !lines[0].isEmpty()) { + history.add(lines[0]); + } + } + in.close(); + } + } catch (Exception e) { + logger.info("error", e); + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + historyComboBox.setModel(historyComboboxModel()); + } + }); + } + + private synchronized void storeHistory() { + try { + File file = Environment.newFile(HISTORY_FILE); + FileWriter out = new FileWriter(file); + for (String sql: history) { + out.write(CsvFile.encodeCell(sql) + LF); + } + out.close(); + } catch (Exception e) { + logger.info("error", e); + } + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + historyComboBox.setModel(historyComboboxModel()); + } + }); + } + + private final ItemListener historyCBItemListener = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED && e.getItem() != null && historyComboBox.getSelectedIndex() > 0) { + appendStatement(e.getItem().toString(), false, null, true); + historyComboBox.setSelectedIndex(0); + } + } + }; + + private DefaultComboBoxModel historyComboboxModel() { + ArrayList model = new ArrayList(history); + if (!model.isEmpty()) { + model.add(0, new String(model.get(0) + " ")); + } + historyComboBox.removeItemListener(historyCBItemListener); + DefaultComboBoxModel cbModel = new DefaultComboBoxModel(model.toArray()); + historyComboBox.addItemListener(historyCBItemListener); + return cbModel; + } + + private synchronized void appendHistory(String sql) { + sql = sql.trim(); + if (!sql.isEmpty() && sql.length() < 100000) { + history.remove(sql); + history.add(0, sql); + if (history.size() > MAX_HISTORY_SIZE) { + history.remove(history.size() - 1); + } + } + } + + private int retrieveErrorPos(String sqlStatement, CharSequence errorMessage) { + if (DBMS.ORACLE.equals(session.dbms)) { + String statement = "declare " + + "l_theCursor integer default dbms_sql.open_cursor;" + "begin " + " begin " + + " dbms_sql.parse( l_theCursor, ?, dbms_sql.native );" + + " exception when others then ? := dbms_sql.last_error_position;" + " end;" + + " dbms_sql.close_cursor( l_theCursor );" + "end;"; + + CallableStatement cStmt = null; + try { + Connection connection = session.getConnection(); + cStmt = connection.prepareCall(statement); + cStmt.registerOutParameter(2, Types.INTEGER); + cStmt.setString(1, sqlStatement); + + cStmt.execute(); + + return cStmt.getInt(2); + } catch (Exception e) { + logger.info("error", e); + } finally { + if (cStmt != null) { + try { + cStmt.close(); + } catch (SQLException e) { + } + } + } + } else if (DBMS.POSTGRESQL.equals(session.dbms)) { + Pattern pattern = Pattern.compile("\\n\\s*Position: ([0-9]+)"); + Matcher matcher = pattern.matcher(errorMessage); + if (matcher.find()) { + return Integer.parseInt(matcher.group(1)) - 1; + } + } + return -1; + } + + private void toSingleLine() { + String currentStatement = editorPane.getCurrentStatement(false); + String newStatement = UIUtil.toSingleLineSQL(currentStatement); + if (!currentStatement.equals(newStatement)) { + editorPane.replaceCurrentStatement(newStatement, false); + } + } + + private void toggleLineContinuation() { + String currentStatement = editorPane.getCurrentStatement(false); + String newStatement; + Pattern p = Pattern.compile("(?:(?:;( |\\t|\\r)*(?:--[^\\n]*)?)|(?:\\n( |\\t|\\r)*)) ?\\\\( |\\t|\\r)*\\n", Pattern.DOTALL); + Matcher m = p.matcher(currentStatement); + if (m.find()) { + newStatement = currentStatement.replaceAll("((?:(?:;(?: |\\t|\\r)*?(?:--[^\\n]*)?))) ?\\\\([ \\t\\r]*\\n)", "$1$2"); + newStatement = newStatement.replaceAll("((?:\\n(?: |\\t|\\r)*?)) ?\\\\([ \\t\\r]*)(?=\\n)", "$1$2"); + } else { + newStatement = addLineContinuation(currentStatement); + } + if (!currentStatement.equals(newStatement)) { + editorPane.replaceCurrentStatement(newStatement, false); + } + } + + private String addLineContinuation(String statement) { + String newStatement = statement; + newStatement = newStatement.replace("\r", ""); + newStatement = newStatement.replaceAll("((?:(?:;(?: |\\t|\\r)*(?:--[^\\n]*)?)))(\\n(\\r)?)", "$1 \\\\$2"); + newStatement = newStatement.replaceAll("((?:(?:\\n(?: |\\t|\\r)*)))(?=\\n)", "$1 \\\\"); + newStatement = newStatement.replaceAll("\\\\(\\s*)$", "$1"); + return newStatement; + } + + private void analyzeSQL() { + String currentStatement = editorPane.getCurrentStatement(false); + File tempFile = Configuration.getInstance().createTempFile(); + try { + BufferedWriter out = new BufferedWriter(new FileWriter(tempFile)); + Pair loc = editorPane.getCurrentStatementLocation(false, false, null, false); + if (loc != null) { + for (int i = 0; i < loc.a; ++i) { + out.write("\n"); + } + } + out.write(currentStatement); + out.close(); + AssociationProposerView associationProposer = new AssociationProposerView(getOwner(), datamodel.get(), tempFile, executionContext); + if (associationProposer.isAccepted()) { + openDataModelEditor(true); + } + } catch (Exception e) { + UIUtil.showException(this, "Error", e); + } + tempFile.delete(); + } + + private void substituteVariables() { + String currentStatement = editorPane.getCurrentStatement(true); + String newStatement = sqlPlusSupport.replaceVariables(currentStatement, null); + if (!currentStatement.equals(newStatement)) { + editorPane.replaceCurrentStatement(newStatement, true); + } + } + + /** + * @return true iff console editor is empty + */ + public boolean isEmpty() { + return editorPane.getDocument().getLength() == 0; + } + + /** + * Sets the row limit. + * + * @param limit the row limit + */ + public void setRowLimit(Integer limit) { + limitComboBox.setSelectedItem(limit); + } + + private int initialContentSize; + private int initialContentHash; + private boolean dirty; + + /** + * Loads content from file. + * + * @param file the file + */ + public void loadFromFile(File file) throws IOException { + this.file = file; + if (file.exists()) { + BufferedReader in = new BufferedReader(new FileReader(file)); + StringBuilder sb = new StringBuilder(); + int c; + while ((c = in.read()) != -1) { + if (c != '\r') { + sb.append((char) c); + } + } + in.close(); + editorPane.setText(sb.toString()); + dirty = false; + } else { + editorPane.setText(""); + dirty = true; + } + initialContentSize = editorPane.getDocument().getLength(); + initialContentHash = editorPane.getText().hashCode(); + consoleContainerPanel.setVisible(false); + UIUtil.invokeLater(new Runnable() { + @Override + public void run() { + consoleContainerPanel.setVisible(true); + grabFocus(); + } + }); + setCaretPosition(0); + onContentStateChange(file, dirty); + } + + /** + * Stores content to file if console is dirty or new file is given. + * + * @param newFile the file or null to store into assigned file + */ + public void storeToFile(File newFile) throws IOException { + if (newFile != null || file != null && dirty) { + if (newFile != null) { + file = newFile; + } + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); + int lines = editorPane.getLineCount(); + for (int line = 0; line < lines; ++line) { + out.print(getLineContent(line).replace("\r", "").replace("\n", "")); + if (line < lines - 1) { + out.println(); + } + } + out.close(); + initialContentSize = editorPane.getDocument().getLength(); + initialContentHash = editorPane.getText().hashCode(); + dirty = false; + onContentStateChange(file, dirty); + } + } + + private void checkDirty() { + boolean newState = false; + if (initialContentSize != editorPane.getDocument().getLength()) { + newState = true; + } else { + newState = initialContentHash != editorPane.getText().hashCode(); + } + if (newState != dirty) { + dirty = newState; + onContentStateChange(file, dirty); + } + } + + /** + * Reloads tab content + * + * @param tabContentPanel to be reloaded + * @param sql statement to be executed again + */ + private void reload(TabContentPanel tabContentPanel, String sql) { + try { + UIUtil.setWaitCursor(tabContentPanel); + appendStatement(sql.replaceFirst("(;\\s*)+$", ""), true, tabContentPanel, true); + } finally { + UIUtil.resetWaitCursor(tabContentPanel); + } + } + + /** + * Gets the file associated with this console. + * + * @return file associated with this console or null, if the console is not assigned to a file + */ + public File getFile() { + return file; + } + + public boolean isDirty() { + return dirty; + } + + /** + * Closes this console. + */ + public void close() { + CancellationHandler.cancel(this); + queue.add(STOP); + } + + /** + * Gets the editor pane. + * + * @return the editor pane + */ + public RSyntaxTextAreaWithSQLSyntaxStyle getEditorPane() { + return editorPane; + } + + protected abstract void onContentStateChange(File file, boolean dirty); + + static private ImageIcon runIcon; + static private ImageIcon runAllIcon; + static private ImageIcon cancelIcon; + static private ImageIcon explainIcon; + + private int nextPlanID = 0; + + static { + // load images + runIcon = UIUtil.readImage("/run.png"); + runAllIcon = UIUtil.readImage("/runall.png"); + cancelIcon = UIUtil.readImage("/Cancel.png"); + explainIcon = UIUtil.readImage("/explain.png"); + } + +}