<commit_before>package org.ensembl.healthcheck.eg_gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.ensembl.healthcheck.ConfigurableTestRunner;
import org.ensembl.healthcheck.DatabaseRegistry;
import org.ensembl.healthcheck.DatabaseRegistryEntry;
import org.ensembl.healthcheck.DatabaseServer;
import org.ensembl.healthcheck.DatabaseType;
import org.ensembl.healthcheck.GroupOfTests;
import org.ensembl.healthcheck.ReportManager;
import org.ensembl.healthcheck.SystemPropertySetter;
import org.ensembl.healthcheck.configuration.ConfigurationUserParameters;
import org.ensembl.healthcheck.configuration.ConfigureHost;
import org.ensembl.healthcheck.configurationmanager.ConfigurationByProperties;
import org.ensembl.healthcheck.configurationmanager.ConfigurationFactory;
import org.ensembl.healthcheck.configurationmanager.ConfigurationFactory.ConfigurationType;
import org.ensembl.healthcheck.eg_gui.AdminTab;
import org.ensembl.healthcheck.eg_gui.Constants;
import org.ensembl.healthcheck.eg_gui.DatabaseTabbedPane;
import org.ensembl.healthcheck.eg_gui.GuiReporterTab;
import org.ensembl.healthcheck.eg_gui.TestInstantiatorDynamic;
import org.ensembl.healthcheck.eg_gui.TestProgressDialog;
import org.ensembl.healthcheck.testcase.EnsTestCase;
import org.ensembl.healthcheck.testcase.PerlScriptConfig;
import org.ensembl.healthcheck.util.DBUtils;
import org.ensembl.healthcheck.eg_gui.CopyAndPastePopupBuilder;

/**
 * <p>
 * 	The main window of the healthcheck GUI.
 * </p>
 * 
 * @author michael
 *
 */
public class GuiTestRunnerFrame extends JFrame implements ActionListener {

	/** The logger to use for this class */
	protected static Logger logger = Logger.getLogger("HealthCheckLogger");
	
	/**
	 * Preferred size of the window.
	 *  
	 */
	protected int windowWidth  = Constants.INITIAL_APPLICATION_WINDOW_WIDTH;
	protected int windowHeight = Constants.INITIAL_APPLICATION_WINDOW_HEIGHT;
	
	/**
	 * Name of the server that will be set as default, if there is a 
	 * configuration for this.
	 */
	String defaultSecondaryServerName = "mysql.ebi.ac.uk";
	
	/**
	 * Title of the Window
	 * 
	 */
	String windowTitle = "Healthchecks";

	/**
	 * Directories in which configuration files for database servers will be 
	 * searched for.
	 * 
	 */
	final String[] dirsWithDbServerConfigs = new String[] {

		// ~ does not work in java to reference the home directory:
		//
		// "~/.ensj",
		//
		System.getProperty("user.home") + "/.ensj"
	};

	//protected DatabaseTabbedPane databaseTabbedPane;
	protected DatabaseTabbedPaneWithSearchBox databaseTabbedPaneWithSearchBox;
	protected JTextField         MysqlConnectionCmd;
	protected final JList        listOfTestsToBeRun;
	protected final JButton      rmSelectedTests;
	protected final JButton      runAllTests;
	protected final JButton      runSelectedTests;
	protected final JTree        tree;
	protected final JComboBox    dbServerSelector;
	protected final JComboBox    secondaryDbServerSelector;
	
	protected List<ConfigureHost> dbDetails;

	protected TestProgressDialog testProgressDialog;
	
	// The tabs on the main window.
	//
	final protected JTabbedPane tab;
	final protected JPanel      tabSetup;
	      protected int         tabSetupTabIndex;
	      protected String      tabSetupName = "Setup";
	      protected JPanel      tabResults;
	      protected int         tabResultsTabIndex;
	      protected String      tabResultsName = "Results";
	      protected JPanel      tabResultsLegacy;
	      protected int         tabResultsLegacyTabIndex;
	      protected AdminTab    tabAdmin;
	      protected int         tabAdminTabIndex;

	      // Holds a reference to the gui reporter. It is a component of the
	      // JPanel tabResults.
	      //
	      protected GuiReporterTab currentGuiReporter;
	      
	      protected Thread currentGuiTestRunnerThread;
	      
	      protected GuiLogHandler guiLogHandler;
	


	protected void processWindowEvent(WindowEvent e) {
		
		if (e.getID() == WindowEvent.WINDOW_CLOSING) {

			// If a healthcheck session is currently running, terminate this.
			// Perl based healthchecks don't automatically terminate when the
			// window closes, so this is done here explicitly.
			//
			if (currentGuiTestRunnerThread != null) {		
	    		currentGuiTestRunnerThread.interrupt();
	       	}
			
		}
		super.processWindowEvent(e);
	}

	/**
	 * <p>
	 * 	Sets the primary and secondary host details in DBUtils.
	 * </p>
	 * 
	 * @param primaryHostDetails
	 * @param secondaryHostDetails
	 */
	protected void setPrimaryAndSecondaryAndSystemPropertiesHost(
			ConfigureHost primaryHostDetails,
			ConfigureHost secondaryHostDetails
		) {
		
		ConfigurationUserParameters combinedHostConfig = createConfigurationObject(primaryHostDetails, secondaryHostDetails);
		
		// And finally set the new configuration file in which the 
		// secondary host has been configured.
		//
		DBUtils.setHostConfiguration((ConfigureHost) combinedHostConfig);
		
		SystemPropertySetter systemPropertySetter = new SystemPropertySetter(combinedHostConfig);
		systemPropertySetter.setPropertiesForHealthchecks();
	}
	
	protected ConfigurationUserParameters createConfigurationObject(
			ConfigureHost primaryHostDetails,
			ConfigureHost secondaryHostDetails
		) {
		
		Properties secondaryHostProperties = new Properties();
		
		if (secondaryHostDetails!=null) {
			secondaryHostProperties.setProperty("secondary.host",     secondaryHostDetails.getHost());
			secondaryHostProperties.setProperty("secondary.port",     secondaryHostDetails.getPort());
			secondaryHostProperties.setProperty("secondary.user",     secondaryHostDetails.getUser());
			secondaryHostProperties.setProperty("secondary.password", <PASSWORD>());
			secondaryHostProperties.setProperty("secondary.driver",   secondaryHostDetails.getDriver());
		}
		
		ConfigureHost secondaryHostConfiguration = 
			(ConfigureHost) ConfigurationByProperties.newInstance(
				ConfigureHost.class, 
				secondaryHostProperties
			);
		
		List<File> propertyFileNames = new ArrayList<File>();
		propertyFileNames.add(new File(ConfigurableTestRunner.getDefaultPropertiesFile()));

		ConfigurationUserParameters ConfigurationByPropertyFiles =
			new ConfigurationFactory<ConfigurationUserParameters>(
				ConfigurationUserParameters.class,
				propertyFileNames
			).getConfiguration(ConfigurationType.Properties);

		
		ConfigurationFactory<ConfigurationUserParameters> confFact =
			new ConfigurationFactory<ConfigurationUserParameters>(
				ConfigurationUserParameters.class,
				primaryHostDetails,
				secondaryHostConfiguration,
				ConfigurationByPropertyFiles
			);
		
		ConfigurationUserParameters combinedHostConfig = confFact.getConfiguration(ConfigurationType.Cascading);
		
		return combinedHostConfig;
	}

	protected String createDbCmdLine() {
		
		int selectedIndex = dbServerSelector.getSelectedIndex();
		
		// if nothing has been selected
		//
		if (selectedIndex==-1) {
			return "No database has been selected.";
		}
		
		ConfigureHost selectedDbServerConf = dbDetails.get(selectedIndex);
		
		String passwordParam;
		
		if (selectedDbServerConf.getPassword().isEmpty()) {
			passwordParam = "";
		} else {
			passwordParam = " --password=" + selectedDbServerConf.getPassword();
		}
		
		return "mysql" 
			+ " --host "     + selectedDbServerConf.getHost() 
			+ " --port "     + selectedDbServerConf.getPort()
			+ " --user "     + selectedDbServerConf.getUser()
			+ passwordParam
		;
	}
	
	protected void updateDbCmdLine() {

		if (MysqlConnectionCmd ==null) { return; }
		MysqlConnectionCmd.setText(createDbCmdLine());
		MysqlConnectionCmd.selectAll();
	}
	
	protected void updateDbCmdLine(String dbName) {

		if (MysqlConnectionCmd ==null) { return; }
		String cmd = createDbCmdLine() + " " + dbName;
		MysqlConnectionCmd.setText(cmd);
		MysqlConnectionCmd.selectAll();
	}
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		
		String cmd = arg0.getActionCommand();

		if (cmd.equals(Constants.selectedDatabaseChanged)) {
			
			DatabaseRadioButton selectedDbRadioButton = (DatabaseRadioButton) arg0.getSource();
			String currentlySelectsDBName = selectedDbRadioButton.getText();
			updateDbCmdLine(currentlySelectsDBName);
		}
		
		// Not implemented yet
		if (cmd.equals(Constants.Add_to_tests_to_be_run)) {
			
		}
		
		if (cmd.equals(Constants.REMOVE_SELECTED_TESTS)) {

			GuiTestRunnerFrameActionPerformer.removeSelectedTests(listOfTestsToBeRun);
		}
		if (cmd.equals(Constants.DB_SERVER_CHANGED)) {

			GuiTestRunnerFrameActionPerformer.setupDatabasePane(
				databaseTabbedPaneWithSearchBox.getDtp(), 
				dbDetails.get(dbServerSelector.getSelectedIndex())
			);
			updateDbCmdLine();
		}
		if (cmd.equals(Constants.RUN_ALL_TESTS) || cmd.equals(Constants.RUN_SELECTED_TESTS)) {

			//
			// Check, if basic conditions have been met so that tests can be 
			// run.
			//
			if (
				(currentGuiTestRunnerThread != null) 
				&& (currentGuiTestRunnerThread.isAlive())
			) {
				
				JOptionPane.showMessageDialog(
						this, 
						"A session of healthchecks is currently running already. "
						+ "Please wait for it to terminate before starting another.", 
						"Error",
						JOptionPane.ERROR_MESSAGE
					);
					return;
			}
			
			if (
				cmd.equals(Constants.RUN_SELECTED_TESTS) 
				&& listOfTestsToBeRun.getSelectedValues().length==0
			) {
				JOptionPane.showMessageDialog(
					this, 
					"You have not selected any tests!", 
					"Error",
					JOptionPane.ERROR_MESSAGE
				);
				return;
			}
			if (
				cmd.equals(Constants.RUN_ALL_TESTS) 
				&& listOfTestsToBeRun.getModel().getSize()==0
			) {
				JOptionPane.showMessageDialog(
					this, 
					"No tests! Please drag tests from the tree in the left into the area above.", 
					"Error",
					JOptionPane.ERROR_MESSAGE
				);
				return;
			}
			
			DatabaseRegistryEntry[] selectedDatabases 
				= databaseTabbedPaneWithSearchBox.getDtp().getSelectedDatabases();

			if (selectedDatabases.length == 0) {
				JOptionPane.showMessageDialog(
					this, 
					"No databases selected!",
					"Error", 
					JOptionPane.ERROR_MESSAGE
				);
			} else {

				ReportManager.initialise();
				
				// If currentGuiReporter has been initialised once, it has 
				// also been added to the tabResults. It has to be removed
				// first, before a new one is created and put in its place.
				//
				if (currentGuiReporter!=null) {
					tabResults.remove(currentGuiReporter);
				}
				currentGuiReporter = new GuiReporterTab();
				
				guiLogHandler = new GuiLogHandler();
				guiLogHandler.setReporter(currentGuiReporter);
				
				// Set the formatter for EnsTestcases to what the user 
				// configured them to look like. 
				//

				// Check, if a formatter was configured. If so, then use
				// this formatter, otherwise create a new one.
				//
				Handler[] configuredHandler = Logger.getLogger(
						EnsTestCase.class.getCanonicalName()
				).getHandlers();
				
				Formatter configuredFormatter;
				
				if (configuredHandler.length == 0) {
					configuredFormatter = new SimpleFormatter();
				} else {
					configuredFormatter = configuredHandler[0].getFormatter();
				}
				
				// Set the formatter.
				guiLogHandler.setFormatter(configuredFormatter);

				testProgressDialog = new TestProgressDialog("", 0, 100);
				
				tabResults.setLayout(new BorderLayout());
				tabResults.add(testProgressDialog, BorderLayout.SOUTH);
				tabResults.add(currentGuiReporter, BorderLayout.CENTER);
				
				tab.setEnabledAt(tabResultsTabIndex,       true);
				tab.setEnabledAt(tabResultsLegacyTabIndex, true);
				tab.setSelectedIndex(tabResultsTabIndex);
				
				tabResultsLegacy.setLayout(new BorderLayout());
				
				ReportManager.setReporter(currentGuiReporter);
				
				PerlScriptConfig psc = new PerlScriptConfig(
						tabAdmin.getPerl5Binary(),
						tabAdmin.getPerlOptions()
				);
				
				setPrimaryAndSecondaryAndSystemPropertiesHost(
					dbDetails.get(dbServerSelector.getSelectedIndex()),
					dbDetails.get(secondaryDbServerSelector.getSelectedIndex())
				);
				
				if (cmd.equals(Constants.RUN_SELECTED_TESTS)) {
					
					currentGuiTestRunnerThread = GuiTestRunnerFrameActionPerformer.runSelectedTests(
						listOfTestsToBeRun, 
						selectedDatabases,
						testProgressDialog,
						tabResultsLegacy,
						tabAdmin.getPerl5Lib(),
						psc,
						guiLogHandler
					);
				}
				if (cmd.equals(Constants.RUN_ALL_TESTS)) {
					currentGuiTestRunnerThread = GuiTestRunnerFrameActionPerformer.runAllTests(
						listOfTestsToBeRun, 
						selectedDatabases,
						testProgressDialog,
						tabResultsLegacy,
						tabAdmin.getPerl5Lib(),
						psc,
						guiLogHandler
					);
				}
			}
		}
	}
	
	public GuiTestRunnerFrame(
		List<GroupOfTests> testGroupList,
		TestInstantiatorDynamic testInstantiator
	) {

		final ActionListener defaultAL = this;
		
		final JPopupMenu popupMenuList = GuiTestRunnerFrameComponentBuilder
				.createListOfTestsToBeExecutedPopupMenu(defaultAL);

		// Functionality of the popup menu is not implemented yet,
		// so no popup menu for the tree
		//
		//final JPopupMenu popupMenuTree = GuiComponentBuilder
		//		.createTreeOfTestGroupsPopupMenu(defaultAL);
		final JPopupMenu popupMenuTree = null;

		listOfTestsToBeRun = GuiTestRunnerFrameComponentBuilder.createListOfTestsToBeRunArea(
				testInstantiator, 
				popupMenuList,
				defaultAL
		);
		tree = GuiTestRunnerFrameComponentBuilder.createTreeOfTestGroups(
			testGroupList,
			popupMenuTree
		);

		rmSelectedTests  = GuiTestRunnerFrameComponentBuilder.createRemoveSelectedTestsButton(defaultAL);
		runAllTests      = GuiTestRunnerFrameComponentBuilder.createRunAllTestsButton(defaultAL);
		runSelectedTests = GuiTestRunnerFrameComponentBuilder.createRunSelectedTestsButton(defaultAL);

		tabSetup = new JPanel();
		
		dbDetails = GuiTestRunnerFrameUtils.createDbDetailsConfigurations(
				dirsWithDbServerConfigs
		);
		
		// Set to false, because checking availability costs too much startup
		// time when there are many servers configured and opens too many 
		// connections.
		//
		boolean checkAvailabilityOfServers = false;
		
		if (checkAvailabilityOfServers) {		
			dbDetails = GuiTestRunnerFrameUtils.grepForAvailableServers(dbDetails);
		}

		dbServerSelector = GuiTestRunnerFrameComponentBuilder.createDbServerSelector(dbDetails);
		dbServerSelector.setActionCommand(Constants.DB_SERVER_CHANGED);
		dbServerSelector.addActionListener(this);
		
		secondaryDbServerSelector = GuiTestRunnerFrameComponentBuilder.createDbServerSelector(dbDetails);
		secondaryDbServerSelector.setActionCommand(Constants.SECONDARY_DB_SERVER_CHANGED);
		secondaryDbServerSelector.addActionListener(this);

		DBUtils.initialise(false);
		
		// databaseTabbedPane must be set up before running
		//
		// dbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
		//
		// because the above statement will trigger an action that will
		// reconfigure what is in the databaseTabbedPane. If databaseTabbedPane
		// is null then, because it has not been initialised, it will result
		// in an error which is hard to find.
		//
		List<String> regexps = new ArrayList<String>();
		regexps.add(".*");

		DatabaseRegistry databaseRegistry = new DatabaseRegistry(regexps, null,
				null, false);
		if (databaseRegistry.getEntryCount() == 0) {
			logger.warning("Warning: no databases found!");
		}

		DatabaseTabbedPane databaseTabbedPane = new DatabaseTabbedPane(
				databaseRegistry, this
			);
		databaseTabbedPaneWithSearchBox = new DatabaseTabbedPaneWithSearchBox(databaseTabbedPane);
		
		//
		// See, if defaultSecondaryServerName can be found in dbDetails. If so,
		// select this as the default secondary server.
		//
		int numServers = dbDetails.size();		
		int defaultSelectedServerIndex = 0;
		
		for (int index=0; index<numServers; index++) {
		
			String serverName = dbDetails.get(index).getHost();
			if (serverName.contains(defaultSecondaryServerName)) {
				defaultSelectedServerIndex = index;
			}
		}
		
		ConfigureHost primaryHostDetails   = null;
		ConfigureHost secondaryHostDetails = null;
		
		if (dbServerSelector.getItemCount()>0) {
			dbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
			primaryHostDetails = dbDetails.get(defaultSelectedServerIndex);
			actionPerformed(new ActionEvent(this, 0, Constants.DB_SERVER_CHANGED));
		}

		if (secondaryDbServerSelector.getItemCount()>0) {
			secondaryDbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
			secondaryHostDetails = dbDetails.get(defaultSelectedServerIndex);
			actionPerformed(new ActionEvent(this, 1, Constants.DB_SERVER_CHANGED));
		}
		
		

		setPrimaryAndSecondaryAndSystemPropertiesHost(primaryHostDetails, secondaryHostDetails);

		this.setTitle(windowTitle);
		tab = new JTabbedPane();
		init();
	}<commit_msg>Removed unnecessary call, it is not necessary to update the database pane, if only the selected secondary server has changed.<commit_after>package org.ensembl.healthcheck.eg_gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.ensembl.healthcheck.ConfigurableTestRunner;
import org.ensembl.healthcheck.DatabaseRegistry;
import org.ensembl.healthcheck.DatabaseRegistryEntry;
import org.ensembl.healthcheck.DatabaseServer;
import org.ensembl.healthcheck.DatabaseType;
import org.ensembl.healthcheck.GroupOfTests;
import org.ensembl.healthcheck.ReportManager;
import org.ensembl.healthcheck.SystemPropertySetter;
import org.ensembl.healthcheck.configuration.ConfigurationUserParameters;
import org.ensembl.healthcheck.configuration.ConfigureHost;
import org.ensembl.healthcheck.configurationmanager.ConfigurationByProperties;
import org.ensembl.healthcheck.configurationmanager.ConfigurationFactory;
import org.ensembl.healthcheck.configurationmanager.ConfigurationFactory.ConfigurationType;
import org.ensembl.healthcheck.eg_gui.AdminTab;
import org.ensembl.healthcheck.eg_gui.Constants;
import org.ensembl.healthcheck.eg_gui.DatabaseTabbedPane;
import org.ensembl.healthcheck.eg_gui.GuiReporterTab;
import org.ensembl.healthcheck.eg_gui.TestInstantiatorDynamic;
import org.ensembl.healthcheck.eg_gui.TestProgressDialog;
import org.ensembl.healthcheck.testcase.EnsTestCase;
import org.ensembl.healthcheck.testcase.PerlScriptConfig;
import org.ensembl.healthcheck.util.DBUtils;
import org.ensembl.healthcheck.eg_gui.CopyAndPastePopupBuilder;

/**
 * <p>
 * 	The main window of the healthcheck GUI.
 * </p>
 * 
 * @author michael
 *
 */
public class GuiTestRunnerFrame extends JFrame implements ActionListener {

	/** The logger to use for this class */
	protected static Logger logger = Logger.getLogger("HealthCheckLogger");
	
	/**
	 * Preferred size of the window.
	 *  
	 */
	protected int windowWidth  = Constants.INITIAL_APPLICATION_WINDOW_WIDTH;
	protected int windowHeight = Constants.INITIAL_APPLICATION_WINDOW_HEIGHT;
	
	/**
	 * Name of the server that will be set as default, if there is a 
	 * configuration for this.
	 */
	String defaultSecondaryServerName = "mysql.ebi.ac.uk";
	
	/**
	 * Title of the Window
	 * 
	 */
	String windowTitle = "Healthchecks";

	/**
	 * Directories in which configuration files for database servers will be 
	 * searched for.
	 * 
	 */
	final String[] dirsWithDbServerConfigs = new String[] {

		// ~ does not work in java to reference the home directory:
		//
		// "~/.ensj",
		//
		System.getProperty("user.home") + "/.ensj"
	};

	//protected DatabaseTabbedPane databaseTabbedPane;
	protected DatabaseTabbedPaneWithSearchBox databaseTabbedPaneWithSearchBox;
	protected JTextField         MysqlConnectionCmd;
	protected final JList        listOfTestsToBeRun;
	protected final JButton      rmSelectedTests;
	protected final JButton      runAllTests;
	protected final JButton      runSelectedTests;
	protected final JTree        tree;
	protected final JComboBox    dbServerSelector;
	protected final JComboBox    secondaryDbServerSelector;
	
	protected List<ConfigureHost> dbDetails;

	protected TestProgressDialog testProgressDialog;
	
	// The tabs on the main window.
	//
	final protected JTabbedPane tab;
	final protected JPanel      tabSetup;
	      protected int         tabSetupTabIndex;
	      protected String      tabSetupName = "Setup";
	      protected JPanel      tabResults;
	      protected int         tabResultsTabIndex;
	      protected String      tabResultsName = "Results";
	      protected JPanel      tabResultsLegacy;
	      protected int         tabResultsLegacyTabIndex;
	      protected AdminTab    tabAdmin;
	      protected int         tabAdminTabIndex;

	      // Holds a reference to the gui reporter. It is a component of the
	      // JPanel tabResults.
	      //
	      protected GuiReporterTab currentGuiReporter;
	      
	      protected Thread currentGuiTestRunnerThread;
	      
	      protected GuiLogHandler guiLogHandler;
	


	protected void processWindowEvent(WindowEvent e) {
		
		if (e.getID() == WindowEvent.WINDOW_CLOSING) {

			// If a healthcheck session is currently running, terminate this.
			// Perl based healthchecks don't automatically terminate when the
			// window closes, so this is done here explicitly.
			//
			if (currentGuiTestRunnerThread != null) {		
	    		currentGuiTestRunnerThread.interrupt();
	       	}
			
		}
		super.processWindowEvent(e);
	}

	/**
	 * <p>
	 * 	Sets the primary and secondary host details in DBUtils.
	 * </p>
	 * 
	 * @param primaryHostDetails
	 * @param secondaryHostDetails
	 */
	protected void setPrimaryAndSecondaryAndSystemPropertiesHost(
			ConfigureHost primaryHostDetails,
			ConfigureHost secondaryHostDetails
		) {
		
		ConfigurationUserParameters combinedHostConfig = createConfigurationObject(primaryHostDetails, secondaryHostDetails);
		
		// And finally set the new configuration file in which the 
		// secondary host has been configured.
		//
		DBUtils.setHostConfiguration((ConfigureHost) combinedHostConfig);
		
		SystemPropertySetter systemPropertySetter = new SystemPropertySetter(combinedHostConfig);
		systemPropertySetter.setPropertiesForHealthchecks();
	}
	
	protected ConfigurationUserParameters createConfigurationObject(
			ConfigureHost primaryHostDetails,
			ConfigureHost secondaryHostDetails
		) {
		
		Properties secondaryHostProperties = new Properties();
		
		if (secondaryHostDetails!=null) {
			secondaryHostProperties.setProperty("secondary.host",     secondaryHostDetails.getHost());
			secondaryHostProperties.setProperty("secondary.port",     secondaryHostDetails.getPort());
			secondaryHostProperties.setProperty("secondary.user",     secondaryHostDetails.getUser());
			secondaryHostProperties.setProperty("secondary.password", <PASSWORD>());
			secondaryHostProperties.setProperty("secondary.driver",   secondaryHostDetails.getDriver());
		}
		
		ConfigureHost secondaryHostConfiguration = 
			(ConfigureHost) ConfigurationByProperties.newInstance(
				ConfigureHost.class, 
				secondaryHostProperties
			);
		
		List<File> propertyFileNames = new ArrayList<File>();
		propertyFileNames.add(new File(ConfigurableTestRunner.getDefaultPropertiesFile()));

		ConfigurationUserParameters ConfigurationByPropertyFiles =
			new ConfigurationFactory<ConfigurationUserParameters>(
				ConfigurationUserParameters.class,
				propertyFileNames
			).getConfiguration(ConfigurationType.Properties);

		
		ConfigurationFactory<ConfigurationUserParameters> confFact =
			new ConfigurationFactory<ConfigurationUserParameters>(
				ConfigurationUserParameters.class,
				primaryHostDetails,
				secondaryHostConfiguration,
				ConfigurationByPropertyFiles
			);
		
		ConfigurationUserParameters combinedHostConfig = confFact.getConfiguration(ConfigurationType.Cascading);
		
		return combinedHostConfig;
	}

	protected String createDbCmdLine() {
		
		int selectedIndex = dbServerSelector.getSelectedIndex();
		
		// if nothing has been selected
		//
		if (selectedIndex==-1) {
			return "No database has been selected.";
		}
		
		ConfigureHost selectedDbServerConf = dbDetails.get(selectedIndex);
		
		String passwordParam;
		
		if (selectedDbServerConf.getPassword().isEmpty()) {
			passwordParam = "";
		} else {
			passwordParam = " <PASSWORD>=" + selectedDbServerConf.getPassword();
		}
		
		return "mysql" 
			+ " --host "     + selectedDbServerConf.getHost() 
			+ " --port "     + selectedDbServerConf.getPort()
			+ " --user "     + selectedDbServerConf.getUser()
			+ passwordParam
		;
	}
	
	protected void updateDbCmdLine() {

		if (MysqlConnectionCmd ==null) { return; }
		MysqlConnectionCmd.setText(createDbCmdLine());
		MysqlConnectionCmd.selectAll();
	}
	
	protected void updateDbCmdLine(String dbName) {

		if (MysqlConnectionCmd ==null) { return; }
		String cmd = createDbCmdLine() + " " + dbName;
		MysqlConnectionCmd.setText(cmd);
		MysqlConnectionCmd.selectAll();
	}
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		
		String cmd = arg0.getActionCommand();

		if (cmd.equals(Constants.selectedDatabaseChanged)) {
			
			DatabaseRadioButton selectedDbRadioButton = (DatabaseRadioButton) arg0.getSource();
			String currentlySelectsDBName = selectedDbRadioButton.getText();
			updateDbCmdLine(currentlySelectsDBName);
		}
		
		// Not implemented yet
		if (cmd.equals(Constants.Add_to_tests_to_be_run)) {
			
		}
		
		if (cmd.equals(Constants.REMOVE_SELECTED_TESTS)) {

			GuiTestRunnerFrameActionPerformer.removeSelectedTests(listOfTestsToBeRun);
		}
		if (cmd.equals(Constants.DB_SERVER_CHANGED)) {

			GuiTestRunnerFrameActionPerformer.setupDatabasePane(
				databaseTabbedPaneWithSearchBox.getDtp(), 
				dbDetails.get(dbServerSelector.getSelectedIndex())
			);
			updateDbCmdLine();
		}
		if (cmd.equals(Constants.RUN_ALL_TESTS) || cmd.equals(Constants.RUN_SELECTED_TESTS)) {

			//
			// Check, if basic conditions have been met so that tests can be 
			// run.
			//
			if (
				(currentGuiTestRunnerThread != null) 
				&& (currentGuiTestRunnerThread.isAlive())
			) {
				
				JOptionPane.showMessageDialog(
						this, 
						"A session of healthchecks is currently running already. "
						+ "Please wait for it to terminate before starting another.", 
						"Error",
						JOptionPane.ERROR_MESSAGE
					);
					return;
			}
			
			if (
				cmd.equals(Constants.RUN_SELECTED_TESTS) 
				&& listOfTestsToBeRun.getSelectedValues().length==0
			) {
				JOptionPane.showMessageDialog(
					this, 
					"You have not selected any tests!", 
					"Error",
					JOptionPane.ERROR_MESSAGE
				);
				return;
			}
			if (
				cmd.equals(Constants.RUN_ALL_TESTS) 
				&& listOfTestsToBeRun.getModel().getSize()==0
			) {
				JOptionPane.showMessageDialog(
					this, 
					"No tests! Please drag tests from the tree in the left into the area above.", 
					"Error",
					JOptionPane.ERROR_MESSAGE
				);
				return;
			}
			
			DatabaseRegistryEntry[] selectedDatabases 
				= databaseTabbedPaneWithSearchBox.getDtp().getSelectedDatabases();

			if (selectedDatabases.length == 0) {
				JOptionPane.showMessageDialog(
					this, 
					"No databases selected!",
					"Error", 
					JOptionPane.ERROR_MESSAGE
				);
			} else {

				ReportManager.initialise();
				
				// If currentGuiReporter has been initialised once, it has 
				// also been added to the tabResults. It has to be removed
				// first, before a new one is created and put in its place.
				//
				if (currentGuiReporter!=null) {
					tabResults.remove(currentGuiReporter);
				}
				currentGuiReporter = new GuiReporterTab();
				
				guiLogHandler = new GuiLogHandler();
				guiLogHandler.setReporter(currentGuiReporter);
				
				// Set the formatter for EnsTestcases to what the user 
				// configured them to look like. 
				//

				// Check, if a formatter was configured. If so, then use
				// this formatter, otherwise create a new one.
				//
				Handler[] configuredHandler = Logger.getLogger(
						EnsTestCase.class.getCanonicalName()
				).getHandlers();
				
				Formatter configuredFormatter;
				
				if (configuredHandler.length == 0) {
					configuredFormatter = new SimpleFormatter();
				} else {
					configuredFormatter = configuredHandler[0].getFormatter();
				}
				
				// Set the formatter.
				guiLogHandler.setFormatter(configuredFormatter);

				testProgressDialog = new TestProgressDialog("", 0, 100);
				
				tabResults.setLayout(new BorderLayout());
				tabResults.add(testProgressDialog, BorderLayout.SOUTH);
				tabResults.add(currentGuiReporter, BorderLayout.CENTER);
				
				tab.setEnabledAt(tabResultsTabIndex,       true);
				tab.setEnabledAt(tabResultsLegacyTabIndex, true);
				tab.setSelectedIndex(tabResultsTabIndex);
				
				tabResultsLegacy.setLayout(new BorderLayout());
				
				ReportManager.setReporter(currentGuiReporter);
				
				PerlScriptConfig psc = new PerlScriptConfig(
						tabAdmin.getPerl5Binary(),
						tabAdmin.getPerlOptions()
				);
				
				setPrimaryAndSecondaryAndSystemPropertiesHost(
					dbDetails.get(dbServerSelector.getSelectedIndex()),
					dbDetails.get(secondaryDbServerSelector.getSelectedIndex())
				);
				
				if (cmd.equals(Constants.RUN_SELECTED_TESTS)) {
					
					currentGuiTestRunnerThread = GuiTestRunnerFrameActionPerformer.runSelectedTests(
						listOfTestsToBeRun, 
						selectedDatabases,
						testProgressDialog,
						tabResultsLegacy,
						tabAdmin.getPerl5Lib(),
						psc,
						guiLogHandler
					);
				}
				if (cmd.equals(Constants.RUN_ALL_TESTS)) {
					currentGuiTestRunnerThread = GuiTestRunnerFrameActionPerformer.runAllTests(
						listOfTestsToBeRun, 
						selectedDatabases,
						testProgressDialog,
						tabResultsLegacy,
						tabAdmin.getPerl5Lib(),
						psc,
						guiLogHandler
					);
				}
			}
		}
	}
	
	public GuiTestRunnerFrame(
		List<GroupOfTests> testGroupList,
		TestInstantiatorDynamic testInstantiator
	) {

		final ActionListener defaultAL = this;
		
		final JPopupMenu popupMenuList = GuiTestRunnerFrameComponentBuilder
				.createListOfTestsToBeExecutedPopupMenu(defaultAL);

		// Functionality of the popup menu is not implemented yet,
		// so no popup menu for the tree
		//
		//final JPopupMenu popupMenuTree = GuiComponentBuilder
		//		.createTreeOfTestGroupsPopupMenu(defaultAL);
		final JPopupMenu popupMenuTree = null;

		listOfTestsToBeRun = GuiTestRunnerFrameComponentBuilder.createListOfTestsToBeRunArea(
				testInstantiator, 
				popupMenuList,
				defaultAL
		);
		tree = GuiTestRunnerFrameComponentBuilder.createTreeOfTestGroups(
			testGroupList,
			popupMenuTree
		);

		rmSelectedTests  = GuiTestRunnerFrameComponentBuilder.createRemoveSelectedTestsButton(defaultAL);
		runAllTests      = GuiTestRunnerFrameComponentBuilder.createRunAllTestsButton(defaultAL);
		runSelectedTests = GuiTestRunnerFrameComponentBuilder.createRunSelectedTestsButton(defaultAL);

		tabSetup = new JPanel();
		
		dbDetails = GuiTestRunnerFrameUtils.createDbDetailsConfigurations(
				dirsWithDbServerConfigs
		);
		
		// Set to false, because checking availability costs too much startup
		// time when there are many servers configured and opens too many 
		// connections.
		//
		boolean checkAvailabilityOfServers = false;
		
		if (checkAvailabilityOfServers) {		
			dbDetails = GuiTestRunnerFrameUtils.grepForAvailableServers(dbDetails);
		}

		dbServerSelector = GuiTestRunnerFrameComponentBuilder.createDbServerSelector(dbDetails);
		dbServerSelector.setActionCommand(Constants.DB_SERVER_CHANGED);
		dbServerSelector.addActionListener(this);
		
		secondaryDbServerSelector = GuiTestRunnerFrameComponentBuilder.createDbServerSelector(dbDetails);
		secondaryDbServerSelector.setActionCommand(Constants.SECONDARY_DB_SERVER_CHANGED);
		secondaryDbServerSelector.addActionListener(this);

		DBUtils.initialise(false);
		
		// databaseTabbedPane must be set up before running
		//
		// dbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
		//
		// because the above statement will trigger an action that will
		// reconfigure what is in the databaseTabbedPane. If databaseTabbedPane
		// is null then, because it has not been initialised, it will result
		// in an error which is hard to find.
		//
		List<String> regexps = new ArrayList<String>();
		regexps.add(".*");

		DatabaseRegistry databaseRegistry = new DatabaseRegistry(regexps, null,
				null, false);
		if (databaseRegistry.getEntryCount() == 0) {
			logger.warning("Warning: no databases found!");
		}

		DatabaseTabbedPane databaseTabbedPane = new DatabaseTabbedPane(
				databaseRegistry, this
			);
		databaseTabbedPaneWithSearchBox = new DatabaseTabbedPaneWithSearchBox(databaseTabbedPane);
		
		//
		// See, if defaultSecondaryServerName can be found in dbDetails. If so,
		// select this as the default secondary server.
		//
		int numServers = dbDetails.size();		
		int defaultSelectedServerIndex = 0;
		
		for (int index=0; index<numServers; index++) {
		
			String serverName = dbDetails.get(index).getHost();
			if (serverName.contains(defaultSecondaryServerName)) {
				defaultSelectedServerIndex = index;
			}
		}
		
		ConfigureHost primaryHostDetails   = null;
		ConfigureHost secondaryHostDetails = null;
		
		if (dbServerSelector.getItemCount()>0) {
			dbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
			primaryHostDetails = dbDetails.get(defaultSelectedServerIndex);
			actionPerformed(new ActionEvent(this, 0, Constants.DB_SERVER_CHANGED));
		}

		if (secondaryDbServerSelector.getItemCount()>0) {
			secondaryDbServerSelector.setSelectedIndex(defaultSelectedServerIndex);
			secondaryHostDetails = dbDetails.get(defaultSelectedServerIndex);
		}
		
		

		setPrimaryAndSecondaryAndSystemPropertiesHost(primaryHostDetails, secondaryHostDetails);

		this.setTitle(windowTitle);
		tab = new JTabbedPane();
		init();
	}
{'fraction_non_alphanumeric': 0.08503391942406202, 'fraction_numerical': 0.001246019659421293, 'mean_word_length': 4.117755420150205, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6538660', 'n_tokens_mistral': 12044, 'n_tokens_neox': 10060, 'n_words': 2119}