/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.framework.ui;

import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.testing.framework.*;

/**
 * Displays the loadbuild test results.
 */
public class LoadBuildDisplayPanel extends JPanel implements ActionListener, MouseListener {
    private Vector loadBuildsCache;
    private Vector testResultsCahce;
    private Vector testSummaryCahce;
    private LoadBuildSummary selectedLoadBuild;
    private final int LOADBUILD = 1;// table selection
    private final int SUMMARY = 2;
    private final int RESULT = 3;
    private int tableSelection;
    private DatabaseSession session;
    private JTable loadBuildTable;
    private JTable testResultTable;
    private JTable testSummaryTable;
    private JTabbedPane ivjLoadBuildTabbedPanel = null;
    private JPanel ivjViewPage = null;
    private JPanel ivjLoadBuildPage = null;
    private JButton ivjLoadErrorTestResultButton = null;
    private JTextArea ivjViewTextArea = null;
    private JButton ivjDeleteButton = null;
    private JScrollPane ivjViewScrollPane = null;
    private JScrollPane ivjLoadBuildScrollPane = null;
    private JTable ivjSelectedTable = null;
    private JButton ivjInspectButton = null;
    private JButton ivjUpButton = null;
    private JButton ivjViewButton = null;

    /**
     * Constructor
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    public LoadBuildDisplayPanel() {
        super();
        initialize();
    }

    /**
     * LoadBuildPanel constructor comment.
     * @param layout java.awt.LayoutManager
     */
    public LoadBuildDisplayPanel(java.awt.LayoutManager layout) {
        super(layout);
    }

    /**
     * LoadBuildPanel constructor comment.
     * @param layout java.awt.LayoutManager
     * @param isDoubleBuffered boolean
     */
    public LoadBuildDisplayPanel(java.awt.LayoutManager layout, boolean isDoubleBuffered) {
        super(layout, isDoubleBuffered);
    }

    /**
     * LoadBuildPanel constructor comment.
     * @param isDoubleBuffered boolean
     */
    public LoadBuildDisplayPanel(boolean isDoubleBuffered) {
        super(isDoubleBuffered);
    }

    /**
     * Method to handle events for the ActionListener interface.
     * @param e java.awt.event.ActionEvent
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    @Override
    public void actionPerformed(java.awt.event.ActionEvent e) {
        // user code begin {1}
        // user code end
        if (e.getSource() == getLoadErrorTestResultButton()) {
            connEtoC2(e);
        }
        if (e.getSource() == getDeleteButton()) {
            connEtoC9(e);
        }
        if (e.getSource() == getUpButton()) {
            connEtoC1(e);
        }
        if (e.getSource() == getInspectButton()) {
            connEtoC3(e);
        }
        if (e.getSource() == getViewButton()) {
            connEtoC4(e);
        }

        // user code begin {2}
        // user code end
    }

    public void buildErrorTestResultForSummary() {
        int index = getSelectedTable().getSelectedRow();

        TestResultsSummary selectedSummary = (TestResultsSummary)testSummaryCahce.elementAt(index);

        Vector testResults = new Vector();

        if ((selectedSummary.getResults() != null) && (selectedSummary.getResults().size() > 0)) {
            for (Enumeration enumtr = selectedSummary.getResults().elements();
                     enumtr.hasMoreElements();) {
                TestResult result = (TestResult)enumtr.nextElement();
                if (result.hasError() || result.hasFatalError() || result.hasProblem()) {
                    testResults.addElement(result);
                }
            }
        } else {
            Vector summariesHasResult = new Vector();
            for (Enumeration<TestResultsSummary> enumtr = selectedSummary.getLoadBuildSummary().getSummaries().elements();
                 enumtr.hasMoreElements();) {
                TestResultsSummary summary = enumtr.nextElement();
                if ((summary.getResults() != null) && (summary.getResults().size() != 0)) {
                    summariesHasResult.addElement(summary);
                }
            }
            for (Enumeration enum1 = summariesHasResult.elements(); enum1.hasMoreElements();) {
                TestResultsSummary summary = (TestResultsSummary)enum1.nextElement();
                TestResultsSummary temp = summary;
                while (temp.getParent() != null) {
                    if (temp.getParent() == selectedSummary) {
                        for (Enumeration enum2 = summary.getResults().elements();
                                 enum2.hasMoreElements();) {
                            TestResult result = (TestResult)enum2.nextElement();
                            if (result.hasError() || result.hasFatalError() || result.hasProblem()) {
                                testResults.addElement(result);
                            }
                        }
                        break;
                    }
                    temp = temp.getParent();
                }
            }
        }
        testResultsCahce = testResults;
    }

    public void clearTable(JTable table) {
        table.setModel(new NonEditableDefaultTableModel());
        table.repaint();
    }

    /**
     * connEtoC1:  (UpButton.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} LoadBuildDisplayPanel.up()V)
     * @param arg1 java.awt.event.ActionEvent
     */
    private void connEtoC1(java.awt.event.ActionEvent arg1) {
        try {
            this.up();
        } catch (java.lang.Throwable ivjExc) {
            handleException(ivjExc);
        }
    }

    /**
     * connEtoC2:  (LoadErrorTestResultButton.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} LoadBuildDisplayPanel.loadErrorTestResults()V)
     * @param arg1 java.awt.event.ActionEvent
     */
    private void connEtoC2(java.awt.event.ActionEvent arg1) {
        try {
            this.loadErrorTestResults();
        } catch (java.lang.Throwable ivjExc) {
            handleException(ivjExc);
        }
    }

    /**
     * connEtoC3:  (InspectButton1.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} LoadBuildDisplayPanel.inspectSelectedLoadBuild()V)
     * @param arg1 java.awt.event.ActionEvent
     */
    private void connEtoC3(java.awt.event.ActionEvent arg1) {
        try {
            this.inspectDatabaseLogin();
        } catch (java.lang.Throwable ivjExc) {
            handleException(ivjExc);
        }
    }

    /**
     * connEtoC4:  (JButton1.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} LoadBuildDisplayPanel.viewStackTrace()V)
     * @param arg1 java.awt.event.ActionEvent
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void connEtoC4(java.awt.event.ActionEvent arg1) {
        try {
            // user code begin {1}
            // user code end
            this.viewStackTrace();

            // user code begin {2}
            // user code end
        } catch (java.lang.Throwable ivjExc) {
            // user code begin {3}
            // user code end
            handleException(ivjExc);
        }
    }

    /**
     * connEtoC9:  (DeleteButton.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} LoadBuildDisplayPanel.deleteLoadBuild()V)
     * @param arg1 java.awt.event.ActionEvent
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void connEtoC9(java.awt.event.ActionEvent arg1) {
        try {
            // user code begin {1}
            // user code end
            this.deleteLoadBuild();

            // user code begin {2}
            // user code end
        } catch (java.lang.Throwable ivjExc) {
            // user code begin {3}
            // user code end
            handleException(ivjExc);
        }
    }

    /**
     * Comment
     */
    public void deleteLoadBuild() {
        int index = getSelectedTable().getSelectedRow();
        if (index < 0) {
            return;
        }
        int option = JOptionPane.showConfirmDialog(this, "Are you sure that  you want to remove this load build?", "", JOptionPane.OK_CANCEL_OPTION);
        if (option != JOptionPane.OK_OPTION) {
            return;
        }

        LoadBuildSummary loadBuild = (LoadBuildSummary)loadBuildsCache.elementAt(index);
        try {
            if (loadBuild.databaseLogin == null) {
                loadBuild = (LoadBuildSummary)session.readObject(loadBuild);
            }
            session.deleteObject(loadBuild);
            loadBuildsCache.removeElementAt(index);
            poppulateLoadBuildTable(loadBuildsCache);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }

    public void down() {
        int index = getSelectedTable().getSelectedRow();
        if (index < 0) {
            return;
        }
        if (tableSelection == LOADBUILD) {
            TestResultsSummary summary = (TestResultsSummary)loadBuildsCache.elementAt(index);
            initilaizeTestSummaryCache(summary);
            if (tableSelection == RESULT) {
                poppulateTestResultTable(testResultsCahce);
            } else {
                poppulateTestSummaryTable(testSummaryCahce);
            }
        } else if (tableSelection == SUMMARY) {
            initilaizeTestSummaryCache((TestResultsSummary)testSummaryCahce.elementAt(index));
            if (tableSelection == RESULT) {
                poppulateTestResultTable(testResultsCahce);
            } else {
                poppulateTestSummaryTable(testSummaryCahce);
            }
        }
    }

    /**
     * Return the DeleteButton property value.
     * @return javax.swing.JButton
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JButton getDeleteButton() {
        if (ivjDeleteButton == null) {
            try {
                ivjDeleteButton = new javax.swing.JButton();
                ivjDeleteButton.setName("DeleteButton");
                ivjDeleteButton.setText("Delete");

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjDeleteButton;
    }

    /**
     * Return the InspectButton1 property value.
     * @return javax.swing.JButton
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JButton getInspectButton() {
        if (ivjInspectButton == null) {
            try {
                ivjInspectButton = new javax.swing.JButton();
                ivjInspectButton.setName("InspectButton");
                ivjInspectButton.setText("Inspect Login");
                ivjInspectButton.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjInspectButton;
    }

    /**
     * Return the LoadBuildPage property value.
     * @return javax.swing.JPanel
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JPanel getLoadBuildPage() {
        if (ivjLoadBuildPage == null) {
            try {
                ivjLoadBuildPage = new javax.swing.JPanel();
                ivjLoadBuildPage.setName("LoadBuildPage");
                ivjLoadBuildPage.setLayout(new java.awt.GridBagLayout());

                java.awt.GridBagConstraints constraintsLoadBuildScrollPane = new java.awt.GridBagConstraints();
                constraintsLoadBuildScrollPane.gridx = 0;
                constraintsLoadBuildScrollPane.gridy = 0;
                constraintsLoadBuildScrollPane.gridwidth = 7;
                constraintsLoadBuildScrollPane.fill = java.awt.GridBagConstraints.BOTH;
                constraintsLoadBuildScrollPane.weightx = 1.0;
                constraintsLoadBuildScrollPane.weighty = 1.0;
                constraintsLoadBuildScrollPane.ipadx = 176;
                constraintsLoadBuildScrollPane.ipady = -67;
                constraintsLoadBuildScrollPane.insets = new java.awt.Insets(0, 0, 5, 0);
                getLoadBuildPage().add(getLoadBuildScrollPane(), constraintsLoadBuildScrollPane);

                java.awt.GridBagConstraints constraintsUpButton = new java.awt.GridBagConstraints();
                constraintsUpButton.gridx = 0;
                constraintsUpButton.gridy = 1;
                constraintsUpButton.anchor = java.awt.GridBagConstraints.WEST;
                constraintsUpButton.insets = new java.awt.Insets(0, 10, 5, 5);
                getLoadBuildPage().add(getUpButton(), constraintsUpButton);

                java.awt.GridBagConstraints constraintsDeleteButton = new java.awt.GridBagConstraints();
                constraintsDeleteButton.gridx = 2;
                constraintsDeleteButton.gridy = 1;
                constraintsDeleteButton.anchor = java.awt.GridBagConstraints.WEST;
                constraintsDeleteButton.insets = new java.awt.Insets(0, 5, 5, 5);
                getLoadBuildPage().add(getDeleteButton(), constraintsDeleteButton);

                java.awt.GridBagConstraints constraintsLoadErrorTestResultButton = new java.awt.GridBagConstraints();
                constraintsLoadErrorTestResultButton.gridx = 1;
                constraintsLoadErrorTestResultButton.gridy = 1;
                constraintsLoadErrorTestResultButton.anchor = java.awt.GridBagConstraints.WEST;
                constraintsLoadErrorTestResultButton.insets = new java.awt.Insets(0, 5, 5, 5);
                getLoadBuildPage().add(getLoadErrorTestResultButton(), constraintsLoadErrorTestResultButton);

                java.awt.GridBagConstraints constraintsInspectButton = new java.awt.GridBagConstraints();
                constraintsInspectButton.gridx = 4;
                constraintsInspectButton.gridy = 1;
                constraintsInspectButton.anchor = java.awt.GridBagConstraints.WEST;
                constraintsInspectButton.insets = new java.awt.Insets(0, 5, 5, 5);
                getLoadBuildPage().add(getInspectButton(), constraintsInspectButton);

                java.awt.GridBagConstraints constraintsViewButton = new java.awt.GridBagConstraints();
                constraintsViewButton.gridx = 6;
                constraintsViewButton.gridy = 1;
                constraintsViewButton.anchor = java.awt.GridBagConstraints.WEST;
                constraintsViewButton.insets = new java.awt.Insets(0, 5, 5, 5);
                getLoadBuildPage().add(getViewButton(), constraintsViewButton);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjLoadBuildPage;
    }

    /**
     * Return the JScrollPane1 property value.
     * @return javax.swing.JScrollPane
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JScrollPane getLoadBuildScrollPane() {
        if (ivjLoadBuildScrollPane == null) {
            try {
                ivjLoadBuildScrollPane = new javax.swing.JScrollPane();
                ivjLoadBuildScrollPane.setName("LoadBuildScrollPane");
                ivjLoadBuildScrollPane.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
                ivjLoadBuildScrollPane.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
                getLoadBuildScrollPane().setViewportView(getSelectedTable());

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjLoadBuildScrollPane;
    }

    /**
     * Return the LoadBuildTabbedPanel property value.
     * @return javax.swing.JTabbedPane
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JTabbedPane getLoadBuildTabbedPanel() {
        if (ivjLoadBuildTabbedPanel == null) {
            try {
                ivjLoadBuildTabbedPanel = new javax.swing.JTabbedPane();
                ivjLoadBuildTabbedPanel.setName("LoadBuildTabbedPanel");
                ivjLoadBuildTabbedPanel.setBackground(java.awt.SystemColor.control);
                ivjLoadBuildTabbedPanel.insertTab("    Result   ", null, getLoadBuildPage(), null, 0);
                ivjLoadBuildTabbedPanel.insertTab("     View    ", null, getViewPage(), null, 1);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjLoadBuildTabbedPanel;
    }

    /**
     * Return the LoadErrorTestResultButton property value.
     * @return javax.swing.JButton
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JButton getLoadErrorTestResultButton() {
        if (ivjLoadErrorTestResultButton == null) {
            try {
                ivjLoadErrorTestResultButton = new javax.swing.JButton();
                ivjLoadErrorTestResultButton.setName("LoadErrorTestResultButton");
                ivjLoadErrorTestResultButton.setText("Load Error Tests");
                ivjLoadErrorTestResultButton.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjLoadErrorTestResultButton;
    }

    /**
     * Return the ScrollPaneTable property value.
     * @return javax.swing.JTable
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JTable getSelectedTable() {
        if (ivjSelectedTable == null) {
            try {
                ivjSelectedTable = new javax.swing.JTable();
                ivjSelectedTable.setName("SelectedTable");
                getLoadBuildScrollPane().setColumnHeaderView(ivjSelectedTable.getTableHeader());
                ivjSelectedTable.setBounds(0, 0, 200, 200);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjSelectedTable;
    }

    /**
     * Return the UpButton property value.
     * @return javax.swing.JButton
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JButton getUpButton() {
        if (ivjUpButton == null) {
            try {
                ivjUpButton = new javax.swing.JButton();
                ivjUpButton.setName("UpButton");
                ivjUpButton.setText("Up");

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjUpButton;
    }

    public int getUpIndex(TestResult theResult) {
        if (theResult.getSummary() == null) {
            for (int i = 0; i < loadBuildsCache.size(); i++) {
                LoadBuildSummary loadBuild = (LoadBuildSummary)loadBuildsCache.elementAt(i);
                if (loadBuild.timestamp.equals(theResult.getLoadBuildSummary().timestamp)) {
                    return i;
                }
            }
        } else if (theResult.getSummary().getParent() == null) {
            initilaizeTestSummaryCache(theResult.getLoadBuildSummary());
        } else {
            initilaizeTestSummaryCache(theResult.getSummary().getParent());
        }

        if (theResult.getSummary() != null) {
            for (int i = 0; i < testSummaryCahce.size(); i++) {
                TestResultsSummary summary = (TestResultsSummary)testSummaryCahce.elementAt(i);
                if (summary.getName().equals(theResult.getSummary().getName())) {
                    return i;
                }
            }
        }
        return -1;
    }

    public int getUpIndex(TestResultsSummary theSummary) {
        if (theSummary.getParent() == null) {
            for (int i = 0; i < loadBuildsCache.size(); i++) {
                LoadBuildSummary loadBuild = (LoadBuildSummary)loadBuildsCache.elementAt(i);
                if (loadBuild.timestamp.equals(theSummary.getLoadBuildSummary().timestamp)) {
                    return i;
                }
            }
        } else {
            if (theSummary.getParent().getParent() == null) {
                initilaizeTestSummaryCache(theSummary.getLoadBuildSummary());
            } else {
                initilaizeTestSummaryCache(theSummary.getParent().getParent());
            }

            for (int i = 0; i < testSummaryCahce.size(); i++) {
                TestResultsSummary summary = (TestResultsSummary)testSummaryCahce.elementAt(i);
                if (summary.getName().equals(theSummary.getParent().getName())) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * Return the JButton1 property value.
     * @return javax.swing.JButton
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JButton getViewButton() {
        if (ivjViewButton == null) {
            try {
                ivjViewButton = new javax.swing.JButton();
                ivjViewButton.setName("ViewButton");
                ivjViewButton.setText("View Exception");

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjViewButton;
    }

    /**
     * Return the ViewPage property value.
     * @return javax.swing.JPanel
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JPanel getViewPage() {
        if (ivjViewPage == null) {
            try {
                ivjViewPage = new javax.swing.JPanel();
                ivjViewPage.setName("ViewPage");
                ivjViewPage.setLayout(new java.awt.GridBagLayout());
                ivjViewPage.setBackground(java.awt.SystemColor.control);
                ivjViewPage.setForeground(java.awt.SystemColor.controlText);

                java.awt.GridBagConstraints constraintsViewScrollPane = new java.awt.GridBagConstraints();
                constraintsViewScrollPane.gridx = 1;
                constraintsViewScrollPane.gridy = 1;
                constraintsViewScrollPane.fill = java.awt.GridBagConstraints.BOTH;
                constraintsViewScrollPane.weightx = 1.0;
                constraintsViewScrollPane.weighty = 1.0;
                constraintsViewScrollPane.ipadx = 947;
                constraintsViewScrollPane.ipady = 323;
                getViewPage().add(getViewScrollPane(), constraintsViewScrollPane);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjViewPage;
    }

    /**
     * Return the JScrollPane1 property value.
     * @return javax.swing.JScrollPane
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JScrollPane getViewScrollPane() {
        if (ivjViewScrollPane == null) {
            try {
                ivjViewScrollPane = new javax.swing.JScrollPane();
                ivjViewScrollPane.setName("ViewScrollPane");
                getViewScrollPane().setViewportView(getViewTextArea());

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjViewScrollPane;
    }

    /**
     * Return the ViewTextArea property value.
     * @return javax.swing.JTextArea
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JTextArea getViewTextArea() {
        if (ivjViewTextArea == null) {
            try {
                ivjViewTextArea = new javax.swing.JTextArea();
                ivjViewTextArea.setName("ViewTextArea");
                ivjViewTextArea.setBounds(0, 0, 237, 19);

                // user code begin {1}
                // user code end
            } catch (java.lang.Throwable ivjExc) {
                // user code begin {2}
                // user code end
                handleException(ivjExc);
            }
        }
        return ivjViewTextArea;
    }

    /**
     * Called whenever the part throws an exception.
     * @param exception java.lang.Throwable
     */
    private void handleException(Throwable exception) {
        exception.printStackTrace(System.out);
    }

    /**
     * Initializes connections
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void initConnections() throws java.lang.Exception {
        // user code begin {1}
        getSelectedTable().addMouseListener(this);
        // user code end
        getLoadErrorTestResultButton().addActionListener(this);
        getDeleteButton().addActionListener(this);
        getUpButton().addActionListener(this);
        getInspectButton().addActionListener(this);
        getViewButton().addActionListener(this);
    }

    /**
     * Initialize the class.
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void initialize() {
        try {
            // user code begin {1}
            // user code end
            setName("LoadBuildPanel");
            setLayout(new java.awt.GridBagLayout());
            setBackground(java.awt.SystemColor.control);
            setSize(640, 417);

            java.awt.GridBagConstraints constraintsLoadBuildTabbedPanel = new java.awt.GridBagConstraints();
            constraintsLoadBuildTabbedPanel.gridx = 0;
            constraintsLoadBuildTabbedPanel.gridy = 0;
            constraintsLoadBuildTabbedPanel.gridwidth = 6;
            constraintsLoadBuildTabbedPanel.gridheight = 6;
            constraintsLoadBuildTabbedPanel.fill = java.awt.GridBagConstraints.BOTH;
            constraintsLoadBuildTabbedPanel.weightx = 1.0;
            constraintsLoadBuildTabbedPanel.weighty = 1.0;
            constraintsLoadBuildTabbedPanel.insets = new java.awt.Insets(1, 1, 1, 1);
            add(getLoadBuildTabbedPanel(), constraintsLoadBuildTabbedPanel);
            initConnections();
        } catch (java.lang.Throwable ivjExc) {
            handleException(ivjExc);
        }

        // user code begin {2}
        getUpButton().setEnabled(false);
        getLoadErrorTestResultButton().setEnabled(false);
        getDeleteButton().setEnabled(false);
        getInspectButton().setEnabled(false);
        getViewButton().setEnabled(false);
        // user code end
    }

    public void initilaizeTestSummaryCache(LoadBuildSummary loadBuild) {
        Vector rootSummaries = new Vector();

        for (Enumeration<TestResultsSummary> enumtr = loadBuild.getSummaries().elements(); enumtr.hasMoreElements();) {
            TestResultsSummary summary = enumtr.nextElement();
            if (summary.getParent() == null) {
                rootSummaries.addElement(summary);
            }
        }
        testSummaryCahce = rootSummaries;
    }

    public void initilaizeTestSummaryCache(TestResultsSummary theSummary) {
        if ((theSummary.getResults() != null) && (theSummary.getResults().size() > 0)) {
            tableSelection = RESULT;
            testResultsCahce = theSummary.getResults();
            return;
        }

        Vector children = new Vector();

        for (Enumeration<TestResultsSummary> enumtr = theSummary.getLoadBuildSummary().getSummaries().elements();
             enumtr.hasMoreElements();) {
            TestResultsSummary summary = enumtr.nextElement();
            if ((summary.getParent() != null) && summary.getParent().getName().equals(theSummary.getName())) {
                children.addElement(summary);
            }
        }
        testSummaryCahce = children;
    }

    public void inspect(Object object) {
        try {
            Class[] argTypes = new Class[1];
            argTypes[0] = Object.class;
            Object[] args = new Object[1];
            args[0] = object;
            (Class.forName("com.ibm.uvm.tools.DebugSupport")).getMethod("inspect", argTypes).invoke(null, args);
        } catch (Exception ignore) {
        }
    }

    public void inspectDatabaseLogin() {
        int index = getSelectedTable().getSelectedRow();
        if (index < 0) {
            return;
        }
        LoadBuildSummary loadBuild = (LoadBuildSummary)loadBuildsCache.elementAt(index);

        // inspect object if databaseLogin already exists
        if ((session == null) || (loadBuild.databaseLogin != null)) {
            inspect(loadBuild.databaseLogin);
            return;
        }

        // read in a full object
        loadBuild = (LoadBuildSummary)session.readObject(loadBuild);
        if ((loadBuildsCache != null) && (index <= loadBuildsCache.size())) {
            loadBuildsCache.removeElementAt(index);
            loadBuildsCache.insertElementAt(loadBuild, index);
        }
        inspect(loadBuild.databaseLogin);
    }

    public void loadErrorTestResults() {
        buildErrorTestResultForSummary();
        poppulateTestResultTable(testResultsCahce);
    }

    /**
     * Invoked when the mouse has been clicked on a component.
     */
    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() > 1) {
            down();
        }
    }

    /**
     * Invoked when the mouse enters a component.
     */
    @Override
    public void mouseEntered(MouseEvent e) {
    }

    /**
     * Invoked when the mouse exits a component.
     */
    @Override
    public void mouseExited(MouseEvent e) {
    }

    /**
     * Invoked when a mouse button has been pressed on a component.
     */
    @Override
    public void mousePressed(MouseEvent e) {
    }

    /**
     * Invoked when a mouse button has been released on a component.
     */
    @Override
    public void mouseReleased(MouseEvent e) {
    }

    public void poppulateLoadBuildTable(Vector summaries) {
        loadBuildsCache = summaries;
        tableSelection = LOADBUILD;
        NonEditableDefaultTableModel tableModel = new NonEditableDefaultTableModel(new String[] { "Name", "Time", "Database", "OS", "JVM", "Machine", "TopLink Version", "Tests", "Setup Failures", "Errors", "Fatal Errors", "Problems", "Total Time" }, 0);
        for (Enumeration enumtr = summaries.elements(); enumtr.hasMoreElements();) {
            TestResultsSummary summary = (TestResultsSummary)enumtr.nextElement();

            Vector row = new Vector();
            row.addElement(summary.getName());
            row.addElement(summary.getLoadBuildSummary().timestamp);
            row.addElement(summary.getLoadBuildSummary().loginChoice);
            row.addElement(summary.getLoadBuildSummary().os);
            row.addElement(summary.getLoadBuildSummary().jvm);
            row.addElement(summary.getLoadBuildSummary().machine);
            row.addElement(summary.getLoadBuildSummary().toplinkVersion);
            row.addElement(summary.getTotalTests());
            row.addElement(summary.getSetupFailures());
            row.addElement(summary.getErrors());
            row.addElement(summary.getFatalErrors());
            row.addElement(summary.getProblems());
            row.addElement(summary.getTotalTime());
            tableModel.addRow(row);
        }
        getSelectedTable().setModel(tableModel);
        selectFirstRow();
        resetButtons();
        getSelectedTable().repaint();
    }

    public void poppulateTestResultTable(Vector results) {
        Collections.sort(results);
        testResultsCahce = results;
        tableSelection = RESULT;

        resetButtons();

        NonEditableDefaultTableModel tableModel = new NonEditableDefaultTableModel(new String[] { "Name", "Outcome", "Test Time", "Total Time", "Has Exception", "Time", "Database", "OS", "JVM", "Machine", "TopLink Version" }, 0);
        for (Enumeration enumtr = results.elements(); enumtr.hasMoreElements();) {
            TestResult result = (TestResult)enumtr.nextElement();
            Vector row = new Vector();
            row.addElement(result.getName());
            row.addElement(result.getOutcome());
            row.addElement(result.getTestTime());
            row.addElement(result.getTotalTime());
            row.addElement(result.getException() != null);
            row.addElement(result.getLoadBuildSummary().timestamp);
            row.addElement(result.getLoadBuildSummary().loginChoice);
            row.addElement(result.getLoadBuildSummary().os);
            row.addElement(result.getLoadBuildSummary().jvm);
            row.addElement(result.getLoadBuildSummary().machine);
            row.addElement(result.getLoadBuildSummary().toplinkVersion);
            tableModel.addRow(row);
        }
        getSelectedTable().setModel(tableModel);
        selectFirstRow();
        resetButtons();
        getSelectedTable().repaint();
    }

    public void poppulateTestSummaryTable(Vector summaries) {
        Collections.sort(summaries);
        testSummaryCahce = summaries;
        tableSelection = SUMMARY;

        resetButtons();

        NonEditableDefaultTableModel tableModel = new NonEditableDefaultTableModel(new String[] { "Name", "Total Tests", "Setup Failures", "Passed", "Errors", "Fatal Errors", "Problems", "Warnings", "Total Time" }, 0);
        for (Enumeration enumtr = summaries.elements(); enumtr.hasMoreElements();) {
            TestResultsSummary summary = (TestResultsSummary)enumtr.nextElement();
            Vector row = new Vector();
            row.addElement(summary.getName());
            row.addElement(summary.getTotalTests());
            row.addElement(summary.getSetupFailures());
            row.addElement(summary.getPassed());
            row.addElement(summary.getErrors());
            row.addElement(summary.getFatalErrors());
            row.addElement(summary.getProblems());
            row.addElement(summary.getWarnings());
            row.addElement(summary.getTotalTime());
            tableModel.addRow(row);
        }
        getSelectedTable().setModel(tableModel);
        selectFirstRow();
        resetButtons();
        getSelectedTable().repaint();
    }

    public void resetButtons() {
        if (getSelectedTable().getRowCount() <= 0) {
            getUpButton().setEnabled(false);
            getLoadErrorTestResultButton().setEnabled(false);
            getDeleteButton().setEnabled(false);
            getInspectButton().setEnabled(false);
            getViewButton().setEnabled(false);
            return;
        }
        if (tableSelection == LOADBUILD) {
            getUpButton().setEnabled(false);
            getLoadErrorTestResultButton().setEnabled(true);
            getDeleteButton().setEnabled(true);
            getInspectButton().setEnabled(true);
            getViewButton().setEnabled(false);
            return;
        }
        if (tableSelection == SUMMARY) {
            getUpButton().setEnabled(true);
            getLoadErrorTestResultButton().setEnabled(true);
            getDeleteButton().setEnabled(false);
            getInspectButton().setEnabled(false);
            getViewButton().setEnabled(false);
            return;
        }
        if (tableSelection == RESULT) {
            getUpButton().setEnabled(true);
            getLoadErrorTestResultButton().setEnabled(false);
            getDeleteButton().setEnabled(false);
            getInspectButton().setEnabled(false);
            getViewButton().setEnabled(true);
        }
    }

    public void selectFirstRow() {
        if (getSelectedTable().getRowCount() > 0) {
            getSelectedTable().setRowSelectionInterval(0, 0);
        }
    }

    /**
     *
     * @param session org.eclipse.persistence.sessions.DatabaseSession
     */
    public void setSession(DatabaseSession session) {
        this.session = session;
    }

    public void up() {
        int index = getSelectedTable().getSelectedRow();
        int upIndex;
        if (index < 0) {
            return;
        }
        if (tableSelection == SUMMARY) {
            TestResultsSummary summary = (TestResultsSummary)testSummaryCahce.elementAt(index);
            upIndex = getUpIndex(summary);
            if (summary.getParent() == null) {
                poppulateLoadBuildTable(loadBuildsCache);
            } else {
                poppulateTestSummaryTable(testSummaryCahce);
            }
            getSelectedTable().setRowSelectionInterval(upIndex, upIndex);
        } else if (tableSelection == RESULT) {
            TestResult result = (TestResult)testResultsCahce.elementAt(index);
            upIndex = getUpIndex(result);
            if (result.getSummary() != null) {
                poppulateTestSummaryTable(testSummaryCahce);
            } else {
                poppulateLoadBuildTable(loadBuildsCache);
            }

            getSelectedTable().setRowSelectionInterval(upIndex, upIndex);
        }
    }

    /**
     * Comment
     */
    public void viewStackTrace() {
        getViewTextArea().setText("");
        int index = getSelectedTable().getSelectedRow();
        if (index < 0) {
            return;
        }
        TestResult result = (TestResult)testResultsCahce.elementAt(index);
        getViewTextArea().setText(result.getExceptionStackTrace());
        getLoadBuildTabbedPanel().setSelectedComponent(getViewPage());
        getViewTextArea().setCaretPosition(1);
    }
}
