dataviewer.DataViewer.java Source code

Java tutorial

Introduction

Here is the source code for dataviewer.DataViewer.java

Source

/*
 * 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.
 */
package dataviewer;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;
import java.awt.Color;
import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.apache.commons.lang3.StringEscapeUtils;

/**
 *
 * @author cpun1
 */
public final class DataViewer extends javax.swing.JFrame {

    private String cur_path = "./";
    private String delimiter = "\\t";
    private boolean transpose = false;
    private boolean export = false;
    private boolean header = false;
    private String selected_file = "";
    private String config = "config";
    private String table;
    private long N = 5000;

    /**
     * Creates new form DataViewer
     */
    public DataViewer() {
        try {
            for (Enum ee : THREAD.values()) {
                t[ee.ordinal()] = new Thread();
            }
            initComponents();
            DropTarget dropTarget = new DropTarget(tr_files, new DropTargetListenerImpl());
            TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {

                @Override
                public void valueChanged(TreeSelectionEvent e) {
                    javax.swing.JTree tree = (javax.swing.JTree) e.getSource();
                    TreePath path = tree.getSelectionPath();
                    Object[] pnode = (Object[]) path.getPath();
                    String name = pnode[pnode.length - 1].toString();
                    String ex = getExtension(name);
                    if (ex.equals(".txt") || ex.equals(".dat") || ex.equals(".csv") || ex.equals(".tsv")) {
                        selected_file = name;
                    } else {
                        selected_file = "";
                    }
                }
            };
            tr_files.addTreeSelectionListener(treeSelectionListener);

            tr_files.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent evt) {
                    if (evt.getClickCount() >= 2) {
                        if (!"".equals(selected_file)) {
                            //count_data();
                            read_data();
                        } else {
                            TreePath path = tr_files.getSelectionPath();
                            if (path.getLastPathComponent().toString().equals(cur_path)) {
                                cur_path = (new File(cur_path)).getParent();
                            } else {
                                cur_path = cur_path + File.separator + path.getLastPathComponent().toString();
                            }
                            fill_tree();
                        }
                    }
                }
            });

            tr_files.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent evt) {
                    if (evt.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
                        cur_path = (new File(cur_path)).getParent();
                        fill_tree();
                    } else if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                        if (!"".equals(selected_file)) {
                            //count_data();
                            read_data();
                        } else {
                            TreePath path = tr_files.getSelectionPath();
                            if (path.getLastPathComponent().toString().equals(cur_path)) {
                                cur_path = (new File(cur_path)).getParent();
                            } else {
                                cur_path = cur_path + File.separator + path.getLastPathComponent().toString();
                            }
                            fill_tree();
                        }
                    } else if (evt.getKeyCode() == KeyEvent.VK_DELETE) {

                        if (!"".equals(selected_file)) {
                            String name = cur_path + File.separator + selected_file;
                            if ((new File(name)).isFile()) {
                                int dialogResult = JOptionPane.showConfirmDialog(null,
                                        "Selected file [" + selected_file
                                                + "] will be removed and not recoverable.",
                                        "Are you sure?", JOptionPane.YES_NO_OPTION);
                                if (dialogResult == JOptionPane.YES_OPTION) {
                                    (new File(name)).delete();
                                    fill_tree();
                                }
                            }

                        } else {
                            JOptionPane.showMessageDialog(null,
                                    "For safety concern, removing folder is not supported.", "Information",
                                    JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            });

            tr_files.setCellRenderer(new MyTreeCellRenderer());
            p_count.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);

            //tp_menu.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ctrl1, "tab_read");
            //tp_menu.getActionMap().put("tab_read", (Action) new ActionListenerImpl());
            //tp_menu.setMnemonicAt(0, KeyEvent.VK_1);
            //tp_menu.setMnemonicAt(1, KeyEvent.VK_2);
            /*InputMap inputMap = tp_menu.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
             ActionMap actionMap = tp_menu.getActionMap();
                
             KeyStroke ctrl1 = KeyStroke.getKeyStroke("ctrl 1");
             inputMap.put(ctrl1, "tab_read");
             actionMap.put("tab_read", new AbstractAction() {
                
             @Override
             public void actionPerformed(ActionEvent arg0) {
             tp_menu.setSelectedIndex(0);
             }
             });
                
             KeyStroke ctrl2 = KeyStroke.getKeyStroke("ctrl 2");
             inputMap.put(ctrl2, "tab_analyze");
             actionMap.put("tab_analyze", new AbstractAction() {
                
             @Override
             public void actionPerformed(ActionEvent arg0) {
             tp_menu.setSelectedIndex(1);
             }
             });*/
            config();
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }

    /**
     * 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() {

        p_count = new javax.swing.JScrollPane();
        txt_count = new javax.swing.JTextArea();
        p_data = new javax.swing.JScrollPane();
        tb_data = new javax.swing.JTable();
        txt_delimiter = new javax.swing.JTextField();
        lb_delimiter = new javax.swing.JLabel();
        ck_header = new javax.swing.JCheckBox();
        btn_refresh = new javax.swing.JButton();
        p_files = new javax.swing.JScrollPane();
        tr_files = new javax.swing.JTree();
        cb_table = new javax.swing.JComboBox();
        lb_table = new javax.swing.JLabel();
        ck_transpose = new javax.swing.JCheckBox();
        ck_export = new javax.swing.JCheckBox();
        btn_remove = new javax.swing.JButton();
        btn_execute = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        tp_sql = new javax.swing.JTextPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        tb_columns = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Data Viewer");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        p_count.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        p_count.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);

        txt_count.setEditable(false);
        txt_count.setBackground(java.awt.SystemColor.control);
        txt_count.setColumns(20);
        txt_count.setLineWrap(true);
        txt_count.setRows(5);
        txt_count.setAutoscrolls(false);
        txt_count.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        p_count.setViewportView(txt_count);

        p_data.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        tb_data.setAutoCreateRowSorter(true);
        tb_data.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        tb_data.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { {}, {}, {}, {} }, new String[] {

        }));
        tb_data.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        tb_data.setCellSelectionEnabled(true);
        p_data.setViewportView(tb_data);

        txt_delimiter.setText("\\t");
        txt_delimiter.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txt_delimiterFocusLost(evt);
            }
        });

        lb_delimiter.setText("Delimiter");

        ck_header.setText("Header");
        ck_header.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ck_headerActionPerformed(evt);
            }
        });

        btn_refresh.setText("Refresh");
        btn_refresh.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_refreshActionPerformed(evt);
            }
        });

        tr_files.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        tr_files.setModel(null);
        tr_files.setDragEnabled(true);
        tr_files.setDropMode(javax.swing.DropMode.ON_OR_INSERT);
        tr_files.setVisibleRowCount(25);
        p_files.setViewportView(tr_files);

        cb_table.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                cb_tableFocusGained(evt);
            }
        });
        cb_table.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cb_tableActionPerformed(evt);
            }
        });

        lb_table.setText("Table");

        ck_transpose.setText("Transpose");
        ck_transpose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ck_transposeActionPerformed(evt);
            }
        });

        ck_export.setText("Export");
        ck_export.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ck_exportActionPerformed(evt);
            }
        });

        btn_remove.setText("Remove");
        btn_remove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_removeActionPerformed(evt);
            }
        });

        btn_execute.setText("Execute");
        btn_execute.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_executeActionPerformed(evt);
            }
        });

        tp_sql.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jScrollPane2.setViewportView(tp_sql);

        jScrollPane1.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        tb_columns.setAutoCreateRowSorter(true);
        tb_columns.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        tb_columns
                .setModel(new javax.swing.table.DefaultTableModel(new Object[][] { {}, {}, {}, {} }, new String[] {

        }));
        jScrollPane1.setViewportView(tb_columns);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING,
                                        layout.createSequentialGroup().addComponent(ck_header)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .addComponent(btn_refresh, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        96, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING,
                                        layout.createSequentialGroup()
                                                .addComponent(lb_table, javax.swing.GroupLayout.PREFERRED_SIZE, 46,
                                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(cb_table, javax.swing.GroupLayout.PREFERRED_SIZE, 274,
                                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING,
                                        layout.createSequentialGroup().addComponent(lb_delimiter)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(txt_delimiter, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        269, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addComponent(p_files, javax.swing.GroupLayout.Alignment.LEADING,
                                        javax.swing.GroupLayout.PREFERRED_SIZE, 325,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                        .addComponent(ck_transpose, javax.swing.GroupLayout.PREFERRED_SIZE, 90,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(ck_export, javax.swing.GroupLayout.PREFERRED_SIZE, 64,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(btn_remove)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(btn_execute))
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING,
                                        layout.createSequentialGroup()
                                                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        109, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jScrollPane2)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(p_count)
                                .addComponent(p_data, javax.swing.GroupLayout.DEFAULT_SIZE, 847, Short.MAX_VALUE))
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                javax.swing.GroupLayout.Alignment.TRAILING,
                layout.createSequentialGroup().addContainerGap().addGroup(layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup()
                                .addComponent(p_count, javax.swing.GroupLayout.PREFERRED_SIZE, 29,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(p_data).addGap(2, 2, 2))
                        .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(lb_delimiter).addComponent(txt_delimiter,
                                                javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(ck_header).addComponent(btn_refresh))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(p_files, javax.swing.GroupLayout.DEFAULT_SIZE, 217, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(lb_table).addComponent(cb_table,
                                                javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(ck_transpose).addComponent(ck_export).addComponent(btn_remove)
                                        .addComponent(btn_execute, javax.swing.GroupLayout.PREFERRED_SIZE, 25,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0,
                                                Short.MAX_VALUE)
                                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 244,
                                                Short.MAX_VALUE))))
                        .addContainerGap()));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        writeConfig();
    }//GEN-LAST:event_formWindowClosing

    private void ck_transposeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ck_transposeActionPerformed
        this.transpose = ck_transpose.isSelected();
        transpose((DefaultTableModel) tb_data.getModel());
    }//GEN-LAST:event_ck_transposeActionPerformed

    private void btn_executeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_executeActionPerformed
        try {
            view(tp_sql.getText());
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }//GEN-LAST:event_btn_executeActionPerformed

    private void cb_tableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cb_tableActionPerformed
        try {
            table = cb_table.getSelectedItem().toString();
            DB db = new DB("./db/" + table + ".db");
            db.open();
            String[] cols = db.get_table_columns(table);
            db.close();

            DefaultTableModel model = new DefaultTableModel();
            //model.addColumn("Column Index");
            model.addColumn("Field");
            int i = 1;

            StyleContext sc = StyleContext.getDefaultStyleContext();
            TabSet tabs = new TabSet(new TabStop[] { new TabStop(20) });
            AttributeSet paraSet = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.TabSet, tabs);
            tp_sql.setParagraphAttributes(paraSet, false);

            StyledDocument doc = tp_sql.getStyledDocument();

            doc.remove(0, doc.getLength());

            doc.insertString(doc.getLength(), "SELECT", null);
            doc.insertString(doc.getLength(), "\n", null);

            for (int j = 1; j < cols.length; ++j) {
                String s = cols[j];
                //model.addRow(new Object[]{i++, s});
                model.addRow(new Object[] { s });
                doc.insertString(doc.getLength(), "\t", null);
                doc.insertString(doc.getLength(), s, null);
                if (j < cols.length - 1) {
                    doc.insertString(doc.getLength(), ",", null);
                }
                doc.insertString(doc.getLength(), "\n", null);
            }

            doc.insertString(doc.getLength(), "FROM", null);
            doc.insertString(doc.getLength(), "\n", null);
            doc.insertString(doc.getLength(), "\t", null);
            doc.insertString(doc.getLength(), table, null);
            /*doc.insertString(doc.getLength(), "\n", null);
             doc.insertString(doc.getLength(), "WHERE", null);
             doc.insertString(doc.getLength(), "\n", null);
             doc.insertString(doc.getLength(), "\t", null);
             doc.insertString(doc.getLength(), "_N_ <= " + N, null);
             doc.insertString(doc.getLength(), ";", null);*/

            tb_columns.setModel(model);

            TableRowSorter trs = new TableRowSorter(model);
            trs.setComparator(0, new IntComparator());
            tb_columns.setRowSorter(trs);

            //highline();
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }//GEN-LAST:event_cb_tableActionPerformed

    private void btn_refreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_refreshActionPerformed
        for (Enum e : THREAD.values()) {
            t[e.ordinal()].stop();
        }
        tr_files.setEnabled(true);
        txt_count.setText("");
        fill_tree();
    }//GEN-LAST:event_btn_refreshActionPerformed

    private void ck_headerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ck_headerActionPerformed
        this.header = ck_header.isSelected();
    }//GEN-LAST:event_ck_headerActionPerformed

    private void txt_delimiterFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txt_delimiterFocusLost
        this.delimiter = txt_delimiter.getText();
    }//GEN-LAST:event_txt_delimiterFocusLost

    private void btn_removeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_removeActionPerformed
        String name = "./db/" + cb_table.getSelectedItem().toString() + ".db";
        if (new File(name).exists()) {
            int dialogResult = JOptionPane
                    .showConfirmDialog(null,
                            "Selected file [" + cb_table.getSelectedItem().toString()
                                    + "] will be removed and not recoverable.",
                            "Are you sure?", JOptionPane.YES_NO_OPTION);
            if (dialogResult == JOptionPane.YES_OPTION) {
                (new File(name)).delete();
                cb_table.removeItem(cb_table.getSelectedItem());
                cb_table.setSelectedItem(null);
                tp_sql.setText("");
                tb_columns.setModel(new DefaultTableModel());
            }
        }

    }//GEN-LAST:event_btn_removeActionPerformed

    private void ck_exportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ck_exportActionPerformed
        this.export = ck_export.isSelected();
    }//GEN-LAST:event_ck_exportActionPerformed

    private void cb_tableFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_cb_tableFocusGained
        List<String> files = Utilities.getAllFileNames("./db", false);
        String[] cols = new String[files.size()];
        int i = 0;
        for (String f : files) {
            cols[i++] = f.replace(getExtension(f), "");
        }
        DefaultComboBoxModel model = new DefaultComboBoxModel(cols);
        cb_table.setModel(model);
        cb_table.showPopup();
    }//GEN-LAST:event_cb_tableFocusGained

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */

        try {

            /*System.setProperty(
             "Quaqua.tabLayoutPolicy", "wrap"
             );*/
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    UIManager.getLookAndFeelDefaults().put("Panel.background", new Color(245, 245, 245));
                    UIManager.getLookAndFeelDefaults().put("OptionPane.background", new Color(245, 245, 245));
                    break;
                }
            }
            /*UIManager.setLookAndFeel(
             ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel()
             );*/

        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(DataViewer.class.getName()).log(java.util.logging.Level.SEVERE, null,
                    ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Utilities.createFolder("output");
                    Utilities.createFolder("db");

                    DataViewer dv = new DataViewer();
                    dv.setIconImage(ImageIO.read(getClass().getResource("/images/dataviewer.png")));
                    dv.setLocationRelativeTo(null);
                    dv.setVisible(true);
                } catch (Exception ex) {
                    System.err.println(ex.getMessage());
                }
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btn_execute;
    private javax.swing.JButton btn_refresh;
    private javax.swing.JButton btn_remove;
    private javax.swing.JComboBox cb_table;
    private javax.swing.JCheckBox ck_export;
    private javax.swing.JCheckBox ck_header;
    private javax.swing.JCheckBox ck_transpose;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lb_delimiter;
    private javax.swing.JLabel lb_table;
    private javax.swing.JScrollPane p_count;
    private javax.swing.JScrollPane p_data;
    private javax.swing.JScrollPane p_files;
    private javax.swing.JTable tb_columns;
    private javax.swing.JTable tb_data;
    private javax.swing.JTextPane tp_sql;
    private javax.swing.JTree tr_files;
    private javax.swing.JTextArea txt_count;
    private javax.swing.JTextField txt_delimiter;
    // End of variables declaration//GEN-END:variables

    class DropTargetListenerImpl implements DropTargetListener {

        public DropTargetListenerImpl() {
        }

        @Override
        public void dragEnter(DropTargetDragEvent e) {
        }

        @Override
        public void dragExit(DropTargetEvent e) {
        }

        @Override
        public void dragOver(DropTargetDragEvent e) {
        }

        @Override
        public void dropActionChanged(DropTargetDragEvent e) {
        }

        @Override
        public void drop(DropTargetDropEvent e) {
            try {
                // Accept the drop first, important!
                e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

                // Get the files that are dropped as java.util.List
                List list = (List) e.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);

                // Now get the first file from the list,
                File file = (File) list.get(0);
                cur_path = file.getParent();
                selected_file = file.getName();
                fill_tree();
            } catch (Exception ex) {
                txt_count.setText(ex.getMessage());
            }
        }
    }

    private void fill_tree() {
        txt_count.setText("");

        DefaultTreeModel tm = (DefaultTreeModel) tr_files.getModel();
        DefaultMutableTreeNode top;
        cur_path = new File(cur_path).getAbsolutePath();
        if (cur_path.charAt(cur_path.length() - 1) == '.') {
            cur_path = cur_path.substring(0, cur_path.length() - 1);
        }
        if (cur_path.charAt(cur_path.length() - 1) == File.separatorChar) {
            cur_path = cur_path.substring(0, cur_path.length() - 1);
        }
        if (tm != null) {
            top = (DefaultMutableTreeNode) tm.getRoot();
            top.removeAllChildren();
            top.setUserObject(cur_path);
        } else {
            top = new DefaultMutableTreeNode(cur_path);
        }

        // get all children nodes and remove them
        // rename the user object
        ArrayList<String> files = this.getAllFileNames(cur_path);
        Collections.sort(files);

        int j = 1;
        int selected_index = -1;
        for (String f : files) {
            String ex = this.getExtension(f);
            boolean is_folder = (new File(cur_path + File.separator + f)).isDirectory();
            if (is_folder || ex.equals(".txt") || ex.equals(".dat") || ex.equals(".csv") || ex.equals(".tsv")) {
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(f);
                top.add(node);
                if (f.equals(selected_file)) {
                    selected_index = j;
                }
                j++;
            }
        }

        //DefaultTreeModel treeModel = new DefaultTreeModel(top);
        //tr_files.setModel(treeModel);
        if (tm == null) {
            tr_files.setModel(new DefaultTreeModel(top));
        } else {
            try {
                tm.reload();
            } catch (Exception e) {
                tm.reload();
            }
        }

        if (selected_index > -1) {
            tr_files.setSelectionRow(selected_index);
        }

        tr_files.grabFocus();
    }

    public void config() {
        try {
            if (!(new File(config)).exists()) {
                writeConfig();
            } else {

                // read parameters from heaven.config
                BufferedReader in = new BufferedReader(new FileReader(config));

                String line = "";
                while ((line = in.readLine()) != null) {
                    String[] s = line.split("=");
                    if (s.length == 2) {
                        String key = s[0].trim();
                        String val = s[1].trim();
                        // load parameters
                        if (key.equals("directory")) {
                            cur_path = val;
                        }
                        if (key.equals("delimiter")) {
                            delimiter = val;
                        }
                        if (key.equals("transpose")) {
                            transpose = (val.toLowerCase().equals("true"));
                        }
                        if (key.equals("export")) {
                            export = (val.toLowerCase().equals("true"));
                        }
                        if (key.equals("header")) {
                            header = (val.toLowerCase().equals("true"));
                        }
                        if (key.equals("N")) {
                            N = Double.valueOf(val.trim()).longValue();
                        }
                    }
                }
                in.close();
            }
            txt_delimiter.setText(String.valueOf(delimiter));
            ck_transpose.setSelected(transpose);
            ck_export.setSelected(export);
            ck_header.setSelected(header);
            fill_tree();
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }

    private void writeConfig() {
        try {
            if ((new File(config)).exists()) {
                (new File(config)).delete();
            }

            BufferedWriter out = new BufferedWriter(new FileWriter(config));

            out.write("directory = " + cur_path);
            out.newLine();
            out.write("delimiter = " + String.valueOf(delimiter));
            out.newLine();
            out.write("transpose = " + ((transpose) ? "true" : "false"));
            out.newLine();
            out.write("export = " + ((export) ? "true" : "false"));
            out.newLine();
            out.write("header = " + ((header) ? "true" : "false"));
            out.newLine();
            out.write("N = " + String.valueOf(N));
            out.close();
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }

    private ArrayList<String> getAllFileNames(String path) {
        ArrayList<String> out = new ArrayList();
        File folder = new File(path);
        for (final File fileEntry : folder.listFiles()) {
            out.add(fileEntry.getName());
        }
        return out;
    }

    private String getExtension(String filename) {
        String extension = "";

        int i = filename.lastIndexOf('.');
        int p = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));

        if (i > p) {
            extension = filename.substring(i + 1);
        }
        return "." + extension;
    }

    public enum THREAD {

        read, view
    }

    Thread[] t = new Thread[THREAD.values().length];

    private void read_data() {
        t[THREAD.read.ordinal()].stop();
        t[THREAD.read.ordinal()] = new Thread(new Runnable() {
            @Override
            public void run() {
                //do stuff
                try {
                    if (!selected_file.equals("")) {
                        cb_table.setEnabled(false);
                        btn_execute.setEnabled(false);
                        tp_sql.setEnabled(false);
                        ck_export.setEnabled(false);
                        btn_remove.setEnabled(false);
                        tb_data.setModel(new DefaultTableModel());

                        txt_count.setText("Please wait while profiling data ...");

                        table = selected_file.replaceAll(getExtension(selected_file), "")
                                .replaceAll("[^a-zA-Z0-9]+", "");

                        DB db = new DB("./db/" + table + ".db");
                        db.initialize();

                        Timing timer = new Timing();

                        InputStream _in = new BufferedInputStream(
                                new FileInputStream(cur_path + File.separator + selected_file));
                        byte[] c = new byte[1024];
                        int j = 0;
                        int count = 0;
                        while ((j = _in.read(c)) != -1) {
                            for (int i = 0; i < j; ++i) {
                                if (c[i] == '\n') {
                                    count++;
                                }
                            }
                        }

                        _in.close();
                        if (header) {
                            count--;
                        }

                        CSVReader in = new CSVReader(new FileReader(cur_path + File.separator + selected_file),
                                '\n');
                        String[] line = null;

                        long _n_ = 0;
                        boolean first = true;
                        while ((line = in.readNext()) != null) {
                            if (first) {
                                first = false;
                                List<String> cols = new ArrayList();
                                cols.add("_N_");

                                String[] s = line[0].split(delimiter);
                                if (header) {
                                    for (String h : s) {
                                        cols.add(h);
                                    }
                                } else {
                                    for (int i = 1; i <= s.length; ++i) {
                                        cols.add("field_" + i);
                                    }
                                }

                                db.createTable(table, cols.toArray(new String[cols.size()]));
                                db.insertBegin(table);

                                if (header) {
                                    continue;
                                }
                            }

                            _n_++;
                            StringBuilder s = new StringBuilder();
                            s.append(_n_).append(StringEscapeUtils.unescapeJava(delimiter)).append(line[0]);
                            db.insertInto(s.toString().split(delimiter));

                            if (_n_ == N) {
                                db.force_insert();
                                view("SELECT * FROM " + table + " WHERE _N_ <= " + N + ";");
                            }
                            if (_n_ % 100000 == 0) {
                                txt_count.setText("Reading " + selected_file + ": "
                                        + Math.floor(_n_ * 1.0 / count * 100) + "% completed.");
                            }

                        }

                        in.close();
                        db.insertFinish();
                        db.create_index(table, "_N_", true, true);
                        db.close();

                        if (_n_ < N) {
                            view("SELECT * FROM " + table + ";");
                        }

                        cb_table.setEnabled(true);
                        btn_execute.setEnabled(true);
                        tp_sql.setEnabled(true);
                        ck_export.setEnabled(true);
                        btn_remove.setEnabled(true);
                        txt_count.setText("Read " + String.valueOf(_n_) + " many lines and showed top "
                                + Math.min(N, _n_) + ". Took " + timer.getSec() + "s.");
                    }
                    tr_files.grabFocus();
                } catch (Exception e) {
                    txt_count.setText(e.getMessage());
                }
            }
        });
        t[THREAD.read.ordinal()].start();
    }

    private void view(String _sql) {

        final String sql = _sql;

        // check pivot

        t[THREAD.view.ordinal()].stop();
        t[THREAD.view.ordinal()] = new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Timing timer = new Timing();
                    boolean alive = t[THREAD.read.ordinal()].isAlive();

                    if (!alive) {
                        txt_count.setText("Running query ... ");
                    }

                    DB db = new DB("./db/" + table + ".db");
                    db.open();

                    ResultSet results = db.execute(sql);

                    String csv = "";
                    CSVWriter out = null;
                    boolean asked = false;

                    if (export && ck_export.isEnabled()) {
                        csv = JOptionPane.showInputDialog(new JFrame(""),
                                "Please enter the name of the file without extension.", "Export File Name",
                                JOptionPane.PLAIN_MESSAGE);
                        if (csv == null) {
                            csv = "";
                        }
                        if (!csv.equals("")) {
                            out = new CSVWriter(new FileWriter("./output/" + csv + ".txt"), '\n',
                                    CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER);
                        }
                    }

                    String _delimiter = StringEscapeUtils.unescapeJava(delimiter);
                    StringBuilder sb = new StringBuilder();
                    List<String> cols = new ArrayList();
                    for (int i = 0; i < results.getMetaData().getColumnCount(); ++i) {
                        String name = results.getMetaData().getColumnName(i + 1);
                        cols.add(name);
                        sb.append(name).append(_delimiter);
                    }
                    sb.setLength(sb.length() - 1);

                    DefaultTableModel model = new DefaultTableModel();
                    for (int i = 0; i < cols.size(); ++i) {
                        model.addColumn(cols.get(i));
                    }

                    if (!csv.equals("")) {
                        out.writeNext(sb.toString());
                    }

                    String[] vals;
                    long count = 0;
                    boolean is_model_render = false;
                    while (results.next()) {
                        count++;

                        vals = new String[cols.size()];

                        sb = new StringBuilder();
                        for (int i = 0; i < cols.size(); ++i) {
                            vals[i] = results.getString(cols.get(i));
                            sb.append(vals[i]).append(_delimiter);
                        }

                        sb.setLength(sb.length() - 1);
                        if (!csv.equals("")) {
                            out.writeNext(sb.toString());
                        }

                        if (asked == false && is_model_render == false && count > N) {
                            if (JOptionPane.showConfirmDialog(null, "Number of rows are more than " + N + ". Stop?",
                                    "", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                                renderData(model);
                                is_model_render = true;
                            }
                            asked = true;
                        }

                        if (is_model_render == false) {
                            model.addRow(vals);
                        }
                    }

                    db.close();
                    if (is_model_render == false) {
                        if (transpose) {
                            tb_data.setModel(model);
                            transpose((DefaultTableModel) tb_data.getModel());
                        } else {
                            renderData(model);
                        }
                    }

                    if (!csv.equals("")) {
                        out.close();
                        txt_count.setText(count + " records are queried from " + table + " and exported to /output/"
                                + csv + ".txt. Took " + timer.getSec() + "s.");
                    } else if (!alive) {
                        if (is_model_render) {
                            txt_count.setText(count + " records are queried from " + table + " but stopped at " + N
                                    + ". Took " + timer.getSec() + "s.");
                        } else {
                            txt_count.setText(count + " records are queried from " + table + ". Took "
                                    + timer.getSec() + "s.");
                        }
                    }

                } catch (Exception e) {
                    txt_count.setText(e.getMessage());
                }
            }
        });

        t[THREAD.view.ordinal()].start();
    }

    private void renderData(DefaultTableModel model) {
        tb_data.setVisible(false);

        tb_data.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                c.setBackground(row % 2 == 0 ? Color.WHITE : new Color(240, 240, 240));

                if (table.isCellSelected(row, column)) {
                    c.setBackground(new Color(200, 0, 0));
                    c.setForeground(Color.white);
                } else if (table.isRowSelected(row)) {
                    c.setBackground(new Color(0, 0, 200));
                    c.setForeground(Color.white);
                } else {
                    c.setForeground(Color.black);
                }
                return c;
            }
        });

        tb_data.setGridColor(new Color(220, 220, 220));
        tb_data.setShowVerticalLines(true);
        tb_data.setModel(model);

        for (int i = 0; i < model.getColumnCount(); ++i) {
            if (model.getColumnName(i).equals("_N_")) {
                TableRowSorter trs = new TableRowSorter(model);
                trs.setComparator(i, new IntComparator());
                tb_data.setRowSorter(trs);
            }
        }

        for (int j = 0; j < tb_data.getColumnCount(); j++) {
            int width = 0;
            TableColumn col = tb_data.getColumnModel().getColumn(j);
            TableCellRenderer renderer = tb_data.getTableHeader().getDefaultRenderer();
            Component comp = renderer.getTableCellRendererComponent(tb_data, col.getHeaderValue(), false, false, 0,
                    0);
            width = Math.max(comp.getPreferredSize().width, width);
            for (int i = 0; i < tb_data.getRowCount(); i++) {
                renderer = tb_data.getCellRenderer(i, j);
                comp = tb_data.prepareRenderer(renderer, i, j);
                width = Math.max(comp.getPreferredSize().width, width);
            }
            tb_data.getColumnModel().getColumn(j).setPreferredWidth(width + 20);
        }

        tb_data.setVisible(true);

    }

    private void transpose(DefaultTableModel model) {
        try {
            if (model.getColumnCount() == 0) {
                return;
            }
            DefaultTableModel new_model = new DefaultTableModel();

            // if not transposed
            if (!model.getColumnName(0).equals("_field_") && transpose == true) {
                new_model.addColumn("_field_");
                for (int r = 1; r <= model.getRowCount(); ++r) {
                    new_model.addColumn("_col_" + r);
                }

                long n = 1;
                for (int c = 0; c < model.getColumnCount(); ++c) {
                    Object[] s = new Object[new_model.getColumnCount()];
                    String colname = model.getColumnName(c);
                    int l = 0;
                    s[l++] = colname;
                    for (int r = 0; r < model.getRowCount(); ++r) {
                        s[r + l] = model.getValueAt(r, c);
                    }
                    new_model.addRow(s);
                }
            }
            if (model.getColumnName(0).equals("_field_") && transpose == false) {
                // if transposed
                for (int r = 0; r < model.getRowCount(); ++r) {
                    new_model.addColumn(model.getValueAt(r, 0));
                }

                List<Integer> colIdx = new ArrayList();
                for (int c = 0; c < model.getColumnCount(); ++c) {
                    if (!model.getColumnName(c).equals("_field_")) {
                        colIdx.add(c);
                    }
                }

                for (int c = 0; c < colIdx.size(); ++c) {
                    Object[] s = new Object[new_model.getColumnCount()];
                    for (int r = 0; r < model.getRowCount(); ++r) {
                        s[r] = model.getValueAt(r, colIdx.get(c));
                    }
                    new_model.addRow(s);
                }
            }

            renderData(new_model);
        } catch (Exception e) {
            txt_count.setText(e.getMessage());
        }
    }

    class IntComparator implements Comparator {

        @Override
        public int compare(Object o1, Object o2) {
            Long int1 = (Long) o1;
            Long int2 = (Long) o2;
            return int1.compareTo(int2);
        }

        @Override
        public boolean equals(Object o2) {
            return this.equals(o2);
        }
    }

    // this is what you want
    private class MyTreeCellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                boolean leaf, int row, boolean hasFocus) {
            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                if (!node.getUserObject().toString().equals(cur_path)) {
                    if ((new File(cur_path + File.separator + node.getUserObject().toString())).isDirectory()) {
                        setIcon(this.getDefaultClosedIcon());
                    }
                } else {
                    setIcon(this.getDefaultOpenIcon());
                }
            }
            return this;
        }
    }

}