introducing AssociationProposer

This commit is contained in:
Wisser
2018-04-21 06:59:24 +02:00
parent bdcc4b9b3d
commit 4b4267468a
17 changed files with 2264 additions and 150 deletions
@@ -26,7 +26,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -219,7 +219,16 @@ public class DataModelEditor extends javax.swing.JDialog {
sortLineList(tables, true);
File modelFinderAssociationsFile = new File(ModelBuilder.getModelBuilderAssociationsFilename(executionContext));
if (merge && modelFinderAssociationsFile.exists()) {
Set<String> allNames = new HashSet<String>();
for (Line as: associations) {
allNames.add(as.cells.get(5));
}
List<CsvFile.Line> associationsFromModelFinder = new CsvFile(modelFinderAssociationsFile).getLines();
for (Iterator<Line> it = associationsFromModelFinder.iterator(); it.hasNext(); ) {
if (allNames.contains(it.next().cells.get(5))) {
it.remove();
}
}
associations.addAll(associationsFromModelFinder);
linesFromModelFinder.addAll(associationsFromModelFinder);
newAssociations += associationsFromModelFinder.size();
@@ -32,7 +32,6 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -402,6 +402,16 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openDataModelEditorActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JPopupMenu$Separator" name="jSeparator13">
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="analyzeSQLMenuItem">
<Properties>
<Property name="text" type="java.lang.String" value="Analyze SQL Script"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="analyzeSQLMenuItemActionPerformed"/>
</Events>
</MenuItem>
</SubComponents>
</Menu>
<Menu class="javax.swing.JMenu" name="jMenu3">
@@ -522,6 +532,7 @@
<SyntheticProperties>
<SyntheticProperty name="menuBar" type="java.lang.String" value="jMenuBar2"/>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowGainedFocus" listener="java.awt.event.WindowFocusListener" parameters="java.awt.event.WindowEvent" handler="formWindowGainedFocus"/>
@@ -71,6 +71,7 @@ import net.sf.jailer.extractionmodel.ExtractionModel.AdditionalSubject;
import net.sf.jailer.modelbuilder.ModelBuilder;
import net.sf.jailer.render.HtmlDataModelRenderer;
import net.sf.jailer.subsetting.ScriptFormat;
import net.sf.jailer.ui.associationproposer.AssociationProposerView;
import net.sf.jailer.ui.databrowser.DataBrowser;
import net.sf.jailer.ui.progress.ExportAndDeleteStageProgressListener;
import net.sf.jailer.util.CancellationHandler;
@@ -325,6 +326,8 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
jMenu1 = new javax.swing.JMenu();
updateDataModel = new javax.swing.JMenuItem();
openDataModelEditor = new javax.swing.JMenuItem();
jSeparator13 = new javax.swing.JPopupMenu.Separator();
analyzeSQLMenuItem = new javax.swing.JMenuItem();
jMenu3 = new javax.swing.JMenu();
dataExport = new javax.swing.JMenuItem();
dataImport = new javax.swing.JMenuItem();
@@ -345,18 +348,15 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle("Extraction Model Editor");
addWindowFocusListener(new java.awt.event.WindowFocusListener() {
@Override
public void windowGainedFocus(java.awt.event.WindowEvent evt) {
public void windowGainedFocus(java.awt.event.WindowEvent evt) {
formWindowGainedFocus(evt);
}
@Override
public void windowLostFocus(java.awt.event.WindowEvent evt) {
public void windowLostFocus(java.awt.event.WindowEvent evt) {
formWindowLostFocus(evt);
}
});
addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent evt) {
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});
@@ -371,8 +371,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
fileMenu.setText("File");
fileMenu.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fileMenuActionPerformed(evt);
}
});
@@ -380,8 +379,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
newModel.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
newModel.setText("New");
newModel.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newModelActionPerformed(evt);
}
});
@@ -390,8 +388,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
load.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
load.setText("Load");
load.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
loadActionPerformed(evt);
}
});
@@ -399,8 +396,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
reload.setText("Reload");
reload.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
reloadActionPerformed(evt);
}
});
@@ -410,8 +406,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
save.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
save.setText("Save");
save.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveActionPerformed(evt);
}
});
@@ -420,8 +415,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
saveAs.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
saveAs.setText("Save as...");
saveAs.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveAsActionPerformed(evt);
}
});
@@ -429,8 +423,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
exportDisplay.setText("Export graph as image");
exportDisplay.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exportDisplayActionPerformed(evt);
}
});
@@ -439,8 +432,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
connectDb.setText("Connect with database");
connectDb.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectDbActionPerformed(evt);
}
});
@@ -448,8 +440,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
disconnectDb.setText("Disconnect");
disconnectDb.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
disconnectDbActionPerformed(evt);
}
});
@@ -458,8 +449,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
exit.setText("Exit");
exit.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exitActionPerformed(evt);
}
});
@@ -472,8 +462,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
ignoreAll.setActionCommand("Disable all associations");
ignoreAll.setLabel("Disable all associations");
ignoreAll.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ignoreAllActionPerformed(evt);
}
});
@@ -481,8 +470,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
removeAllRestrictions.setLabel("Remove all restrictions");
removeAllRestrictions.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeAllRestrictionsActionPerformed(evt);
}
});
@@ -492,8 +480,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, java.awt.event.InputEvent.CTRL_MASK));
jMenuItem2.setText("Filter editor...");
jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItem2ActionPerformed(evt);
}
});
@@ -506,8 +493,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
collapseAll.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, java.awt.event.InputEvent.CTRL_MASK));
collapseAll.setText("Collapse all");
collapseAll.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
collapseAllActionPerformed(evt);
}
});
@@ -516,8 +502,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
expandAll.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, java.awt.event.InputEvent.CTRL_MASK));
expandAll.setLabel("Expand all");
expandAll.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
expandAllActionPerformed(evt);
}
});
@@ -526,8 +511,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
expandAllVisible.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, java.awt.event.InputEvent.CTRL_MASK));
expandAllVisible.setText("Expand visible tables");
expandAllVisible.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
expandAllVisibleActionPerformed(evt);
}
});
@@ -536,8 +520,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK));
jMenuItem3.setText("Fix all");
jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItem3ActionPerformed(evt);
}
});
@@ -546,8 +529,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
jMenuItem4.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U, java.awt.event.InputEvent.CTRL_MASK));
jMenuItem4.setText("Unfix all");
jMenuItem4.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItem4ActionPerformed(evt);
}
});
@@ -556,8 +538,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
refresh.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
refresh.setText("Reset");
refresh.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
refreshActionPerformed(evt);
}
});
@@ -567,8 +548,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
zoomToFit.setText("Zoom to fit");
zoomToFit.setVerifyInputWhenFocusTarget(false);
zoomToFit.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
zoomToFitActionPerformed(evt);
}
});
@@ -578,8 +558,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
showIgnored.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_H, java.awt.event.InputEvent.CTRL_MASK));
showIgnored.setText("Show disabled associations");
showIgnored.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
showIgnoredActionPerformed(evt);
}
});
@@ -588,8 +567,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
showTableDetails.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_D, java.awt.event.InputEvent.CTRL_MASK));
showTableDetails.setText("Show table details");
showTableDetails.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
showTableDetailsActionPerformed(evt);
}
});
@@ -600,8 +578,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
horizontalLayoutMenuItem.setSelected(true);
horizontalLayoutMenuItem.setText("Horizontal layout");
horizontalLayoutMenuItem.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
horizontalLayoutMenuItemActionPerformed(evt);
}
});
@@ -616,8 +593,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptime0.setSelected(true);
steptime0.setText("default");
steptime0.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime0ActionPerformed(evt);
}
});
@@ -626,8 +602,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime10);
steptime10.setText("10");
steptime10.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime10ActionPerformed(evt);
}
});
@@ -636,8 +611,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime20);
steptime20.setText("20");
steptime20.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime20ActionPerformed(evt);
}
});
@@ -646,8 +620,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime30);
steptime30.setText("30");
steptime30.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime30ActionPerformed(evt);
}
});
@@ -656,8 +629,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime50);
steptime50.setText("50");
steptime50.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime50ActionPerformed(evt);
}
});
@@ -666,8 +638,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime75);
steptime75.setText("75");
steptime75.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime75ActionPerformed(evt);
}
});
@@ -676,8 +647,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime100);
steptime100.setText("100");
steptime100.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime100ActionPerformed(evt);
}
});
@@ -686,8 +656,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime200);
steptime200.setText("200");
steptime200.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime200ActionPerformed(evt);
}
});
@@ -696,8 +665,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
steptimeGroup.add(steptime500);
steptime500.setText("500");
steptime500.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
steptime500ActionPerformed(evt);
}
});
@@ -711,8 +679,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
updateDataModel.setText("Analyze Database");
updateDataModel.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
updateDataModelActionPerformed(evt);
}
});
@@ -720,12 +687,20 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
openDataModelEditor.setLabel("Data Model Editor");
openDataModelEditor.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openDataModelEditorActionPerformed(evt);
}
});
jMenu1.add(openDataModelEditor);
jMenu1.add(jSeparator13);
analyzeSQLMenuItem.setText("Analyze SQL Script");
analyzeSQLMenuItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
analyzeSQLMenuItemActionPerformed(evt);
}
});
jMenu1.add(analyzeSQLMenuItem);
jMenuBar2.add(jMenu1);
@@ -733,8 +708,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
dataExport.setLabel("Export Data");
dataExport.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
dataExportActionPerformed(evt);
}
});
@@ -742,8 +716,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
dataImport.setLabel("Import SQL Data");
dataImport.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
dataImportActionPerformed(evt);
}
});
@@ -752,8 +725,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
openDataBrowserItem.setText("Data Browser");
openDataBrowserItem.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openDataBrowserItemActionPerformed(evt);
}
});
@@ -761,8 +733,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
queryBuilder.setText("Query Builder");
queryBuilder.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
queryBuilderActionPerformed(evt);
}
});
@@ -770,8 +741,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
cycleView.setText("Cycle View");
cycleView.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cycleViewActionPerformed(evt);
}
});
@@ -779,8 +749,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
restrictedDependenciesToolMenuItem.setText("Restricted Dependencies View");
restrictedDependenciesToolMenuItem.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
restrictedDependenciesToolMenuItemActionPerformed(evt);
}
});
@@ -788,8 +757,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
renderHtml.setText("HTML Rendering");
renderHtml.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
renderHtmlActionPerformed(evt);
}
});
@@ -801,8 +769,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
helpContent.setText("Manual");
helpContent.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
helpContentActionPerformed(evt);
}
});
@@ -810,8 +777,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
tutorial.setLabel("Tutorial");
tutorial.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tutorialActionPerformed(evt);
}
});
@@ -820,8 +786,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
helpForum.setLabel("Help Forum");
helpForum.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
helpForumActionPerformed(evt);
}
});
@@ -830,8 +795,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
jMenuItem1.setText("About Jailer");
jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItem1ActionPerformed(evt);
}
});
@@ -1005,17 +969,17 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
}
private void openDataModelEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openDataModelEditorActionPerformed
openDataModelEditor(null);
openDataModelEditor(null, false);
}//GEN-LAST:event_openDataModelEditorActionPerformed
/**
* Opens the data model editor.
*/
private void openDataModelEditor(Table toEdit) {
private void openDataModelEditor(Table toEdit, boolean merge) {
try {
if (saveIfNeeded("edit data model", true, false)) {
String modelname = extractionModelEditor.dataModel == null? DataModel.DEFAULT_NAME : extractionModelEditor.dataModel.getName();
DataModelEditor dataModelEditor = new DataModelEditor(this, false, false, toEdit, null, null, modelname, null, executionContext);
DataModelEditor dataModelEditor = new DataModelEditor(this, merge, false, toEdit, null, null, modelname, null, executionContext);
dataModelEditor.setVisible(true);
// if (dataModelEditor.saved) {
reload();
@@ -1204,7 +1168,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
} catch (Exception e) {
if (e instanceof DataModel.NoPrimaryKeyException) {
if (JOptionPane.showOptionDialog(this, e.getMessage(), "No Primary Key", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, new Object[] { "Edit Table", "Cancel" }, null) == 0) {
openDataModelEditor(((NoPrimaryKeyException) e).table);
openDataModelEditor(((NoPrimaryKeyException) e).table, false);
if (onDataModelUpdate != null) {
onDataModelUpdate.run();
}
@@ -1674,7 +1638,14 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
UIUtil.showException(this, "Error", t);
}
}//GEN-LAST:event_reloadActionPerformed
private void analyzeSQLMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analyzeSQLMenuItemActionPerformed
AssociationProposerView assocProposerView = new AssociationProposerView(this, extractionModelEditor.dataModel, null, executionContext);
if (assocProposerView.isAccepted()) {
openDataModelEditor(null, true);
}
}//GEN-LAST:event_analyzeSQLMenuItemActionPerformed
boolean isHorizontalLayout = false;
/**
@@ -1926,6 +1897,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem analyzeSQLMenuItem;
private javax.swing.JMenuItem collapseAll;
private javax.swing.JCheckBoxMenuItem connectDb;
private javax.swing.JMenuItem cycleView;
@@ -1956,6 +1928,7 @@ public class ExtractionModelFrame extends javax.swing.JFrame {
private javax.swing.JSeparator jSeparator10;
private javax.swing.JSeparator jSeparator11;
private javax.swing.JSeparator jSeparator12;
private javax.swing.JPopupMenu.Separator jSeparator13;
private javax.swing.JSeparator jSeparator2;
private javax.swing.JSeparator jSeparator4;
private javax.swing.JSeparator jSeparator5;
@@ -42,7 +42,6 @@ import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.border.SoftBevelBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
@@ -0,0 +1,735 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* 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.associationproposer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
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.Stack;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.util.Pair;
import net.sf.jailer.util.Quoting;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.NotExpression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.parser.ParseException;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Commit;
import net.sf.jsqlparser.statement.SetStatement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.view.AlterView;
import net.sf.jsqlparser.statement.create.view.CreateView;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.execute.Execute;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.merge.Merge;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SelectItemVisitor;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.TableFunction;
import net.sf.jsqlparser.statement.select.ValuesList;
import net.sf.jsqlparser.statement.select.WithItem;
import net.sf.jsqlparser.statement.truncate.Truncate;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.upsert.Upsert;
/**
* Analyzes SQL statements and proposes association definitions.
*
* @author Ralf Wisser
*/
public class AssociationProposer {
private String[] FUNCTIONS_TO_IGNORE = new String[] { "XMLSERIALIZE", "XMLFOREST" };
private final DataModel dataModel;
private final Map<net.sf.jailer.datamodel.Column, net.sf.jailer.datamodel.Table> columnToTable = new IdentityHashMap<net.sf.jailer.datamodel.Column, net.sf.jailer.datamodel.Table>();
private final Set<Equation> equations = new HashSet<Equation>();
private final Set<Association> fromDataModel = new HashSet<Association>();
public AssociationProposer(DataModel dataModel) {
this.dataModel = dataModel;
for (Entry<String, Association> e: dataModel.namedAssociations.entrySet()) {
Association association = e.getValue();
fromDataModel.add(association);
addAssociation(e.getKey(), new Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>(association.source, association.destination), association, false);
association = association.reversalAssociation;
fromDataModel.add(association);
addAssociation(e.getKey(), new Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>(association.source, association.destination), association, false);
}
}
public synchronized String analyze(String sqlStatement, int startLineNumber) {
sqlStatement = removeCommentsAndLiterals(sqlStatement);
for (String function : FUNCTIONS_TO_IGNORE) {
sqlStatement = removeFunction(function, sqlStatement);
}
net.sf.jsqlparser.statement.Statement st;
try {
st = CCJSqlParserUtil.parse(sqlStatement);
} catch (JSQLParserException e) {
String prefix = "Line " + startLineNumber + ": ";
if (e.getCause() instanceof ParseException) {
ParseException pe = (ParseException) e.getCause();
return prefix + pe.getMessage().replaceAll("\\s+", " ");
}
Throwable t = e;
while (t.getMessage() == null && t.getCause() != null) {
t = t.getCause();
}
return prefix + t.getMessage();
}
st.accept(new APStatementVisitor());
closeEquations();
proposeJoinConditions();
sqlStatement = st.toString();
return null;
}
private String removeFunction(String function, String sqlStatement) {
Pattern pattern = Pattern.compile("(\\b\\w+\\b)|\\(\\)|.", Pattern.DOTALL);
Matcher matcher = pattern.matcher(sqlStatement);
int level = 0;
Integer funcLevel = null;
boolean result = matcher.find();
StringBuffer sb = new StringBuffer();
if (result) {
do {
String token = matcher.group(0);
if ("(".equals(token)) {
++level;
} else if (")".equals(token)) {
--level;
}
int l = token.length();
matcher.appendReplacement(sb, "");
if (function.equalsIgnoreCase(token)) {
if (funcLevel == null) {
funcLevel = level;
--l;
sb.append("1");
}
}
if (funcLevel != null) {
while (l > 0) {
--l;
sb.append(' ');
}
} else {
sb.append(token);
}
if (funcLevel != null && ")".equals(token)) {
if (funcLevel == level) {
funcLevel = null;
}
}
result = matcher.find();
} while (result);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* Removes comments and literals from SQL statement.
*
* @param statement
* the statement
*
* @return statement the statement without comments and literals
*/
private String removeCommentsAndLiterals(String statement) {
Pattern pattern = Pattern.compile("('([^']*'))|(/\\*.*?\\*/)|(\\-\\-.*?(?=\n|$))", Pattern.DOTALL);
Matcher matcher = pattern.matcher(statement);
boolean result = matcher.find();
StringBuffer sb = new StringBuffer();
if (result) {
do {
int l = matcher.group(0).length();
matcher.appendReplacement(sb, "");
if (matcher.group(1) != null) {
l -= 2;
sb.append("'");
}
while (l > 0) {
--l;
sb.append(' ');
}
if (matcher.group(1) != null) {
sb.append("'");
}
result = matcher.find();
} while (result);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* Select scope.
*/
private class Scope {
Map<String, String> aliasToTable = new HashMap<String, String>();
public List<Expression> expressions = new ArrayList<Expression>();
// List<Cond>
public String toString() {
return aliasToTable.toString() + "\n" + expressions;
}
}
private class APStatementVisitor extends ExpressionVisitorAdapter implements StatementVisitor, SelectItemVisitor, SelectVisitor {
private Stack<Scope> scopes = new Stack<Scope>();
@Override
public void visit(Commit commit) {
}
@Override
public void visit(Delete delete) {
}
@Override
public void visit(Update update) {
if (update.getSelect() != null) {
update.getSelect().accept(this);
}
}
@Override
public void visit(Insert insert) {
if (insert.getSelect() != null) {
insert.getSelect().accept(this);
}
}
@Override
public void visit(Replace replace) {
}
@Override
public void visit(Drop drop) {
}
@Override
public void visit(Truncate truncate) {
}
@Override
public void visit(CreateIndex createIndex) {
}
@Override
public void visit(CreateTable createTable) {
}
@Override
public void visit(CreateView createView) {
}
@Override
public void visit(AlterView alterView) {
}
@Override
public void visit(Alter alter) {
}
@Override
public void visit(Statements stmts) {
}
@Override
public void visit(Execute execute) {
}
@Override
public void visit(SetStatement set) {
}
@Override
public void visit(Merge merge) {
}
@Override
public void visit(Select select) {
if (select.getWithItemsList() != null) {
for (WithItem item: select.getWithItemsList()) {
item.accept(this);
}
}
if (select.getSelectBody() != null) {
select.getSelectBody().accept(this);
}
}
@Override
public void visit(Upsert upsert) {
}
@Override
public void visit(AllColumns allColumns) {
}
@Override
public void visit(AllTableColumns allTableColumns) {
}
@Override
public void visit(SelectExpressionItem selectExpressionItem) {
selectExpressionItem.getExpression().accept(this);
}
@Override
public void visit(PlainSelect plainSelect) {
scopes.push(new Scope());
if (plainSelect.getSelectItems() != null) {
for (SelectItem item: plainSelect.getSelectItems()) {
item.accept(this);
}
}
FromItemVisitor fromItemVisitor = new FromItemVisitor() {
@Override
public void visit(TableFunction tableFunction) {
}
@Override
public void visit(ValuesList valuesList) {
}
@Override
public void visit(LateralSubSelect lateralSubSelect) {
if (lateralSubSelect.getSubSelect() != null) {
if (lateralSubSelect.getSubSelect().getSelectBody() != null) {
lateralSubSelect.getSubSelect().getSelectBody().accept(APStatementVisitor.this);
}
}
}
@Override
public void visit(SubJoin subjoin) {
if (subjoin.getLeft() != null) {
subjoin.getLeft().accept(this);
}
if (subjoin.getJoin() != null) {
if (subjoin.getJoin().getRightItem() != null) {
subjoin.getJoin().getRightItem().accept(this);
}
if (subjoin.getJoin().getOnExpression() != null) {
scopes.peek().expressions.add(subjoin.getJoin().getOnExpression());
}
}
}
@Override
public void visit(SubSelect subSelect) {
if (subSelect.getSelectBody() != null) {
subSelect.getSelectBody().accept(APStatementVisitor.this);
}
}
@Override
public void visit(Table tableName) {
String alias;
if (tableName.getAlias() != null) {
alias = tableName.getAlias().getName();
} else {
alias = tableName.getName();
}
String fn = "";
if (tableName.getSchemaName() != null) {
fn = Quoting.staticUnquote(tableName.getSchemaName().toUpperCase(Locale.ENGLISH)) + ".";
}
fn += Quoting.staticUnquote(tableName.getName().toUpperCase(Locale.ENGLISH));
scopes.peek().aliasToTable.put(Quoting.staticUnquote(alias.toUpperCase(Locale.ENGLISH)), fn);
}
};
if (plainSelect.getFromItem() != null) {
plainSelect.getFromItem().accept(fromItemVisitor);
}
if (plainSelect.getJoins() != null) {
for (Join join: plainSelect.getJoins()) {
if (join.getOnExpression() != null) {
scopes.peek().expressions.add(join.getOnExpression());
}
if (join.getRightItem() != null) {
join.getRightItem().accept(fromItemVisitor);
}
}
}
if (plainSelect.getWhere() != null) {
scopes.peek().expressions.add(plainSelect.getWhere());
}
for (Expression expr: scopes.peek().expressions) {
expr.accept(this);
}
analyseTopScope();
scopes.pop();
}
@Override
public void visit(SetOperationList setOpList) {
for (SelectBody select: setOpList.getSelects()) {
select.accept(this);
}
}
@Override
public void visit(WithItem withItem) {
if (withItem.getWithItemList() != null) {
for (SelectItem item: withItem.getWithItemList()) {
item.accept(new SelectItemVisitor() {
@Override
public void visit(SelectExpressionItem selectExpressionItem) {
selectExpressionItem.accept(APStatementVisitor.this);
}
@Override
public void visit(AllTableColumns allTableColumns) {
}
@Override
public void visit(AllColumns allColumns) {
}
});
}
}
withItem.getSelectBody().accept(this);
}
@Override
public void visit(SubSelect subSelect) {
if (subSelect.getSelectBody() != null) {
subSelect.getSelectBody().accept(this);
}
}
@Override
public void visit(AnalyticExpression expr) {
}
private void analyseTopScope() {
for (Expression expr: scopes.peek().expressions) {
expr.accept(new ExpressionVisitorAdapter() {
@Override
public void visit(NotExpression aThis) {
}
@Override
public void visit(AllComparisonExpression allComparisonExpression) {
}
@Override
public void visit(ExistsExpression existsExpression) {
}
@Override
public void visit(WhenClause whenClause) {
}
@Override
public void visit(CaseExpression caseExpression) {
}
@Override
public void visit(SubSelect subSelect) {
}
@Override
public void visit(Column tableColumn) {
}
@Override
public void visit(EqualsTo equalsTo) {
Expression leftExpression = equalsTo.getLeftExpression();
Expression rightExpression = equalsTo.getRightExpression();
while (leftExpression instanceof Parenthesis) {
leftExpression = ((Parenthesis) leftExpression).getExpression();
}
while (rightExpression instanceof Parenthesis) {
rightExpression = ((Parenthesis) rightExpression).getExpression();
}
if (leftExpression instanceof Column && rightExpression instanceof Column) {
Column left = (Column) leftExpression;
Column right = (Column) rightExpression;
net.sf.jailer.datamodel.Column leftColumn = getColumn(left);
if (leftColumn != null) {
// TODO: nicht, wenn aliase gleich
// TODO: equalsIgnoreQuoting
net.sf.jailer.datamodel.Column rightColumn = getColumn(right);
if (rightColumn != null) {
equations.add(new Equation(leftColumn, rightColumn, false));
equations.add(new Equation(rightColumn, leftColumn, false));
}
}
}
}
});
}
}
private net.sf.jailer.datamodel.Column getColumn(Column column) {
String alias = column.getTable().getName();
if (alias != null) {
for (boolean withSchema: new boolean[] { true, false }) {
for (int i = scopes.size() - 1; i >= 0; --i) {
String tn = scopes.get(i).aliasToTable.get(Quoting.staticUnquote(alias.toUpperCase(Locale.ENGLISH)));
if (tn != null) {
int iDot = tn.indexOf('.');
String tnSchema;
String tnName;
if (iDot >= 0) {
tnSchema = tn.substring(0, iDot);
tnName = tn.substring(iDot + 1);
} else {
tnSchema = "";
tnName = tn;
}
for (net.sf.jailer.datamodel.Table table: dataModel.getTables()) {
String schema = Quoting.staticUnquote(table.getSchema("").toUpperCase(Locale.ENGLISH));
String uName = Quoting.staticUnquote(table.getUnqualifiedName().toUpperCase(Locale.ENGLISH));
if (uName.equals(tnName)) {
if (!withSchema || schema.equals(tnSchema)) {
String uqColName = Quoting.staticUnquote(column.getColumnName());
for (net.sf.jailer.datamodel.Column dColumn: table.getColumns()) {
if (Quoting.staticUnquote(dColumn.name).equalsIgnoreCase(uqColName)) {
columnToTable.put(dColumn, table);
return dColumn;
}
}
return null;
}
}
}
}
}
}
}
return null;
}
}
private static class Equation {
public final net.sf.jailer.datamodel.Column a;
public final net.sf.jailer.datamodel.Column b;
public final boolean isTransient;
public Equation(net.sf.jailer.datamodel.Column a, net.sf.jailer.datamodel.Column b, boolean isTransient) {
this.a = a;
this.b = b;
this.isTransient = isTransient;
}
public String toString() {
return a + " = " + b;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : System.identityHashCode(a));
result = prime * result + ((b == null) ? 0 : System.identityHashCode(b));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Equation other = (Equation) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (a != other.a)
return false;
if (b == null) {
if (other.b != null)
return false;
} else if (b != other.b)
return false;
return true;
}
public Equation join(Equation other) {
if (b == other.a && a != other.b) {
return new Equation(a, other.b, true);
}
return null;
}
}
private void closeEquations() {
Set<Equation> joined = new HashSet<Equation>();
do {
for (Equation e1: equations) {
for (Equation e2: equations) {
Equation join = e1.join(e2);
if (join != null && !equations.contains(join)) {
joined.add(join);
}
}
}
equations.addAll(joined);
joined.clear();
} while (!joined.isEmpty());
}
private void proposeJoinConditions() {
Set<Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>> pairs = new LinkedHashSet<Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>>();
List<Equation> sortedEquations = new ArrayList<Equation>(equations);
Collections.sort(sortedEquations, new Comparator<Equation>() {
@Override
public int compare(Equation o1, Equation o2) {
net.sf.jailer.datamodel.Table tab1 = columnToTable.get(o1.a);
net.sf.jailer.datamodel.Table tab2 = columnToTable.get(o2.a);
if (tab1 != tab2) {
return tab1.getName().compareTo(tab2.getName());
}
return o1.a.name.compareTo(o2.a.name);
}
});
for (Equation e: sortedEquations) {
net.sf.jailer.datamodel.Table tabA = columnToTable.get(e.a);
net.sf.jailer.datamodel.Table tabB = columnToTable.get(e.b);
if (!pairs.contains(new Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>(tabB, tabA))) {
pairs.add(new Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>(tabA, tabB));
}
}
for (Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table> pair: pairs) {
boolean hasNonTransientEquation = false;
StringBuilder sb = new StringBuilder();
for (Equation e: sortedEquations) {
if (columnToTable.get(e.a) == pair.a) {
if (columnToTable.get(e.b) == pair.b) {
if (!e.isTransient) {
hasNonTransientEquation = true;
}
if (sb.length() > 0) {
sb.append(" and \n");
}
sb.append("A." + e.a.name + " = B." + e.b.name);
}
}
}
if (hasNonTransientEquation) {
String name = ("AP" + (UUID.randomUUID().toString()));
Association association = new Association(pair.a, pair.b, false, false, sb.toString(), dataModel, false, null, "Association Proposer");
Association revAssociation = new Association(pair.b, pair.a, false, false, sb.toString(), dataModel, true, null, "Association Proposer");
association.setName(name);
association.reversalAssociation = revAssociation;
revAssociation.reversalAssociation = association;
addAssociation(name, pair, association, true);
}
}
}
private final List<Association> newAssociations = new ArrayList<Association>();
private final List<Association> newKnownAssociations = new ArrayList<Association>();
private final List<Association> knownAssociations = new ArrayList<Association>();
private final Map<Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>, List<Association>> assocPerSourceDest
= new HashMap<Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table>, List<Association>>();
private void addAssociation(String name, Pair<net.sf.jailer.datamodel.Table, net.sf.jailer.datamodel.Table> pair,
Association association, boolean check) {
List<Association> assocList = assocPerSourceDest.get(pair);
if (assocList == null) {
assocList = new ArrayList<Association>();
assocPerSourceDest.put(pair, assocList);
}
if (check) {
Map<net.sf.jailer.datamodel.Column, net.sf.jailer.datamodel.Column> mapping = association.createSourceToDestinationKeyMapping();
Map<net.sf.jailer.datamodel.Column, net.sf.jailer.datamodel.Column> revMapping = association.reversalAssociation.createSourceToDestinationKeyMapping();
if (!mapping.isEmpty() && !revMapping.isEmpty()) {
for (Association other: assocList) {
Map<net.sf.jailer.datamodel.Column, net.sf.jailer.datamodel.Column> otherMapping = other.createSourceToDestinationKeyMapping();
if (mapping.equals(otherMapping) || revMapping.equals(otherMapping)) {
if (fromDataModel.contains(other) && !knownAssociations.contains(other)) {
newKnownAssociations.add(association);
knownAssociations.add(other);
}
return;
}
}
}
}
assocList.add(association);
if (check) {
newAssociations.add(association);
}
}
public synchronized List<Association> pickUpNewAssociations() {
ArrayList<Association> result = new ArrayList<Association>(newAssociations);
newAssociations.clear();
return result;
}
public synchronized List<Association> pickUpKnownAssociations() {
ArrayList<Association> result = new ArrayList<Association>(newKnownAssociations);
newKnownAssociations.clear();
return result;
}
}
@@ -0,0 +1,350 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-118,0,0,1,-112"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="4" insetsBottom="4" insetsRight="4" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JProgressBar" name="jProgressBar1">
<Properties>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="6" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="statusLabel">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="0" id="blue" palette="1" red="0" type="palette"/>
</Property>
<Property name="text" type="java.lang.String" value="Ready"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="7" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="8" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="closeButton">
<Properties>
<Property name="text" type="java.lang.String" value="Close"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="100" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="14" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JTabbedPane" name="tabbedPane">
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" value=""/>
</AccessibilityProperties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="15" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="propsTabPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Proposals">
<Property name="tabTitle" type="java.lang.String" value="Proposals"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel3">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="10" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="2.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="proposalTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="4" rowCount="4">
<Column editable="true" title="Title 1" type="java.lang.Object"/>
<Column editable="true" title="Title 2" type="java.lang.Object"/>
<Column editable="true" title="Title 3" type="java.lang.Object"/>
<Column editable="true" title="Title 4" type="java.lang.Object"/>
</Table>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel4">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="selectAllButton">
<Properties>
<Property name="text" type="java.lang.String" value="Select all"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectAllButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="deselectAllButton">
<Properties>
<Property name="text" type="java.lang.String" value="Deselect all"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deselectAllButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="acceptButton">
<Properties>
<Property name="text" type="java.lang.String" value="Accept selected proposals"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="acceptButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel7">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="50" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="8" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="panel8">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Condition Editor"/>
</Border>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.6"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="conditionEditorPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
<Component class="javax.swing.JButton" name="applyButton">
<Properties>
<Property name="text" type="java.lang.String" value="Apply"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="applyButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="11" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="knownPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Known">
<Property name="tabTitle" type="java.lang.String" value="Known"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="knownTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="4" rowCount="4">
<Column editable="true" title="Title 1" type="java.lang.Object"/>
<Column editable="true" title="Title 2" type="java.lang.Object"/>
<Column editable="true" title="Title 3" type="java.lang.Object"/>
<Column editable="true" title="Title 4" type="java.lang.Object"/>
</Table>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="problemTabPanel">
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
</AccessibilityProperties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Problems">
<Property name="tabTitle" type="java.lang.String" value="Problems"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="loadButton">
<Properties>
<Property name="text" type="java.lang.String" value="Load and Analyze SQL Script"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="loadButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="8" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="emptyLineCheckBox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Empty line separates statements"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="12" insetsBottom="8" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="dummyLabel1">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="69" red="0" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" value=" "/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="7" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="text" type="java.lang.String" value="Analyzes SQL statements and proposes association definitions."/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="4" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="8" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -0,0 +1,920 @@
/*
* Copyright 2007 - 2018 the original author or authors.
*
* 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.associationproposer;
import java.awt.Color;
import java.awt.Component;
import java.awt.TextArea;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.fife.rsta.ui.EscapableDialog;
import org.fife.ui.rtextarea.RTextScrollPane;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.modelbuilder.ModelBuilder;
import net.sf.jailer.ui.DataModelEditor;
import net.sf.jailer.ui.UIUtil;
import net.sf.jailer.ui.databrowser.sqlconsole.SQLPlusSupport;
import net.sf.jailer.ui.syntaxtextarea.DataModelBasedSQLCompletionProvider;
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;
import net.sf.jailer.util.Quoting;
/**
* Analyzes SQL statements and proposes association definitions.
*
* @author Ralf Wisser
*/
public class AssociationProposerView extends javax.swing.JPanel {
// TODO: Docu Label mit Infos, was ein SQL Script ist
private int numErrors;
private RSyntaxTextAreaWithSQLSyntaxStyle editorPane;
private TextArea checksPane;
private DefaultTableModel proposalsModel;
private DefaultTableModel knownModel;
private final DataModel dataModel;
private JDialog dialog;
final AssociationProposer associationProposer;
private DataModelBasedSQLCompletionProvider provider;
private final ExecutionContext executionContext;
/**
* Creates new form ConstraintChecker
* @param scriptFile file to load, if not <code>null</code>
*/
public AssociationProposerView(JFrame owner, DataModel dataModel, final File scriptFile, ExecutionContext executionContext) {
this.dataModel = dataModel;
this.associationProposer = new AssociationProposer(dataModel);
this.executionContext = executionContext;
initComponents();
editorPane = new RSyntaxTextAreaWithSQLSyntaxStyle(false, false) {
@Override
protected void runBlock() {
super.runBlock();
applyButtonActionPerformed(null);
}
};
if (dataModel != null) {
try {
provider = new DataModelBasedSQLCompletionProvider(null, dataModel);
provider.setDefaultClause(SQLCompletionProvider.Clause.WHERE);
new SQLAutoCompletion(provider, editorPane);
} catch (SQLException e) {
}
}
editorPane.setRows(6);
editorPane.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update() {
applyButton.setEnabled(true);
}
});
RTextScrollPane jScrollPane = new RTextScrollPane();
jScrollPane.setViewportView(editorPane);
conditionEditorPanel.add(jScrollPane);
jScrollPane.setLineNumbersEnabled(true);
checksPane = new TextArea();
checksPane.setEditable(false);
JScrollPane jScrollPane2 = new JScrollPane();
jScrollPane2.setViewportView(checksPane);
problemTabPanel.add(jScrollPane2);
statusLabel.setVisible(false);
proposalTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
proposalsModel = new DefaultTableModel(new String[] { " ", "A", "B", "Condition" }, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return column == 0;
}
@Override
public void setValueAt(Object aValue, int row, int column) {
super.setValueAt(aValue, row, column);
updateButtonsState();
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if(columnIndex == 0){
return Boolean.class;
}
return super.getColumnClass(columnIndex);
}
};
final JCheckBox checkBox = new JCheckBox(" ");
checkBox.setHorizontalAlignment(SwingConstants.RIGHT);
DefaultCellEditor anEditor = new DefaultCellEditor(checkBox);
anEditor.setClickCountToStart(1);
proposalTable.setDefaultEditor(Boolean.class, anEditor);
proposalTable.setModel(proposalsModel);
final TableCellRenderer defaultTableCellRenderer = proposalTable.getDefaultRenderer(String.class);
TableCellRenderer renderer = new TableCellRenderer() {
final Color BG1 = new Color(255, 255, 255);
final Color BG2 = new Color(230, 255, 255);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component render = defaultTableCellRenderer.getTableCellRendererComponent(table, value, isSelected, false, row, column);
if (value instanceof Boolean) {
JCheckBox checkBox = new JCheckBox(" ");
checkBox.setHorizontalAlignment(SwingConstants.RIGHT);
checkBox.setSelected(Boolean.TRUE.equals(value));
render = checkBox;
}
if (!isSelected) {
render.setBackground((row % 2 == 0) ? BG1 : BG2);
}
if (render instanceof JLabel) {
((JLabel) render).setToolTipText(UIUtil.toHTML(String.valueOf(value), 200));
}
return render;
}
};
proposalTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
proposalTable.setDefaultRenderer(Object.class, renderer);
proposalTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateConditionEditorState();
}
});
proposalTable.setAutoCreateRowSorter(true);
List<SortKey> keys = new ArrayList<SortKey>();
keys.add(new SortKey(1, SortOrder.ASCENDING));
keys.add(new SortKey(2, SortOrder.ASCENDING));
proposalTable.getRowSorter().setSortKeys(keys);
knownModel = new DefaultTableModel(new String[] { "A", "B", "Condition" }, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
knownTable.setModel(knownModel);
knownTable.setAutoCreateRowSorter(true);
knownTable.setRowSelectionAllowed(false);
knownTable.setDefaultRenderer(Object.class, renderer);
keys = new ArrayList<SortKey>();
keys.add(new SortKey(0, SortOrder.ASCENDING));
keys.add(new SortKey(1, SortOrder.ASCENDING));
knownTable.getRowSorter().setSortKeys(keys);
updateButtonsState();
updateConditionEditorState();
if (scriptFile != null) {
loadButton.setVisible(false);
emptyLineCheckBox.setSelected(true);
emptyLineCheckBox.setVisible(false);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
loadSQLScript(scriptFile);
}
});
}
dialog = new EscapableDialog(owner, "Analyze SQL") {
};
dialog.setModal(true);
dialog.getContentPane().add(this);
dialog.pack();
dialog.setSize(800, 600);
dialog.setLocation(owner.getX() + (owner.getWidth() - dialog.getWidth()) / 2, Math.max(0, owner.getY() + (owner.getHeight() - dialog.getHeight()) / 2));
UIUtil.fit(dialog);
dialog.setVisible(true);
}
private void updateConditionEditorState() {
int i = proposalTable.getSelectedRow();
if (i >= 0) {
editorPane.setText(String.valueOf(proposalsModel.getValueAt(i, 3)));
editorPane.setCaretPosition(0);
editorPane.setEnabled(true);
editorPane.setEditable(true);
applyButton.setEnabled(false);
if (provider != null) {
provider.removeAliases();
Table table1 = newAssociations.get(i).source;
Table table2 = newAssociations.get(i).destination;
if (table1 != null) {
provider.addAlias("A", table1);
}
if (table2 != null) {
provider.addAlias("B", table2);
}
}
} else {
editorPane.setText("");
editorPane.setEnabled(false);
editorPane.setEditable(false);
applyButton.setEnabled(false);
}
}
private void applyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyButtonActionPerformed
int i = proposalTable.getSelectedRow();
if (i >= 0) {
proposalsModel.setValueAt(editorPane.getText(), i, 3);
applyButton.setEnabled(false);
}
}//GEN-LAST:event_applyButtonActionPerformed
private boolean allowButtonUpdates = true;
private void updateButtonsState() {
if (allowButtonUpdates) {
if (proposalsModel.getRowCount() == 0) {
selectAllButton.setEnabled(false);
deselectAllButton.setEnabled(false);
acceptButton.setEnabled(false);
} else {
boolean allSelected = true;
boolean allDeSelected = true;
boolean hasSelected = false;
for (int i = 0; i < proposalsModel.getRowCount(); ++i) {
if (Boolean.TRUE.equals(proposalsModel.getValueAt(i, 0))) {
hasSelected = true;
allDeSelected = false;
} else {
allSelected = false;
}
}
selectAllButton.setEnabled(!allSelected);
deselectAllButton.setEnabled(!allDeSelected);
acceptButton.setEnabled(hasSelected);
}
}
}
private void loadSQLScript(File sqlFile) {
if (sqlFile == null) {
String fn = UIUtil.choseFile(null, ".", "Load SQL Script", "", this, false, true);
if (fn == null) {
return;
}
sqlFile = new File(fn);
}
try {
loadButton.setEnabled(false);
final File file = sqlFile;
jProgressBar1.setMaximum(1000);
final boolean emptyLineSeparates = emptyLineCheckBox.isSelected();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
FileInputStream inputStream = new FileInputStream(file);
long fileSize = Math.max(file.length(), 1);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
SQLPlusSupport sqlPlusSupport = new SQLPlusSupport();
String line = null;
StringBuffer currentStatement = new StringBuffer();
long bytesRead = 0;
LineReader lineReader = new LineReader(bufferedReader);
int lineNr = 0;
while ((line = lineReader.readLine()) != null) {
++lineNr;
bytesRead += line.length() + 1;
line = line.trim();
if (line.startsWith("--")) {
continue;
}
if (line.endsWith(";") || emptyLineSeparates && line.length() == 0) {
if (line.length() > 0) {
currentStatement.append(line.substring(0, line.length() - 1));
}
String stmt = currentStatement.toString().trim();
if (stmt.length() > 0) {
stmt =
stmt
.replaceFirst("(?is)(;\\s*)+$", "")
.replaceAll("((?:(?:;(?: |\\t|\\r)*?(?:--[^\\n]*)?))) ?\\\\([ \\t\\r]*\\n)", "$1$2")
.replaceAll("((?:\\n(?: |\\t|\\r)*?)) ?\\\\([ \\t\\r]*)(?=\\n)", "$1");
stmt = sqlPlusSupport.replaceVariables(stmt, null);
if (!sqlPlusSupport.executeSQLPLusStatement(stmt)) {
addResult(bytesRead * 1000L / fileSize, null, null, associationProposer.analyze(stmt, lineNr));
}
}
currentStatement.setLength(0);
} else {
currentStatement.append(line + " \n");
}
}
bufferedReader.close();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
addResult(1000L, associationProposer.pickUpNewAssociations(), associationProposer.pickUpKnownAssociations(), null);
jProgressBar1.setValue(1000);
loadButton.setEnabled(true);
}
});
} catch (Throwable e) {
final Throwable fe = e;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
UIUtil.showException(AssociationProposerView.this, "Error", fe);
loadButton.setEnabled(true);
}
});
}
}});
thread.setDaemon(true);
thread.start();
} catch (Throwable e) {
UIUtil.showException(this, "Error", e);
}
}
private List<Association> newAssociations = new ArrayList<Association>();
private final int MAX_ERRORS = 1000;
private void addResult(final long progess, final List<Association> associations, final List<Association> knownAssociations, final String error) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (error != null) {
++numErrors;
if (numErrors == MAX_ERRORS) {
checksPane.append("more...\n");
} else if (numErrors < MAX_ERRORS) {
checksPane.append(error + "\n");
}
}
if (associations != null) {
for (Association association: associations) {
newAssociations.add(association);
proposalsModel.addRow(new Object[] { true, association.source.getName(), association.destination.getName(), association.getUnrestrictedJoinCondition() });
}
}
if (knownAssociations != null) {
for (Association association: knownAssociations) {
newAssociations.add(association);
knownModel.addRow(new Object[] { association.source.getName(), association.destination.getName(), association.getUnrestrictedJoinCondition() });
}
}
if (associations != null || knownAssociations != null) {
statusLabel.setVisible(true);
statusLabel.setText(proposalsModel.getRowCount() + " Proposals, " + knownModel.getRowCount() + " already known associations, " + numErrors + " Problems");
adjustTableColumnsWidth();
}
jProgressBar1.setValue((int) progess);
updateButtonsState();
}
});
}
/**
* 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jPanel1 = new javax.swing.JPanel();
jProgressBar1 = new javax.swing.JProgressBar();
statusLabel = new javax.swing.JLabel();
closeButton = new javax.swing.JButton();
tabbedPane = new javax.swing.JTabbedPane();
propsTabPanel = new javax.swing.JPanel();
jPanel3 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
proposalTable = new javax.swing.JTable();
jPanel4 = new javax.swing.JPanel();
selectAllButton = new javax.swing.JButton();
deselectAllButton = new javax.swing.JButton();
acceptButton = new javax.swing.JButton();
jPanel7 = new javax.swing.JPanel();
panel8 = new javax.swing.JPanel();
conditionEditorPanel = new javax.swing.JPanel();
applyButton = new javax.swing.JButton();
knownPanel = new javax.swing.JPanel();
jScrollPane2 = new javax.swing.JScrollPane();
knownTable = new javax.swing.JTable();
problemTabPanel = new javax.swing.JPanel();
loadButton = new javax.swing.JButton();
emptyLineCheckBox = new javax.swing.JCheckBox();
dummyLabel1 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jSeparator1 = new javax.swing.JSeparator();
setLayout(new java.awt.GridBagLayout());
jPanel1.setLayout(new java.awt.GridBagLayout());
jProgressBar1.setStringPainted(true);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
jPanel1.add(jProgressBar1, gridBagConstraints);
statusLabel.setForeground(java.awt.Color.blue);
statusLabel.setText("Ready");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 7;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(2, 0, 8, 0);
jPanel1.add(statusLabel, gridBagConstraints);
closeButton.setText("Close");
closeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 100;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
jPanel1.add(closeButton, gridBagConstraints);
propsTabPanel.setLayout(new java.awt.GridBagLayout());
jPanel3.setLayout(new java.awt.GridBagLayout());
jPanel2.setLayout(new java.awt.GridBagLayout());
proposalTable.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"
}
));
jScrollPane1.setViewportView(proposalTable);
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(jScrollPane1, gridBagConstraints);
jPanel4.setLayout(new java.awt.GridBagLayout());
selectAllButton.setText("Select all");
selectAllButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selectAllButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
jPanel4.add(selectAllButton, gridBagConstraints);
deselectAllButton.setText("Deselect all");
deselectAllButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deselectAllButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
jPanel4.add(deselectAllButton, gridBagConstraints);
acceptButton.setText("Accept selected proposals");
acceptButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
acceptButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 1.0;
jPanel4.add(acceptButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
jPanel2.add(jPanel4, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 2.0;
gridBagConstraints.weighty = 1.0;
jPanel3.add(jPanel2, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 10;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
propsTabPanel.add(jPanel3, gridBagConstraints);
jPanel7.setLayout(new java.awt.GridBagLayout());
panel8.setBorder(javax.swing.BorderFactory.createTitledBorder("Condition Editor"));
panel8.setLayout(new java.awt.GridBagLayout());
conditionEditorPanel.setLayout(new java.awt.BorderLayout());
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;
panel8.add(conditionEditorPanel, gridBagConstraints);
applyButton.setText("Apply");
applyButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
applyButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
panel8.add(applyButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.6;
jPanel7.add(panel8, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 50;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(8, 0, 0, 0);
propsTabPanel.add(jPanel7, gridBagConstraints);
tabbedPane.addTab("Proposals", propsTabPanel);
knownPanel.setLayout(new java.awt.BorderLayout());
knownTable.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"
}
));
jScrollPane2.setViewportView(knownTable);
knownPanel.add(jScrollPane2, java.awt.BorderLayout.CENTER);
tabbedPane.addTab("Known", knownPanel);
problemTabPanel.setLayout(new java.awt.BorderLayout());
tabbedPane.addTab("Problems", problemTabPanel);
problemTabPanel.getAccessibleContext().setAccessibleName("");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 15;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanel1.add(tabbedPane, gridBagConstraints);
tabbedPane.getAccessibleContext().setAccessibleDescription("");
loadButton.setText("Load and Analyze SQL Script");
loadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
loadButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 8, 0);
jPanel1.add(loadButton, gridBagConstraints);
emptyLineCheckBox.setSelected(true);
emptyLineCheckBox.setText("Empty line separates statements");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 12, 8, 0);
jPanel1.add(emptyLineCheckBox, gridBagConstraints);
dummyLabel1.setForeground(new java.awt.Color(0, 105, 0));
dummyLabel1.setText(" ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 7;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
jPanel1.add(dummyLabel1, gridBagConstraints);
jLabel5.setText("Analyzes SQL statements and proposes association definitions.");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 0);
jPanel1.add(jLabel5, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 8, 0);
jPanel1.add(jSeparator1, 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, 4, 4);
add(jPanel1, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
dialog.dispose();
}//GEN-LAST:event_closeButtonActionPerformed
private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadButtonActionPerformed
loadSQLScript(null);
}//GEN-LAST:event_loadButtonActionPerformed
private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllButtonActionPerformed
setProposalsSelected(true);
}//GEN-LAST:event_selectAllButtonActionPerformed
private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed
setProposalsSelected(false);
}//GEN-LAST:event_deselectAllButtonActionPerformed
private void acceptButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_acceptButtonActionPerformed
acceptProposals();
}//GEN-LAST:event_acceptButtonActionPerformed
private void setProposalsSelected(boolean selected) {
allowButtonUpdates = false;
try {
for (int i = 0; i < proposalsModel.getRowCount(); ++i) {
proposalsModel.setValueAt(selected, i, 0);
}
} finally {
allowButtonUpdates = true;
updateButtonsState();
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton acceptButton;
private javax.swing.JButton applyButton;
private javax.swing.JButton closeButton;
private javax.swing.JPanel conditionEditorPanel;
private javax.swing.JButton deselectAllButton;
private javax.swing.JLabel dummyLabel1;
private javax.swing.JCheckBox emptyLineCheckBox;
private javax.swing.JLabel jLabel5;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JPanel jPanel7;
private javax.swing.JProgressBar jProgressBar1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JPanel knownPanel;
private javax.swing.JTable knownTable;
private javax.swing.JButton loadButton;
private javax.swing.JPanel panel8;
private javax.swing.JPanel problemTabPanel;
private javax.swing.JTable proposalTable;
private javax.swing.JPanel propsTabPanel;
private javax.swing.JButton selectAllButton;
private javax.swing.JLabel statusLabel;
private javax.swing.JTabbedPane tabbedPane;
// End of variables declaration//GEN-END:variables
static final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
static {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (;;) {
try {
queue.take().run();
} catch (Throwable t) {
}
}
}
});
thread.setDaemon(true);
thread.start();
}
public void adjustTableColumnsWidth() {
adjustTableColumnsWidth(proposalTable, true);
adjustTableColumnsWidth(knownTable, false);
}
public void adjustTableColumnsWidth(JTable table, boolean fixFirstColumn) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn column = table.getColumnModel().getColumn(i);
Component comp = table.getDefaultRenderer(String.class).getTableCellRendererComponent(table, column.getHeaderValue(), false, false, 0, i);
int width = 1;
width = Math.max(width, comp.getPreferredSize().width);
int line = 0;
for (; line < table.getRowCount(); ++line) {
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, 500));
if (i == 0 && fixFirstColumn) {
column.setWidth(column.getPreferredWidth());
}
}
}
private static class LineReader {
private final BufferedReader reader;
private boolean eofRead = false;
public LineReader(BufferedReader reader) {
this.reader = reader;
}
public String readLine() throws IOException {
String line = reader.readLine();
if (line == null && !eofRead) {
eofRead = true;
return ";";
}
return line;
}
}
private boolean accepted = false;
public boolean isAccepted() {
return accepted;
}
private void acceptProposals() {
try {
List<String> names = new ArrayList<String>();
for (int i = 0; i < proposalsModel.getRowCount(); ++i) {
if (Boolean.TRUE.equals(proposalsModel.getValueAt(i, 0))) {
names.add("P_" + Quoting.staticUnquote(String.valueOf(proposalsModel.getValueAt(i, 1))) + "_" + Quoting.staticUnquote(String.valueOf(proposalsModel.getValueAt(i, 2))));
} else {
names.add("?");
}
}
Map<String, Integer> nameCount = new HashMap<String, Integer>();
for (String name: names) {
Integer count = nameCount.get(name);
if (count == null) {
count = 1;
} else {
++count;
}
nameCount.put(name, count);
}
for (int i = 0; i < names.size(); ++i) {
String name = names.get(i);
int n = 0;
while (nameCount.get(name) != null && nameCount.get(name) > 1 || dataModel.namedAssociations.containsKey(name)) {
name = names.get(i) + "_" + (++n);
}
if (n > 0) {
nameCount.put(name, 2);
}
names.set(i, name);
}
BufferedWriter out = new BufferedWriter(new FileWriter(ModelBuilder.getModelBuilderAssociationsFilename(executionContext)));
out.append("\n");
for (int i = 0; i < proposalsModel.getRowCount(); ++i) {
if (Boolean.TRUE.equals(proposalsModel.getValueAt(i, 0))) {
String condition = String.valueOf(proposalsModel.getValueAt(i, 3));
condition = condition.replaceAll(" *\\n", " ");
out.append(
CsvFile.encodeCell(String.valueOf(proposalsModel.getValueAt(i, 1))) + "; " +
CsvFile.encodeCell(String.valueOf(proposalsModel.getValueAt(i, 2))) + "; ; ; " +
CsvFile.encodeCell(condition) + "; " + names.get(i) + "; " + DataModelEditor.DATA_MODEL_EDITOR_AUTHOR + "\n");
}
}
out.close();
accepted = true;
dialog.dispose();
} catch (Throwable t) {
UIUtil.showException(this, "Error", t);
}
}
}
@@ -1,7 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Copyright 2007 - 2018 the original author or authors.
*
* 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.constraintcheck;
@@ -48,8 +58,9 @@ import net.sf.jailer.util.CancellationHandler;
import net.sf.jailer.util.SqlUtil;
/**
*
* @author RalfW
* Checks FK constraints.
*
* @author Ralf Wisser
*/
public abstract class ConstraintChecker extends javax.swing.JPanel {
@@ -165,6 +165,16 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="dataModelEditorjMenuItemActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JPopupMenu$Separator" name="jSeparator11">
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="analyseSQLMenuItem1">
<Properties>
<Property name="text" type="java.lang.String" value="Analyze SQL Script"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="analyseSQLMenuItem1ActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JPopupMenu$Separator" name="jSeparator10">
</MenuItem>
<MenuItem class="javax.swing.JCheckBoxMenuItem" name="showDataModelMenuItem">
@@ -66,6 +66,7 @@ import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
@@ -115,6 +116,7 @@ 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.associationproposer.AssociationProposerView;
import net.sf.jailer.ui.Environment;
import net.sf.jailer.ui.ExtractionModelFrame;
import net.sf.jailer.ui.ImportDialog;
@@ -924,6 +926,8 @@ public class DataBrowser extends javax.swing.JFrame {
menuTools = new javax.swing.JMenu();
analyseMenuItem = new javax.swing.JMenuItem();
dataModelEditorjMenuItem = 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();
schemaMappingMenuItem = new javax.swing.JMenuItem();
@@ -1136,7 +1140,7 @@ public class DataBrowser extends javax.swing.JFrame {
jLayeredPane1.setLayer(layeredPaneContent, javax.swing.JLayeredPane.PALETTE_LAYER);
jLayeredPane1.add(layeredPaneContent);
layeredPaneContent.setBounds(0, 0, 26, 59);
layeredPaneContent.setBounds(0, 0, 24, 58);
desktopSplitPane.setLeftComponent(jLayeredPane1);
@@ -1489,6 +1493,15 @@ public class DataBrowser extends javax.swing.JFrame {
}
});
menuTools.add(dataModelEditorjMenuItem);
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");
@@ -1938,7 +1951,7 @@ public class DataBrowser extends javax.swing.JFrame {
}// GEN-LAST:event_analyseMenuItemActionPerformed
private void dataModelEditorjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_dataModelEditorjMenuItemActionPerformed
openDataModelEditor();
openDataModelEditor(false);
}// GEN-LAST:event_dataModelEditorjMenuItemActionPerformed
/**
@@ -2106,10 +2119,10 @@ public class DataBrowser extends javax.swing.JFrame {
/**
* Opens the data model editor.
*/
private void openDataModelEditor() {
private void openDataModelEditor(boolean merge) {
try {
String modelname = datamodel == null || datamodel.get() == null ? DataModel.DEFAULT_NAME : datamodel.get().getName();
DataModelEditor dataModelEditor = new DataModelEditor(this, false, false, null, null, null, modelname, null, executionContext);
DataModelEditor dataModelEditor = new DataModelEditor(this, merge, false, null, null, null, modelname, null, executionContext);
dataModelEditor.setVisible(true);
removeMetaDataSource(session);
desktop.reloadDataModel(desktop.schemaMapping);
@@ -2186,6 +2199,7 @@ public class DataBrowser extends javax.swing.JFrame {
private javax.swing.JMenuItem aboutMenuItem;
private javax.swing.JPanel addSQLConsoleTab;
private javax.swing.JMenuItem analyseMenuItem;
private javax.swing.JMenuItem analyseSQLMenuItem1;
private javax.swing.JLabel associatedWith;
private javax.swing.JPanel borderBrowserPanel;
private javax.swing.JPanel borderBrowserTabPane;
@@ -2243,6 +2257,7 @@ public class DataBrowser extends javax.swing.JFrame {
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 jSeparator3;
private javax.swing.JPopupMenu.Separator jSeparator4;
@@ -2330,7 +2345,7 @@ public class DataBrowser extends javax.swing.JFrame {
updateDataModel();
break;
case 1:
openDataModelEditor();
openDataModelEditor(false);
break;
}
} else if (!new File(DataModel.getColumnsFile(executionContext)).exists()) {
@@ -2340,7 +2355,7 @@ public class DataBrowser extends javax.swing.JFrame {
updateDataModel();
break;
case 1:
openDataModelEditor();
openDataModelEditor(false);
break;
}
}
@@ -3127,6 +3142,16 @@ public class DataBrowser extends javax.swing.JFrame {
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;
@@ -3285,6 +3310,13 @@ public class DataBrowser extends javax.swing.JFrame {
}
}//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 MetaDataDetailsPanel metaDataDetailsPanel;
private List<SQLConsoleWithTitle> sqlConsoles = new ArrayList<SQLConsoleWithTitle>();
@@ -90,6 +90,7 @@ 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;
@@ -102,6 +103,7 @@ 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.DataBrowser;
@@ -155,7 +157,10 @@ public abstract class SQLConsole extends javax.swing.JPanel {
private final ImageIcon scaledExplainIcon;
private final SQLPlusSupport sqlPlusSupport = new SQLPlusSupport();
private File file;
private JMenuItem menuItemToggle;
private JMenuItem menuItemSubstituteVariables;
private JMenuItem menuItemAnalyse;
private final String IGNORED_STATEMENTS = "(\\s*/\\s*)";
/**
@@ -178,7 +183,7 @@ public abstract class SQLConsole extends javax.swing.JPanel {
this.datamodel = datamodel;
this.executionContext = executionContext;
initComponents();
initMenuItems();
historyComboBox.setMaximumRowCount(25);
GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
@@ -214,6 +219,10 @@ public abstract class SQLConsole extends javax.swing.JPanel {
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();
@@ -262,34 +271,10 @@ public abstract class SQLConsole extends javax.swing.JPanel {
@Override
protected void appendPopupMenu(JPopupMenu menu) {
menu.addSeparator();
JMenuItem item = new JMenuItem("Toggle Line Continuation");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
toggleLineContinuation();
}
});
item.setToolTipText(
"<html>Adds (or remove) line-continuation-character ('\\') <br>" +
" to each line terminated by ';' <br>"
+ "(allowing you to execute PL/SQL code)");
menu.add(item);
item = new JMenuItem("Substitute Variables");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
substituteVariables();
}
});
item.setToolTipText(
"<html>Substitutes variables <i>(&amp;VAR[.])</i> with corresponding values. <br><br>\n" +
"<b>Statements:</b>\n" +
"<table>\n" +
"<tr><td><b>&nbsp;DEFINE VAR=\"VALUE\"</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>Assigns a value to variable VAR</td></tr>\n" +
"<tr><td><b>&nbsp;DEFINE</b></td><td></td><td>Lists all variables</td></tr>\n" +
"<tr><td><b>&nbsp;&amp;VAR</b>&nbsp;&nbsp;or&nbsp;&nbsp;<b>&nbsp;&amp;VAR.</b></td><td></td><td>Variable substitution (inside other statements)</td></tr>\n" +
"</table>");
menu.add(item);
menu.add(menuItemToggle);
menu.add(menuItemSubstituteVariables);
menu.addSeparator();
menu.add(menuItemAnalyse);
}
};
@@ -399,12 +384,67 @@ public abstract class SQLConsole extends javax.swing.JPanel {
thread.start();
}
private static int threadNum = 1;
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(
"<html>Adds (or remove) line-continuation-character ('\\') <br>" +
" to each line terminated by ';' <br>"
+ "(allowing you to execute PL/SQL code)");
item = new JMenuItem("Substitute Variables");
item.setEnabled(false);
menuItemSubstituteVariables = item;
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
substituteVariables();
}
});
item.setToolTipText(
"<html>Substitutes variables <i>(&amp;VAR[.])</i> with corresponding values. <br><br>\n" +
"<b>Statements:</b>\n" +
"<table>\n" +
"<tr><td><b>&nbsp;DEFINE VAR=\"VALUE\"</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>Assigns a value to variable VAR</td></tr>\n" +
"<tr><td><b>&nbsp;DEFINE</b></td><td></td><td>Lists all variables</td></tr>\n" +
"<tr><td><b>&nbsp;&amp;VAR</b>&nbsp;&nbsp;or&nbsp;&nbsp;<b>&nbsp;&amp;VAR.</b></td><td></td><td>Variable substitution (inside other statements)</td></tr>\n" +
"</table>");
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 (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;
@@ -1112,6 +1152,8 @@ public abstract class SQLConsole extends javax.swing.JPanel {
protected abstract void refreshMetaData();
protected abstract void selectTable(MDTable mdTable);
protected abstract void setOutlineTables(List<OutlineInfo> outlineTables, int indexOfInfoAtCaret);
protected abstract JFrame getOwner();
protected abstract void openDataModelEditor(boolean merge);
private boolean dataHasChanged = false;
@@ -1939,6 +1981,29 @@ public abstract class SQLConsole extends javax.swing.JPanel {
}
}
private void analyzeSQL() {
String currentStatement = editorPane.getCurrentStatement(false);
File tempFile = Configuration.getInstance().createTempFile();
try {
BufferedWriter out = new BufferedWriter(new FileWriter(tempFile));
Pair<Integer, Integer> 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);
@@ -37,7 +37,6 @@ import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowSorter;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.TableColumnModel;
@@ -4,7 +4,6 @@ import java.awt.Component;
import java.awt.ComponentOrientation;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
@@ -4,7 +4,6 @@ import java.awt.Component;
import java.awt.ComponentOrientation;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
@@ -888,6 +888,7 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement
} else {
loc = getCurrentStatementLocation(eosLines);
}
updateMenuItems(loc != null && !isTextEmpty(loc.a, loc.b));
runBlock.setEnabled(allowRun && loc != null && !isTextEmpty(loc.a, loc.b));
explain.setEnabled(canExplain() && allowRun && loc != null && !isTextEmpty(loc.a, loc.b));
runAll.setEnabled(allowRun && RSyntaxTextAreaWithSQLSyntaxStyle.this.getDocument().getLength() > 0);
@@ -1094,6 +1095,9 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement
}
}
protected void updateMenuItems(boolean isTextSelected) {
}
private ImageIcon icon;
private ImageIcon iconBegin;
private ImageIcon iconBeginEnd;