package org.genedb.db.loading.auxiliary;
import org.apache.log4j.Logger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Abstract Clear class implemented by Clear classes to delete features or other elements from the database
*
*
*/
public abstract class Clear {
//Fixed
private static final Logger logger = Logger.getLogger(Clear.class);
private static final ResourceBundle config = ResourceBundle.getBundle("project");
private static String getConfigParam(String key) {
try {
return config.getString(key);
} catch (MissingResourceException e) {
return System.getProperty(key);
}
}
//Configurable variables
private Connection conn;
private String organismCommonName;
protected String analysisProgram;
/**
* Main method that deals with arguments sent to clear objects
* @param <T>
* @param clazz
* @param args
* @throws Exception
*/
protected static <T extends Clear> void main(Class<T> clazz, String[] args) throws Exception {
if (args.length != 1 && args.length != 2) {
System.err.printf("Usage: java %s <organism common name> [<analysis program>]\n", clazz.getName());
System.exit(1);
}
String organismCommonName = args[0];
String analysisProgram = null;
if (args.length > 1) {
analysisProgram = args[1];
}
T instance = clazz.getDeclaredConstructor(String.class, String.class).newInstance(organismCommonName, analysisProgram);
instance.clear();
}
/**
* Use this constructor when it is ok to get the database details from the project.properties file
*
* @param organismCommonName
* @param analysisProgram
* @throws ClassNotFoundException
* @throws SQLException
*/
protected Clear(String organismCommonName, String analysisProgram) throws ClassNotFoundException, SQLException {
if (organismCommonName.length() == 0)
throw new IllegalArgumentException("Empty organism name");
String url = String.format("jdbc:postgresql://%s:%s/%s",
getConfigParam("dbhost"),
getConfigParam("dbport"),
getConfigParam("dbname"));
String username = getConfigParam("dbuser");
String password = getConfigParam("dbpassword");
Class.forName("org.postgresql.Driver");
logger.debug(String.format("Connecting to database '%s' as user '%s'", url, username));
this.conn = DriverManager.getConnection(url, username, password);
this.organismCommonName = organismCommonName;
this.analysisProgram = null;
if (analysisProgram != null) {
this.analysisProgram = analysisProgram;
}
}
/**
* Use this constructor when you want to specify the connection (e.g. when trying to use clear via the loaders to run tests on the pfalciparum)
* See some of the loader classes for examples
*
* @param conn
* @param organismCommonName
* @param analysisProgram
*/
protected Clear(Connection conn, String organismCommonName, String analysisProgram) {
this.conn = conn;
this.organismCommonName = organismCommonName;
this.analysisProgram = analysisProgram;
}
/**
* Executes all the delete sql commands
*
* @throws SQLException
*/
protected void clear() throws SQLException {
for (DeleteSpec deleteSpec: getDeleteSpecs())
deleteSpec.execute();
}
/**
* Needs to be implemented by classes implementing this abstract class
*
* @return an array of delete statements
*/
protected abstract DeleteSpec[] getDeleteSpecs();
/**
* Class representing the sql delete statement and any sort of description provided
*
*/
protected class DeleteSpec {
private String description, sql;
private int numberBindParams;
public DeleteSpec(String description, String sql) {
this.description = description;
this.sql = sql;
this.numberBindParams = 1;
}
public DeleteSpec(String description, String sql, int numberBindParams) {
this.description = description;
this.sql = sql;
this.numberBindParams = numberBindParams;
}
private void execute() throws SQLException {
PreparedStatement st = conn.prepareStatement(sql);
try {
if (numberBindParams == 1) {
st.setString(1, organismCommonName);
}
else if (numberBindParams == 2) {
st.setString(1, analysisProgram);
st.setString(2, organismCommonName);
}
else {
logger.error(String.format("Incorrect number of bind parameters: %d", numberBindParams));
}
int numberDeleted = st.executeUpdate();
logger.info(String.format("Deleted %d %s for %s %s using %s", numberDeleted, description, analysisProgram, organismCommonName, sql));
}
finally {
try { st.close(); } catch (SQLException e) { logger.error(e); }
}
}
}
}