From 479c633c30387d9f91ff6cee97adc979d231d59f Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Fri, 4 Aug 2006 17:16:59 +0000 Subject: [PATCH] make database and table iterable; slight rearrangement of logic in getNextRow git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@92 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/Database.java | 54 ++++++- .../healthmarketscience/jackcess/Table.java | 145 ++++++++++++++---- .../jackcess/DatabaseTest.java | 12 +- 3 files changed, 168 insertions(+), 43 deletions(-) diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java index a4c5e02..181a5a3 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/Database.java @@ -49,7 +49,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; + import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -59,7 +61,9 @@ import org.apache.commons.logging.LogFactory; * * @author Tim McCune */ -public class Database { +public class Database + implements Iterable +{ private static final Log LOG = LogFactory.getLog(Database.class); @@ -291,6 +295,18 @@ public class Database { } return _tableNames; } + + /** + * @return an unmodifiable Iterator of the user Tables in this Database. + * @throws IllegalStateException if an IOException or SQLException is thrown + * by one of the operations, the actual exception will be contained + * within + * @throws ConcurrentModificationException if a table is added to the + * database while an Iterator is in use. + */ + public Iterator
iterator() { + return new TableIterator(); + } /** * @param name Table name @@ -761,6 +777,9 @@ public class Database { return ((tableName != null) ? tableName.toUpperCase() : null); } + /** + * Utility class for storing table page number and actual name. + */ private static class TableInfo { public Integer pageNumber; @@ -772,5 +791,38 @@ public class Database { tableName = newTableName; } } + + /** + * Table iterator for this database, unmodifiable. + */ + private class TableIterator implements Iterator
+ { + private Iterator _tableNameIter; + + private TableIterator() { + _tableNameIter = getTableNames().iterator(); + } + + public boolean hasNext() { + return _tableNameIter.hasNext(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Table next() { + if(!hasNext()) { + throw new NoSuchElementException(); + } + try { + return getTable(_tableNameIter.next()); + } catch(IOException e) { + throw new IllegalStateException(e); + } catch(SQLException e) { + throw new IllegalStateException(e); + } + } + } } diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java index 405478e..1a896ad 100644 --- a/src/java/com/healthmarketscience/jackcess/Table.java +++ b/src/java/com/healthmarketscience/jackcess/Table.java @@ -39,6 +39,8 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -46,7 +48,9 @@ import org.apache.commons.logging.LogFactory; * A single database table * @author Tim McCune */ -public class Table { +public class Table + implements Iterable> +{ private static final Log LOG = LogFactory.getLog(Table.class); @@ -256,40 +260,43 @@ public class Table { Column column = (Column) iter.next(); boolean isNull = nullMask.isNull(columnNumber); Object value = null; - if (column.getType() == DataType.BOOLEAN) { - value = new Boolean(!isNull); //Boolean values are stored in the null mask - } else { - if (!column.isVariableLength()) - { - //Read in fixed length column data - columnData = new byte[column.getLength()]; - _buffer.position(dataStart + column.getFixedDataOffset()); - _buffer.get(columnData); - } - else - { - if (!isNull) - { - // read in var length column data - int varDataIdx = (rowVarColumnCount - - column.getVarLenTableIndex() - 1); - int varDataStart = varColumnOffsets[varDataIdx]; - int varDataEnd = ((varDataIdx > 0) ? - varColumnOffsets[varDataIdx - 1] : - lastVarColumnStart); - columnData = new byte[varDataEnd - varDataStart]; - _buffer.position(_rowStart + varDataStart); - _buffer.get(columnData); - } - } - if (!isNull && columnData != null && - (columnNames == null || columnNames.contains(column.getName()))) - { - //Add the value if we are interested in it. - value = column.read(columnData); + if((columnNames == null) || (columnNames.contains(column.getName()))) { + + if (column.getType() == DataType.BOOLEAN) { + value = new Boolean(!isNull); //Boolean values are stored in the null mask + } else { + if(!isNull) { + if (!column.isVariableLength()) + { + //Read in fixed length column data + columnData = new byte[column.getLength()]; + _buffer.position(dataStart + column.getFixedDataOffset()); + _buffer.get(columnData); + } + else + { + // read in var length column data + int varDataIdx = (rowVarColumnCount - + column.getVarLenTableIndex() - 1); + int varDataStart = varColumnOffsets[varDataIdx]; + int varDataEnd = ((varDataIdx > 0) ? + varColumnOffsets[varDataIdx - 1] : + lastVarColumnStart); + columnData = new byte[varDataEnd - varDataStart]; + _buffer.position(_rowStart + varDataStart); + _buffer.get(columnData); + } + // parse the column data + value = column.read(columnData); + } + if (!isNull && columnData != null) + { + //Add the value if we are interested in it. + value = column.read(columnData); + } } + rtn.put(column.getName(), value); } - rtn.put(column.getName(), value); } return rtn; } @@ -341,6 +348,32 @@ public class Table { } } + /** + * Calls reset on this table and returns a modifiable Iterator + * which will iterate through all the rows of this table. Use of the + * Iterator follows the same restrictions as a call to + * getNextRow. + * @throws IllegalStateException if an IOException is thrown by one of the + * operations, the actual exception will be contained within + */ + public Iterator> iterator() + { + return iterator(null); + } + + /** + * Calls reset on this table and returns a modifiable Iterator + * which will iterate through all the rows of this table, returning only the + * given columns. Use of the Iterator follows the same restrictions as a + * call to getNextRow. + * @throws IllegalStateException if an IOException is thrown by one of the + * operations, the actual exception will be contained within + */ + public Iterator> iterator(Collection columnNames) + { + return new RowIterator(columnNames); + } + /** * Read the table definition */ @@ -716,5 +749,49 @@ public class Table { (format.SIZE_ROW_LOCATION * (rowNum - 1))) & OFFSET_MASK)); } - + + /** + * Row iterator for this table, supports modification. + */ + private final class RowIterator implements Iterator> + { + private Collection _columnNames; + private Map _next; + + private RowIterator(Collection columnNames) + { + try { + reset(); + _columnNames = columnNames; + _next = getNextRow(_columnNames); + } catch(IOException e) { + throw new IllegalStateException(e); + } + } + + public boolean hasNext() { return _next != null; } + + public void remove() { + try { + deleteCurrentRow(); + } catch(IOException e) { + throw new IllegalStateException(e); + } + } + + public Map next() { + if(!hasNext()) { + throw new NoSuchElementException(); + } + try { + Map rtn = _next; + _next = getNextRow(_columnNames); + return rtn; + } catch(IOException e) { + throw new IllegalStateException(e); + } + } + + } + } diff --git a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java index a4d6a71..18d3b47 100644 --- a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java @@ -253,9 +253,8 @@ public class DatabaseTest extends TestCase { } private int countRows(Table table) throws Exception { - table.reset(); int rtn = 0; - while (table.getNextRow() != null) { + for(Map row : table) { rtn++; } return rtn; @@ -494,17 +493,14 @@ public class DatabaseTest extends TestCase { private static void dumpDatabase(Database mdb) throws Exception { System.out.println("DATABASE:"); - - for(String tableName : mdb.getTableNames()) { - dumpTable(mdb.getTable(tableName)); + for(Table table : mdb) { + dumpTable(table); } } private static void dumpTable(Table table) throws Exception { System.out.println("TABLE: " + table.getName()); - table.reset(); - Object row = null; - while((row = table.getNextRow()) != null) { + for(Object row : table) { System.out.println(row); } } -- 2.39.5