mirror of
https://github.com/Wisser/Jailer.git
synced 2026-05-24 11:39:31 -05:00
introducing AssociationProposer
This commit is contained in:
@@ -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>(&VAR[.])</i> with corresponding values. <br><br>\n" +
|
||||
"<b>Statements:</b>\n" +
|
||||
"<table>\n" +
|
||||
"<tr><td><b> DEFINE VAR=\"VALUE\"</b></td><td> </td><td>Assigns a value to variable VAR</td></tr>\n" +
|
||||
"<tr><td><b> DEFINE</b></td><td></td><td>Lists all variables</td></tr>\n" +
|
||||
"<tr><td><b> &VAR</b> or <b> &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>(&VAR[.])</i> with corresponding values. <br><br>\n" +
|
||||
"<b>Statements:</b>\n" +
|
||||
"<table>\n" +
|
||||
"<tr><td><b> DEFINE VAR=\"VALUE\"</b></td><td> </td><td>Assigns a value to variable VAR</td></tr>\n" +
|
||||
"<tr><td><b> DEFINE</b></td><td></td><td>Lists all variables</td></tr>\n" +
|
||||
"<tr><td><b> &VAR</b> or <b> &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;
|
||||
|
||||
Reference in New Issue
Block a user