]> source.dussan.org Git - jackcess.git/commitdiff
make database and table iterable; slight rearrangement of logic in getNextRow
authorJames Ahlborn <jtahlborn@yahoo.com>
Fri, 4 Aug 2006 17:16:59 +0000 (17:16 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Fri, 4 Aug 2006 17:16:59 +0000 (17:16 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@92 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/Database.java
src/java/com/healthmarketscience/jackcess/Table.java
test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java

index a4c5e02a109d88c3216b7967742e34881317acc2..181a5a370b1cd5205fbc64f87d1413322bed333a 100644 (file)
@@ -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<Table>
+{
   
   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<Table> 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<Table>
+  {
+    private Iterator<String> _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);
+      }
+    }
+  }
   
 }
index 405478e567fa090356b0bdc13829d4564abf0ad1..1a896ad5afd8f70a14aadd2850688b3a5cef18cc 100644 (file)
@@ -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<Map<String, Object>>
+{
   
   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 <code>reset</code> 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
+   * <code>getNextRow</code>.
+   * @throws IllegalStateException if an IOException is thrown by one of the
+   *         operations, the actual exception will be contained within
+   */
+  public Iterator<Map<String, Object>> iterator()
+  {
+    return iterator(null);
+  }
+  
+  /**
+   * Calls <code>reset</code> 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 <code>getNextRow</code>.
+   * @throws IllegalStateException if an IOException is thrown by one of the
+   *         operations, the actual exception will be contained within
+   */
+  public Iterator<Map<String, Object>> iterator(Collection<String> 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<Map<String, Object>>
+  {
+    private Collection<String> _columnNames;
+    private Map<String, Object> _next;
+    
+    private RowIterator(Collection<String> 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<String, Object> next() {
+      if(!hasNext()) {
+        throw new NoSuchElementException();
+      }
+      try {
+        Map<String, Object> rtn = _next;
+        _next = getNextRow(_columnNames);
+        return rtn;
+      } catch(IOException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+    
+  }
+
 }
index a4d6a71bf86e7898edb934b666d5ccffa9375cef..18d3b47afe4b98c0787e0b7156a74db8725d9744 100644 (file)
@@ -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<String, Object> 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);
     }
   }