package com.github.ryhmrt.mssqldiff;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeModel;
import com.github.ryhmrt.mssqldiff.convertor.TableListConvertor;
import com.github.ryhmrt.mssqldiff.csv.SchemaCsv;
import com.github.ryhmrt.mssqldiff.csv.SchemaCsvReaderFileImpl;
import com.github.ryhmrt.mssqldiff.data.Diff;
import com.github.ryhmrt.mssqldiff.data.Diff.Type;
import com.github.ryhmrt.mssqldiff.data.Table;
import com.github.ryhmrt.mssqldiff.data.TableDiff;
import com.github.ryhmrt.mssqldiff.differ.ListDiffer;
import com.github.ryhmrt.mssqldiff.differ.TableDiffer;
import com.github.ryhmrt.mssqldiff.gui.CsvFileSelector;
import com.github.ryhmrt.mssqldiff.util.SqlUtil;
public class Main {
private JFrame jFrame = null; // @jve:decl-index=0:visual-constraint="10,10"
private JPanel jContentPane = null;
private JMenuBar jJMenuBar = null;
private JMenu fileMenu = null;
private JMenu helpMenu = null;
private JMenuItem exitMenuItem = null;
private JMenuItem aboutMenuItem = null;
private JDialog aboutDialog = null; // @jve:decl-index=0:visual-constraint="520,10"
private JPanel aboutContentPane = null;
private JLabel aboutVersionLabel = null;
private CsvFileSelector fromCsvFileSelector = null;
private JPanel csvFilePanel = null;
private CsvFileSelector toCsvFileSelector = null;
private JPanel summaryPanel = null;
private JButton diffButton = null;
private JTree summaryTree = null;
private JSplitPane resultPane = null;
private JTextPane detailPane = null;
private JLabel fromLabel = null;
private JLabel toLabel = null;
private JScrollPane summaryTreeScrollPane = null;
private JScrollPane detailScrollPane = null;
private JPanel diffExecutePanel = null;
private JCheckBox ignorePermissionCheck = null;
private List<TableDiff> tableDiffs = Collections.emptyList(); // @jve:decl-index=0:
/**
* This method initializes jFrame
*
* @return javax.swing.JFrame
*/
private JFrame getJFrame() {
if (jFrame == null) {
jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setJMenuBar(getJJMenuBar());
jFrame.setSize(500, 400);
jFrame.setContentPane(getJContentPane());
jFrame.setTitle("MSSQLDIFF");
}
return jFrame;
}
/**
* This method initializes jContentPane
*
* @return javax.swing.JPanel
*/
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(getCsvFilePanel(), BorderLayout.NORTH);
jContentPane.add(getResultPane(), BorderLayout.CENTER);
}
return jContentPane;
}
/**
* This method initializes jJMenuBar
*
* @return javax.swing.JMenuBar
*/
private JMenuBar getJJMenuBar() {
if (jJMenuBar == null) {
jJMenuBar = new JMenuBar();
jJMenuBar.add(getFileMenu());
jJMenuBar.add(getHelpMenu());
}
return jJMenuBar;
}
/**
* This method initializes jMenu
*
* @return javax.swing.JMenu
*/
private JMenu getFileMenu() {
if (fileMenu == null) {
fileMenu = new JMenu();
fileMenu.setText("File");
fileMenu.add(getExitMenuItem());
}
return fileMenu;
}
/**
* This method initializes jMenu
*
* @return javax.swing.JMenu
*/
private JMenu getHelpMenu() {
if (helpMenu == null) {
helpMenu = new JMenu();
helpMenu.setText("Help");
helpMenu.add(getAboutMenuItem());
}
return helpMenu;
}
/**
* This method initializes jMenuItem
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getExitMenuItem() {
if (exitMenuItem == null) {
exitMenuItem = new JMenuItem();
exitMenuItem.setText("Exit");
exitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
return exitMenuItem;
}
/**
* This method initializes jMenuItem
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getAboutMenuItem() {
if (aboutMenuItem == null) {
aboutMenuItem = new JMenuItem();
aboutMenuItem.setText("About");
aboutMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog aboutDialog = getAboutDialog();
aboutDialog.pack();
Point loc = getJFrame().getLocation();
loc.translate(20, 20);
aboutDialog.setLocation(loc);
aboutDialog.setVisible(true);
}
});
}
return aboutMenuItem;
}
/**
* This method initializes aboutDialog
*
* @return javax.swing.JDialog
*/
private JDialog getAboutDialog() {
if (aboutDialog == null) {
aboutDialog = new JDialog(getJFrame(), true);
aboutDialog.setTitle("About");
aboutDialog.setSize(new Dimension(180, 38));
aboutDialog.setContentPane(getAboutContentPane());
}
return aboutDialog;
}
/**
* This method initializes aboutContentPane
*
* @return javax.swing.JPanel
*/
private JPanel getAboutContentPane() {
if (aboutContentPane == null) {
aboutContentPane = new JPanel();
aboutContentPane.setLayout(new BorderLayout());
aboutContentPane.add(getAboutVersionLabel(), BorderLayout.CENTER);
}
return aboutContentPane;
}
/**
* This method initializes aboutVersionLabel
*
* @return javax.swing.JLabel
*/
private JLabel getAboutVersionLabel() {
if (aboutVersionLabel == null) {
aboutVersionLabel = new JLabel();
aboutVersionLabel.setText("Version 0.0 SNAPSHOT");
aboutVersionLabel.setHorizontalAlignment(SwingConstants.CENTER);
}
return aboutVersionLabel;
}
/**
* This method initializes fromCsvFileSelector
*
* @return com.github.ryhmrt.mssqldiff.gui.CsvFileSelector
*/
private CsvFileSelector getFromCsvFileSelector() {
if (fromCsvFileSelector == null) {
fromCsvFileSelector = new CsvFileSelector(jFrame);
}
return fromCsvFileSelector;
}
/**
* This method initializes csvFilePanel
*
* @return javax.swing.JPanel
*/
private JPanel getCsvFilePanel() {
if (csvFilePanel == null) {
GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
gridBagConstraints5.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints5.weightx = 1.0;
gridBagConstraints5.gridx = 1;
gridBagConstraints5.gridy = 1;
GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
gridBagConstraints4.gridx = 0;
gridBagConstraints4.gridy = 1;
GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
gridBagConstraints3.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints3.weightx = 1.0;
gridBagConstraints3.gridx = 1;
gridBagConstraints3.gridy = 0;
GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
gridBagConstraints2.gridx = 0;
gridBagConstraints2.gridy = 0;
fromLabel = new JLabel();
fromLabel.setText("from:");
toLabel = new JLabel();
toLabel.setText("to:");
csvFilePanel = new JPanel();
csvFilePanel.setLayout(new GridBagLayout());
csvFilePanel.add(fromLabel, gridBagConstraints2);
csvFilePanel.add(getFromCsvFileSelector(), gridBagConstraints3);
csvFilePanel.add(toLabel, gridBagConstraints4);
csvFilePanel.add(getToCsvFileSelector(), gridBagConstraints5);
}
return csvFilePanel;
}
/**
* This method initializes toCsvFileSelector
*
* @return com.github.ryhmrt.mssqldiff.gui.CsvFileSelector
*/
private CsvFileSelector getToCsvFileSelector() {
if (toCsvFileSelector == null) {
toCsvFileSelector = new CsvFileSelector(jFrame);
}
return toCsvFileSelector;
}
/**
* This method initializes summaryPanel
*
* @return javax.swing.JPanel
*/
private JPanel getSummaryPanel() {
if (summaryPanel == null) {
summaryPanel = new JPanel();
summaryPanel.setLayout(new BorderLayout());
summaryPanel.setMinimumSize(new Dimension(150, 100));
summaryPanel.add(getSummaryTreeScrollPane(), BorderLayout.CENTER);
summaryPanel.add(getDiffExecutePanel(), BorderLayout.NORTH);
}
return summaryPanel;
}
/**
* This method initializes diffButton
*
* @return javax.swing.JButton
*/
private JButton getDiffButton() {
if (diffButton == null) {
diffButton = new JButton();
diffButton.setText("Diff");
diffButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
diff();
}
});
}
return diffButton;
}
/**
* This method initializes summaryTree
*
* @return javax.swing.JTree
*/
private JTree getSummaryTree() {
if (summaryTree == null) {
summaryTree = new JTree(new Object[0]);
summaryTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
detailPane.setText(SqlUtil.WARNING + getSql(e.getPath().getLastPathComponent()));
}
});
}
return summaryTree;
}
private String getSql(Object current) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)current;
if (node.getUserObject() instanceof TableDiff) {
return ((TableDiff)node.getUserObject()).toSqlWithoutPermissions();
} else if (node.getUserObject() instanceof Diff) {
return ((Diff<?>)node.getUserObject()).toSql();
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < node.getChildCount(); i++) {
sb.append(getSql(node.getChildAt(i)));
sb.append("\n");
}
return sb.toString();
}
}
/**
* This method initializes resultPane
*
* @return javax.swing.JSplitPane
*/
private JSplitPane getResultPane() {
if (resultPane == null) {
resultPane = new JSplitPane();
resultPane.setLeftComponent(getSummaryPanel());
resultPane.setRightComponent(getDetailScrollPane());
}
return resultPane;
}
/**
* This method initializes detailPane
*
* @return javax.swing.JTextPane
*/
private JTextPane getDetailPane() {
if (detailPane == null) {
detailPane = new JTextPane();
detailPane.setFont(new Font("Monospaced", Font.PLAIN, 14));
}
return detailPane;
}
private void diff() {
try {
List<Table> fromTables = loadTables(fromCsvFileSelector.getFilePath());
List<Table> toTables = loadTables(toCsvFileSelector.getFilePath());
ListDiffer<Table, TableDiff, TableDiffer> differ = new ListDiffer<Table, TableDiff, TableDiffer>();
tableDiffs = differ.diff(new TableDiffer(), fromTables, toTables);
showDiffTree();
} catch (RuntimeException ex) {
JOptionPane.showMessageDialog(jFrame, ex.getMessage(), "Error!", JOptionPane.ERROR_MESSAGE);
}
}
private void showDiffTree() {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("diff", true);
for (TableDiff tableDiff : tableDiffs) {
DefaultMutableTreeNode tableNode = new DefaultMutableTreeNode(tableDiff, true);
if (!tableDiff.getColumnDiffs().isEmpty()) {
if (ignorePermissionCheck.isSelected()) {
// 権限無視の場合は、テーブルの下に直接カラムを追加
for (Object data : tableDiff.getColumnDiffs()) {
tableNode.add(new DefaultMutableTreeNode(data, false));
}
} else {
tableNode.add(createChildNodes("columns", tableDiff.getColumnDiffs()));
}
}
if (ignorePermissionCheck.isSelected()) {
// 権限無視の場合、権限のみの変更であればテーブルごとスキップ
if (tableDiff.getType() == Type.MODIFIED && tableDiff.getColumnDiffs().isEmpty()) {
continue;
}
} else {
if (!tableDiff.getPermissionDiffs().isEmpty()) {
tableNode.add(createChildNodes("permissions", tableDiff.getPermissionDiffs()));
}
}
rootNode.add(tableNode);
}
TreeModel treeModel = new DefaultTreeModel(rootNode);
summaryTree.setModel(treeModel);
}
private MutableTreeNode createChildNodes(String title, List<?> childDataList) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(title, true);
for (Object data : childDataList) {
node.add(new DefaultMutableTreeNode(data, false));
}
return node;
}
private List<Table> loadTables(String filePath) {
SchemaCsvReaderFileImpl reader = new SchemaCsvReaderFileImpl(filePath);
List<SchemaCsv> src = reader.read();
TableListConvertor conv = new TableListConvertor();
return conv.convert(src);
}
/**
* This method initializes summaryTreeScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getSummaryTreeScrollPane() {
if (summaryTreeScrollPane == null) {
summaryTreeScrollPane = new JScrollPane();
summaryTreeScrollPane.setViewportView(getSummaryTree());
}
return summaryTreeScrollPane;
}
/**
* This method initializes detailScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getDetailScrollPane() {
if (detailScrollPane == null) {
detailScrollPane = new JScrollPane();
detailScrollPane.setViewportView(getDetailPane());
}
return detailScrollPane;
}
/**
* This method initializes diffExecutePanel
*
* @return javax.swing.JPanel
*/
private JPanel getDiffExecutePanel() {
if (diffExecutePanel == null) {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(2);
gridLayout.setColumns(1);
diffExecutePanel = new JPanel();
diffExecutePanel.setLayout(gridLayout);
diffExecutePanel.add(getDiffButton(), null);
diffExecutePanel.add(getIgnorePermissionCheck(), null);
}
return diffExecutePanel;
}
/**
* This method initializes ignorePermissionCheck
*
* @return javax.swing.JCheckBox
*/
private JCheckBox getIgnorePermissionCheck() {
if (ignorePermissionCheck == null) {
ignorePermissionCheck = new JCheckBox();
ignorePermissionCheck.setText("Ignore permissions");
ignorePermissionCheck.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
showDiffTree();
}
});
}
return ignorePermissionCheck;
}
/**
* Launches this application
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Main application = new Main();
application.getJFrame().setVisible(true);
}
});
}
}