package mtvi.tools.gdc; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import mtvi.gdc.Answer; import mtvi.gdc.Config; import mtvi.gdc.DataCollection; import mtvi.gdc.Entry; import mtvi.gdc.EntryData; import mtvi.gdc.GdcException; import mtvi.gdc.question.Question; import mtvi.sql.ConnectionException; import mtvi.sql.SQLConnection; import mtvi.util.IntVector; /** * EntryManager that performs all read operations directly from the database. */ public class DatabaseEntryManager extends AbstractEntryManager { public int[] getAllEntryIDs(DataCollection col) throws GdcException { try { SQLConnection dbConnection = getConf().getDssConnection(); if (dbConnection == null) throw new SQLException("dssConnection not set"); Connection conn = null; CallableStatement cs = null; ResultSet rs = null; try { conn = dbConnection.openConnection("Getting all entryIDs for collection"); IntVector vec = new IntVector(); cs = conn.prepareCall("{ call gdc_GetAllEntryIDs(?) }"); cs.setInt(1, col.getCollectionID()); rs = cs.executeQuery(); while (rs.next()) vec.addElement(rs.getInt(1)); return vec.toArray(); } finally { try { if (rs != null) { rs.close(); } if (cs != null) { cs.close(); } } catch (Exception ex) { } dbConnection.closeConnection(conn); } } catch (ConnectionException ce) { throw new GdcException("Connection error", ce); } catch (SQLException se) { throw new GdcException("Database error", se); } } public Entry getEntry(int entryID, DataCollection col) throws GdcException { try { SQLConnection dbConnection = getConf().getDssConnection(); if (dbConnection == null) throw new SQLException("dssConnection not set"); Connection conn = null; ResultSet rs = null; CallableStatement cs = null; try { conn = dbConnection.openConnection("Getting a single entry"); cs = conn.prepareCall("{ call gdc_GetEntry(?) }"); cs.setInt(1, entryID); rs = cs.executeQuery(); EntryBuilder entryBuilder = new EntryBuilder(rs, col); return entryBuilder.buildEntry(); } finally { try { if (rs != null) { rs.close(); } if (cs != null) { cs.close(); } } catch (Exception ex) { } dbConnection.closeConnection(conn); } } catch (ConnectionException ce) { throw new GdcException("Connection error", ce); } catch (SQLException se) { throw new GdcException("Database error", se); } } public EntryIterator getAllEntries(final DataCollection col) throws GdcException { return new EntryIterator() { private EntryBuilder m_builder = null; private CallableStatement m_callableStatement = null; private ResultSet m_resultSet = null; private SQLConnection m_dbConnection = null; private Connection m_connection = null; public void open() throws GdcException { try { m_dbConnection = getConf().getDssConnection(); if (m_dbConnection == null) { throw new GdcException("dssConnection not set"); } try { m_connection = m_dbConnection.openConnection("Getting a single entry"); m_callableStatement = m_connection .prepareCall("{ call gdc_GetAllEntries(?) }", java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); m_callableStatement.setFetchSize(Integer.MIN_VALUE); m_callableStatement.setInt(1, col.getCollectionID()); m_resultSet = m_callableStatement.executeQuery(); m_builder = new EntryBuilder(m_resultSet, col); } finally { if (m_builder == null) { close(); } } } catch (ConnectionException ce) { throw new GdcException("Error creating EntryIterator", ce); } catch (SQLException se) { throw new GdcException("Error opening EntryIterator", se); } } public boolean hasNext() { return (!m_builder.isDone()); } public Entry next() throws GdcException { try { return m_builder.buildEntry(); } catch (SQLException se) { throw new GdcException("Error building entry", se); } } public void close() throws GdcException { try { if (m_resultSet != null) { m_resultSet.close(); m_resultSet = null; } if (m_callableStatement != null) { m_callableStatement.close(); m_callableStatement = null; } if (m_connection != null) { m_dbConnection.closeConnection(m_connection); m_connection = null; } } catch (Exception ex) { throw new GdcException("Error closing EntryIterator", ex); } } }; } /** Inner class to build an entry from a ResultSet. */ private class EntryBuilder { // collection we're building entries for private DataCollection m_collection = null; // ResultSet with the entry data to process private ResultSet m_rs = null; private final List m_answers = new ArrayList(); private final List m_answerParts = new ArrayList(); private boolean m_done = false; /** * Creates a new EntryBuilder for the specified collection and positions * the ResultSet on the first row. */ public EntryBuilder(ResultSet rs, DataCollection col) throws SQLException { m_rs = rs; m_collection = col; m_done = !rs.next(); } /** * Builds a new Entry using the ResultSet. Returns null if the end of * the ResultSet has been reached. The result set is expected to be * positioned at the first row of the entry's data set. */ public Entry buildEntry() throws SQLException { if (isDone()) { return null; } int entryID = m_rs.getInt(1); int questionID = 0; Question ques = null; EntryData answerPart = null; m_answers.clear(); Entry entry = new Entry(entryID, // entry ID m_collection, // collection entry belongs to m_rs.getTimestamp(2).getTime(), // date entered (as a long) m_rs.getInt(3), // user ID m_rs.getInt(4) // referrral count ); Config cfg = getConf(); boolean b64 = (cfg != null && cfg.getBase64Supported() && m_rs.getBoolean("IsBase64")); for (;;) { if (m_rs.getInt(1) != entryID) { if (questionID != 0) { ques = m_collection.getQuestion(questionID); if (ques != null) m_answers.add(new Answer(questionID, ques.assembleAnswer(m_answerParts, b64))); } entry.setAnswers(m_answers); entry.setStateID(m_rs.getInt(5)); return entry; } if (m_rs.getInt(5) != questionID) { if (questionID != 0) { ques = m_collection.getQuestion(questionID); if (ques != null) m_answers.add(new Answer(questionID, ques.assembleAnswer(m_answerParts, b64))); } questionID = m_rs.getInt(5); m_answerParts.clear(); } answerPart = new EntryData(); answerPart.m_string = m_rs.getString(6); answerPart.m_int = m_rs.getInt(7); answerPart.m_date = m_rs.getTimestamp(8); m_answerParts.add(answerPart); if (!m_rs.next()) { if (questionID != 0) { ques = m_collection.getQuestion(questionID); if (ques != null) m_answers.add(new Answer(questionID, ques.assembleAnswer(m_answerParts, b64))); } m_done = true; entry.setAnswers(m_answers); // entry.setStateID(m_rs.getInt(5)); return entry; } } } /** * Returns true if all the entries for this EntryBuilder's ResultSet * have been built (ie, the end of the ResultSet has been reached). */ public boolean isDone() { return m_done; } } }