/*
 * 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 org.eclipse.persistence.Version;

public class TestingBrowserFrame extends javax.swing.JFrame implements java.awt.event.ActionListener {
    private javax.swing.JPanel ivjJFrameContentPane = null;
    private TestingBrowserPanel ivjTestingBrowserPanel1 = null;
    private javax.swing.JMenuItem ivjExitMenuItem = null;
    private javax.swing.JMenu ivjFile = null;
    private javax.swing.JMenuBar ivjTestingBrowserFrameJMenuBar = null;
    private javax.swing.JSeparator ivjJSeparator1 = null;
    private javax.swing.JSeparator ivjJSeparator11 = null;
    private javax.swing.JSeparator ivjJSeparator2 = null;
    private javax.swing.JMenuItem ivjKillMenuItem = null;
    private javax.swing.JMenu ivjLoadBuildMenu = null;
    private javax.swing.JMenuItem ivjLogResultsMenuItem = null;
    private javax.swing.JMenuItem ivjQueryResultsMenuItem = null;
    private javax.swing.JMenuItem ivjRebuildTestsMenuItem = null;
    private javax.swing.JMenuItem ivjResetMenuItem = null;
    private javax.swing.JMenuItem ivjResetModelsMenuItem = null;
    private javax.swing.JMenuItem ivjRunMenuItem = null;
    private javax.swing.JMenuItem ivjSaveResultsMenuItem = null;
    private javax.swing.JMenuItem ivjSetupMenuItem = null;
    private javax.swing.JMenuItem ivjStopMenuItem = null;
    private javax.swing.JMenu ivjTestMenu = null;

    /**
     * Constructor
     */

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

    /**
     * TestingBrowserFrame constructor comment.
     * @param title java.lang.String
     */
    public TestingBrowserFrame(String title) {
        super(title);
    }

    /**
     * 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}
        if (e.getSource() == getExitMenuItem()) {
            this.setVisible(false);
            this.dispose();
            System.exit(0);
        }

        // user code end
        if (e.getSource() == getRunMenuItem()) {
            connEtoC1(e);
        }
        if (e.getSource() == getSetupMenuItem()) {
            connEtoC2(e);
        }
        if (e.getSource() == getResetMenuItem()) {
            connEtoC3(e);
        }
        if (e.getSource() == getStopMenuItem()) {
            connEtoC4(e);
        }
        if (e.getSource() == getQueryResultsMenuItem()) {
            connEtoC5(e);
        }
        if (e.getSource() == getSaveResultsMenuItem()) {
            connEtoC6(e);
        }
        if (e.getSource() == getResetModelsMenuItem()) {
            connEtoC7(e);
        }
        if (e.getSource() == getRebuildTestsMenuItem()) {
            connEtoC8(e);
        }
        if (e.getSource() == getKillMenuItem()) {
            connEtoC9(e);
        }
        if (e.getSource() == getLogResultsMenuItem()) {
            connEtoC10(e);
        }

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

    /**
     * connEtoC1:  (RunMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1RunTest()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC10:  (LogResultsMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1LogTestResults()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC2:  (SetupMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1SetupTest()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC3:  (ResetMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1ResetTest()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC4:  (StopMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1StopTest()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.testingBrowserPanel1StopTest();

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

    /**
     * connEtoC5:  (QueryResultsMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1QueryLoadBuild()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC6:  (SaveResultsMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1SaveLoadBuild()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC7:  (ResetModelsMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1RefreshModels()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC8:  (RebuildTestsMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1RefreshTests()V)
     * @param arg1 java.awt.event.ActionEvent
     */

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

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

    /**
     * connEtoC9:  (KillMenuItem.action.actionPerformed(java.awt.event.ActionEvent) --{@literal >} TestingBrowserFrame.testingBrowserPanel1KillTest()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.testingBrowserPanel1KillTest();

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

    /**
     * Return the ExitMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getExitMenuItem() {
        if (ivjExitMenuItem == null) {
            try {
                ivjExitMenuItem = new javax.swing.JMenuItem();
                ivjExitMenuItem.setName("ExitMenuItem");
                ivjExitMenuItem.setText("Exit");
                ivjExitMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the File property value.
     * @return javax.swing.JMenu
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenu getFile() {
        if (ivjFile == null) {
            try {
                ivjFile = new javax.swing.JMenu();
                ivjFile.setName("File");
                ivjFile.setText("File");
                ivjFile.setBackground(java.awt.SystemColor.control);
                ivjFile.setActionCommand("FileMenu");
                ivjFile.add(getExitMenuItem());

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

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

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

                java.awt.GridBagConstraints constraintsTestingBrowserPanel1 = new java.awt.GridBagConstraints();
                constraintsTestingBrowserPanel1.gridx = 1;
                constraintsTestingBrowserPanel1.gridy = 1;
                constraintsTestingBrowserPanel1.fill = java.awt.GridBagConstraints.BOTH;
                constraintsTestingBrowserPanel1.weightx = 1.0;
                constraintsTestingBrowserPanel1.weighty = 1.0;
                constraintsTestingBrowserPanel1.insets = new java.awt.Insets(2, 2, 2, 2);
                getJFrameContentPane().add(getTestingBrowserPanel1(), constraintsTestingBrowserPanel1);

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

    /**
     * Return the JSeparator1 property value.
     * @return javax.swing.JSeparator
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JSeparator getJSeparator1() {
        if (ivjJSeparator1 == null) {
            try {
                ivjJSeparator1 = new javax.swing.JSeparator();
                ivjJSeparator1.setName("JSeparator1");

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

    /**
     * Return the JSeparator11 property value.
     * @return javax.swing.JSeparator
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JSeparator getJSeparator11() {
        if (ivjJSeparator11 == null) {
            try {
                ivjJSeparator11 = new javax.swing.JSeparator();
                ivjJSeparator11.setName("JSeparator11");

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

    /**
     * Return the JSeparator2 property value.
     * @return javax.swing.JSeparator
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JSeparator getJSeparator2() {
        if (ivjJSeparator2 == null) {
            try {
                ivjJSeparator2 = new javax.swing.JSeparator();
                ivjJSeparator2.setName("JSeparator2");

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

    /**
     * Return the KillMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getKillMenuItem() {
        if (ivjKillMenuItem == null) {
            try {
                ivjKillMenuItem = new javax.swing.JMenuItem();
                ivjKillMenuItem.setName("KillMenuItem");
                ivjKillMenuItem.setText("Kill");
                ivjKillMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the LoadBuildMenu property value.
     * @return javax.swing.JMenu
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenu getLoadBuildMenu() {
        if (ivjLoadBuildMenu == null) {
            try {
                ivjLoadBuildMenu = new javax.swing.JMenu();
                ivjLoadBuildMenu.setName("LoadBuildMenu");
                ivjLoadBuildMenu.setText("Test Results");
                ivjLoadBuildMenu.setBackground(java.awt.SystemColor.control);
                ivjLoadBuildMenu.setActionCommand("FileMenu");
                ivjLoadBuildMenu.add(getRebuildTestsMenuItem());
                ivjLoadBuildMenu.add(getResetModelsMenuItem());
                ivjLoadBuildMenu.add(getJSeparator11());
                ivjLoadBuildMenu.add(getLogResultsMenuItem());
                ivjLoadBuildMenu.add(getJSeparator2());
                ivjLoadBuildMenu.add(getSaveResultsMenuItem());
                ivjLoadBuildMenu.add(getQueryResultsMenuItem());

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

    /**
     * Return the LogResultsMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getLogResultsMenuItem() {
        if (ivjLogResultsMenuItem == null) {
            try {
                ivjLogResultsMenuItem = new javax.swing.JMenuItem();
                ivjLogResultsMenuItem.setName("LogResultsMenuItem");
                ivjLogResultsMenuItem.setText("Log Results");
                ivjLogResultsMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the QueryResultsMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getQueryResultsMenuItem() {
        if (ivjQueryResultsMenuItem == null) {
            try {
                ivjQueryResultsMenuItem = new javax.swing.JMenuItem();
                ivjQueryResultsMenuItem.setName("QueryResultsMenuItem");
                ivjQueryResultsMenuItem.setText("Query Test Results");
                ivjQueryResultsMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the RebuildTestsMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getRebuildTestsMenuItem() {
        if (ivjRebuildTestsMenuItem == null) {
            try {
                ivjRebuildTestsMenuItem = new javax.swing.JMenuItem();
                ivjRebuildTestsMenuItem.setName("RebuildTestsMenuItem");
                ivjRebuildTestsMenuItem.setText("Rebuild Tests");
                ivjRebuildTestsMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the ResetMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getResetMenuItem() {
        if (ivjResetMenuItem == null) {
            try {
                ivjResetMenuItem = new javax.swing.JMenuItem();
                ivjResetMenuItem.setName("ResetMenuItem");
                ivjResetMenuItem.setText("Reset");
                ivjResetMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the ResetModelsMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getResetModelsMenuItem() {
        if (ivjResetModelsMenuItem == null) {
            try {
                ivjResetModelsMenuItem = new javax.swing.JMenuItem();
                ivjResetModelsMenuItem.setName("ResetModelsMenuItem");
                ivjResetModelsMenuItem.setText("Reset Models");
                ivjResetModelsMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the RunMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getRunMenuItem() {
        if (ivjRunMenuItem == null) {
            try {
                ivjRunMenuItem = new javax.swing.JMenuItem();
                ivjRunMenuItem.setName("RunMenuItem");
                ivjRunMenuItem.setText("Run");
                ivjRunMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the SaveResultsMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getSaveResultsMenuItem() {
        if (ivjSaveResultsMenuItem == null) {
            try {
                ivjSaveResultsMenuItem = new javax.swing.JMenuItem();
                ivjSaveResultsMenuItem.setName("SaveResultsMenuItem");
                ivjSaveResultsMenuItem.setText("Save Results");
                ivjSaveResultsMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the SetupMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getSetupMenuItem() {
        if (ivjSetupMenuItem == null) {
            try {
                ivjSetupMenuItem = new javax.swing.JMenuItem();
                ivjSetupMenuItem.setName("SetupMenuItem");
                ivjSetupMenuItem.setText("Setup");
                ivjSetupMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the StopMenuItem property value.
     * @return javax.swing.JMenuItem
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuItem getStopMenuItem() {
        if (ivjStopMenuItem == null) {
            try {
                ivjStopMenuItem = new javax.swing.JMenuItem();
                ivjStopMenuItem.setName("StopMenuItem");
                ivjStopMenuItem.setText("Stop");
                ivjStopMenuItem.setBackground(java.awt.SystemColor.control);

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

    /**
     * Return the TestingBrowserFrameJMenuBar property value.
     * @return javax.swing.JMenuBar
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenuBar getTestingBrowserFrameJMenuBar() {
        if (ivjTestingBrowserFrameJMenuBar == null) {
            try {
                ivjTestingBrowserFrameJMenuBar = new javax.swing.JMenuBar();
                ivjTestingBrowserFrameJMenuBar.setName("TestingBrowserFrameJMenuBar");
                ivjTestingBrowserFrameJMenuBar.setBackground(java.awt.SystemColor.control);
                ivjTestingBrowserFrameJMenuBar.add(getFile());
                ivjTestingBrowserFrameJMenuBar.add(getTestMenu());
                ivjTestingBrowserFrameJMenuBar.add(getLoadBuildMenu());

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

    /**
     * Return the TestingBrowserPanel1 property value.
     * @return org.eclipse.persistence.testing.framework.ui.TestingBrowserPanel
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private TestingBrowserPanel getTestingBrowserPanel1() {
        if (ivjTestingBrowserPanel1 == null) {
            try {
                ivjTestingBrowserPanel1 = new org.eclipse.persistence.testing.framework.ui.TestingBrowserPanel();
                ivjTestingBrowserPanel1.setName("TestingBrowserPanel1");

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

    /**
     * Return the TestMenu property value.
     * @return javax.swing.JMenu
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private javax.swing.JMenu getTestMenu() {
        if (ivjTestMenu == null) {
            try {
                ivjTestMenu = new javax.swing.JMenu();
                ivjTestMenu.setName("TestMenu");
                ivjTestMenu.setText("Test");
                ivjTestMenu.setBackground(java.awt.SystemColor.control);
                ivjTestMenu.setActionCommand("FileMenu");
                ivjTestMenu.add(getRunMenuItem());
                ivjTestMenu.add(getSetupMenuItem());
                ivjTestMenu.add(getResetMenuItem());
                ivjTestMenu.add(getJSeparator1());
                ivjTestMenu.add(getKillMenuItem());
                ivjTestMenu.add(getStopMenuItem());

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

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

        /* Uncomment the following lines to print uncaught exceptions to stdout */
        System.out.println("--------- UNCAUGHT EXCEPTION ---------");
        exception.printStackTrace(System.out);
    }

    /**
     * Initializes connections
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void initConnections() throws java.lang.Exception {
        // user code begin {1}
        getExitMenuItem().addActionListener(this);
        // user code end
        getRunMenuItem().addActionListener(this);
        getSetupMenuItem().addActionListener(this);
        getResetMenuItem().addActionListener(this);
        getStopMenuItem().addActionListener(this);
        getQueryResultsMenuItem().addActionListener(this);
        getSaveResultsMenuItem().addActionListener(this);
        getResetModelsMenuItem().addActionListener(this);
        getRebuildTestsMenuItem().addActionListener(this);
        getKillMenuItem().addActionListener(this);
        getLogResultsMenuItem().addActionListener(this);
    }

    /**
     * Initialize the class.
     */

    /* WARNING: THIS METHOD WILL BE REGENERATED. */
    private void initialize() {
        try {
            // user code begin {1}
            // user code end
            setName("TestingBrowserFrame");
            setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
            setJMenuBar(getTestingBrowserFrameJMenuBar());
            setSize(901, 574);
            setTitle("Testing Browser" + ":  EclipseLink " + Version.getVersionString());
            setContentPane(getJFrameContentPane());
            initConnections();
        } catch (java.lang.Throwable ivjExc) {
            handleException(ivjExc);
        }

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

    /**
     * build a window event handler (anonymous class)
     * this handler closes the window *and* shuts down the system
     */
    protected static java.awt.event.WindowListener getWindowShutdown() {
        return new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent e) {
                    java.awt.Window window = e.getWindow();
                    window.setVisible(false);
                    window.dispose();
                    System.exit(0);
                }
            };
    }

    /**
     * main entrypoint - starts the part when it is run as an application
     * @param args java.lang.String[]
     */
    public static void main(java.lang.String[] args) {
    try {
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
            TestingBrowserFrame aTestingBrowserFrame;
            aTestingBrowserFrame = new TestingBrowserFrame();
            aTestingBrowserFrame.addWindowListener(getWindowShutdown());
            aTestingBrowserFrame.setVisible(true);
        } catch (Throwable exception) {
            System.err.println("Exception occurred in main() of javax.swing.JFrame");
            exception.printStackTrace(System.out);
        }
    }

    public void testingBrowserPanel1KillTest() {
        getTestingBrowserPanel1().killTest();
    }

    public void testingBrowserPanel1LogTestResults() {
        getTestingBrowserPanel1().logTestResults();
    }

    public void testingBrowserPanel1QueryLoadBuild() {
        getTestingBrowserPanel1().queryLoadBuild();
    }

    public void testingBrowserPanel1RefreshModels() {
        getTestingBrowserPanel1().refreshModels();
    }

    public void testingBrowserPanel1RefreshTests() {
        getTestingBrowserPanel1().refreshTests();
    }

    public void testingBrowserPanel1ResetTest() {
        getTestingBrowserPanel1().resetTest();
    }

    public void testingBrowserPanel1RunTest() {
        getTestingBrowserPanel1().runTest();
    }

    public void testingBrowserPanel1SaveLoadBuild() {
        getTestingBrowserPanel1().saveLoadBuild();
    }

    public void testingBrowserPanel1SetupTest() {
        getTestingBrowserPanel1().setupTest();
    }

    public void testingBrowserPanel1StopTest() {
        getTestingBrowserPanel1().stopTest();
    }
}
