/** * AnalyzerBeans * Copyright (C) 2014 Neopost - Customer Information Management * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied 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 distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.eobjects.analyzer.storage; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.AbstractList; import java.util.List; class SqlDatabaseList<E> extends AbstractList<E> implements List<E>, SqlDatabaseCollection { private final Connection _connection; private final String _tableName; private volatile int _size; public SqlDatabaseList(Connection connection, String tableName, String valueTypeName) { _connection = connection; _tableName = tableName; _size = 0; SqlDatabaseUtils.performUpdate(_connection, SqlDatabaseUtils.CREATE_TABLE_PREFIX + tableName + " (list_index INTEGER PRIMARY KEY, list_value " + valueTypeName + ")"); } @Override public synchronized E remove(int index) { E oldValue = get(index); SqlDatabaseUtils.performUpdate(_connection, "DELETE FROM " + _tableName + " WHERE list_index=" + index); SqlDatabaseUtils.performUpdate(_connection, "UPDATE " + _tableName + " SET list_index = list_index-1 WHERE list_index > " + index); _size--; return oldValue; } @Override public synchronized void clear() { SqlDatabaseUtils.performUpdate(_connection, "DELETE FROM " + _tableName); _size = 0; } @Override public E get(int index) { Statement st = null; ResultSet rs = null; try { st = _connection.createStatement(); rs = st.executeQuery("SELECT list_value FROM " + _tableName + " WHERE list_index=" + index + ";"); if (rs.next()) { @SuppressWarnings("unchecked") E result = (E) rs.getObject(1); if (rs.wasNull()) { return null; } return result; } throw new IndexOutOfBoundsException("No such index: " + index); } catch (SQLException e) { throw new IllegalStateException(e); } finally { SqlDatabaseUtils.safeClose(rs, st); } } @Override public int size() { return _size; } public synchronized boolean add(E elem) { PreparedStatement st = null; try { if (_size == 0) { // first time is different st = _connection.prepareStatement("INSERT INTO " + _tableName + " VALUES(0, ?)"); } else { st = _connection.prepareStatement("INSERT INTO " + _tableName + " VALUES((SELECT MAX(list_index)+1 FROM " + _tableName + "), ?)"); } st.setObject(1, elem); st.execute(); _size++; } catch (SQLException e) { throw new IllegalStateException(e); } finally { SqlDatabaseUtils.safeClose(null, st); } return true; } public synchronized void add(int index, E element) { SqlDatabaseUtils.performUpdate(_connection, "UPDATE " + _tableName + " SET list_index = list_index+1 WHERE list_index > " + index); PreparedStatement st = null; try { st = _connection.prepareStatement("INSERT INTO " + _tableName + " VALUES(?, ?)"); st.setObject(1, index); st.setObject(2, element); st.executeUpdate(); _size++; } catch (SQLException e) { throw new IllegalStateException(e); } finally { SqlDatabaseUtils.safeClose(null, st); } }; public synchronized E set(int index, E element) { E oldValue = get(index); PreparedStatement st = null; try { st = _connection.prepareStatement("UPDATE " + _tableName + " SET list_value=? WHERE list_index=?"); st.setObject(1, element); st.setObject(2, index); st.executeUpdate(); } catch (SQLException e) { throw new IllegalStateException(e); } finally { SqlDatabaseUtils.safeClose(null, st); } return oldValue; }; @Override public String getTableName() { return _tableName; }; @Override protected void finalize() throws Throwable { super.finalize(); SqlDatabaseUtils.performUpdate(_connection, "DROP TABLE " + getTableName()); } }