diff --git a/releasenotes.txt b/releasenotes.txt index 970053b23..0b5df539a 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -1,5 +1,6 @@ 7.8 - - Improved render quality on high resolution screens. + - New feature "Analyze SQL" analyzes SQL statements and proposes association definitions. + - Improved render quality on high resolution screens. 7.7.3 - incremental SQL formatting. diff --git a/src/main/gui/net/sf/jailer/ui/AssociationEditor.form b/src/main/gui/net/sf/jailer/ui/AssociationEditor.form index 1973c2407..302e07030 100644 --- a/src/main/gui/net/sf/jailer/ui/AssociationEditor.form +++ b/src/main/gui/net/sf/jailer/ui/AssociationEditor.form @@ -1,15 +1,20 @@ -
+ - + + + + + + @@ -19,17 +24,9 @@ - - - - - - - - - + @@ -38,7 +35,6 @@ - @@ -60,6 +56,7 @@ + @@ -68,7 +65,6 @@ - @@ -90,7 +86,7 @@ - + @@ -100,7 +96,7 @@ - + @@ -110,33 +106,13 @@ - - - - - - - - - - - - - - - - - - - - - + - + @@ -146,7 +122,7 @@ - + @@ -170,7 +146,7 @@ - + @@ -180,7 +156,7 @@ - + @@ -211,7 +187,7 @@ - + @@ -233,30 +209,7 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/gui/net/sf/jailer/ui/AssociationEditor.java b/src/main/gui/net/sf/jailer/ui/AssociationEditor.java index 640db9bd6..dd3aa1f34 100644 --- a/src/main/gui/net/sf/jailer/ui/AssociationEditor.java +++ b/src/main/gui/net/sf/jailer/ui/AssociationEditor.java @@ -16,9 +16,16 @@ package net.sf.jailer.ui; import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -30,8 +37,13 @@ import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.ListCellRenderer; +import org.fife.ui.rtextarea.RTextScrollPane; + import net.sf.jailer.database.Session; import net.sf.jailer.datamodel.Association; +import net.sf.jailer.datamodel.Column; +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.util.CsvFile.Line; @@ -51,241 +63,243 @@ public class AssociationEditor extends javax.swing.JDialog { * All associations (as csv-lines). */ private Collection associations; + + /** + * All columns. + */ + private Map columns; + + private RSyntaxTextAreaWithSQLSyntaxStyle joinCondition; /** * Creates new form TableEditor * * @param tables all tables (as csv-lines) * @param associations all associations (as csv-line) + * @param columns */ - public AssociationEditor(java.awt.Dialog parent, Collection tables, List associations) { + public AssociationEditor(java.awt.Dialog parent, Collection tables, List associations, Map columns) { super(parent, true); this.tables = tables; this.associations = associations; + this.columns = columns; initComponents(); AutoCompletion.enable(destination); AutoCompletion.enable(source); + joinCondition = new RSyntaxTextAreaWithSQLSyntaxStyle(false, false) { + @Override + protected void runBlock() { + super.runBlock(); + onOk(); + } + }; + + try { + provider = new CompletionProvider(null, null); + provider.setDefaultClause(SQLCompletionProvider.Clause.WHERE); + new SQLAutoCompletion(provider, joinCondition); + } catch (SQLException e) { + } + + joinCondition.setRows(3); + RTextScrollPane jScrollPane = new RTextScrollPane(); + jScrollPane.setViewportView(joinCondition); + + GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 9; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + getContentPane().add(jScrollPane, gridBagConstraints); + + ItemListener itemListener = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + provider.updateAliases(); + } + }; + source.addItemListener(itemListener); + destination.addItemListener(itemListener); + type.setRenderer(createTypeRenderer()); pack(); setLocation(parent.getLocation().x + parent.getSize().width/2 - getPreferredSize().width/2, parent.getLocation().y + parent.getSize().height/2 - getPreferredSize().height/2); UIUtil.initPeer(); } + + private CompletionProvider provider; /** 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; + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; - jPanel2 = new javax.swing.JPanel(); - source = new net.sf.jailer.ui.JComboBox(); - type = new net.sf.jailer.ui.JComboBox(); - destination = new net.sf.jailer.ui.JComboBox(); - cardinality = new net.sf.jailer.ui.JComboBox(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - joinCondition = new javax.swing.JTextField(); - jLabel5 = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); - jLabel7 = new javax.swing.JLabel(); - jLabel8 = new javax.swing.JLabel(); - nameField = new javax.swing.JTextField(); - jLabel9 = new javax.swing.JLabel(); - jPanel1 = new javax.swing.JPanel(); - jButton1 = new javax.swing.JButton(); - jLabel3 = new javax.swing.JLabel(); - jButton2 = new javax.swing.JButton(); - jLabel4 = new javax.swing.JLabel(); - jLabel10 = new javax.swing.JLabel(); + source = new JComboBox(); + type = new JComboBox(); + destination = new JComboBox(); + cardinality = new JComboBox(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + nameField = new javax.swing.JTextField(); + jLabel9 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jButton1 = new javax.swing.JButton(); + jLabel3 = new javax.swing.JLabel(); + jButton2 = new javax.swing.JButton(); - getContentPane().setLayout(new java.awt.GridBagLayout()); + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Association"); + getContentPane().setLayout(new java.awt.GridBagLayout()); - setTitle("Association"); - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - getContentPane().add(jPanel2, gridBagConstraints); + source.setMaximumRowCount(20); + source.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); + getContentPane().add(source, gridBagConstraints); - source.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - source.setMaximumRowCount(20); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); - getContentPane().add(source, gridBagConstraints); + type.setModel(createTypeModel()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); + getContentPane().add(type, gridBagConstraints); - type.setModel(createTypeModel()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); - getContentPane().add(type, gridBagConstraints); + destination.setMaximumRowCount(20); + destination.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 5; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); + getContentPane().add(destination, gridBagConstraints); - destination.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - destination.setMaximumRowCount(20); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 5; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); - getContentPane().add(destination, gridBagConstraints); + cardinality.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "", "1:n", "n:1", "1:1", "n:m" })); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 10; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); + getContentPane().add(cardinality, gridBagConstraints); - cardinality.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "", "1:n", "n:1", "1:1", "n:m" })); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 6; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0); - getContentPane().add(cardinality, gridBagConstraints); + jLabel1.setText(" Name "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 11; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + getContentPane().add(jLabel1, gridBagConstraints); - jLabel1.setText(" Name "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 10; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel1, gridBagConstraints); + jLabel2.setText(" Join condition* "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 9; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + getContentPane().add(jLabel2, gridBagConstraints); - jLabel2.setText(" Join condition* "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 9; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel2, gridBagConstraints); + jLabel6.setText(" From A"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + getContentPane().add(jLabel6, gridBagConstraints); - joinCondition.setText("jTextField2"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 9; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - getContentPane().add(joinCondition, gridBagConstraints); + jLabel7.setText(" To B"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + getContentPane().add(jLabel7, gridBagConstraints); - jLabel5.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - getContentPane().add(jLabel5, gridBagConstraints); + jLabel8.setText(" Type"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + getContentPane().add(jLabel8, gridBagConstraints); - jLabel6.setText(" From "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel6, gridBagConstraints); + nameField.setText("jTextField1"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 11; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + getContentPane().add(nameField, gridBagConstraints); - jLabel7.setText(" To"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 5; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel7, gridBagConstraints); + jLabel9.setText(" Cardinality "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 10; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + getContentPane().add(jLabel9, gridBagConstraints); - jLabel8.setText(" Type"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel8, gridBagConstraints); + jPanel1.setLayout(new java.awt.GridBagLayout()); - nameField.setText("jTextField1"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 10; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 1.0; - getContentPane().add(nameField, gridBagConstraints); + jButton1.setText("Ok"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); + jPanel1.add(jButton1, gridBagConstraints); - jLabel9.setText(" Cardinality "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 6; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - getContentPane().add(jLabel9, gridBagConstraints); + jLabel3.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N + jLabel3.setText(" * use 'A' as alias for From, use 'B' as alias for To."); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 0, 0, 0); + jPanel1.add(jLabel3, gridBagConstraints); - jPanel1.setLayout(new java.awt.GridBagLayout()); + jButton2.setText("Cancel"); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jButton2.addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentResized(java.awt.event.ComponentEvent evt) { + jButton2ComponentResized(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); + jPanel1.add(jButton2, gridBagConstraints); - jButton1.setText("Ok"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(evt); - } - }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 40; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + getContentPane().add(jPanel1, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridheight = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); - jPanel1.add(jButton1, gridBagConstraints); - - jLabel3.setFont(new java.awt.Font("Dialog", 0, 12)); - jLabel3.setText(" *use 'A' as alias for From, use 'B' as alias for To. "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(8, 0, 0, 0); - jPanel1.add(jLabel3, gridBagConstraints); - - jButton2.setText("Cancel"); - jButton2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(evt); - } - }); - jButton2.addComponentListener(new java.awt.event.ComponentAdapter() { - @Override - public void componentResized(java.awt.event.ComponentEvent evt) { - jButton2ComponentResized(evt); - } - }); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridheight = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0); - jPanel1.add(jButton2, gridBagConstraints); - - jLabel4.setFont(new java.awt.Font("Dialog", 0, 12)); - jLabel4.setText(" Upper case, no space between A/B and dot!"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.weightx = 1.0; - jPanel1.add(jLabel4, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 40; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - getContentPane().add(jPanel1, gridBagConstraints); - - jLabel10.setText(" "); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 20; - gridBagConstraints.gridy = 0; - getContentPane().add(jLabel10, gridBagConstraints); - - pack(); - }// //GEN-END:initComponents + pack(); + }// //GEN-END:initComponents private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed setVisible(false); @@ -295,6 +309,10 @@ public class AssociationEditor extends javax.swing.JDialog { * On OK. */ private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + onOk(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void onOk() { String msg = null; if (nameField.getText().trim().length() == 0) { msg = "No association name"; @@ -314,7 +332,7 @@ public class AssociationEditor extends javax.swing.JDialog { isOk = true; setVisible(false); } - }//GEN-LAST:event_jButton1ActionPerformed + } private void jButton2ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jButton2ComponentResized }//GEN-LAST:event_jButton2ComponentResized @@ -395,7 +413,8 @@ public class AssociationEditor extends javax.swing.JDialog { source.setSelectedItem(association.cells.get(0)); destination.setSelectedItem(association.cells.get(1)); type.setSelectedItem(association.cells.get(2)); - joinCondition.setText(association.cells.get(4)); + joinCondition.setText(association.cells.get(4) + "\n"); + joinCondition.setCaretPosition(0); String cardinality = association.cells.get(3); this.cardinality.setSelectedItem(cardinality); nameField.setText(association.cells.get(5)); @@ -406,7 +425,9 @@ public class AssociationEditor extends javax.swing.JDialog { Object origCardinality = this.cardinality.getSelectedItem(); String origJoinCondition = joinCondition.getText(); String origName = nameField.getText(); - + + provider.updateAliases(); + isOk = false; setVisible(true); if (isOk && !(origName.equals(nameField.getText()) @@ -420,7 +441,7 @@ public class AssociationEditor extends javax.swing.JDialog { association.cells.set(1, (String) destination.getSelectedItem()); association.cells.set(2, (String) type.getSelectedItem()); association.cells.set(3, (String) this.cardinality.getSelectedItem()); - association.cells.set(4, joinCondition.getText()); + association.cells.set(4, joinCondition.getText().replaceAll("\\s*\\n", " ").trim()); association.cells.set(5, nameField.getText()); association.cells.set(6, "Data Model Editor"); association.length = 6; @@ -428,91 +449,135 @@ public class AssociationEditor extends javax.swing.JDialog { } return false; } - - // Variablendeklaration - nicht modifizieren//GEN-BEGIN:variables - private net.sf.jailer.ui.JComboBox cardinality; - private net.sf.jailer.ui.JComboBox destination; - private javax.swing.JButton jButton1; - private javax.swing.JButton jButton2; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel10; - 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.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JTextField joinCondition; - private javax.swing.JTextField nameField; - private net.sf.jailer.ui.JComboBox source; - private net.sf.jailer.ui.JComboBox type; - // Ende der Variablendeklaration//GEN-END:variables - private class CompletionProvider extends SQLCompletionProvider { + // Variables declaration - do not modify//GEN-BEGIN:variables + private JComboBox cardinality; + private JComboBox destination; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JTextField nameField; + private JComboBox source; + private JComboBox type; + // End of variables declaration//GEN-END:variables + + private class TableModel { + String schema; + String name; + String origName; + List columns; + } + + private class CompletionProvider extends SQLCompletionProvider { + + private final List tableModels = new ArrayList(); public CompletionProvider(Session session, String metaDataSource) throws SQLException { super(session, metaDataSource); - // TODO Auto-generated constructor stub + for (Line tabLine: tables) { + TableModel tableModel = new TableModel(); + tableModel.origName = tabLine.cells.get(0); + tableModel.name = tableModel.origName; + int iDot = tableModel.name.indexOf(':'); + if (iDot < 0) { + tableModel.schema = ""; + } else { + tableModel.schema = tableModel.name.substring(0, iDot); + tableModel.name = tableModel.name.substring(iDot + 1); + } + tableModel.columns = new ArrayList(); + if (columns.containsKey(tabLine.cells.get(0))) { + Line line = columns.get(tabLine.cells.get(0)); + for (int i = 1; i < line.length; ++i) { + Column column = Column.parse(line.cells.get(i)); + tableModel.columns.add(column.name); + } + } + tableModels.add(tableModel); + } } @Override - protected List getColumns(String table, long timeOut, JComponent waitCursorSubject) { - // TODO Auto-generated method stub - return null; + protected List getColumns(TableModel table, long timeOut, JComponent waitCursorSubject) { + return table.columns; } @Override protected String getDefaultSchema(String metaDataSource) { - // TODO Auto-generated method stub - return null; + return ""; } @Override protected String findSchema(String metaDataSource, String name) { - // TODO Auto-generated method stub + return name; + } + + @Override + protected TableModel findTable(String schema, String name) { + for (TableModel tab: tableModels) { + if (tab.schema.equals(schema) && tab.name.equals(name)) { + return tab; + } + } return null; } @Override - protected String findTable(String schema, String name) { - // TODO Auto-generated method stub - return null; + protected String getTableName(TableModel table) { + return table.name; } @Override - protected String getTableName(String table) { - // TODO Auto-generated method stub - return null; - } - - @Override - protected List getTables(String schema) { - // TODO Auto-generated method stub - return null; + protected List getTables(String schema) { + List result = new ArrayList(); + for (TableModel tab: tableModels) { + if (tab.schema.equals(schema)) { + result.add(tab); + } + } + return result; } @Override protected String getSchemaName(String schema) { - // TODO Auto-generated method stub - return null; + return schema; } @Override protected List getSchemas(String metaDataSource) { - // TODO Auto-generated method stub - return null; + Set result = new HashSet(); + result.add(""); + for (TableModel tab : tableModels) { + result.add(tab.schema); + } + return new ArrayList(result); } @Override - protected List getAssociations(String source, String destination) { - // TODO Auto-generated method stub - return null; + protected List getAssociations(TableModel source, TableModel destination) { + return Collections.emptyList(); } + private void updateAliases() { + removeAliases(); + String sName = String.valueOf(source.getSelectedItem()); + String dName = String.valueOf(destination.getSelectedItem()); + for (TableModel tab: tableModels) { + if (tab.origName.equals(sName)) { + provider.addAlias("A", tab); + } + if (tab.origName.equals(dName)) { + provider.addAlias("B", tab); + } + } + } } private static final long serialVersionUID = 603961628104674406L; diff --git a/src/main/gui/net/sf/jailer/ui/DataModelEditor.java b/src/main/gui/net/sf/jailer/ui/DataModelEditor.java index b2f92c5ad..1ad66a8d7 100644 --- a/src/main/gui/net/sf/jailer/ui/DataModelEditor.java +++ b/src/main/gui/net/sf/jailer/ui/DataModelEditor.java @@ -41,6 +41,8 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; +import javax.swing.SortOrder; +import javax.swing.RowSorter.SortKey; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; @@ -50,6 +52,7 @@ import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import net.sf.jailer.ExecutionContext; import net.sf.jailer.JailerVersion; @@ -407,6 +410,7 @@ public class DataModelEditor extends javax.swing.JDialog { updateButtons(); } }); + initRowSorter(tablesTable, new int[] { 0, 2 }); adjustTableColumnsWidth(tablesTable); associationsTable.setDefaultRenderer(Object.class, associationsListItemRenderer); @@ -425,6 +429,7 @@ public class DataModelEditor extends javax.swing.JDialog { updateButtons(); } }); + initRowSorter(associationsTable, new int[] { 0, 1, 4, 2, 3, 5 }); invalidate(); if (initiallyDirty) { @@ -432,28 +437,29 @@ public class DataModelEditor extends javax.swing.JDialog { } UIUtil.initPeer(); - if (toEdit != null) { - addWindowListener(new WindowListener() { - @Override - public void windowActivated(WindowEvent e) { - } - @Override - public void windowClosed(WindowEvent e) { - } - @Override - public void windowClosing(WindowEvent e) { - } - @Override - public void windowDeactivated(WindowEvent e) { - } - @Override - public void windowDeiconified(WindowEvent e) { - } - @Override - public void windowIconified(WindowEvent e) { - } - @Override - public void windowOpened(WindowEvent e) { + addWindowListener(new WindowListener() { + @Override + public void windowActivated(WindowEvent e) { + } + @Override + public void windowClosed(WindowEvent e) { + } + @Override + public void windowClosing(WindowEvent e) { + } + @Override + public void windowDeactivated(WindowEvent e) { + } + @Override + public void windowDeiconified(WindowEvent e) { + } + @Override + public void windowIconified(WindowEvent e) { + } + @Override + public void windowOpened(WindowEvent e) { + jSplitPane1.setDividerLocation(0.3); + if (toEdit != null) { for (Line l: tables) { if (toEdit.getName().equals(l.cells.get(0))) { if (new TableEditor(DataModelEditor.this, displayNames, tables, associations, excludeFromDeletion).edit(l, columns)) { @@ -464,17 +470,55 @@ public class DataModelEditor extends javax.swing.JDialog { } } } - }); - } + } + }); if (merge) { ModelBuilder.cleanUp(executionContext); } } + private void initRowSorter(JTable table, final int[] mapping) { + TableRowSorter sorter = new TableRowSorter(table.getModel()) { + @Override + protected boolean useToString(int column) { + return false; + } + + @Override + public void toggleSortOrder(int column) { + List sortKeys = getSortKeys(); + if (sortKeys.size() > 0) { + if (sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING) { + setSortKeys(null); + return; + } + } + super.toggleSortOrder(column); + } + + @Override + public Comparator getComparator(final int n) { + return new Comparator() { + @SuppressWarnings("unchecked") + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof Line) { + if (o2 instanceof Line) { + return ((Line) o1).cells.get(mapping[n]).compareTo(((Line) o2).cells.get(mapping[n])); + } + } + return String.valueOf(o1).compareTo(String.valueOf(o2)); + } + }; + } + }; + table.setRowSorter(sorter); + } + public void adjustTableColumnsWidth(JTable table) { DefaultTableModel dtm = (DefaultTableModel) table.getModel(); - for (int i = 0; i < table.getColumnCount(); i++) { + for (int i = 0; i < table.getColumnCount() - 1; i++) { TableColumn column = table.getColumnModel().getColumn(i); Component comp = table.getDefaultRenderer(String.class).getTableCellRendererComponent(table, column.getHeaderValue(), false, false, 0, i); int width = 1; @@ -485,8 +529,9 @@ public class DataModelEditor extends javax.swing.JDialog { comp = table.getCellRenderer(line, i).getTableCellRendererComponent(table, dtm.getValueAt(line, i), false, false, line, i); width = Math.max(width, comp.getPreferredSize().width); } - column.setPreferredWidth(Math.min(width, 400)); + column.setPreferredWidth(Math.min(width, 200)); } + table.getColumnModel().getColumn(table.getColumnModel().getColumnCount() - 1).setPreferredWidth(80); } private KnownIdentifierMap createKnownIdentifierMap() throws IOException { @@ -806,7 +851,7 @@ public class DataModelEditor extends javax.swing.JDialog { cells.add(""); } CsvFile.Line line = new CsvFile.Line("?", cells); - if (new AssociationEditor(this, tables, associations).edit(line)) { + if (new AssociationEditor(this, tables, associations, columns).edit(line)) { associations.add(0, line); associationsTable.setModel(createAssociationsListModel()); repaint(); @@ -820,7 +865,7 @@ public class DataModelEditor extends javax.swing.JDialog { line = associations.get(associationsTable.getRowSorter().convertRowIndexToModel(associationsTable.getSelectedRow())); } if (line != null) { - if (new AssociationEditor(this, tables, associations).edit(line)) { + if (new AssociationEditor(this, tables, associations, columns).edit(line)) { markDirty(); repaint(); } diff --git a/src/main/gui/net/sf/jailer/ui/resource/search.png b/src/main/gui/net/sf/jailer/ui/resource/search.png index 08dd81c97..d963fea3a 100644 Binary files a/src/main/gui/net/sf/jailer/ui/resource/search.png and b/src/main/gui/net/sf/jailer/ui/resource/search.png differ