All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bridgedb.rdb.construct.GdbConstructImpl3 Maven / Gradle / Ivy

The newest version!
package org.bridgedb.rdb.construct;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import org.bridgedb.IDMapperException;
import org.bridgedb.Xref;

public class GdbConstructImpl3 implements GdbConstruct
{
	private static int GDB_COMPAT_VERSION = 3;

	private final Connection con; //TODO: initialize
	private final DBConnector dbConnector; //TODO
	private String dbName; //TODO
	private Exception recentException = null;
	
	public GdbConstructImpl3(String dbName, DBConnector dbConnector, int props) throws IDMapperException
	{
		con = dbConnector.createConnection(dbName, props);
		this.dbConnector = dbConnector;
		this.dbName = dbName;
	}
	
	/**
	   compact the database.
	   @throws IDMapperException on failure
	 */
	final public void compact() throws IDMapperException
	{
		dbConnector.compact(con);
	}
	
	/**
	   finalize the database.
	   @throws IDMapperException on failure
	 */
	final public void finalize() throws IDMapperException
	{
		dbConnector.compact(con);
		createGdbIndices();
		dbConnector.closeConnection(con, DBConnector.PROP_FINALIZE);
		String newDb = dbConnector.finalizeNewDatabase(dbName);
		dbName = newDb;
		recentException = null;
	}

    private PreparedStatement pstGene = null;
    private PreparedStatement pstLink = null;
    private PreparedStatement pstAttr = null;

	/** {@inheritDoc} */
	public int addGene(Xref ref)
	{
		recentException = null;
		//TODO: bpText is unused
    	if (pstGene == null) throw new NullPointerException();
		try 
		{
			pstGene.setString(1, ref.getId());
			pstGene.setString(2, ref.getDataSource().getSystemCode());
			pstGene.executeUpdate();
		} 
		catch (SQLException e) 
		{
			recentException = e;
			return 1;
		}
		return 0;
    }
    
	/** {@inheritDoc} */
    public int addAttribute(Xref ref, String attr, String val)
    {
    	recentException = null;
    	try {
    		pstAttr.setString(1, attr);
			pstAttr.setString(2, val);
			pstAttr.setString(3, ref.getId());
			pstAttr.setString(4, ref.getDataSource().getSystemCode());
			pstAttr.executeUpdate();
		} catch (SQLException e) {
			recentException = e;
			return 1;
		}
		return 0;
    }

	/** {@inheritDoc} */
    public int addLink(Xref left, Xref right) 
    {
    	if (pstLink == null) throw new NullPointerException();
    	recentException = null;
    	try 
    	{
			pstLink.setString(1, left.getId());
			pstLink.setString(2, left.getDataSource().getSystemCode());
			pstLink.setString(3, right.getId());
			pstLink.setString(4, right.getDataSource().getSystemCode());
			pstLink.executeUpdate();
		} 
    	catch (SQLException e) 
		{
    		recentException = e;
			return 1;
		}
		return 0;
	}

	/**
	   prepare for inserting genes and/or links.
	   @throws IDMapperException on failure
	 */
	public void preInsert() throws IDMapperException
	{
		try
		{
			con.setAutoCommit(false);
			pstGene = con.prepareStatement(
				"INSERT INTO datanode " +
				"	(id, code)" +
				"VALUES (?, ?)"
	 		);
			pstLink = con.prepareStatement(
				"INSERT INTO link " +
				"	(idLeft, codeLeft," +
				"	 idRight, codeRight)" +
				"VALUES (?, ?, ?, ?)"
	 		);
			pstAttr = con.prepareStatement(
					"INSERT INTO attribute " +
					"	(attrname, attrvalue, id, code)" +
					"VALUES (?, ?, ?, ?)"
					);
		}
		catch (SQLException e)
		{
			throw new IDMapperException (e);
		}
	}

	public void setInfo(String key, String value) throws IDMapperException
	{
		try
		{
			/** 
			 * This is a bit awkward because we store keys as columns.
			 * TODO: in a future schema version this should be a regular 2-column table.
			 */
			if (!key.matches("^\\w+$")) throw new IllegalArgumentException("key: '" + key + "' contains invalid characters");
			PreparedStatement pstInfo1 = con.prepareStatement (
					"ALTER TABLE info " +
					"ADD COLUMN " + key + " VARCHAR (50)"
		 		);
			pstInfo1.execute();
			PreparedStatement pstInfo2 = con.prepareStatement (
						"UPDATE info SET " + key + " = ? " +
						"WHERE schemaversion = " + GDB_COMPAT_VERSION
			 		);
			pstInfo2.setString(1, value);
			pstInfo2.execute();
		}
		catch (SQLException ex)
		{
			throw new IDMapperException(ex);
		}
	}
	
	
	/**
	   Create indices on the database
	   You can call this at any time after creating the tables,
	   but it is good to do it only after inserting all data.
	   @throws IDMapperException on failure
	 */
	public void createGdbIndices() throws IDMapperException 
	{
		try
		{
			Statement sh = con.createStatement();
			sh.execute(
					"CREATE INDEX i_codeLeft" +
					" ON link(codeLeft)"
			);
			sh.execute(
					"CREATE INDEX i_idRight" +
					" ON link(idRight)"
			);
			sh.execute(
					"CREATE INDEX i_codeRight" +
					" ON link(codeRight)"
			);
			sh.execute(
					"CREATE INDEX i_code" +
					" ON " + "datanode" + "(code)"
			);
		}
		catch (SQLException e)
		{
			throw new IDMapperException (e);
		}
	}

	/**
	 * Executes several SQL statements to create the tables and indexes in the database the given
	 * connection is connected to
	 * Note: Official GDB's are created by AP, not with this code.
	 * This is just here for testing purposes.
	 * @throws IDMapperException 
	 */
	public void createGdbTables() throws IDMapperException 
	{
//		Logger.log.info("Info:  Creating tables");
		try 
		{
			Statement sh = con.createStatement();
//			sh.execute("DROP TABLE info");
//			sh.execute("DROP TABLE link");
//			sh.execute("DROP TABLE datanode");
//			sh.execute("DROP TABLE attribute");
//			sh.close();
			
//			sh = con.createStatement();
			sh.execute(
					"CREATE TABLE					" +
					"		info							" +
					"(	  schemaversion INTEGER PRIMARY KEY		" +
			")");
//			Logger.log.info("Info table created");
			sh.execute( //Add compatibility version of GDB
					"INSERT INTO info VALUES ( " + GDB_COMPAT_VERSION + ")");
//			Logger.log.info("Version stored in info");
			sh.execute(
					"CREATE TABLE					" +
					"		link							" +
					" (   idLeft VARCHAR(50) NOT NULL,		" +
					"     codeLeft VARCHAR(50) NOT NULL,	" +
					"     idRight VARCHAR(50) NOT NULL,		" +
					"     codeRight VARCHAR(50) NOT NULL,	" +
					"     bridge VARCHAR(50),				" +
					"     PRIMARY KEY (idLeft, codeLeft,    " +
					"		idRight, codeRight) 			" +
					" )										");
//			Logger.log.info("Link table created");
			sh.execute(
					"CREATE TABLE					" +
					"		datanode						" +
					" (   id VARCHAR(50),					" +
					"     code VARCHAR(50),					" +
					"     PRIMARY KEY (id, code)    		" +
					" )										");
//			Logger.log.info("DataNode table created");
			sh.execute(
					"CREATE TABLE							" +
					"		attribute 						" +
					" (   id VARCHAR(50),					" +
					"     code VARCHAR(50),					" +
					"     attrname VARCHAR(50),				" +
					"	  attrvalue VARCHAR(255)			" +
					" )										");
//			Logger.log.info("Attribute table created");
		} 
		catch (SQLException e)
		{
			throw new IDMapperException (e);
		}
	}


	/**
	   commit inserted data.
	   @throws IDMapperException on failure
	 */
	final public void commit() throws IDMapperException
	{
		try
		{
			con.commit();
		}
		catch (SQLException e)
		{
			throw new IDMapperException (e);
		}
	}
	
	/**
	 * Older method to open a connection to a Gene database
	 * using a DBConnector to handle differences
	 * between different RDBMS-es. The other createInstance() is preferred.
	 * 

* Use this instead of constructor to create an instance of SimpleGdb that matches the schema version. * @param dbName The file containing the Gene Database. * @param newDbConnector handles the differences between types of RDBMS. * A new instance of DbConnector class is instantiated automatically. * @param props PROP_RECREATE if you want to create a new database, overwriting any existing ones. Otherwise, PROP_NONE. * @return a new Gdb * @throws IDMapperException on failure */ public static GdbConstruct createInstance(String dbName, DBConnector newDbConnector, int props) throws IDMapperException { try { // create a fresh db connector of the correct type. DBConnector dbConnector = newDbConnector.getClass().newInstance(); return new GdbConstructImpl3(dbName, dbConnector, props); } catch (InstantiationException e) { throw new IDMapperException (e); } catch (IllegalAccessException e) { throw new IDMapperException (e); } } @Override public Exception recentException() { return recentException; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy