* move database open/create options to DBBuilder
* tweak how import filters work to make them more flexible?
- tweak lookup apis (specify column vs column name)
-- separate classes into more packages (api,builder,util,impl)
+* separate classes into more packages (api,builder,util,impl)
* remove debug log blocks
* add Row interface
* change savepoint to use table number instead of name?
import java.util.Iterator;
import java.util.Map;
-import com.healthmarketscience.jackcess.util.ErrorHandler;
import com.healthmarketscience.jackcess.util.ColumnMatcher;
+import com.healthmarketscience.jackcess.util.ErrorHandler;
+import com.healthmarketscience.jackcess.util.IterableBuilder;
/**
* Manages iteration for a Table. Different cursors provide different methods
*/
public boolean isCurrentRowDeleted() throws IOException;
- /**
- * Returns an Iterable whose iterator() method calls {@link #afterLast} on
- * this cursor and returns a modifiable Iterator which will iterate through
- * all the rows of this table in reverse order. Use of the Iterator follows
- * the same restrictions as a call to {@link #getPreviousRow}.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> reverseIterable();
-
- /**
- * Returns an Iterable whose iterator() method calls {@link #afterLast} on
- * this table and returns a modifiable Iterator which will iterate through
- * all the rows of this table in reverse order, returning only the given
- * columns. Use of the Iterator follows the same restrictions as a call to
- * {@link #getPreviousRow}.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> reverseIterable(
- Collection<String> columnNames);
-
/**
* Calls {@link #beforeFirst} on this cursor 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
* {@link #getNextRow}.
+ * <p/>
+ * For more flexible iteration see {@link #newIterable}.
* @throws RuntimeIOException if an IOException is thrown by one of the
* operations, the actual exception will be contained within
*/
public Iterator<Row> iterator();
/**
- * Returns an Iterable whose iterator() method calls {@link #beforeFirst} 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 {@link #getNextRow}.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> iterable(
- Collection<String> columnNames);
-
- /**
- * Returns an Iterable whose iterator() method calls {@link #beforeFirst} on
- * this cursor and returns a modifiable Iterator which will iterate through
- * all the rows of this table which match the given column pattern. Use of
- * the Iterator follows the same restrictions as a call to {@link
- * #getNextRow}. See {@link #findFirstRow(Column,Object)} for details on
- * #the columnPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> columnMatchIterable(
- Column columnPattern, Object valuePattern);
-
- /**
- * Returns an Iterable whose iterator() method calls {@link #beforeFirst} on
- * this table and returns a modifiable Iterator which will iterate through
- * all the rows of this table which match the given column pattern,
- * returning only the given columns. Use of the Iterator follows the same
- * restrictions as a call to {@link #getNextRow}. See {@link
- * #findFirstRow(Column,Object)} for details on the columnPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> columnMatchIterable(
- Collection<String> columnNames,
- Column columnPattern, Object valuePattern);
-
- /**
- * Returns an Iterable whose iterator() method calls {@link #beforeFirst} on
- * this cursor and returns a modifiable Iterator which will iterate through
- * all the rows of this table which match the given row pattern. Use of the
- * Iterator follows the same restrictions as a call to {@link #getNextRow}.
- * See {@link #findFirstRow(Map)} for details on the rowPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> rowMatchIterable(
- Map<String,?> rowPattern);
-
- /**
- * Returns an Iterable whose iterator() method calls {@link #beforeFirst} on
- * this table and returns a modifiable Iterator which will iterate through
- * all the rows of this table which match the given row pattern, returning
- * only the given columns. Use of the Iterator follows the same
- * restrictions as a call to {@link #getNextRow}. See {@link
- * #findFirstRow(Map)} for details on the rowPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
+ * Convenience method for constructing a new IterableBuilder for this
+ * cursor. An IterableBuilder provides a variety of options for more
+ * flexible iteration.
*/
- public Iterable<Row> rowMatchIterable(
- Collection<String> columnNames,
- Map<String,?> rowPattern);
+ public IterableBuilder newIterable();
/**
* Delete the current row.
* @param table the table over which this cursor will traverse
*/
public static Cursor createCursor(Table table) throws IOException {
- return new CursorBuilder(table).toCursor();
+ return table.newCursor().toCursor();
}
/**
public static IndexCursor createCursor(Table table, Index index)
throws IOException
{
- return new CursorBuilder(table).setIndex(index).toIndexCursor();
+ return table.newCursor().setIndex(index).toIndexCursor();
}
/**
Object[] startRow, Object[] endRow)
throws IOException
{
- return new CursorBuilder(table).setIndex(index)
+ return table.newCursor().setIndex(index)
.setStartRow(startRow)
.setEndRow(endRow)
.toIndexCursor();
boolean endInclusive)
throws IOException
{
- return new CursorBuilder(table).setIndex(index)
+ return table.newCursor().setIndex(index)
.setStartRow(startRow)
.setStartRowInclusive(startInclusive)
.setEndRow(endRow)
package com.healthmarketscience.jackcess;
import java.io.IOException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
+
+import com.healthmarketscience.jackcess.util.EntryIterableBuilder;
/**
* Cursor backed by an index with extended traversal options.
throws IOException;
/**
- * Returns a modifiable Iterator which will iterate through all the rows of
- * this table which match the given index entries.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> entryIterator(Object... entryValues);
-
- /**
- * Returns a modifiable Iterator which will iterate through all the rows of
- * this table which match the given index entries, returning only the given
- * columns.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> entryIterator(
- Collection<String> columnNames, Object... entryValues);
-
- /**
- * Returns an Iterable whose iterator() method returns the result of a call
- * to {@link #entryIterator(Object...)}
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterable<Row> entryIterable(Object... entryValues);
-
- /**
- * Returns an Iterable whose iterator() method returns the result of a call
- * to {@link #entryIterator(Collection,Object...)}
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
+ * Convenience method for constructing a new EntryIterableBuilder for this
+ * cursor. An EntryIterableBuilder provides a variety of options for more
+ * flexible iteration based on a specific index entry.
+ *
+ * @param entryValues the column values for the index's columns.
*/
- public Iterable<Row> entryIterable(
- Collection<String> columnNames, Object... entryValues);
-
+ public EntryIterableBuilder newEntryIterable(Object... entryValues);
}
* use the Cursor directly.
*/
public Cursor getDefaultCursor();
+
+ /**
+ * Convenience method for constructing a new CursorBuilder for this Table.
+ */
+ public CursorBuilder newCursor();
}
import java.util.Map;
import java.util.NoSuchElementException;
-import com.healthmarketscience.jackcess.impl.TableImpl.RowState;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.Cursor;
import com.healthmarketscience.jackcess.CursorBuilder;
-import com.healthmarketscience.jackcess.util.ErrorHandler;
-import com.healthmarketscience.jackcess.util.ColumnMatcher;
-import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.RuntimeIOException;
+import com.healthmarketscience.jackcess.impl.TableImpl.RowState;
+import com.healthmarketscience.jackcess.util.ColumnMatcher;
+import com.healthmarketscience.jackcess.util.ErrorHandler;
+import com.healthmarketscience.jackcess.util.IterableBuilder;
import com.healthmarketscience.jackcess.util.SimpleColumnMatcher;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* Manages iteration for a Table. Different cursors provide different methods
reset(MOVE_REVERSE);
}
- public boolean isBeforeFirst() throws IOException
- {
- if(getFirstPosition().equals(_curPos)) {
- return !recheckPosition(MOVE_REVERSE);
- }
- return false;
+ public boolean isBeforeFirst() throws IOException {
+ return isAtBeginning(MOVE_FORWARD);
}
- public boolean isAfterLast() throws IOException
- {
- if(getLastPosition().equals(_curPos)) {
- return !recheckPosition(MOVE_FORWARD);
+ public boolean isAfterLast() throws IOException {
+ return isAtBeginning(MOVE_REVERSE);
+ }
+
+ protected boolean isAtBeginning(boolean moveForward) throws IOException {
+ if(getDirHandler(moveForward).getBeginningPosition().equals(_curPos)) {
+ return !recheckPosition(!moveForward);
}
return false;
}
-
+
public boolean isCurrentRowDeleted() throws IOException
{
// we need to ensure that the "deleted" flag has been read for this row
_prevPos = _curPos;
_rowState.reset();
}
-
- public Iterable<Row> reverseIterable() {
- return reverseIterable(null);
- }
-
- public Iterable<Row> reverseIterable(
- final Collection<String> columnNames)
- {
- return new Iterable<Row>() {
- public Iterator<Row> iterator() {
- return new RowIterator(columnNames, MOVE_REVERSE);
- }
- };
- }
-
- public Iterator<Row> iterator()
- {
- return iterator(null);
- }
- public Iterable<Row> iterable(
- final Collection<String> columnNames)
- {
- return new Iterable<Row>() {
- public Iterator<Row> iterator() {
- return CursorImpl.this.iterator(columnNames);
- }
- };
- }
-
- /**
- * Calls <code>beforeFirst</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 RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> iterator(Collection<String> columnNames)
- {
- return new RowIterator(columnNames, MOVE_FORWARD);
- }
-
- public Iterable<Row> columnMatchIterable(
- Column columnPattern, Object valuePattern)
- {
- return columnMatchIterable((ColumnImpl)columnPattern, valuePattern);
- }
-
- public Iterable<Row> columnMatchIterable(
- ColumnImpl columnPattern, Object valuePattern)
- {
- return columnMatchIterable(null, columnPattern, valuePattern);
- }
-
- /**
- * Calls <code>beforeFirst</code> on this cursor and returns a modifiable
- * Iterator which will iterate through all the rows of this table which
- * match the given column pattern. Use of the Iterator follows the same
- * restrictions as a call to <code>getNextRow</code>. See
- * {@link #findFirstRow(Column,Object)} for details on the columnPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> columnMatchIterator(
- Column columnPattern, Object valuePattern)
- {
- return columnMatchIterator((ColumnImpl)columnPattern, valuePattern);
- }
-
- public Iterator<Row> columnMatchIterator(
- ColumnImpl columnPattern, Object valuePattern)
- {
- return columnMatchIterator(null, columnPattern, valuePattern);
+ public Iterator<Row> iterator() {
+ return new RowIterator(null, true, MOVE_FORWARD);
}
- public Iterable<Row> columnMatchIterable(
- Collection<String> columnNames,
- Column columnPattern, Object valuePattern)
- {
- return columnMatchIterable(columnNames, (ColumnImpl)columnPattern,
- valuePattern);
- }
-
- public Iterable<Row> columnMatchIterable(
- final Collection<String> columnNames,
- final ColumnImpl columnPattern, final Object valuePattern)
- {
- return new Iterable<Row>() {
- public Iterator<Row> iterator() {
- return CursorImpl.this.columnMatchIterator(
- columnNames, columnPattern, valuePattern);
- }
- };
+ public IterableBuilder newIterable() {
+ return new IterableBuilder(this);
}
- /**
- * Calls <code>beforeFirst</code> on this table and returns a modifiable
- * Iterator which will iterate through all the rows of this table which
- * match the given column pattern, returning only the given columns. Use of
- * the Iterator follows the same restrictions as a call to
- * <code>getNextRow</code>. See {@link #findFirstRow(Column,Object)} for
- * details on the columnPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> columnMatchIterator(
- Collection<String> columnNames, Column columnPattern,
- Object valuePattern)
- {
- return columnMatchIterator(columnNames, (ColumnImpl)columnPattern,
- valuePattern);
- }
-
- public Iterator<Row> columnMatchIterator(
- Collection<String> columnNames, ColumnImpl columnPattern,
- Object valuePattern)
- {
- return new ColumnMatchIterator(columnNames, columnPattern, valuePattern);
- }
+ public Iterator<Row> iterator(IterableBuilder iterBuilder) {
- public Iterable<Row> rowMatchIterable(
- Map<String,?> rowPattern)
- {
- return rowMatchIterable(null, rowPattern);
- }
-
- /**
- * Calls <code>beforeFirst</code> on this cursor and returns a modifiable
- * Iterator which will iterate through all the rows of this table which
- * match the given row pattern. Use of the Iterator follows the same
- * restrictions as a call to <code>getNextRow</code>. See
- * {@link #findFirstRow(Map)} for details on the rowPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> rowMatchIterator(
- Map<String,?> rowPattern)
- {
- return rowMatchIterator(null, rowPattern);
- }
-
- public Iterable<Row> rowMatchIterable(
- final Collection<String> columnNames,
- final Map<String,?> rowPattern)
- {
- return new Iterable<Row>() {
- public Iterator<Row> iterator() {
- return CursorImpl.this.rowMatchIterator(
- columnNames, rowPattern);
- }
- };
+ switch(iterBuilder.getType()) {
+ case SIMPLE:
+ return new RowIterator(iterBuilder.getColumnNames(),
+ iterBuilder.isReset(), iterBuilder.isForward());
+ case COLUMN_MATCH: {
+ @SuppressWarnings("unchecked")
+ Map.Entry<Column,Object> matchPattern = (Map.Entry<Column,Object>)
+ iterBuilder.getMatchPattern();
+ return new ColumnMatchIterator(
+ iterBuilder.getColumnNames(), (ColumnImpl)matchPattern.getKey(),
+ matchPattern.getValue(), iterBuilder.isReset(),
+ iterBuilder.isForward(), iterBuilder.getColumnMatcher());
+ }
+ case ROW_MATCH: {
+ @SuppressWarnings("unchecked")
+ Map<String,?> matchPattern = (Map<String,?>)
+ iterBuilder.getMatchPattern();
+ return new RowMatchIterator(
+ iterBuilder.getColumnNames(), matchPattern,iterBuilder.isReset(),
+ iterBuilder.isForward(), iterBuilder.getColumnMatcher());
+ }
+ default:
+ throw new RuntimeException("unknown match type " + iterBuilder.getType());
+ }
}
- /**
- * Calls <code>beforeFirst</code> on this table and returns a modifiable
- * Iterator which will iterate through all the rows of this table which
- * match the given row pattern, returning only the given columns. Use of
- * the Iterator follows the same restrictions as a call to
- * <code>getNextRow</code>. See {@link #findFirstRow(Map)} for details on
- * the rowPattern.
- * @throws RuntimeIOException if an IOException is thrown by one of the
- * operations, the actual exception will be contained within
- */
- public Iterator<Row> rowMatchIterator(
- Collection<String> columnNames, Map<String,?> rowPattern)
- {
- return new RowMatchIterator(columnNames, rowPattern);
- }
-
public void deleteCurrentRow() throws IOException {
_table.deleteRow(_rowState, _curPos.getRowId());
}
* @return {@code true} if another valid row was found in the given
* direction, {@code false} otherwise
*/
- private boolean moveToAnotherRow(boolean moveForward)
+ protected boolean moveToAnotherRow(boolean moveForward)
throws IOException
{
if(_curPos.equals(getDirHandler(moveForward).getEndPosition())) {
public boolean findFirstRow(ColumnImpl columnPattern, Object valuePattern)
throws IOException
{
- PositionImpl curPos = _curPos;
- PositionImpl prevPos = _prevPos;
- boolean found = false;
- try {
- beforeFirst();
- found = findNextRowImpl(columnPattern, valuePattern);
- return found;
- } finally {
- if(!found) {
- try {
- restorePosition(curPos, prevPos);
- } catch(IOException e) {
- LOG.error("Failed restoring position", e);
- }
- }
- }
+ return findAnotherRow(columnPattern, valuePattern, true, MOVE_FORWARD,
+ _columnMatcher);
}
public boolean findNextRow(Column columnPattern, Object valuePattern)
public boolean findNextRow(ColumnImpl columnPattern, Object valuePattern)
throws IOException
+ {
+ return findAnotherRow(columnPattern, valuePattern, false, MOVE_FORWARD,
+ _columnMatcher);
+ }
+
+ protected boolean findAnotherRow(ColumnImpl columnPattern, Object valuePattern,
+ boolean reset, boolean moveForward,
+ ColumnMatcher columnMatcher)
+ throws IOException
{
PositionImpl curPos = _curPos;
PositionImpl prevPos = _prevPos;
boolean found = false;
try {
- found = findNextRowImpl(columnPattern, valuePattern);
+ if(reset) {
+ reset(moveForward);
+ }
+ found = findAnotherRowImpl(columnPattern, valuePattern, moveForward,
+ columnMatcher);
return found;
} finally {
if(!found) {
public boolean findFirstRow(Map<String,?> rowPattern) throws IOException
{
- PositionImpl curPos = _curPos;
- PositionImpl prevPos = _prevPos;
- boolean found = false;
- try {
- beforeFirst();
- found = findNextRowImpl(rowPattern);
- return found;
- } finally {
- if(!found) {
- try {
- restorePosition(curPos, prevPos);
- } catch(IOException e) {
- LOG.error("Failed restoring position", e);
- }
- }
- }
+ return findAnotherRow(rowPattern, true, MOVE_FORWARD, _columnMatcher);
}
public boolean findNextRow(Map<String,?> rowPattern)
throws IOException
+ {
+ return findAnotherRow(rowPattern, false, MOVE_FORWARD, _columnMatcher);
+ }
+
+ protected boolean findAnotherRow(Map<String,?> rowPattern, boolean reset,
+ boolean moveForward,
+ ColumnMatcher columnMatcher)
+ throws IOException
{
PositionImpl curPos = _curPos;
PositionImpl prevPos = _prevPos;
boolean found = false;
try {
- found = findNextRowImpl(rowPattern);
+ if(reset) {
+ reset(moveForward);
+ }
+ found = findAnotherRowImpl(rowPattern, moveForward, columnMatcher);
return found;
} finally {
if(!found) {
public boolean currentRowMatches(ColumnImpl columnPattern, Object valuePattern)
throws IOException
{
- return _columnMatcher.matches(getTable(), columnPattern.getName(),
- valuePattern,
- getCurrentRowValue(columnPattern));
+ return currentRowMatchesImpl(columnPattern, valuePattern, _columnMatcher);
+ }
+
+ protected boolean currentRowMatchesImpl(ColumnImpl columnPattern,
+ Object valuePattern,
+ ColumnMatcher columnMatcher)
+ throws IOException
+ {
+ return columnMatcher.matches(getTable(), columnPattern.getName(),
+ valuePattern,
+ getCurrentRowValue(columnPattern));
}
public boolean currentRowMatches(Map<String,?> rowPattern)
throws IOException
+ {
+ return currentRowMatchesImpl(rowPattern, _columnMatcher);
+ }
+
+ protected boolean currentRowMatchesImpl(Map<String,?> rowPattern,
+ ColumnMatcher columnMatcher)
+ throws IOException
{
Row row = getCurrentRow(rowPattern.keySet());
for(Map.Entry<String,Object> e : row.entrySet()) {
String columnName = e.getKey();
- if(!_columnMatcher.matches(getTable(), columnName,
- rowPattern.get(columnName), e.getValue())) {
+ if(!columnMatcher.matches(getTable(), columnName,
+ rowPattern.get(columnName), e.getValue())) {
return false;
}
}
* @return {@code true} if a valid row was found with the given value,
* {@code false} if no row was found
*/
- protected boolean findNextRowImpl(ColumnImpl columnPattern, Object valuePattern)
+ protected boolean findAnotherRowImpl(
+ ColumnImpl columnPattern, Object valuePattern, boolean moveForward,
+ ColumnMatcher columnMatcher)
throws IOException
{
- while(moveToNextRow()) {
- if(currentRowMatches(columnPattern, valuePattern)) {
+ while(moveToAnotherRow(moveForward)) {
+ if(currentRowMatchesImpl(columnPattern, valuePattern, columnMatcher)) {
return true;
}
}
* @return {@code true} if a valid row was found with the given values,
* {@code false} if no row was found
*/
- protected boolean findNextRowImpl(Map<String,?> rowPattern)
+ protected boolean findAnotherRowImpl(Map<String,?> rowPattern,
+ boolean moveForward,
+ ColumnMatcher columnMatcher)
throws IOException
{
- while(moveToNextRow()) {
- if(currentRowMatches(rowPattern)) {
+ while(moveToAnotherRow(moveForward)) {
+ if(currentRowMatchesImpl(rowPattern, columnMatcher)) {
return true;
}
}
/**
* Base implementation of iterator for this cursor, modifiable.
*/
- protected abstract class BaseIterator
- implements Iterator<Row>
+ protected abstract class BaseIterator implements Iterator<Row>
{
protected final Collection<String> _columnNames;
+ protected final boolean _moveForward;
+ protected final ColumnMatcher _colMatcher;
protected Boolean _hasNext;
protected boolean _validRow;
- protected BaseIterator(Collection<String> columnNames)
+ protected BaseIterator(Collection<String> columnNames,
+ boolean reset, boolean moveForward,
+ ColumnMatcher columnMatcher)
{
_columnNames = columnNames;
+ _moveForward = moveForward;
+ _colMatcher = ((columnMatcher != null) ? columnMatcher : _columnMatcher);
+ if(reset) {
+ reset(_moveForward);
+ }
}
public boolean hasNext() {
*/
private final class RowIterator extends BaseIterator
{
- private final boolean _moveForward;
-
- private RowIterator(Collection<String> columnNames, boolean moveForward)
+ private RowIterator(Collection<String> columnNames, boolean reset,
+ boolean moveForward)
{
- super(columnNames);
- _moveForward = moveForward;
- reset(_moveForward);
+ super(columnNames, reset, moveForward, null);
}
@Override
private final Object _valuePattern;
private ColumnMatchIterator(Collection<String> columnNames,
- ColumnImpl columnPattern, Object valuePattern)
+ ColumnImpl columnPattern, Object valuePattern,
+ boolean reset, boolean moveForward,
+ ColumnMatcher columnMatcher)
{
- super(columnNames);
+ super(columnNames, reset, moveForward, columnMatcher);
_columnPattern = columnPattern;
_valuePattern = valuePattern;
- beforeFirst();
}
@Override
protected boolean findNext() throws IOException {
- return findNextRow(_columnPattern, _valuePattern);
+ return findAnotherRow(_columnPattern, _valuePattern, false, _moveForward,
+ _colMatcher);
}
}
private final Map<String,?> _rowPattern;
private RowMatchIterator(Collection<String> columnNames,
- Map<String,?> rowPattern)
+ Map<String,?> rowPattern,
+ boolean reset, boolean moveForward,
+ ColumnMatcher columnMatcher)
{
- super(columnNames);
+ super(columnNames, reset, moveForward, columnMatcher);
_rowPattern = rowPattern;
- beforeFirst();
}
@Override
protected boolean findNext() throws IOException {
- return findNextRow(_rowPattern);
+ return findAnotherRow(_rowPattern, false, _moveForward, _colMatcher);
}
}
try {
_tableFinder = new DefaultTableFinder(
- new CursorBuilder(_systemCatalog)
+ _systemCatalog.newCursor()
.setIndexByColumnNames(CAT_COL_PARENT_ID, CAT_COL_NAME)
.setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)
.toIndexCursor());
_systemCatalog.getName());
// use table scan instead
_tableFinder = new FallbackTableFinder(
- new CursorBuilder(_systemCatalog)
+ _systemCatalog.newCursor()
.setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)
.toCursor());
}
Map<Integer,List<Query.Row>> queryRowMap =
new HashMap<Integer,List<Query.Row>>();
for(Row row :
- CursorImpl.createCursor(_systemCatalog).iterable(SYSTEM_CATALOG_COLUMNS))
+ CursorImpl.createCursor(_systemCatalog).newIterable().setColumnNames(
+ SYSTEM_CATALOG_COLUMNS))
{
String name = (String) row.get(CAT_COL_NAME);
if (name != null && TYPE_QUERY.equals(row.get(CAT_COL_TYPE))) {
throws IOException
{
try {
- return new CursorBuilder(table)
+ return table.newCursor()
.setIndexByColumns(table.getColumn(colName))
.setSpecificEntry(colValue)
.toCursor();
boolean systemTables)
throws IOException
{
- for(Row row : getTableNamesCursor().iterable(
+ for(Row row : getTableNamesCursor().newIterable().setColumnNames(
SYSTEM_CATALOG_TABLE_NAME_COLUMNS)) {
String tableName = (String)row.get(CAT_COL_NAME);
private void initIdCursor() throws IOException {
if(_systemCatalogIdCursor == null) {
- _systemCatalogIdCursor = new CursorBuilder(_systemCatalog)
+ _systemCatalogIdCursor = _systemCatalog.newCursor()
.setIndexByColumnNames(CAT_COL_ID)
.toIndexCursor();
}
@Override
protected Cursor getTableNamesCursor() throws IOException {
- return new CursorBuilder(_systemCatalog)
+ return _systemCatalog.newCursor()
.setIndex(_systemCatalogCursor.getIndex())
.setStartEntry(_tableParentId, IndexData.MIN_VALUE)
.setEndEntry(_tableParentId, IndexData.MAX_VALUE)
@Override
public TableInfo lookupTable(String tableName) throws IOException {
- for(Row row : _systemCatalogCursor.iterable(
+ for(Row row : _systemCatalogCursor.newIterable().setColumnNames(
SYSTEM_CATALOG_TABLE_NAME_COLUMNS)) {
Short type = (Short)row.get(CAT_COL_TYPE);
import com.healthmarketscience.jackcess.impl.TableImpl.RowState;
import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher;
import com.healthmarketscience.jackcess.util.ColumnMatcher;
+import com.healthmarketscience.jackcess.util.EntryIterableBuilder;
import com.healthmarketscience.jackcess.util.SimpleColumnMatcher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
PositionImpl prevPos = _prevPos;
boolean found = false;
try {
- found = findFirstRowByEntryImpl(toRowValues(entryValues), true);
+ found = findFirstRowByEntryImpl(toRowValues(entryValues), true,
+ _columnMatcher);
return found;
} finally {
if(!found) {
PositionImpl prevPos = _prevPos;
boolean found = false;
try {
- findFirstRowByEntryImpl(toRowValues(entryValues), false);
+ findFirstRowByEntryImpl(toRowValues(entryValues), false,
+ _columnMatcher);
found = true;
} finally {
if(!found) {
public boolean currentRowMatchesEntry(Object... entryValues)
throws IOException
{
- return currentRowMatchesEntryImpl(toRowValues(entryValues));
+ return currentRowMatchesEntryImpl(toRowValues(entryValues), _columnMatcher);
}
-
- public Iterator<Row> entryIterator(Object... entryValues)
- {
- return entryIterator((Collection<String>)null, entryValues);
- }
-
- public Iterator<Row> entryIterator(
- Collection<String> columnNames, Object... entryValues)
- {
- return new EntryIterator(columnNames, toRowValues(entryValues));
- }
-
- public Iterable<Row> entryIterable(Object... entryValues)
- {
- return entryIterable((Collection<String>)null, entryValues);
+
+ public EntryIterableBuilder newEntryIterable(Object... entryValues) {
+ return new EntryIterableBuilder(this, entryValues);
}
-
- public Iterable<Row> entryIterable(
- final Collection<String> columnNames, final Object... entryValues)
- {
- return new Iterable<Row>() {
- public Iterator<Row> iterator() {
- return new EntryIterator(columnNames, toRowValues(entryValues));
- }
- };
+
+ public Iterator<Row> entryIterator(EntryIterableBuilder iterBuilder) {
+ return new EntryIterator(iterBuilder.getColumnNames(),
+ toRowValues(iterBuilder.getEntryValues()),
+ iterBuilder.getColumnMatcher());
}
@Override
}
@Override
- protected boolean findNextRowImpl(ColumnImpl columnPattern, Object valuePattern)
+ protected boolean findAnotherRowImpl(
+ ColumnImpl columnPattern, Object valuePattern, boolean moveForward,
+ ColumnMatcher columnMatcher)
throws IOException
{
- if(!isBeforeFirst()) {
+ if(!isAtBeginning(moveForward)) {
// use the default table scan for finding rows mid-cursor
- return super.findNextRowImpl(columnPattern, valuePattern);
+ return super.findAnotherRowImpl(columnPattern, valuePattern, moveForward,
+ columnMatcher);
}
// searching for the first match
if(rowValues == null) {
// bummer, use the default table scan
- return super.findNextRowImpl(columnPattern, valuePattern);
+ return super.findAnotherRowImpl(columnPattern, valuePattern, moveForward,
+ columnMatcher);
}
// sweet, we can use our index
// either we found a row with the given value, or none exist in the
// table
- return currentRowMatches(columnPattern, valuePattern);
+ return currentRowMatchesImpl(columnPattern, valuePattern, columnMatcher);
}
/**
* {@code false} if no row was found
*/
protected boolean findFirstRowByEntryImpl(Object[] rowValues,
- boolean requireMatch)
+ boolean requireMatch,
+ ColumnMatcher columnMatcher)
throws IOException
{
if(!findPotentialRow(rowValues, requireMatch)) {
return true;
}
- return currentRowMatchesEntryImpl(rowValues);
+ return currentRowMatchesEntryImpl(rowValues, columnMatcher);
}
@Override
- protected boolean findNextRowImpl(Map<String,?> rowPattern)
+ protected boolean findAnotherRowImpl(Map<String,?> rowPattern,
+ boolean moveForward,
+ ColumnMatcher columnMatcher)
throws IOException
{
- if(!isBeforeFirst()) {
+ if(!isAtBeginning(moveForward)) {
// use the default table scan for finding rows mid-cursor
- return super.findNextRowImpl(rowPattern);
+ return super.findAnotherRowImpl(rowPattern, moveForward, columnMatcher);
}
// searching for the first match
if(rowValues == null) {
// bummer, use the default table scan
- return super.findNextRowImpl(rowPattern);
+ return super.findAnotherRowImpl(rowPattern, moveForward, columnMatcher);
}
// sweet, we can use our index
// longer match
do {
- if(!currentRowMatches(indexRowPattern)) {
+ if(!currentRowMatchesImpl(indexRowPattern, columnMatcher)) {
// there are no more rows which could possibly match
break;
}
// note, if rowPattern == indexRowPattern, no need to do an extra
// comparison with the current row
- if((rowPattern == indexRowPattern) || currentRowMatches(rowPattern)) {
+ if((rowPattern == indexRowPattern) ||
+ currentRowMatchesImpl(rowPattern, columnMatcher)) {
// found it!
return true;
}
- } while(moveToNextRow());
+ } while(moveToAnotherRow(moveForward));
// none of the potential rows matched
return false;
}
- private boolean currentRowMatchesEntryImpl(Object[] rowValues)
+ private boolean currentRowMatchesEntryImpl(Object[] rowValues,
+ ColumnMatcher columnMatcher)
throws IOException
{
if(_indexEntryPattern == null) {
String columnName = col.getName();
Object patValue = rowValues[col.getColumnIndex()];
Object rowValue = row.get(columnName);
- if(!_columnMatcher.matches(getTable(), columnName,
- patValue, rowValue)) {
+ if(!columnMatcher.matches(getTable(), columnName, patValue, rowValue)) {
return false;
}
}
{
private final Object[] _rowValues;
- private EntryIterator(Collection<String> columnNames, Object[] rowValues)
+ private EntryIterator(Collection<String> columnNames, Object[] rowValues,
+ ColumnMatcher columnMatcher)
{
- super(columnNames);
+ super(columnNames, false, MOVE_FORWARD, columnMatcher);
_rowValues = rowValues;
try {
- _hasNext = findFirstRowByEntryImpl(rowValues, true);
+ _hasNext = findFirstRowByEntryImpl(rowValues, true, _columnMatcher);
_validRow = _hasNext;
} catch(IOException e) {
throw new RuntimeIOException(e);
@Override
protected boolean findNext() throws IOException {
- return (moveToNextRow() && currentRowMatchesEntryImpl(_rowValues));
+ return (moveToNextRow() &&
+ currentRowMatchesEntryImpl(_rowValues, _colMatcher));
}
}
import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.ColumnBuilder;
+import com.healthmarketscience.jackcess.CursorBuilder;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Index;
import com.healthmarketscience.jackcess.IndexBuilder;
}
return _defaultCursor;
}
+
+ public CursorBuilder newCursor() {
+ return new CursorBuilder(this);
+ }
public void reset() {
getDefaultCursor().reset();
throws IOException
{
if(_complexValIdCursor == null) {
- _complexValIdCursor = new CursorBuilder(_flatTable)
+ _complexValIdCursor = _flatTable.newCursor()
.setIndexByColumns(_complexValFkCol)
.toIndexCursor();
}
- return _complexValIdCursor.entryIterator(columnNames, complexValueFk);
+ return _complexValIdCursor.newEntryIterable(complexValueFk)
+ .setColumnNames(columnNames).iterator();
}
public List<Row> getRawValues(int complexValueFk,
Collection<String> columnNames)
{
toEntryValues(fromRow);
- return _toCursor.entryIterator(columnNames, _entryValues);
+ return _toCursor.newEntryIterable(_entryValues)
+ .setColumnNames(columnNames).iterator();
}
/**
Collection<String> columnNames)
{
toEntryValues(fromRow);
- return _toCursor.entryIterator(columnNames, _entryValues);
+ return _toCursor.newEntryIterable(_entryValues)
+ .setColumnNames(columnNames).iterator();
}
/**
int type)
throws Exception
{
- return new CursorBuilder(table)
+ return table.newCursor()
.setIndex(idx)
.setStartEntry(3 - type)
.setStartRowInclusive(type == 0)
List<Map<String, Object>> foundRows =
new ArrayList<Map<String, Object>>();
- for(Map<String, Object> row : cursor.reverseIterable()) {
+ for(Map<String, Object> row : cursor.newIterable().reverse()) {
foundRows.add(row);
}
assertEquals(expectedRows, foundRows);
private static void doTestFindAll(Table table, Cursor cursor, Index index)
throws Exception
{
- Column valCol = table.getColumn("value");
List<? extends Map<String,Object>> rows = RowFilterTest.toList(
- cursor.columnMatchIterable(valCol, "data2"));
+ cursor.newIterable().setMatchPattern("value", "data2"));
List<? extends Map<String, Object>> expectedRows = null;
}
assertEquals(expectedRows, rows);
+ Column valCol = table.getColumn("value");
rows = RowFilterTest.toList(
- cursor.columnMatchIterable(valCol, "data4"));
+ cursor.newIterable().setMatchPattern(valCol, "data4"));
if(index == null) {
expectedRows =
assertEquals(expectedRows, rows);
rows = RowFilterTest.toList(
- cursor.columnMatchIterable(valCol, "data9"));
+ cursor.newIterable().setMatchPattern(valCol, "data9"));
assertTrue(rows.isEmpty());
rows = RowFilterTest.toList(
- cursor.rowMatchIterable(Collections.singletonMap("id", 8)));
+ cursor.newIterable().setMatchPattern(
+ Collections.singletonMap("id", 8)));
expectedRows =
createExpectedTable(
expectedRows = tmpRows;
assertFalse(expectedRows.isEmpty());
- rows = RowFilterTest.toList(cursor.rowMatchIterable(row));
+ rows = RowFilterTest.toList(cursor.newIterable().setMatchPattern(row));
assertEquals(expectedRows, rows);
}
rows = RowFilterTest.toList(
- cursor.rowMatchIterable(createExpectedRow(
- "id", 8, "value", "data13")));
+ cursor.newIterable().addMatchPattern("id", 8)
+ .addMatchPattern("value", "data13"));
assertTrue(rows.isEmpty());
}
"value", "data" + 4),
cursor.getCurrentRow());
}
+
+ assertEquals(Arrays.asList(createExpectedRow("id", 4,
+ "value", "data" + 4)),
+ RowFilterTest.toList(
+ cursor.newIterable()
+ .setMatchPattern("value", "data4")
+ .setColumnMatcher(SimpleColumnMatcher.INSTANCE)));
+
+ assertEquals(Arrays.asList(createExpectedRow("id", 3,
+ "value", "data" + 3)),
+ RowFilterTest.toList(
+ cursor.newIterable()
+ .setMatchPattern("value", "DaTa3")
+ .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)));
+
+ assertEquals(Arrays.asList(createExpectedRow("id", 2,
+ "value", "data" + 2)),
+ RowFilterTest.toList(
+ cursor.newIterable()
+ .addMatchPattern("value", "DaTa2")
+ .addMatchPattern("id", 2)
+ .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE)));
}
public void testIndexCursor() throws Exception
IndexCursor cursor = CursorBuilder.createCursor(t1, idx);
List<String> expectedData = new ArrayList<String>();
- for(Map<String,Object> row : cursor.entryIterable(
- Arrays.asList("data"), 1)) {
+ for(Map<String,Object> row : cursor.newEntryIterable(1)
+ .addColumnNames("data")) {
expectedData.add((String)row.get("data"));
}
assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
expectedData = new ArrayList<String>();
- for(Iterator<? extends Map<String,Object>> iter = cursor.entryIterator(1);
+ for(Iterator<? extends Map<String,Object>> iter =
+ cursor.newEntryIterable(1).iterator();
iter.hasNext(); ) {
expectedData.add((String)iter.next().get("data"));
iter.remove();
assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
expectedData = new ArrayList<String>();
- for(Map<String,Object> row : cursor.entryIterable(
- Arrays.asList("data"), 1)) {
+ for(Map<String,Object> row : cursor.newEntryIterable(1)
+ .addColumnNames("data")) {
expectedData.add((String)row.get("data"));
}
Cursor cursor = CursorBuilder.createCursor(t1);
List<String> expectedData = new ArrayList<String>();
- for(Map<String,Object> row : cursor.iterable(
+ for(Map<String,Object> row : cursor.newIterable().setColumnNames(
Arrays.asList("otherfk1", "data"))) {
if(row.get("otherfk1").equals(1)) {
expectedData.add((String)row.get("data"));
assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData);
expectedData = new ArrayList<String>();
- for(Map<String,Object> row : cursor.iterable(
+ for(Map<String,Object> row : cursor.newIterable().setColumnNames(
Arrays.asList("otherfk1", "data"))) {
if(row.get("otherfk1").equals(1)) {
expectedData.add((String)row.get("data"));
t.addRow(1, "row1");
t.addRow(3, "row3");
- Cursor c = new CursorBuilder(t)
+ Cursor c = t.newCursor()
.setIndexByName(IndexBuilder.PRIMARY_KEY_NAME).toCursor();
for(int i = 1; i <= 3; ++i) {
t2.addRow(null, "rowdata-" + i + DatabaseTest.createString(100));
}
- Cursor c1 = new CursorBuilder(t1).setIndex(t1.getPrimaryKeyIndex())
+ Cursor c1 = t1.newCursor().setIndex(t1.getPrimaryKeyIndex())
.toCursor();
- Cursor c2 = new CursorBuilder(t2).setIndex(t2.getPrimaryKeyIndex())
+ Cursor c2 = t2.newCursor().setIndex(t2.getPrimaryKeyIndex())
.toCursor();
Iterator<? extends Map<String,Object>> i1 = c1.iterator();
- Iterator<? extends Map<String,Object>> i2 = c2.reverseIterable().iterator();
+ Iterator<? extends Map<String,Object>> i2 = c2.newIterable().reverse().iterator();
int t1rows = 0;
int t2rows = 0;