/*
 * AutoSummENGGui.java
 *
 * Created on 7 Μάρτιος 2007, 2:38 μμ
 */

package gr.demokritos.iit.jinsect.gui;

import gr.demokritos.iit.jinsect.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.Semaphore;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent;
import gr.demokritos.iit.jinsect.console.resultAssessor;
import gr.demokritos.iit.jinsect.console.summaryEvaluator;
import gr.demokritos.iit.jinsect.gui.utils.JTextAreaPrintStream;
import java.util.TreeMap;
import java.util.Vector;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

/**
 *
 * @author  ggianna
 */
public class AutoSummENGGui extends javax.swing.JFrame {
    public Thread tCur = null;
    /** Creates new form AutoSummENGGui and loads its settings */
    public AutoSummENGGui() {
        initComponents();
        loadSettings();
    }
    
    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        MeasureOptionGrp = new javax.swing.ButtonGroup();
        OptionsPanel = new javax.swing.JPanel();
        SwitchesPanel = new javax.swing.JPanel();
        SwitchesTabbedPanel = new javax.swing.JTabbedPane();
        GenOptPnl = new javax.swing.JPanel();
        OtherOptsPnl = new javax.swing.JPanel();
        jLabel9 = new javax.swing.JLabel();
        ThreadCntEdt = new javax.swing.JSpinner();
        DoPnl = new javax.swing.JPanel();
        DoCharChk = new javax.swing.JCheckBox();
        DoWordChk = new javax.swing.JCheckBox();
        VerbosityPnl = new javax.swing.JPanel();
        SilentChk = new javax.swing.JCheckBox();
        ProgressChk = new javax.swing.JCheckBox();
        UsePnl = new javax.swing.JPanel();
        OccurencesChk = new javax.swing.JRadioButton();
        DistrosChk = new javax.swing.JRadioButton();
        CharOptPnl = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        CharMinEdt = new javax.swing.JSpinner();
        jLabel4 = new javax.swing.JLabel();
        CharMaxEdt = new javax.swing.JSpinner();
        jLabel5 = new javax.swing.JLabel();
        CharDistEdt = new javax.swing.JSpinner();
        WordOptPnl = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        WordMinEdt = new javax.swing.JSpinner();
        jLabel8 = new javax.swing.JLabel();
        WordMaxEdt = new javax.swing.JSpinner();
        jLabel7 = new javax.swing.JLabel();
        WordDistEdt = new javax.swing.JSpinner();
        DirsPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        ModelsRootDirEdt = new javax.swing.JTextField();
        BrowseModelDirBtn = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        SummariesRootDirEdt = new javax.swing.JTextField();
        BrowseSummaryDirBtn = new javax.swing.JButton();
        jLabel10 = new javax.swing.JLabel();
        OutputFileEdt = new javax.swing.JTextField();
        BrowseOutputFileBtn = new javax.swing.JButton();
        ButtonPanel = new javax.swing.JPanel();
        DoEvalBtn = new javax.swing.JButton();
        ExitBtn = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        OutputMemo = new javax.swing.JTextArea();
        DetailedResultsPnl = new javax.swing.JScrollPane();
        DetailedResultsTbl = new javax.swing.JTable();
        LogScrollPane = new javax.swing.JScrollPane();
        LogMemo = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("AutoSummENG GUI v0.5");
        setName("AutoSummENGGUIForm");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                formWindowClosed(evt);
            }
        });

        getAccessibleContext().setAccessibleName("AutoSummENG GUI v0.8");
        OptionsPanel.setLayout(new java.awt.BorderLayout());

        SwitchesPanel.setLayout(new java.awt.BorderLayout());

        GenOptPnl.setLayout(new java.awt.GridLayout(2, 2));

        OtherOptsPnl.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        OtherOptsPnl.setBorder(javax.swing.BorderFactory.createTitledBorder("Other Options"));
        jLabel9.setText("Simultaneous Threads:");
        OtherOptsPnl.add(jLabel9);

        OtherOptsPnl.add(ThreadCntEdt);

        GenOptPnl.add(OtherOptsPnl);

        DoPnl.setLayout(new java.awt.GridLayout(3, 0, 0, 5));

        DoPnl.setBorder(javax.swing.BorderFactory.createTitledBorder("Perform evaluation using:"));
        DoPnl.setMinimumSize(new java.awt.Dimension(141, 100));
        DoPnl.setPreferredSize(new java.awt.Dimension(200, 80));
        DoCharChk.setSelected(true);
        DoCharChk.setText("Character N-Grams");
        DoCharChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        DoCharChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        DoCharChk.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                DoCharChkStateChanged(evt);
            }
        });

        DoPnl.add(DoCharChk);

        DoWordChk.setText("Word N-Grams");
        DoWordChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        DoWordChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        DoWordChk.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                DoWordChkStateChanged(evt);
            }
        });

        DoPnl.add(DoWordChk);

        GenOptPnl.add(DoPnl);

        VerbosityPnl.setLayout(new java.awt.GridLayout(3, 0, 0, 5));

        VerbosityPnl.setBorder(javax.swing.BorderFactory.createTitledBorder("Verbosity"));
        SilentChk.setText("Silent run");
        SilentChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        SilentChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        VerbosityPnl.add(SilentChk);

        ProgressChk.setText("Progress Report (even in silent run)");
        ProgressChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        ProgressChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        VerbosityPnl.add(ProgressChk);

        GenOptPnl.add(VerbosityPnl);

        UsePnl.setLayout(new java.awt.GridLayout(3, 0, 0, 5));

        UsePnl.setBorder(javax.swing.BorderFactory.createTitledBorder("Graph Edge Values are:"));
        UsePnl.setPreferredSize(new java.awt.Dimension(200, 80));
        MeasureOptionGrp.add(OccurencesChk);
        OccurencesChk.setSelected(true);
        OccurencesChk.setText("Neighbouring Occurences");
        OccurencesChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        OccurencesChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        UsePnl.add(OccurencesChk);

        MeasureOptionGrp.add(DistrosChk);
        DistrosChk.setText("Average Distance");
        DistrosChk.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        DistrosChk.setMargin(new java.awt.Insets(0, 0, 0, 0));
        UsePnl.add(DistrosChk);

        GenOptPnl.add(UsePnl);

        SwitchesTabbedPanel.addTab("General Options", GenOptPnl);

        CharOptPnl.setLayout(new java.awt.GridLayout(3, 2));

        jLabel3.setText("Minimum Character N-Gram Order (i.e. Length)");
        CharOptPnl.add(jLabel3);

        CharOptPnl.add(CharMinEdt);

        jLabel4.setText("Maximum Character N-Gram Order (i.e. Length)");
        CharOptPnl.add(jLabel4);

        CharOptPnl.add(CharMaxEdt);

        jLabel5.setText("Maximum Character N-Gram Neighbour Distance");
        CharOptPnl.add(jLabel5);

        CharOptPnl.add(CharDistEdt);

        SwitchesTabbedPanel.addTab("Character Options", CharOptPnl);

        WordOptPnl.setLayout(new java.awt.GridLayout(3, 2));

        WordOptPnl.setEnabled(false);
        jLabel6.setText("Minimum Word N-Gram Order (i.e. Length)");
        WordOptPnl.add(jLabel6);

        WordOptPnl.add(WordMinEdt);

        jLabel8.setText("Maximum Word N-Gram Order (i.e. Length)");
        WordOptPnl.add(jLabel8);

        WordOptPnl.add(WordMaxEdt);

        jLabel7.setText("Maximum Word N-Gram Neighbour Distance");
        WordOptPnl.add(jLabel7);

        WordOptPnl.add(WordDistEdt);

        SwitchesTabbedPanel.addTab("Word Options", WordOptPnl);

        SwitchesPanel.add(SwitchesTabbedPanel, java.awt.BorderLayout.CENTER);

        OptionsPanel.add(SwitchesPanel, java.awt.BorderLayout.CENTER);

        DirsPanel.setLayout(new java.awt.GridLayout(3, 3, 10, 10));

        jLabel1.setText("Models Root Directory:");
        DirsPanel.add(jLabel1);

        DirsPanel.add(ModelsRootDirEdt);

        BrowseModelDirBtn.setText("Browse...");
        BrowseModelDirBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BrowseModelDirBtnActionPerformed(evt);
            }
        });

        DirsPanel.add(BrowseModelDirBtn);

        jLabel2.setText("Summaries Root Directory:");
        DirsPanel.add(jLabel2);

        DirsPanel.add(SummariesRootDirEdt);

        BrowseSummaryDirBtn.setText("Browse...");
        BrowseSummaryDirBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BrowseSummaryDirBtnActionPerformed(evt);
            }
        });

        DirsPanel.add(BrowseSummaryDirBtn);

        jLabel10.setText("Output File:");
        DirsPanel.add(jLabel10);

        DirsPanel.add(OutputFileEdt);

        BrowseOutputFileBtn.setText("Browse...");
        BrowseOutputFileBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BrowseOutputFileBtnActionPerformed(evt);
            }
        });

        DirsPanel.add(BrowseOutputFileBtn);

        OptionsPanel.add(DirsPanel, java.awt.BorderLayout.NORTH);

        getContentPane().add(OptionsPanel, java.awt.BorderLayout.NORTH);

        DoEvalBtn.setText("Evaluate");
        DoEvalBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                DoEvalBtnActionPerformed(evt);
            }
        });

        ButtonPanel.add(DoEvalBtn);

        ExitBtn.setText("Exit");
        ExitBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitBtnActionPerformed(evt);
            }
        });

        ButtonPanel.add(ExitBtn);

        getContentPane().add(ButtonPanel, java.awt.BorderLayout.SOUTH);

        jPanel1.setLayout(new java.awt.GridLayout(1, 2, 20, 0));

        OutputMemo.setColumns(20);
        OutputMemo.setRows(5);
        OutputMemo.setBorder(javax.swing.BorderFactory.createTitledBorder("Output"));
        jScrollPane1.setViewportView(OutputMemo);

        jPanel1.add(jScrollPane1);

        DetailedResultsPnl.setName("DetailedResultsPnl");
        DetailedResultsPnl.setPreferredSize(new java.awt.Dimension(300, 403));
        DetailedResultsTbl.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "System ID", "Topic", "GraphValue"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.Double.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        DetailedResultsPnl.setViewportView(DetailedResultsTbl);

        jPanel1.add(DetailedResultsPnl);

        LogMemo.setColumns(20);
        LogMemo.setRows(5);
        LogMemo.setBorder(javax.swing.BorderFactory.createTitledBorder("Log"));
        LogScrollPane.setViewportView(LogMemo);

        jPanel1.add(LogScrollPane);

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

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

    /** Stops current running task. */
    /** Saves settings and terminates the application */
    private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
        saveSettings();
        System.exit(0);
    }//GEN-LAST:event_formWindowClosed

    private void BrowseOutputFileBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BrowseOutputFileBtnActionPerformed
        // Select a dir
        JFileChooser fc = new JFileChooser();
        fc.setCurrentDirectory((OutputFileEdt.getText().length() == 0) ? 
            new java.io.File(".") : new java.io.File(OutputFileEdt.getText()));
        fc.setSelectedFile(fc.getCurrentDirectory());
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int iRet = fc.showOpenDialog(this);
        if (iRet == JFileChooser.APPROVE_OPTION)
        {
            OutputFileEdt.setText(fc.getSelectedFile().getAbsolutePath());
        }        

    }//GEN-LAST:event_BrowseOutputFileBtnActionPerformed

    /** Performs evaluation based on the selected GUI settings. */
    private void DoEvalBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DoEvalBtnActionPerformed
        if (!canAddTask()) {
            JOptionPane.showMessageDialog(this, "Maximum allowed tasks already executing...");
            return;
        }
        
        Semaphore sSem = new Semaphore(1);
        // Determine do method
        String sDo;
        if (DoWordChk.isSelected() && DoCharChk.isSelected()) {
            sDo = summaryEvaluator.DO_ALL;
        } else
            if (DoWordChk.isSelected())
                sDo = summaryEvaluator.DO_WORDS;
            else
                sDo = summaryEvaluator.DO_CHARS;
        
        final summaryEvaluator s = new summaryEvaluator(sSem, sDo, (Integer)(WordMinEdt.getValue()), 
                (Integer)(WordMaxEdt.getValue()), (Integer)(WordDistEdt.getValue()), 
                (Integer)(CharMinEdt.getValue()), 
                (Integer)(CharMaxEdt.getValue()), (Integer)(CharDistEdt.getValue()), 
                (Integer)(ThreadCntEdt.getValue()), OutputFileEdt.getText(), 
                SummariesRootDirEdt.getText(), ModelsRootDirEdt.getText(),
                SilentChk.isSelected(), 
                OccurencesChk.isSelected() ? summaryEvaluator.USE_OCCURENCES_AS_WEIGHT : 
                    summaryEvaluator.USE_DISTRO_AVERAGE_AS_WEIGHT, 
                ProgressChk.isSelected());
        
        final String sAssessorDo = sDo;
        // Redirect System.err, System.out
        Runnable r = new Runnable() {
            public void run() {
                PrintStream pErrTmp = System.err;
                PrintStream pOutTmp = System.out;
                try {
                    JTextAreaPrintStream jLog = new JTextAreaPrintStream(LogMemo);
                    JTextAreaPrintStream jOutput = new JTextAreaPrintStream(OutputMemo);
                    
                    System.setErr(jLog);
                    System.setOut(jOutput);
                    System.err.println("Started job..." + DateFormat.getDateTimeInstance().format(new Date()));
                    // Evaluate
                    s.run();
                    // Read detailed results
                    readDetailedResultsFromFile(OutputFileEdt.getText());
                    
                    // Get averages to output
                    String[] saAssessorArgs = {"-insectFile=" + OutputFileEdt.getText(),
                        "-dirPrefix=" + new File(OutputFileEdt.getText()).getParent() + 
                            System.getProperty("file.separator"),
                        "-noCorrelationCheck",
                        "-noResponsiveness",
                        "-do=" + sAssessorDo};
                    resultAssessor.main(saAssessorArgs);
                    try {
                        // Read final output file
                        FileReader frIn = new FileReader(new File(OutputFileEdt.getText()).getParent() + 
                                System.getProperty("file.separator") + 
                                resultAssessor.OVERALL_OUTPUT_FILENAME);
                        BufferedReader brIn = new BufferedReader(frIn);
                        String sCurLine;
                        // Create title
                        jOutput.println("FINAL RESULTS:\n--------------");
                        // Print output file to Output stream
                        while ((sCurLine = brIn.readLine()) != null) {
                            jOutput.println(sCurLine);
                        }
                    } catch (FileNotFoundException ex) {
                        System.err.println("Cannot find overall results file. Error:");
                        ex.printStackTrace(System.err);
                    }
                    catch (IOException ioex) {
                        System.err.println("Cannot read overall results file. Error:");
                        ioex.printStackTrace(System.err);
                    }
                    
                    System.err.println("Job finished..." + DateFormat.getDateTimeInstance().format(new Date()));
                }
                finally {
                    removeTask(this);
                    System.setErr(pErrTmp);
                    System.setOut(pOutTmp);
                }                        
            }
        };
        addTask(r);
        
    }//GEN-LAST:event_DoEvalBtnActionPerformed
    
    private void DoCharChkStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_DoCharChkStateChanged
        //CharOptPnl.setVisible(((JCheckBox)evt.getSource()).isSelected());
    }//GEN-LAST:event_DoCharChkStateChanged

    private void DoWordChkStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_DoWordChkStateChanged
        //WordOptPnl.setVisible(((JCheckBox)evt.getSource()).isSelected());
    }//GEN-LAST:event_DoWordChkStateChanged

    /** Terminates the application, stopping any running tasks. */
    private void ExitBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ExitBtnActionPerformed
        if (JOptionPane.showConfirmDialog(this, "Do you wish to end the application?", "Confirm",
                JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
            // Clear running task
            if (taskInProgress())
                removeTask(getActiveTask());
            // Hide form
            this.setVisible(false);
            this.dispose(); // Terminate
        }
    }//GEN-LAST:event_ExitBtnActionPerformed

    /** Select the directory of the peer summaries. */
    private void BrowseSummaryDirBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BrowseSummaryDirBtnActionPerformed
        // Select a dir
        JFileChooser fc = new JFileChooser();
        fc.setCurrentDirectory((SummariesRootDirEdt.getText().length() == 0) ? 
            new java.io.File(".") : new java.io.File(SummariesRootDirEdt.getText()));
        fc.setSelectedFile(fc.getCurrentDirectory());
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int iRet = fc.showOpenDialog(this);
        if (iRet == JFileChooser.APPROVE_OPTION)
        {
            SummariesRootDirEdt.setText(fc.getSelectedFile().getAbsolutePath());
        }        
    }//GEN-LAST:event_BrowseSummaryDirBtnActionPerformed

    /** Select the directory of the model summaries. */
    private void BrowseModelDirBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BrowseModelDirBtnActionPerformed
        // Select a dir
        JFileChooser fc = new JFileChooser();
        fc.setCurrentDirectory((ModelsRootDirEdt.getText().length() == 0) ? 
            new java.io.File(".") : new java.io.File(ModelsRootDirEdt.getText()));
        fc.setSelectedFile(fc.getCurrentDirectory());
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int iRet = fc.showOpenDialog(this);
        if (iRet == JFileChooser.APPROVE_OPTION)
        {
            ModelsRootDirEdt.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }//GEN-LAST:event_BrowseModelDirBtnActionPerformed
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new AutoSummENGGui().setVisible(true);
            }
        });
    }
    
    /** Save GUI settings in file. */
    private void saveSettings() {
        Properties pOut = new Properties();
        // Dirs
        pOut.setProperty("ModelDir", ModelsRootDirEdt.getText());
        pOut.setProperty("SummaryDir", SummariesRootDirEdt.getText());
        pOut.setProperty("OutputFile", OutputFileEdt.getText());
        
        // Global settings
        pOut.setProperty("Threads", ThreadCntEdt.getValue().toString());
        pOut.setProperty("Silent", String.valueOf(SilentChk.isSelected()));
        pOut.setProperty("ShowProgress", String.valueOf(ProgressChk.isSelected()));
        pOut.setProperty("DoWord", String.valueOf(DoWordChk.isSelected()));
        pOut.setProperty("DoChar", String.valueOf(DoCharChk.isSelected()));
        pOut.setProperty("Use", OccurencesChk.isSelected() ? "Occurences" : "Distros");
        // Char settings
        pOut.setProperty("CharMin", String.valueOf(CharMinEdt.getValue()));
        pOut.setProperty("CharMax", String.valueOf(CharMaxEdt.getValue()));
        pOut.setProperty("CharDist", String.valueOf(CharDistEdt.getValue()));
        // Word settings
        pOut.setProperty("WordMin", String.valueOf(WordMinEdt.getValue()));
        pOut.setProperty("WordMax", String.valueOf(WordMaxEdt.getValue()));
        pOut.setProperty("WordDist", String.valueOf(WordDistEdt.getValue()));
        
        // Save
        try {
            FileOutputStream fsOut = new FileOutputStream("AutoSummENGGUI.properties");
            pOut.storeToXML(fsOut, "");
            fsOut.flush();
            fsOut.close();
        }
        catch (IOException ioe) {
            ioe.printStackTrace(System.err);
        }
    
    }
    
    /** Load GUI settings from file. */
    private void loadSettings() {
        Properties pIn = new Properties();
        // Load
        try {
            if (!(new File("AutoSummENGGUI.properties").exists()))
                return;
            FileInputStream fsIn = new FileInputStream("AutoSummENGGUI.properties");
            pIn.loadFromXML(fsIn);
            fsIn.close();
        }
        catch (IOException ioe) {
            ioe.printStackTrace(System.err);
            return;
        }
        
        try {            
            // Dirs
            ModelsRootDirEdt.setText(pIn.getProperty("ModelDir", "./models"));
            SummariesRootDirEdt.setText(pIn.getProperty("SummaryDir", "./summaries"));
            OutputFileEdt.setText(pIn.getProperty("OutputFile", "./jinsect.table"));
            // Global settings
            ThreadCntEdt.setValue(Integer.valueOf(pIn.getProperty("Threads", "2")));
            SilentChk.setSelected(Boolean.valueOf(pIn.getProperty("Silent", 
                    Boolean.TRUE.toString())));
            ProgressChk.setSelected(Boolean.valueOf(pIn.getProperty("ShowProgress", 
                    Boolean.TRUE.toString())));
            DoWordChk.setSelected(Boolean.valueOf(pIn.getProperty("DoWord", 
                    Boolean.TRUE.toString())));
            DoWordChkStateChanged(new ChangeEvent(DoWordChk)); // Update as if pressed
            
            DoCharChk.setSelected(Boolean.valueOf(pIn.getProperty("DoChar", 
                    Boolean.TRUE.toString())));
            DoCharChkStateChanged(new ChangeEvent(DoCharChk)); // Update as if pressed
            
            if (pIn.getProperty("Use", "Occurences").equals("Occurences"))
                OccurencesChk.setSelected(true);
            else
                DistrosChk.setSelected(true);

            // Char settings
            CharMinEdt.setValue(Integer.valueOf(pIn.getProperty("CharMin", "3")));
            CharMaxEdt.setValue(Integer.valueOf(pIn.getProperty("CharMax", "3")));
            CharDistEdt.setValue(Integer.valueOf(pIn.getProperty("CharDist", "3")));
            // Word settings
            WordMinEdt.setValue(Integer.valueOf(pIn.getProperty("WordMin", "1")));
            WordMaxEdt.setValue(Integer.valueOf(pIn.getProperty("WordMax", "2")));
            WordDistEdt.setValue(Integer.valueOf(pIn.getProperty("WordDist", "3")));
        }
        catch (Exception e) {
            System.err.println("Could not load settings...");
            return;
        }
        
        // Init model table
        PerformanceTableModel tTmp = new PerformanceTableModel();        
        DetailedResultsTbl.setModel(tTmp);
    }
    
    /** Returns whether the task queue is not full.  */
    private boolean canAddTask() {
        return tCur == null;
    }
    
    /** Returns whether there is a task in progress. */
    private boolean taskInProgress() {
        return tCur != null;
    }
    
    /** Adds a task to the task queue.
     *@param r A Runnable object that is added as a task to the task queue, and started.
     */
    private void addTask(Runnable r) {
        Thread tEval = new Thread(r);
        tCur = tEval;
        tEval.start();
    }
    
    /** Returns current active task.
     *@return The active task which is first in the task queue.
     */
    private Runnable getActiveTask() {
        return tCur;
    }
    
    /** Removes a task from the task queue.
     *@param r The task to remove
     */
    private void removeTask(Runnable r) {
        tCur = null;
    }
    
    /** Read detailed results into corresponding gui table. 
     *@param sFilename The filename to import.
     */
    private void readDetailedResultsFromFile(String sFilename) {
        
        // Init table model
        PerformanceTableModel tTmp = new PerformanceTableModel();
        
        // Load file
        String sDetailedRes = utils.loadFileToStringWithNewlines(sFilename);
        String[] sRows = sDetailedRes.split("\n");
        for (int iRowCnt=0; iRowCnt < sRows.length; iRowCnt++) {
            String sLine = sRows[iRowCnt];
            if (sLine.startsWith("Theme"))
                continue; // Ignores first line
            // Split line into results
            String[] sResult = sLine.split("\\s+");
            if (sResult.length > 0)
                tTmp.append(sResult[1], sResult[0], Double.valueOf(sResult[3]).doubleValue());
        }
        DetailedResultsTbl.setModel(tTmp);
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton BrowseModelDirBtn;
    private javax.swing.JButton BrowseOutputFileBtn;
    private javax.swing.JButton BrowseSummaryDirBtn;
    private javax.swing.JPanel ButtonPanel;
    private javax.swing.JSpinner CharDistEdt;
    private javax.swing.JSpinner CharMaxEdt;
    private javax.swing.JSpinner CharMinEdt;
    private javax.swing.JPanel CharOptPnl;
    private javax.swing.JScrollPane DetailedResultsPnl;
    private javax.swing.JTable DetailedResultsTbl;
    private javax.swing.JPanel DirsPanel;
    private javax.swing.JRadioButton DistrosChk;
    private javax.swing.JCheckBox DoCharChk;
    private javax.swing.JButton DoEvalBtn;
    private javax.swing.JPanel DoPnl;
    private javax.swing.JCheckBox DoWordChk;
    private javax.swing.JButton ExitBtn;
    private javax.swing.JPanel GenOptPnl;
    private javax.swing.JTextArea LogMemo;
    private javax.swing.JScrollPane LogScrollPane;
    private javax.swing.ButtonGroup MeasureOptionGrp;
    private javax.swing.JTextField ModelsRootDirEdt;
    private javax.swing.JRadioButton OccurencesChk;
    private javax.swing.JPanel OptionsPanel;
    private javax.swing.JPanel OtherOptsPnl;
    private javax.swing.JTextField OutputFileEdt;
    private javax.swing.JTextArea OutputMemo;
    private javax.swing.JCheckBox ProgressChk;
    private javax.swing.JCheckBox SilentChk;
    private javax.swing.JTextField SummariesRootDirEdt;
    private javax.swing.JPanel SwitchesPanel;
    private javax.swing.JTabbedPane SwitchesTabbedPanel;
    private javax.swing.JSpinner ThreadCntEdt;
    private javax.swing.JPanel UsePnl;
    private javax.swing.JPanel VerbosityPnl;
    private javax.swing.JSpinner WordDistEdt;
    private javax.swing.JSpinner WordMaxEdt;
    private javax.swing.JSpinner WordMinEdt;
    private javax.swing.JPanel WordOptPnl;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables
    
}

class PerformanceTableModel implements TableModel {
    /** Contains the hash of name-column (name-column vectors). */
    private TreeMap<String,Vector> lCols;
    
    final static String COLUMNNAME_SYSTEMID = "1. System ID";
    final static String COLUMNNAME_TOPICID = "2. Topic ID";
    final static String COLUMNNAME_PERFORMANCE = "3. Performance";
    
    /** Initialize the model. */
    public PerformanceTableModel() {
        // Init columns
        Vector<String> vSysID = new Vector<String>();
        Vector<String> vTopicID = new Vector<String>();
        Vector<Double> vPerformance = new Vector<Double>();
        lCols = new TreeMap<String,Vector>();
        
        // Init List of Columns
        lCols.put(COLUMNNAME_SYSTEMID, vSysID);
        lCols.put(COLUMNNAME_TOPICID, vTopicID);
        lCols.put(COLUMNNAME_PERFORMANCE, vPerformance);
    }
        
    public void addTableModelListener(TableModelListener l) {
    }

    public Class<?> getColumnClass(int columnIndex) {
        return lCols.get(lCols.keySet().toArray()[columnIndex]).getClass();
    }
    public int getColumnCount() {
        return lCols.size();
    }
    public String getColumnName(int columnIndex) {
        return lCols.keySet().toArray()[columnIndex].toString();
    }

    public int getRowCount() {
        return lCols.get(COLUMNNAME_SYSTEMID).size();
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        return lCols.get(lCols.keySet().toArray()[columnIndex]).get(rowIndex);
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public void removeTableModelListener(TableModelListener l) {
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        String sColName = ((String[])lCols.keySet().toArray())[columnIndex];
        lCols.get(sColName).set(rowIndex, aValue);
    }

    public void append(String sSysID, String sTopicID, double dValue) {
        ((Vector<String>)lCols.get(COLUMNNAME_SYSTEMID)).add(sSysID);
        ((Vector<String>)lCols.get(COLUMNNAME_TOPICID)).add(sTopicID);
        ((Vector<Double>)lCols.get(COLUMNNAME_PERFORMANCE)).add(new Double(dValue));
    }
    
}