/*
Copyright (C) 2006 EBI
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the itmplied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.biomart.builder.view.gui.panels;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import org.biomart.builder.model.Mart;
import org.biomart.builder.model.Schema;
import org.biomart.builder.model.Schema.JDBCSchema;
import org.biomart.builder.view.gui.panels.TwoColumnTablePanel.StringStringTablePanel;
import org.biomart.common.resources.Resources;
import org.biomart.common.view.gui.dialogs.StackTrace;
/**
* Connection panels represent all the different options available when
* establishing a schema. They don't do the common stuff - name, type, etc. -
* but do the stuff specific to a particular type of schema. They handle
* validation of input, and can modify or create schemas based on the input.
*
* @author Richard Holland <holland@ebi.ac.uk>
* @version $Revision: 1.7 $, $Date: 2007-11-06 16:29:38 $, modified by $Author:
* rh4 $
* @since 0.5
*/
public abstract class SchemaConnectionPanel extends JPanel {
/**
* Creates a new schema based on the values in the panel's fields.
*
* @param schemaName
* the name of the schema to be created.
* @return the created schema. It will return <tt>null</tt> if creation
* failed, eg. the currently field values are not valid.
*/
public abstract Schema createSchemaFromSettings(String schemaName);
/**
* Modifies a schema based on the values in the panel's fields.
*
* @param schema
* the schema to modify.
* @return the modified schema. It will return <tt>null</tt> if
* modification failed, eg. the currently field values are not
* valid.
*/
public abstract Schema copySettingsToExistingSchema(Schema schema);
/**
* Resets the fields based on a given template. Specify <tt>null</tt> for
* the template if you want complete defaults.
*
* @param template
* the template to reset the fields for.
*/
public abstract void copySettingsFromSchema(Schema template);
/**
* Validates the current values of the fields in the panel.
*
* @param report
* <tt>true</tt> if the user needs to know about the failures.
* @return <tt>true</tt> if all is well, <tt>false</tt> if not, and may
* possible pop up some messages for the user to read en route.
*/
public abstract boolean validateFields(final boolean report);
/**
* Using a properties object from history that matches this class, copy
* settings and populate the dialog from it.
*
* @param template
* the properties to copy into the dialog.
*/
public abstract void copySettingsFromProperties(final Properties template);
/**
* Work out what class of {@link Schema} objects this panel edits.
*
* @return the type of {@link Schema} objects this panel edits.
*/
public abstract Class getSchemaClass();
/**
* This connection panel implementation allows a user to define some JDBC
* connection parameters, such as hostname, username, driver class and if
* necessary the location where the driver can be found. It uses this to
* construct a JDBC URL, dynamically, and ultimately creates a
* {@link JDBCSchema} implementation which represents the connection.
*/
public static class JDBCSchemaConnectionPanel extends SchemaConnectionPanel
implements DocumentListener {
private static final Map DRIVER_MAP = new HashMap();
private static final Map DRIVER_NAME_MAP = new HashMap();
private static final long serialVersionUID = 1;
// NOTE: Please add any more default drivers that we support to this
// pair
// of static lists.
static {
// JDBC URL formats.
// The keys are driver classes, the values are arrays.
// The first entry in the array should be the default port number
// for this
// JDBC driver type, and the second entry should be an example JDBC
// URL.
// Within the URL, the keywords <HOSTNAME>, <PORT> and <DATABASE>
// must all
// appear in the order mentioned. Any other order will break the
// regex
// replacement function elsewhere in this class.
JDBCSchemaConnectionPanel.DRIVER_MAP.put("com.mysql.jdbc.Driver",
new String[] { "3306",
"jdbc:mysql://<HOST>:<PORT>/<DATABASE>" });
JDBCSchemaConnectionPanel.DRIVER_MAP.put(
"oracle.jdbc.driver.OracleDriver", new String[] { "1531",
"jdbc:oracle:thin:@<HOST>:<PORT>:<DATABASE>" });
JDBCSchemaConnectionPanel.DRIVER_MAP.put("org.postgresql.Driver",
new String[] { "5432",
"jdbc:postgresql://<HOST>:<PORT>/<DATABASE>" });
// Names.
// The keys are database names, the values are driver classes.
JDBCSchemaConnectionPanel.DRIVER_NAME_MAP.put(Resources
.get("driverClassMySQL"), "com.mysql.jdbc.Driver");
JDBCSchemaConnectionPanel.DRIVER_NAME_MAP.put(Resources
.get("driverClassOracle"),
"oracle.jdbc.driver.OracleDriver");
JDBCSchemaConnectionPanel.DRIVER_NAME_MAP.put(Resources
.get("driverClassPostgreSQL"), "org.postgresql.Driver");
}
private final Mart mart;
private String currentJDBCURLTemplate;
private JTextField database;
private JTextField driverClass;
private JTextField host;
private JFileChooser jarFileChooser;
private JTextField jdbcURL;
private JPasswordField password;
private JFormattedTextField port;
private JComboBox predefinedDriverClass;
private JTextField schemaName;
private JTextField username;
private JTextField regex;
private JTextField expression;
private StringStringTablePanel preview;
private JCheckBox keyguessing;
/**
* This constructor creates a panel with all the fields necessary to
* construct a {@link JDBCSchema} instance, save the name which will be
* passed in elsewhere.
* <p>
* You must call {@link #copySettingsFromSchema(Schema)} before
* displaying this panel, otherwise the values displayed are not defined
* and may result in unpredictable behaviour. Or, call
* {@link #copySettingsFromProperties(Properties)} to achieve the same
* results.
*
* @param mart
* the mart this schema will belong to.
*/
public JDBCSchemaConnectionPanel(final Mart mart) {
super();
this.mart = mart;
// Create the layout manager for this panel.
this.setLayout(new GridBagLayout());
// Create constraints for labels that are not in the last row.
final GridBagConstraints labelConstraints = new GridBagConstraints();
labelConstraints.gridwidth = GridBagConstraints.RELATIVE;
labelConstraints.fill = GridBagConstraints.HORIZONTAL;
labelConstraints.anchor = GridBagConstraints.LINE_END;
labelConstraints.insets = new Insets(0, 2, 0, 0);
// Create constraints for fields that are not in the last row.
final GridBagConstraints fieldConstraints = new GridBagConstraints();
fieldConstraints.gridwidth = GridBagConstraints.REMAINDER;
fieldConstraints.fill = GridBagConstraints.NONE;
fieldConstraints.anchor = GridBagConstraints.LINE_START;
fieldConstraints.insets = new Insets(0, 1, 0, 2);
// Create constraints for labels that are in the last row.
final GridBagConstraints labelLastRowConstraints = (GridBagConstraints) labelConstraints
.clone();
labelLastRowConstraints.gridheight = GridBagConstraints.REMAINDER;
// Create constraints for fields that are in the last row.
final GridBagConstraints fieldLastRowConstraints = (GridBagConstraints) fieldConstraints
.clone();
fieldLastRowConstraints.gridheight = GridBagConstraints.REMAINDER;
// Create all the useful fields in the dialog box.
this.jdbcURL = new JTextField(40);
this.host = new JTextField(20);
this.port = new JFormattedTextField(new DecimalFormat("0"));
this.port.setColumns(4);
this.database = new JTextField(10);
this.schemaName = new JTextField(10);
this.username = new JTextField(10);
this.password = new JPasswordField(10);
this.keyguessing = new JCheckBox(Resources.get("myISAMLabel"));
// The driver class box displays the currently selected driver
// class. As it changes, other fields become highlighted.
this.driverClass = new JTextField(20);
this.driverClass.getDocument().addDocumentListener(this);
this.driverClass.setText(null); // Force into default state.
//this.keyguessing.setVisible(false);
// The predefined driver class box displays everything we know
// about by default, as defined by the map at the start of this
// class.
this.predefinedDriverClass = new JComboBox(
JDBCSchemaConnectionPanel.DRIVER_NAME_MAP.keySet().toArray(
new String[0]));
this.predefinedDriverClass.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
// This method is called when the driver class field is
// changed, either by the user typing in it, or using
// the drop-down to select a predefine value.
// Work out which database type was selected.
final String classType = (String) JDBCSchemaConnectionPanel.this.predefinedDriverClass
.getSelectedItem();
// Use it to look up the default class for that database
// type, then reset the drop-down to nothing-selected.
if (!JDBCSchemaConnectionPanel.this.isEmpty(classType)) {
final String driverClassName = (String) JDBCSchemaConnectionPanel.DRIVER_NAME_MAP
.get(classType);
if (!JDBCSchemaConnectionPanel.this.driverClass
.getText().equals(driverClassName)) {
JDBCSchemaConnectionPanel.this.keyguessing
.setVisible(driverClassName
.indexOf("mysql") >= 0);
JDBCSchemaConnectionPanel.this.keyguessing
.setSelected(driverClassName
.indexOf("mysql") >= 0);
JDBCSchemaConnectionPanel.this.driverClass
.setText(driverClassName);
}
}
}
});
// Create a listener that listens for changes on the host, port
// and database fields, and uses this to automatically update
// and construct a JDBC URL based on their contents.
this.host.getDocument().addDocumentListener(this);
this.port.getDocument().addDocumentListener(this);
this.database.getDocument().addDocumentListener(this);
// Create a file chooser for finding the JAR file where the driver
// lives.
this.jarFileChooser = new JFileChooser();
this.jarFileChooser.setFileFilter(new FileFilter() {
// Accepts only files ending in ".jar".
public boolean accept(final File f) {
return f.isDirectory()
|| f.getName().toLowerCase().endsWith(
Resources.get("jarExtension"));
}
public String getDescription() {
return Resources.get("JARFileFilterDescription");
}
});
// Create the regex and expression fields.
this.regex = new JTextField(50);
this.expression = new JTextField(20);
// Two-column string/string panel of matches
this.preview = new StringStringTablePanel(Collections.EMPTY_MAP) {
private static final long serialVersionUID = 1L;
public String getFirstColumnHeader() {
return Resources.get("partitionedSchemaHeader");
}
public String getSecondColumnHeader() {
return Resources.get("partitionedSchemaPrefixHeader");
}
};
// On-change listener for regex+expression to update panel of
// matches
// by creating a temporary dummy schema with the specified regexes
// and
// seeing what it produces. Alerts if nothing produced.
final DocumentListener dl = new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
this.changed();
}
public void insertUpdate(DocumentEvent e) {
this.changed();
}
public void removeUpdate(DocumentEvent e) {
this.changed();
}
private void changed() {
// If the fields aren't valid, we can't create it.
if (!JDBCSchemaConnectionPanel.this.validateFields(false))
return;
Map partitions = Collections.EMPTY_MAP;
try {
final Schema tempSch = JDBCSchemaConnectionPanel.this
.privateCreateSchemaFromSettings("__PARTITION_PREVIEW");
if (tempSch.getPartitionRegex() != null
&& tempSch.getPartitionNameExpression() != null)
partitions = tempSch.getPartitions();
} catch (final Throwable t) {
// Make doubly sure.
partitions = Collections.EMPTY_MAP;
} finally {
JDBCSchemaConnectionPanel.this.preview
.setValues(partitions);
}
}
};
this.regex.getDocument().addDocumentListener(dl);
this.expression.getDocument().addDocumentListener(dl);
this.jdbcURL.getDocument().addDocumentListener(dl);
// Add the driver class label and field.
JLabel label = new JLabel(Resources.get("driverClassLabel"));
this.add(label, labelConstraints);
JPanel field = new JPanel();
field.add(this.predefinedDriverClass);
field.add(this.keyguessing);
field.add(this.driverClass);
this.add(field, fieldConstraints);
// Add the host label, and the host field, port label, port field.
label = new JLabel(Resources.get("hostLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.host);
label = new JLabel(Resources.get("portLabel"));
field.add(label);
field.add(this.port);
this.add(field, fieldConstraints);
// Add the database and schema fields.
label = new JLabel(Resources.get("databaseLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.database);
label = new JLabel(Resources.get("schemaNameLabel"));
field.add(label);
field.add(this.schemaName);
this.add(field, fieldConstraints);
// Add the JDBC URL label and field.
label = new JLabel(Resources.get("jdbcURLLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.jdbcURL);
this.add(field, fieldConstraints);
// Add the username label, and the username field, password
// label and password field across the username field space
// in order to save space.
label = new JLabel(Resources.get("usernameLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.username);
label = new JLabel(Resources.get("passwordLabel"));
field.add(label);
field.add(this.password);
this.add(field, fieldConstraints);
// Add the partition stuff.
// Fields for the regex and expression
label = new JLabel(Resources.get("schemaRegexLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.regex);
this.add(field, fieldConstraints);
label = new JLabel(Resources.get("schemaExprLabel"));
this.add(label, labelConstraints);
field = new JPanel();
field.add(this.expression);
this.add(field, fieldConstraints);
// Two-column string/string panel of matches
label = new JLabel(Resources.get("partitionedSchemasLabel"));
this.add(label, labelLastRowConstraints);
field = new JPanel();
field.add(this.preview);
this.add(field, fieldLastRowConstraints);
}
public void copySettingsFromProperties(final Properties template) {
// Copy the driver class.
this.driverClass.setText(template.getProperty("driverClass"));
// Make sure the right fields get enabled.
this.driverClassChanged();
// Carry on copying.
final String jdbcURL = template.getProperty("jdbcURL");
this.jdbcURL.setText(jdbcURL);
this.username.setText(template.getProperty("username"));
this.password.setText(template.getProperty("password"));
this.schemaName.setText(template.getProperty("schema"));
this.regex.setText(template.getProperty("partitionRegex"));
this.expression.setText(template
.getProperty("partitionNameExpression"));
this.keyguessing.setSelected(Boolean.valueOf(
template.getProperty("keyguessing")).booleanValue());
// Parse the JDBC URL into host, port and database, if the
// driver is known to us (defined in the map at the start
// of this class).
String regexURL = this.currentJDBCURLTemplate;
if (regexURL != null) {
// Replace the three placeholders in the JDBC URL template
// with regex patterns. Obviously, this depends on the
// three placeholders appearing in the correct order.
// If they don't, then you're stuffed.
regexURL = regexURL.replaceAll("<HOST>", "(.*)");
regexURL = regexURL.replaceAll("<PORT>", "(.*)");
regexURL = regexURL.replaceAll("<DATABASE>", "(.*)");
// Use the regex to parse out the host, port and database
// from the JDBC URL.
final Pattern regex = Pattern.compile(regexURL);
final Matcher matcher = regex.matcher(jdbcURL);
if (matcher.matches()) {
this.host.setText(matcher.group(1));
this.port.setText(matcher.group(2));
this.database.setText(matcher.group(3));
}
}
}
private void documentEvent(final DocumentEvent e) {
if (e.getDocument().equals(this.driverClass.getDocument()))
this.driverClassChanged();
else
this.updateJDBCURL();
}
private void driverClassChanged() {
// Work out which class we should try out.
final String className = this.driverClass.getText();
// If it's not empty...
if (!this.isEmpty(className)) {
this.keyguessing
.setVisible(className
.indexOf("mysql") >= 0);
// Is this a preset class?
for (final Iterator i = JDBCSchemaConnectionPanel.DRIVER_NAME_MAP
.entrySet().iterator(); i.hasNext();) {
final Map.Entry entry = (Map.Entry) i.next();
final String mapName = (String) entry.getKey();
final String mapClassName = (String) entry.getValue();
if (mapClassName.equals(className))
this.predefinedDriverClass.setSelectedItem(mapName);
}
// Do we know about this, as defined in the map at the start
// of this class?
if (JDBCSchemaConnectionPanel.DRIVER_MAP.containsKey(className)) {
// Yes, so we can use the map to construct a JDBC URL
// template, into which host, port, and database can be
// placed as required.
// Obtain the template and split it.
final String[] parts = (String[]) JDBCSchemaConnectionPanel.DRIVER_MAP
.get(className);
// The second part is the JDBC URL template itself. Remember
// which template was selected, then disable the JDBC URL
// field in the interface as its contents will now be
// computed automatically. Enable the host/database/port
// fields instead.
this.currentJDBCURLTemplate = parts[1];
this.jdbcURL.setEnabled(false);
this.host.setEnabled(true);
this.port.setEnabled(true);
this.database.setEnabled(true);
// The first part of the template is the default port
// number, so set the port field to that number.
this.port.setText(parts[0]);
}
// This else statement deals with JDBC drivers that we do not
// have a template for.
else {
// Blank out our current template, so that we don't try
// and use it by accident.
this.currentJDBCURLTemplate = null;
// Enable the user-specified JDBC URL field, and disable
// the host/port/database fields as they're no longer
// required.
this.jdbcURL.setEnabled(true);
this.host.setEnabled(false);
this.port.setEnabled(false);
this.database.setEnabled(false);
}
}
// If it's empty, disable the fields that depend on it.
else {
this.keyguessing.setVisible(false);
this.host.setEnabled(false);
this.port.setEnabled(false);
this.database.setEnabled(false);
this.jdbcURL.setEnabled(false);
}
}
public Class getSchemaClass() {
return JDBCSchema.class;
}
private boolean isEmpty(final String string) {
// Strings are empty if they are null or all whitespace.
return string == null || string.trim().length() == 0;
}
private void updateJDBCURL() {
// If we don't have a current template, we can't parse it,
// so don't even attempt to do so.
if (this.currentJDBCURLTemplate == null)
return;
// Update the JDBC URL based on our current settings. Do this
// by replacing the placeholders in the template with the
// current values of the host/port/database fields. If there
// are no values in these fields, leave the placeholders
// as they are.
String newURL = this.currentJDBCURLTemplate;
if (!this.isEmpty(this.host.getText()))
newURL = newURL.replaceAll("<HOST>", this.host.getText());
if (!this.isEmpty(this.port.getText()))
newURL = newURL.replaceAll("<PORT>", this.port.getText());
if (!this.isEmpty(this.database.getText()))
newURL = newURL.replaceAll("<DATABASE>", this.database
.getText());
// Set the JDBC URL field to contain the URL we constructed.
this.jdbcURL.setText(newURL);
}
public void changedUpdate(final DocumentEvent e) {
this.documentEvent(e);
}
public Schema createSchemaFromSettings(final String name) {
// If the fields aren't valid, we can't create it.
if (!this.validateFields(true))
return null;
try {
// Return that schema.
return this.privateCreateSchemaFromSettings(name);
} catch (final Throwable t) {
StackTrace.showStackTrace(t);
}
// If we got here, something went wrong, so behave
// as though validation failed.
return null;
}
private Schema privateCreateSchemaFromSettings(final String name)
throws Exception {
// Record the user's specifications.
final String driverClassName = this.driverClass.getText();
final String url = this.jdbcURL.getText();
final String database = this.database.getText();
final String schemaName = this.schemaName.getText();
final String username = this.username.getText();
final String password = new String(this.password.getPassword());
final String regex = this.isEmpty(this.regex.getText()) ? null
: this.regex.getText().trim();
final String expression = this.isEmpty(this.expression.getText()) ? null
: this.expression.getText().trim();
// Construct a JDBCSchema based on them.
final JDBCSchema schema = new JDBCSchema(this.mart,
driverClassName, url, database, schemaName, username,
password, name, this.keyguessing.isSelected(), regex,
expression);
// Return that schema.
return schema;
}
public void insertUpdate(final DocumentEvent e) {
this.documentEvent(e);
}
public Schema copySettingsToExistingSchema(final Schema schema) {
// If the fields are not valid, we can't modify it.
if (!this.validateFields(true))
return null;
// We can only update JDBCSchema objects.
if (schema instanceof JDBCSchema)
try {
// Use the user input to update the fields on
// the existing schema object.
final JDBCSchema jschema = (JDBCSchema) schema;
jschema.setDriverClassName(this.driverClass.getText());
jschema.setUrl(this.jdbcURL.getText());
jschema.setDataLinkDatabase(this.database.getText());
jschema.setDataLinkSchema(this.schemaName.getText());
jschema.setUsername(this.username.getText());
jschema
.setPassword(new String(this.password.getPassword()));
jschema.setPartitionRegex(this
.isEmpty(this.regex.getText()) ? null : this.regex
.getText().trim());
jschema.setPartitionNameExpression(this
.isEmpty(this.expression.getText()) ? null
: this.expression.getText().trim());
jschema.setKeyGuessing(this.keyguessing.isSelected());
} catch (final Throwable t) {
StackTrace.showStackTrace(t);
}
// Return the modified schema, or the original schema if
// it was not a JDBC schema.
return schema;
}
public void removeUpdate(final DocumentEvent e) {
this.documentEvent(e);
}
public void copySettingsFromSchema(final Schema template) {
// Set the copy-settings box to nothing-selected.
this.predefinedDriverClass.setSelectedIndex(-1);
// If the template is a JDBC schema, copy the settings
// from it.
if (template instanceof JDBCSchema) {
final JDBCSchema jdbcSchema = (JDBCSchema) template;
// Copy the driver class.
this.driverClass.setText(jdbcSchema.getDriverClassName());
// Make sure the right fields get enabled.
this.driverClassChanged();
// Carry on copying.
final String jdbcURL = jdbcSchema.getUrl();
this.jdbcURL.setText(jdbcURL);
this.username.setText(jdbcSchema.getUsername());
this.password.setText(jdbcSchema.getPassword());
this.schemaName.setText(jdbcSchema.getDataLinkSchema());
this.regex.setText(jdbcSchema.getPartitionRegex());
this.expression
.setText(jdbcSchema.getPartitionNameExpression());
// Parse the JDBC URL into host, port and database, if the
// driver is known to us (defined in the map at the start
// of this class).
String regexURL = this.currentJDBCURLTemplate;
// Replace the three placeholders in the JDBC URL template
// with regex patterns. Obviously, this depends on the
// three placeholders appearing in the correct order.
// If they don't, then you're stuffed.
regexURL = regexURL.replaceAll("<HOST>", "(.*)");
regexURL = regexURL.replaceAll("<PORT>", "(.*)");
regexURL = regexURL.replaceAll("<DATABASE>", "(.*)");
// Use the regex to parse out the host, port and database
// from the JDBC URL.
final Pattern regex = Pattern.compile(regexURL);
final Matcher matcher = regex.matcher(jdbcURL);
if (matcher.matches()) {
this.host.setText(matcher.group(1));
this.port.setText(matcher.group(2));
this.database.setText(matcher.group(3));
}
}
// Otherwise, set some sensible defaults.
else {
this.driverClass.setText(null);
// Make sure the right fields get enabled.
this.driverClassChanged();
// Carry on resetting.
this.jdbcURL.setText(null);
this.host.setText(null);
this.port.setText(null);
this.database.setText(null);
this.schemaName.setText(null);
this.username.setText(null);
this.password.setText(null);
this.regex.setText(null);
this.expression.setText(null);
this.preview.setValues(Collections.EMPTY_MAP);
}
}
public boolean validateFields(final boolean report) {
// Make a list to hold any validation messages that may occur.
final List messages = new ArrayList();
// If we don't have a class, complain.
if (this.isEmpty(this.driverClass.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("driverClass")));
// If the user had to specify their own JDBC URL, make sure
// they have done so.
if (this.jdbcURL.isEnabled()) {
if (this.isEmpty(this.jdbcURL.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("jdbcURL")));
}
// Otherwise, make sure they have specified all three of host, port
// and database.
else {
if (this.isEmpty(this.host.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("host")));
if (this.isEmpty(this.port.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("port")));
if (this.isEmpty(this.database.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("database")));
}
// Make sure they have given a schema name.
if (this.isEmpty(this.schemaName.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("schemaName")));
// Make sure they have given a username. (Password is optional as
// not all databases require one).
if (this.isEmpty(this.username.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("username")));
// Check regex+expression are both missing or both present (EOR).
if (this.isEmpty(this.regex.getText())
^ this.isEmpty(this.expression.getText()))
messages.add(Resources.get("schemaRegexExprEmpty"));
// If there any messages to show the user, show them.
if (report && !messages.isEmpty())
JOptionPane.showMessageDialog(null, messages
.toArray(new String[0]), Resources
.get("validationTitle"),
JOptionPane.INFORMATION_MESSAGE);
// Validation succeeds if there were no messages.
return messages.isEmpty();
}
}
}